@refactico/pages 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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",
@@ -687,101 +1569,122 @@ const ImageBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
687
1569
  ] })
688
1570
  ]
689
1571
  }
690
- );
691
- }
692
- return /* @__PURE__ */ jsxRuntime.jsxs(
693
- "div",
694
- {
695
- className: "group relative",
696
- onFocus: () => setShowToolbar(true),
697
- 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
- ] })
1572
+ );
1573
+ }
1574
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1575
+ "div",
1576
+ {
1577
+ ref: containerRef,
1578
+ className: "group relative",
1579
+ onFocus: () => setShowToolbar(true),
1580
+ onBlur: (e) => {
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,7 +1720,12 @@ 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";
@@ -853,58 +1761,78 @@ const CodeBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
853
1761
  {
854
1762
  className: `group relative rounded-xl overflow-hidden ${isDark ? "bg-slate-950" : "bg-slate-900"}`,
855
1763
  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(
1764
+ /* @__PURE__ */ jsxRuntime.jsxs(
1765
+ "div",
1766
+ {
1767
+ 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"}`,
1768
+ children: [
1769
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1770
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5", children: [
1771
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full bg-red-500/80" }),
1772
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full bg-yellow-500/80" }),
1773
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full bg-green-500/80" })
1774
+ ] }),
1775
+ !readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
1776
+ "input",
1777
+ {
1778
+ type: "text",
1779
+ value: block.filename || "",
1780
+ onChange: handleFilenameChange,
1781
+ placeholder: "filename.js",
1782
+ className: "text-sm text-slate-400 bg-transparent outline-none placeholder:text-slate-600 w-32"
1783
+ }
1784
+ ) : block.filename ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-slate-400", children: block.filename }) : null
1785
+ ] }),
1786
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1787
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1788
+ /* @__PURE__ */ jsxRuntime.jsx(
1789
+ "select",
1790
+ {
1791
+ value: block.language,
1792
+ onChange: handleLanguageChange,
1793
+ className: "text-xs px-2 py-1.5 bg-slate-700 text-slate-300 rounded-lg border border-slate-600 outline-none",
1794
+ children: SUPPORTED_LANGUAGES.map((lang) => /* @__PURE__ */ jsxRuntime.jsx(
1795
+ "option",
1796
+ {
1797
+ value: lang,
1798
+ children: lang
1799
+ },
1800
+ lang
1801
+ ))
1802
+ }
1803
+ ),
1804
+ /* @__PURE__ */ jsxRuntime.jsx(
1805
+ "button",
1806
+ {
1807
+ onClick: toggleLineNumbers,
1808
+ 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"}`,
1809
+ children: "#"
1810
+ }
1811
+ )
1812
+ ] }),
1813
+ /* @__PURE__ */ jsxRuntime.jsx(
1814
+ "button",
1815
+ {
1816
+ onClick: copyToClipboard,
1817
+ className: "p-1.5 rounded-lg hover:bg-slate-700 text-slate-400 hover:text-white transition-colors",
1818
+ title: "Copy code",
1819
+ children: copied ? /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { size: 16 }) : /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { size: 16 })
1820
+ }
1821
+ )
1822
+ ] })
1823
+ ]
1824
+ }
1825
+ ),
1826
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex", children: [
1827
+ 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(
1828
+ "div",
1829
+ {
1830
+ className: "text-xs text-slate-600 leading-6 font-mono",
1831
+ children: num
1832
+ },
1833
+ num
1834
+ )) }),
1835
+ /* @__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
1836
  "textarea",
909
1837
  {
910
1838
  ref: textareaRef,
@@ -912,8 +1840,8 @@ const CodeBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
912
1840
  onChange: handleCodeChange,
913
1841
  placeholder: "// Write your code here...",
914
1842
  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 },
1843
+ 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",
1844
+ style: { tabSize: 2, height: "auto" },
917
1845
  onKeyDown: (e) => {
918
1846
  if (e.key === "Tab") {
919
1847
  e.preventDefault();
@@ -937,10 +1865,45 @@ const CodeBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
937
1865
  );
938
1866
  };
939
1867
 
940
- const TableBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1868
+ const TableBlock = ({
1869
+ block,
1870
+ onUpdate,
1871
+ readOnly,
1872
+ theme = "light"
1873
+ }) => {
941
1874
  const [showToolbar, setShowToolbar] = react.useState(false);
942
- const [selectedCell, setSelectedCell] = react.useState(null);
1875
+ const [activeCell, setActiveCell] = react.useState(null);
1876
+ const [toolbarPosition, setToolbarPosition] = react.useState(null);
1877
+ const containerRef = react.useRef(null);
1878
+ const toolbarRef = react.useRef(null);
1879
+ const cellRefs = react.useRef(/* @__PURE__ */ new Map());
943
1880
  const isDark = theme === "dark";
1881
+ const updateToolbarPosition = (row, col) => {
1882
+ const cellKey = `${row}-${col}`;
1883
+ const cellEl = cellRefs.current.get(cellKey);
1884
+ const containerEl = containerRef.current;
1885
+ if (cellEl && containerEl) {
1886
+ const cellRect = cellEl.getBoundingClientRect();
1887
+ const containerRect = containerEl.getBoundingClientRect();
1888
+ const containerWidth = containerRect.width;
1889
+ let left = cellRect.left - containerRect.left;
1890
+ const toolbarWidth = 520;
1891
+ const availableRight = containerWidth - left;
1892
+ if (availableRight < toolbarWidth) {
1893
+ left = Math.max(0, containerWidth - toolbarWidth);
1894
+ }
1895
+ setToolbarPosition({
1896
+ top: cellRect.top - containerRect.top - 44,
1897
+ // 44px above cell
1898
+ left: Math.max(0, left)
1899
+ });
1900
+ }
1901
+ };
1902
+ const handleCellFocus = (row, col) => {
1903
+ setActiveCell({ row, col });
1904
+ setShowToolbar(true);
1905
+ setTimeout(() => updateToolbarPosition(row, col), 0);
1906
+ };
944
1907
  const updateCell = (rowIndex, colIndex, content) => {
945
1908
  const currentRow = block.rows[rowIndex];
946
1909
  if (!currentRow) return;
@@ -973,6 +1936,44 @@ const TableBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
973
1936
  const newRows = block.rows.map((row) => row.filter((_, i) => i !== colIndex));
974
1937
  onUpdate({ ...block, rows: newRows });
975
1938
  };
1939
+ const moveRowUp = (rowIndex) => {
1940
+ if (rowIndex === 0) return;
1941
+ const newRows = [...block.rows];
1942
+ const temp = newRows[rowIndex - 1];
1943
+ newRows[rowIndex - 1] = newRows[rowIndex];
1944
+ newRows[rowIndex] = temp;
1945
+ onUpdate({ ...block, rows: newRows });
1946
+ };
1947
+ const moveRowDown = (rowIndex) => {
1948
+ if (rowIndex >= block.rows.length - 1) return;
1949
+ const newRows = [...block.rows];
1950
+ const temp = newRows[rowIndex];
1951
+ newRows[rowIndex] = newRows[rowIndex + 1];
1952
+ newRows[rowIndex + 1] = temp;
1953
+ onUpdate({ ...block, rows: newRows });
1954
+ };
1955
+ const moveColumnLeft = (colIndex) => {
1956
+ if (colIndex === 0) return;
1957
+ const newRows = block.rows.map((row) => {
1958
+ const newRow = [...row];
1959
+ const temp = newRow[colIndex - 1];
1960
+ newRow[colIndex - 1] = newRow[colIndex];
1961
+ newRow[colIndex] = temp;
1962
+ return newRow;
1963
+ });
1964
+ onUpdate({ ...block, rows: newRows });
1965
+ };
1966
+ const moveColumnRight = (colIndex) => {
1967
+ if (colIndex >= (block.rows[0]?.length ?? 0) - 1) return;
1968
+ const newRows = block.rows.map((row) => {
1969
+ const newRow = [...row];
1970
+ const temp = newRow[colIndex];
1971
+ newRow[colIndex] = newRow[colIndex + 1];
1972
+ newRow[colIndex + 1] = temp;
1973
+ return newRow;
1974
+ });
1975
+ onUpdate({ ...block, rows: newRows });
1976
+ };
976
1977
  const toggleHeader = () => {
977
1978
  const newRows = block.rows.map(
978
1979
  (row, rowIndex) => row.map((cell) => ({
@@ -982,26 +1983,14 @@ const TableBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
982
1983
  );
983
1984
  onUpdate({ ...block, rows: newRows, hasHeader: !block.hasHeader });
984
1985
  };
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
1986
  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
1987
  return /* @__PURE__ */ jsxRuntime.jsxs(
1002
1988
  "div",
1003
1989
  {
1990
+ ref: containerRef,
1004
1991
  className: "group relative",
1992
+ tabIndex: 0,
1993
+ onClick: () => setShowToolbar(true),
1005
1994
  onFocus: () => setShowToolbar(true),
1006
1995
  onBlur: (e) => {
1007
1996
  if (!e.currentTarget.contains(e.relatedTarget)) {
@@ -1009,114 +1998,194 @@ const TableBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1009
1998
  }
1010
1999
  },
1011
2000
  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,
2001
+ showToolbar && !readOnly && activeCell && toolbarPosition && /* @__PURE__ */ jsxRuntime.jsxs(
2002
+ "div",
2003
+ {
2004
+ ref: toolbarRef,
2005
+ style: { top: toolbarPosition.top, left: toolbarPosition.left },
2006
+ 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"}`,
2007
+ children: [
2008
+ /* @__PURE__ */ jsxRuntime.jsxs(
2009
+ "button",
2010
+ {
2011
+ onMouseDown: (e) => {
2012
+ e.preventDefault();
2013
+ addRow();
2014
+ },
2015
+ className: `flex items-center gap-1 ${toolbarBtnClass()}`,
2016
+ title: "Add Row",
2017
+ children: [
2018
+ /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { size: 14 }),
2019
+ " Row"
2020
+ ]
2021
+ }
2022
+ ),
2023
+ /* @__PURE__ */ jsxRuntime.jsxs(
2024
+ "button",
2025
+ {
2026
+ onMouseDown: (e) => {
2027
+ e.preventDefault();
2028
+ addColumn();
2029
+ },
2030
+ className: `flex items-center gap-1 ${toolbarBtnClass()}`,
2031
+ title: "Add Column",
2032
+ children: [
2033
+ /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { size: 14 }),
2034
+ " Col"
2035
+ ]
2036
+ }
2037
+ ),
2038
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
2039
+ /* @__PURE__ */ jsxRuntime.jsx(
2040
+ "button",
2041
+ {
2042
+ onMouseDown: (e) => {
2043
+ e.preventDefault();
2044
+ toggleHeader();
2045
+ },
2046
+ className: toolbarBtnClass(block.hasHeader),
2047
+ children: "Header"
2048
+ }
2049
+ ),
2050
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
2051
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xs ${isDark ? "text-slate-500" : "text-slate-400"}`, children: "Row:" }),
2052
+ /* @__PURE__ */ jsxRuntime.jsx(
2053
+ "button",
2054
+ {
2055
+ onMouseDown: (e) => {
2056
+ e.preventDefault();
2057
+ moveRowUp(activeCell.row);
2058
+ updateToolbarPosition(activeCell.row - 1, activeCell.col);
2059
+ },
2060
+ disabled: activeCell.row === 0,
2061
+ className: `p-1 rounded ${activeCell.row === 0 ? "opacity-30 cursor-not-allowed" : ""} ${toolbarBtnClass()}`,
2062
+ title: "Move Row Up",
2063
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronUpIcon, { size: 14 })
2064
+ }
2065
+ ),
2066
+ /* @__PURE__ */ jsxRuntime.jsx(
2067
+ "button",
2068
+ {
2069
+ onMouseDown: (e) => {
2070
+ e.preventDefault();
2071
+ moveRowDown(activeCell.row);
2072
+ updateToolbarPosition(activeCell.row + 1, activeCell.col);
2073
+ },
2074
+ disabled: activeCell.row >= block.rows.length - 1,
2075
+ className: `p-1 rounded ${activeCell.row >= block.rows.length - 1 ? "opacity-30 cursor-not-allowed" : ""} ${toolbarBtnClass()}`,
2076
+ title: "Move Row Down",
2077
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { size: 14 })
2078
+ }
2079
+ ),
2080
+ /* @__PURE__ */ jsxRuntime.jsx(
2081
+ "button",
2082
+ {
2083
+ onMouseDown: (e) => {
2084
+ e.preventDefault();
2085
+ deleteRow(activeCell.row);
2086
+ setActiveCell(null);
2087
+ setShowToolbar(false);
2088
+ },
2089
+ disabled: block.rows.length <= 1,
2090
+ className: `p-1 rounded text-red-500 hover:bg-red-100 ${block.rows.length <= 1 ? "opacity-30 cursor-not-allowed" : ""}`,
2091
+ title: "Delete Row",
2092
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 14 })
2093
+ }
2094
+ ),
2095
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
2096
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xs ${isDark ? "text-slate-500" : "text-slate-400"}`, children: "Col:" }),
2097
+ /* @__PURE__ */ jsxRuntime.jsx(
2098
+ "button",
2099
+ {
2100
+ onMouseDown: (e) => {
2101
+ e.preventDefault();
2102
+ moveColumnLeft(activeCell.col);
2103
+ updateToolbarPosition(activeCell.row, activeCell.col - 1);
2104
+ },
2105
+ disabled: activeCell.col === 0,
2106
+ className: `p-1 rounded ${activeCell.col === 0 ? "opacity-30 cursor-not-allowed" : ""} ${toolbarBtnClass()}`,
2107
+ title: "Move Column Left",
2108
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeftIcon, { size: 14 })
2109
+ }
2110
+ ),
2111
+ /* @__PURE__ */ jsxRuntime.jsx(
2112
+ "button",
2113
+ {
2114
+ onMouseDown: (e) => {
2115
+ e.preventDefault();
2116
+ moveColumnRight(activeCell.col);
2117
+ updateToolbarPosition(activeCell.row, activeCell.col + 1);
2118
+ },
2119
+ disabled: activeCell.col >= (block.rows[0]?.length ?? 0) - 1,
2120
+ className: `p-1 rounded ${activeCell.col >= (block.rows[0]?.length ?? 0) - 1 ? "opacity-30 cursor-not-allowed" : ""} ${toolbarBtnClass()}`,
2121
+ title: "Move Column Right",
2122
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { size: 14 })
2123
+ }
2124
+ ),
2125
+ /* @__PURE__ */ jsxRuntime.jsx(
2126
+ "button",
2127
+ {
2128
+ onMouseDown: (e) => {
2129
+ e.preventDefault();
2130
+ deleteColumn(activeCell.col);
2131
+ setActiveCell(null);
2132
+ setShowToolbar(false);
2133
+ },
2134
+ disabled: (block.rows[0]?.length ?? 0) <= 1,
2135
+ className: `p-1 rounded text-red-500 hover:bg-red-100 ${(block.rows[0]?.length ?? 0) <= 1 ? "opacity-30 cursor-not-allowed" : ""}`,
2136
+ title: "Delete Column",
2137
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 14 })
2138
+ }
2139
+ )
2140
+ ]
2141
+ }
2142
+ ),
2143
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-xl", children: /* @__PURE__ */ jsxRuntime.jsx(
2144
+ "table",
2145
+ {
2146
+ className: `w-full border-collapse border ${isDark ? "border-slate-600" : "border-slate-300"}`,
2147
+ children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: block.rows.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
2148
+ "tr",
1081
2149
  {
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",
2150
+ className: "group/row",
2151
+ children: row.map((cell, colIndex) => {
2152
+ const isHeader = block.hasHeader && rowIndex === 0;
2153
+ const CellTag = isHeader ? "th" : "td";
2154
+ const isActive = activeCell?.row === rowIndex && activeCell?.col === colIndex;
2155
+ const alignClass = cell.alignment === "center" ? "text-center" : cell.alignment === "right" ? "text-right" : "text-left";
2156
+ return /* @__PURE__ */ jsxRuntime.jsx(
2157
+ CellTag,
1098
2158
  {
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
- ]
2159
+ ref: (el) => {
2160
+ if (el) cellRefs.current.set(`${rowIndex}-${colIndex}`, el);
2161
+ },
2162
+ 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" : ""}`,
2163
+ children: readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
2164
+ "div",
2165
+ {
2166
+ className: `px-3 py-2 min-h-[40px] ${isDark ? "text-slate-200" : "text-slate-700"}`,
2167
+ children: cell.content
2168
+ }
2169
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2170
+ "input",
2171
+ {
2172
+ type: "text",
2173
+ value: cell.content,
2174
+ onChange: (e) => updateCell(rowIndex, colIndex, e.target.value),
2175
+ onFocus: () => handleCellFocus(rowIndex, colIndex),
2176
+ 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"}`,
2177
+ placeholder: isHeader ? "Header" : ""
2178
+ }
2179
+ )
2180
+ },
2181
+ colIndex
2182
+ );
2183
+ })
1106
2184
  },
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)) }) }) })
2185
+ rowIndex
2186
+ )) })
2187
+ }
2188
+ ) })
1120
2189
  ]
1121
2190
  }
1122
2191
  );
@@ -1127,7 +2196,12 @@ const styleMap = {
1127
2196
  dashed: "border-dashed",
1128
2197
  dotted: "border-dotted"
1129
2198
  };
1130
- const DividerBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
2199
+ const DividerBlock = ({
2200
+ block,
2201
+ onUpdate,
2202
+ readOnly,
2203
+ theme = "light"
2204
+ }) => {
1131
2205
  const isDark = theme === "dark";
1132
2206
  const cycleStyle = () => {
1133
2207
  if (readOnly) return;
@@ -1143,19 +2217,36 @@ const DividerBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1143
2217
  onClick: cycleStyle,
1144
2218
  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
2219
  }
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
- ] })
2220
+ ),
2221
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
2222
+ "p",
2223
+ {
2224
+ className: `text-xs text-center mt-1 opacity-0 group-hover:opacity-100 transition-opacity ${isDark ? "text-slate-500" : "text-slate-400"}`,
2225
+ children: [
2226
+ "Click to change style (",
2227
+ block.style || "solid",
2228
+ ")"
2229
+ ]
2230
+ }
2231
+ )
1152
2232
  ] });
1153
2233
  };
1154
2234
 
1155
- const QuoteBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
2235
+ const QuoteBlock = ({
2236
+ block,
2237
+ onUpdate,
2238
+ readOnly,
2239
+ theme = "light"
2240
+ }) => {
1156
2241
  const [showToolbar, setShowToolbar] = react.useState(false);
1157
2242
  const textareaRef = react.useRef(null);
2243
+ const containerRef = react.useRef(null);
1158
2244
  const isDark = theme === "dark";
2245
+ const { showBelow } = useToolbarPosition({
2246
+ containerRef,
2247
+ isVisible: showToolbar && !readOnly,
2248
+ minSpaceAbove: 60
2249
+ });
1159
2250
  const styleClasses = {
1160
2251
  default: `border-l-4 pl-4 italic ${isDark ? "border-slate-600" : "border-slate-300"}`,
1161
2252
  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 +2271,7 @@ const QuoteBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1180
2271
  return /* @__PURE__ */ jsxRuntime.jsxs(
1181
2272
  "div",
1182
2273
  {
2274
+ ref: containerRef,
1183
2275
  className: "group relative",
1184
2276
  onFocus: () => setShowToolbar(true),
1185
2277
  onBlur: (e) => {
@@ -1188,69 +2280,98 @@ const QuoteBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1188
2280
  }
1189
2281
  },
1190
2282
  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
- ] }) })
2283
+ showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
2284
+ "div",
2285
+ {
2286
+ 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"}`,
2287
+ children: [
2288
+ /* @__PURE__ */ jsxRuntime.jsx(
2289
+ "button",
2290
+ {
2291
+ onClick: () => setStyle("default"),
2292
+ className: toolbarBtnClass(block.style === "default" || !block.style),
2293
+ children: "Simple"
2294
+ }
2295
+ ),
2296
+ /* @__PURE__ */ jsxRuntime.jsx(
2297
+ "button",
2298
+ {
2299
+ onClick: () => setStyle("bordered"),
2300
+ className: toolbarBtnClass(block.style === "bordered"),
2301
+ children: "Bordered"
2302
+ }
2303
+ ),
2304
+ /* @__PURE__ */ jsxRuntime.jsx(
2305
+ "button",
2306
+ {
2307
+ onClick: () => setStyle("modern"),
2308
+ className: toolbarBtnClass(block.style === "modern"),
2309
+ children: "Modern"
2310
+ }
2311
+ )
2312
+ ]
2313
+ }
2314
+ ),
2315
+ /* @__PURE__ */ jsxRuntime.jsx(
2316
+ "blockquote",
2317
+ {
2318
+ className: `${styleClasses[block.style || "default"]} ${isDark ? "text-slate-300" : "text-slate-700"}`,
2319
+ children: readOnly ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2320
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg leading-relaxed whitespace-pre-wrap", children: block.content }),
2321
+ block.author && /* @__PURE__ */ jsxRuntime.jsxs(
2322
+ "cite",
2323
+ {
2324
+ className: `block mt-3 text-sm not-italic ${isDark ? "text-slate-400" : "text-slate-500"}`,
2325
+ children: [
2326
+ "— ",
2327
+ block.author
2328
+ ]
2329
+ }
2330
+ )
2331
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2332
+ /* @__PURE__ */ jsxRuntime.jsx(
2333
+ "textarea",
2334
+ {
2335
+ ref: textareaRef,
2336
+ value: block.content,
2337
+ onChange: handleContentChange,
2338
+ placeholder: "Enter quote...",
2339
+ className: `w-full text-lg leading-relaxed bg-transparent outline-none resize-none ${isDark ? "placeholder:text-slate-500" : "placeholder:text-slate-400"}`,
2340
+ rows: 1
2341
+ }
2342
+ ),
2343
+ /* @__PURE__ */ jsxRuntime.jsx(
2344
+ "input",
2345
+ {
2346
+ type: "text",
2347
+ value: block.author || "",
2348
+ onChange: handleAuthorChange,
2349
+ placeholder: "— Author name",
2350
+ 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"}`
2351
+ }
2352
+ )
2353
+ ] })
2354
+ }
2355
+ )
1246
2356
  ]
1247
2357
  }
1248
2358
  );
1249
2359
  };
1250
2360
 
1251
- const ListBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
2361
+ const ListBlock = ({
2362
+ block,
2363
+ onUpdate,
2364
+ readOnly,
2365
+ theme = "light"
2366
+ }) => {
1252
2367
  const [showToolbar, setShowToolbar] = react.useState(false);
2368
+ const containerRef = react.useRef(null);
1253
2369
  const isDark = theme === "dark";
2370
+ const { showBelow } = useToolbarPosition({
2371
+ containerRef,
2372
+ isVisible: showToolbar && !readOnly,
2373
+ minSpaceAbove: 60
2374
+ });
1254
2375
  const updateItem = (index, value) => {
1255
2376
  const newItems = [...block.items];
1256
2377
  newItems[index] = value;
@@ -1308,6 +2429,7 @@ const ListBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1308
2429
  return /* @__PURE__ */ jsxRuntime.jsxs(
1309
2430
  "div",
1310
2431
  {
2432
+ ref: containerRef,
1311
2433
  className: "group relative",
1312
2434
  onFocus: () => setShowToolbar(true),
1313
2435
  onBlur: (e) => {
@@ -1316,65 +2438,90 @@ const ListBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1316
2438
  }
1317
2439
  },
1318
2440
  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",
2441
+ showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
2442
+ "div",
2443
+ {
2444
+ 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"}`,
2445
+ children: [
2446
+ /* @__PURE__ */ jsxRuntime.jsx(
2447
+ "button",
2448
+ {
2449
+ onClick: () => setListType("bullet"),
2450
+ className: toolbarBtnClass(block.listType === "bullet"),
2451
+ children: "• Bullet"
2452
+ }
2453
+ ),
2454
+ /* @__PURE__ */ jsxRuntime.jsx(
2455
+ "button",
2456
+ {
2457
+ onClick: () => setListType("numbered"),
2458
+ className: toolbarBtnClass(block.listType === "numbered"),
2459
+ children: "1. Numbered"
2460
+ }
2461
+ ),
2462
+ /* @__PURE__ */ jsxRuntime.jsx(
2463
+ "button",
2464
+ {
2465
+ onClick: () => setListType("checklist"),
2466
+ className: toolbarBtnClass(block.listType === "checklist"),
2467
+ children: " Checklist"
2468
+ }
2469
+ )
2470
+ ]
2471
+ }
2472
+ ),
2473
+ /* @__PURE__ */ jsxRuntime.jsx(
2474
+ ListWrapper,
2475
+ {
2476
+ 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"}`,
2477
+ children: block.items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
2478
+ "li",
1370
2479
  {
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)) }),
2480
+ className: "group/item flex items-center gap-2",
2481
+ children: [
2482
+ block.listType === "checklist" && /* @__PURE__ */ jsxRuntime.jsx(
2483
+ "button",
2484
+ {
2485
+ onClick: () => toggleChecked(index),
2486
+ disabled: readOnly,
2487
+ 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"}`,
2488
+ children: block.checkedItems?.[index] && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { size: 12 })
2489
+ }
2490
+ ),
2491
+ readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
2492
+ "span",
2493
+ {
2494
+ className: block.checkedItems?.[index] ? isDark ? "line-through text-slate-500" : "line-through text-slate-400" : "",
2495
+ children: item
2496
+ }
2497
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2498
+ /* @__PURE__ */ jsxRuntime.jsx(
2499
+ "input",
2500
+ {
2501
+ type: "text",
2502
+ "data-list-input": block.id,
2503
+ value: item,
2504
+ onChange: (e) => updateItem(index, e.target.value),
2505
+ onKeyDown: (e) => handleKeyDown(e, index),
2506
+ placeholder: "List item...",
2507
+ 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"}`
2508
+ }
2509
+ ),
2510
+ /* @__PURE__ */ jsxRuntime.jsx(
2511
+ "button",
2512
+ {
2513
+ onClick: () => removeItem(index),
2514
+ 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"}`,
2515
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 14 })
2516
+ }
2517
+ )
2518
+ ] })
2519
+ ]
2520
+ },
2521
+ index
2522
+ ))
2523
+ }
2524
+ ),
1378
2525
  !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
1379
2526
  "button",
1380
2527
  {
@@ -1442,10 +2589,21 @@ const variantLabels = {
1442
2589
  error: "Error",
1443
2590
  tip: "Tip"
1444
2591
  };
1445
- const CalloutBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
2592
+ const CalloutBlock = ({
2593
+ block,
2594
+ onUpdate,
2595
+ readOnly,
2596
+ theme = "light"
2597
+ }) => {
1446
2598
  const [showToolbar, setShowToolbar] = react.useState(false);
1447
2599
  const textareaRef = react.useRef(null);
2600
+ const containerRef = react.useRef(null);
1448
2601
  const isDark = theme === "dark";
2602
+ const { showBelow } = useToolbarPosition({
2603
+ containerRef,
2604
+ isVisible: showToolbar && !readOnly,
2605
+ minSpaceAbove: 60
2606
+ });
1449
2607
  const handleContentChange = (e) => {
1450
2608
  onUpdate({ ...block, content: e.target.value });
1451
2609
  if (textareaRef.current) {
@@ -1465,6 +2623,7 @@ const CalloutBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1465
2623
  return /* @__PURE__ */ jsxRuntime.jsxs(
1466
2624
  "div",
1467
2625
  {
2626
+ ref: containerRef,
1468
2627
  className: "group relative",
1469
2628
  onFocus: () => setShowToolbar(true),
1470
2629
  onBlur: (e) => {
@@ -1473,19 +2632,25 @@ const CalloutBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1473
2632
  }
1474
2633
  },
1475
2634
  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",
2635
+ showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
2636
+ "div",
1478
2637
  {
1479
- onClick: () => setVariant(variant),
1480
- className: toolbarBtnClass(block.variant === variant),
1481
- children: [
1482
- variantIcons[variant],
1483
- " ",
1484
- variantLabels[variant]
1485
- ]
1486
- },
1487
- variant
1488
- )) }),
2638
+ 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"}`,
2639
+ children: Object.keys(variantStyles).map((variant) => /* @__PURE__ */ jsxRuntime.jsxs(
2640
+ "button",
2641
+ {
2642
+ onClick: () => setVariant(variant),
2643
+ className: toolbarBtnClass(block.variant === variant),
2644
+ children: [
2645
+ variantIcons[variant],
2646
+ " ",
2647
+ variantLabels[variant]
2648
+ ]
2649
+ },
2650
+ variant
2651
+ ))
2652
+ }
2653
+ ),
1489
2654
  /* @__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
2655
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xl flex-shrink-0 ${styles.icon}`, children: variantIcons[block.variant] }),
1491
2656
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: readOnly ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -1559,37 +2724,103 @@ const BlockWrapper = ({
1559
2724
  }
1560
2725
  return () => document.removeEventListener("mousedown", handleClickOutside);
1561
2726
  }, [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]);
2727
+ const handleBlockClick = react.useCallback(
2728
+ (e) => {
2729
+ const target = e.target;
2730
+ const interactiveElements = ["INPUT", "TEXTAREA", "BUTTON", "SELECT"];
2731
+ if (interactiveElements.includes(target.tagName)) {
2732
+ return;
2733
+ }
2734
+ if (!readOnly) {
2735
+ setIsSelected(true);
2736
+ }
2737
+ },
2738
+ [readOnly]
2739
+ );
1572
2740
  const renderBlock = react.useCallback(() => {
1573
2741
  const commonProps = { readOnly, theme };
1574
2742
  switch (block.type) {
1575
2743
  case "text":
1576
- return /* @__PURE__ */ jsxRuntime.jsx(TextBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2744
+ return /* @__PURE__ */ jsxRuntime.jsx(
2745
+ TextBlock,
2746
+ {
2747
+ block,
2748
+ onUpdate: (b) => onUpdate(b),
2749
+ ...commonProps
2750
+ }
2751
+ );
1577
2752
  case "heading":
1578
- return /* @__PURE__ */ jsxRuntime.jsx(HeadingBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2753
+ return /* @__PURE__ */ jsxRuntime.jsx(
2754
+ HeadingBlock,
2755
+ {
2756
+ block,
2757
+ onUpdate: (b) => onUpdate(b),
2758
+ ...commonProps
2759
+ }
2760
+ );
1579
2761
  case "image":
1580
- return /* @__PURE__ */ jsxRuntime.jsx(ImageBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2762
+ return /* @__PURE__ */ jsxRuntime.jsx(
2763
+ ImageBlock,
2764
+ {
2765
+ block,
2766
+ onUpdate: (b) => onUpdate(b),
2767
+ ...commonProps
2768
+ }
2769
+ );
1581
2770
  case "code":
1582
- return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2771
+ return /* @__PURE__ */ jsxRuntime.jsx(
2772
+ CodeBlock,
2773
+ {
2774
+ block,
2775
+ onUpdate: (b) => onUpdate(b),
2776
+ ...commonProps
2777
+ }
2778
+ );
1583
2779
  case "table":
1584
- return /* @__PURE__ */ jsxRuntime.jsx(TableBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2780
+ return /* @__PURE__ */ jsxRuntime.jsx(
2781
+ TableBlock,
2782
+ {
2783
+ block,
2784
+ onUpdate: (b) => onUpdate(b),
2785
+ ...commonProps
2786
+ }
2787
+ );
1585
2788
  case "divider":
1586
- return /* @__PURE__ */ jsxRuntime.jsx(DividerBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2789
+ return /* @__PURE__ */ jsxRuntime.jsx(
2790
+ DividerBlock,
2791
+ {
2792
+ block,
2793
+ onUpdate: (b) => onUpdate(b),
2794
+ ...commonProps
2795
+ }
2796
+ );
1587
2797
  case "quote":
1588
- return /* @__PURE__ */ jsxRuntime.jsx(QuoteBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2798
+ return /* @__PURE__ */ jsxRuntime.jsx(
2799
+ QuoteBlock,
2800
+ {
2801
+ block,
2802
+ onUpdate: (b) => onUpdate(b),
2803
+ ...commonProps
2804
+ }
2805
+ );
1589
2806
  case "list":
1590
- return /* @__PURE__ */ jsxRuntime.jsx(ListBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2807
+ return /* @__PURE__ */ jsxRuntime.jsx(
2808
+ ListBlock,
2809
+ {
2810
+ block,
2811
+ onUpdate: (b) => onUpdate(b),
2812
+ ...commonProps
2813
+ }
2814
+ );
1591
2815
  case "callout":
1592
- return /* @__PURE__ */ jsxRuntime.jsx(CalloutBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2816
+ return /* @__PURE__ */ jsxRuntime.jsx(
2817
+ CalloutBlock,
2818
+ {
2819
+ block,
2820
+ onUpdate: (b) => onUpdate(b),
2821
+ ...commonProps
2822
+ }
2823
+ );
1593
2824
  default: {
1594
2825
  const _exhaustiveCheck = block;
1595
2826
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
@@ -1600,43 +2831,53 @@ const BlockWrapper = ({
1600
2831
  }
1601
2832
  }, [block, onUpdate, readOnly, theme]);
1602
2833
  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]);
2834
+ const handleKeyDown = react.useCallback(
2835
+ (e) => {
2836
+ if (readOnly || !isSelected) return;
2837
+ switch (e.key) {
2838
+ case "Escape":
2839
+ setIsSelected(false);
2840
+ setShowAddMenu(false);
2841
+ break;
2842
+ case "Delete":
2843
+ case "Backspace":
2844
+ if (!e.target.matches("input, textarea, [contenteditable]")) {
2845
+ e.preventDefault();
2846
+ onDelete();
2847
+ }
2848
+ break;
2849
+ case "ArrowUp":
2850
+ if (e.altKey) {
2851
+ e.preventDefault();
2852
+ onMoveUp();
2853
+ }
2854
+ break;
2855
+ case "ArrowDown":
2856
+ if (e.altKey) {
2857
+ e.preventDefault();
2858
+ onMoveDown();
2859
+ }
2860
+ break;
2861
+ case "d":
2862
+ if (e.ctrlKey || e.metaKey) {
2863
+ e.preventDefault();
2864
+ onDuplicate();
2865
+ }
2866
+ break;
2867
+ }
2868
+ },
2869
+ [readOnly, isSelected, onDelete, onMoveUp, onMoveDown, onDuplicate]
2870
+ );
1638
2871
  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
2872
  const blockTypeLabel = block.type.charAt(0).toUpperCase() + block.type.slice(1);
2873
+ const showControls = !readOnly;
2874
+ const handleAddBlock = react.useCallback(
2875
+ (type) => {
2876
+ onAddBlock(type, index);
2877
+ setShowAddMenu(false);
2878
+ },
2879
+ [onAddBlock, index]
2880
+ );
1640
2881
  return /* @__PURE__ */ jsxRuntime.jsxs(
1641
2882
  "div",
1642
2883
  {
@@ -1661,109 +2902,126 @@ const BlockWrapper = ({
1661
2902
  {
1662
2903
  role: "toolbar",
1663
2904
  "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"}`,
2905
+ 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
2906
  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(
2907
+ /* @__PURE__ */ jsxRuntime.jsxs(
2908
+ "div",
2909
+ {
2910
+ className: "flex items-center gap-1",
2911
+ role: "group",
2912
+ "aria-label": "Reorder controls",
2913
+ children: [
2914
+ /* @__PURE__ */ jsxRuntime.jsx(
2915
+ "button",
2916
+ {
2917
+ type: "button",
2918
+ className: `${buttonBaseClass} cursor-grab active:cursor-grabbing`,
2919
+ title: "Drag to reorder",
2920
+ "aria-label": "Drag to reorder block",
2921
+ onClick: (e) => {
2922
+ e.stopPropagation();
2923
+ setIsSelected(true);
2924
+ },
2925
+ children: /* @__PURE__ */ jsxRuntime.jsx(DragIcon, { size: 16 })
2926
+ }
2927
+ ),
2928
+ /* @__PURE__ */ jsxRuntime.jsx(
2929
+ "button",
2930
+ {
2931
+ type: "button",
2932
+ onClick: (e) => {
2933
+ e.stopPropagation();
2934
+ onMoveUp();
2935
+ },
2936
+ disabled: index === 0,
2937
+ className: `${buttonBaseClass} disabled:opacity-30 disabled:cursor-not-allowed`,
2938
+ title: "Move up (Alt+↑)",
2939
+ "aria-label": "Move block up",
2940
+ "aria-disabled": index === 0,
2941
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronUpIcon, { size: 16 })
2942
+ }
2943
+ ),
2944
+ /* @__PURE__ */ jsxRuntime.jsx(
2945
+ "button",
2946
+ {
2947
+ type: "button",
2948
+ onClick: (e) => {
2949
+ e.stopPropagation();
2950
+ onMoveDown();
2951
+ },
2952
+ disabled: index === totalBlocks - 1,
2953
+ className: `${buttonBaseClass} disabled:opacity-30 disabled:cursor-not-allowed`,
2954
+ title: "Move down (Alt+↓)",
2955
+ "aria-label": "Move block down",
2956
+ "aria-disabled": index === totalBlocks - 1,
2957
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { size: 16 })
2958
+ }
2959
+ )
2960
+ ]
2961
+ }
2962
+ ),
2963
+ /* @__PURE__ */ jsxRuntime.jsxs(
2964
+ "div",
2965
+ {
2966
+ className: "flex items-center gap-1",
2967
+ role: "group",
2968
+ "aria-label": "Block actions",
2969
+ children: [
2970
+ /* @__PURE__ */ jsxRuntime.jsx(
2971
+ "button",
2972
+ {
2973
+ type: "button",
2974
+ onClick: (e) => {
2975
+ e.stopPropagation();
2976
+ setShowAddMenu(!showAddMenu);
2977
+ },
2978
+ className: `${buttonBaseClass} hover:!text-indigo-500`,
2979
+ title: "Add block below",
2980
+ "aria-label": "Add new block below",
2981
+ "aria-expanded": showAddMenu,
2982
+ "aria-haspopup": "menu",
2983
+ children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { size: 16 })
2984
+ }
2985
+ ),
2986
+ /* @__PURE__ */ jsxRuntime.jsx(
2987
+ "button",
2988
+ {
2989
+ type: "button",
2990
+ onClick: (e) => {
2991
+ e.stopPropagation();
2992
+ onDuplicate();
2993
+ },
2994
+ className: `${buttonBaseClass} hover:!text-indigo-500`,
2995
+ title: "Duplicate (Ctrl+D)",
2996
+ "aria-label": "Duplicate block",
2997
+ children: /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { size: 16 })
2998
+ }
2999
+ ),
3000
+ /* @__PURE__ */ jsxRuntime.jsx(
3001
+ "button",
3002
+ {
3003
+ type: "button",
3004
+ onClick: (e) => {
3005
+ e.stopPropagation();
3006
+ onDelete();
3007
+ },
3008
+ className: `${buttonBaseClass} hover:!text-red-500`,
3009
+ title: "Delete",
3010
+ "aria-label": "Delete block",
3011
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 16 })
3012
+ }
3013
+ )
3014
+ ]
3015
+ }
3016
+ ),
3017
+ showAddMenu && /* @__PURE__ */ jsxRuntime.jsx(
1757
3018
  AddBlockMenu,
1758
3019
  {
1759
- onAdd: (type) => {
1760
- onAddBlock(type, index);
1761
- setShowAddMenu(false);
1762
- },
3020
+ onAdd: handleAddBlock,
1763
3021
  onClose: () => setShowAddMenu(false),
1764
3022
  theme
1765
3023
  }
1766
- ) })
3024
+ )
1767
3025
  ]
1768
3026
  }
1769
3027
  ),
@@ -1946,14 +3204,14 @@ const PagesEditor = ({
1946
3204
  ]
1947
3205
  }
1948
3206
  ),
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(
3207
+ showInitialAddMenu && /* @__PURE__ */ jsxRuntime.jsx(
1950
3208
  AddBlockMenu,
1951
3209
  {
1952
3210
  onAdd: (type) => addBlock(type),
1953
3211
  onClose: () => setShowInitialAddMenu(false),
1954
3212
  theme
1955
3213
  }
1956
- ) })
3214
+ )
1957
3215
  ] })
1958
3216
  ] })
1959
3217
  ) : (
@@ -1999,19 +3257,21 @@ const PagesEditor = ({
1999
3257
  ]
2000
3258
  }
2001
3259
  ),
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(
3260
+ showInitialAddMenu && /* @__PURE__ */ jsxRuntime.jsx(
2003
3261
  AddBlockMenu,
2004
3262
  {
2005
3263
  onAdd: (type) => addBlock(type),
2006
3264
  onClose: () => setShowInitialAddMenu(false),
2007
3265
  theme
2008
3266
  }
2009
- ) })
3267
+ )
2010
3268
  ] }) }) })
2011
3269
  ] }) }) });
2012
3270
  };
2013
3271
 
2014
- function useBlockToolbar({ readOnly = false } = {}) {
3272
+ function useBlockToolbar({
3273
+ readOnly = false
3274
+ } = {}) {
2015
3275
  const [showToolbar, setShowToolbar] = react.useState(false);
2016
3276
  const handleFocus = react.useCallback(() => {
2017
3277
  if (!readOnly) {