@velo-sci/notebook-react 0.6.1 → 0.6.3

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.
Files changed (3) hide show
  1. package/dist/index.cjs +826 -741
  2. package/dist/index.js +825 -740
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -56,12 +56,12 @@ function useNotebookEvent(type, handler) {
56
56
  }
57
57
 
58
58
  // src/components/SciNotebook.tsx
59
- import React12, { useMemo as useMemo6, useEffect as useEffect10, useState as useState12, useCallback as useCallback11 } from "react";
59
+ import React13, { useMemo as useMemo5, useEffect as useEffect11, useState as useState13, useCallback as useCallback12 } from "react";
60
60
  import { createNotebook } from "@velo-sci/notebook-core";
61
61
  import { RenderPipeline } from "@velo-sci/notebook-renderer";
62
62
 
63
63
  // src/components/Cell.tsx
64
- import { useMemo as useMemo3, useCallback as useCallback8, useRef as useRef6, useEffect as useEffect7, useState as useState9 } from "react";
64
+ import { useMemo as useMemo2, useCallback as useCallback9, useRef as useRef7, useEffect as useEffect8, useState as useState10 } from "react";
65
65
 
66
66
  // src/components/FloatingToolbar.tsx
67
67
  import { useEffect as useEffect2, useRef, useState as useState2, useCallback } from "react";
@@ -192,10 +192,11 @@ function parseInlineStyle(css) {
192
192
 
193
193
  // src/components/MathEditor.tsx
194
194
  import { useState as useState3, useCallback as useCallback2, useRef as useRef2, useEffect as useEffect3 } from "react";
195
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
195
+
196
+ // src/components/math-categories.ts
196
197
  var MATH_CATEGORIES = [
197
198
  {
198
- name: "Estructuras",
199
+ name: "Structures",
199
200
  icon: "\u2B1A",
200
201
  blocks: [
201
202
  { label: "a/b", latex: "\\frac{\u25A2}{\u25A2}", cursor: 6 },
@@ -212,7 +213,7 @@ var MATH_CATEGORIES = [
212
213
  ]
213
214
  },
214
215
  {
215
- name: "Integrales",
216
+ name: "Integrals",
216
217
  icon: "\u222B",
217
218
  blocks: [
218
219
  { label: "\u222B", latex: "\\int{\u25A2}\\,d{\u25A2}", cursor: 5 },
@@ -223,7 +224,7 @@ var MATH_CATEGORIES = [
223
224
  ]
224
225
  },
225
226
  {
226
- name: "Sumatorias",
227
+ name: "Summations",
227
228
  icon: "\u2211",
228
229
  blocks: [
229
230
  { label: "\u2211", latex: "\\sum_{\u25A2}^{\u25A2}{\u25A2}", cursor: 5 },
@@ -240,11 +241,11 @@ var MATH_CATEGORIES = [
240
241
  { label: "3\xD73", latex: "\\begin{pmatrix} \u25A2 & \u25A2 & \u25A2 \\\\ \u25A2 & \u25A2 & \u25A2 \\\\ \u25A2 & \u25A2 & \u25A2 \\end{pmatrix}", cursor: 16 },
241
242
  { label: "[2\xD72]", latex: "\\begin{bmatrix} \u25A2 & \u25A2 \\\\ \u25A2 & \u25A2 \\end{bmatrix}", cursor: 16 },
242
243
  { label: "|2\xD72|", latex: "\\begin{vmatrix} \u25A2 & \u25A2 \\\\ \u25A2 & \u25A2 \\end{vmatrix}", cursor: 16 },
243
- { label: "cases", latex: "\\begin{cases} \u25A2 & \\text{si } \u25A2 \\\\ \u25A2 & \\text{si } \u25A2 \\end{cases}", cursor: 14 }
244
+ { label: "cases", latex: "\\begin{cases} \u25A2 & \\text{if } \u25A2 \\\\ \u25A2 & \\text{if } \u25A2 \\end{cases}", cursor: 14 }
244
245
  ]
245
246
  },
246
247
  {
247
- name: "Griegos",
248
+ name: "Greek",
248
249
  icon: "\u03B1",
249
250
  blocks: [
250
251
  { label: "\u03B1", latex: "\\alpha" },
@@ -275,7 +276,7 @@ var MATH_CATEGORIES = [
275
276
  ]
276
277
  },
277
278
  {
278
- name: "Operadores",
279
+ name: "Operators",
279
280
  icon: "\xB1",
280
281
  blocks: [
281
282
  { label: "\xB1", latex: "\\pm" },
@@ -307,7 +308,7 @@ var MATH_CATEGORIES = [
307
308
  ]
308
309
  },
309
310
  {
310
- name: "Flechas",
311
+ name: "Arrows",
311
312
  icon: "\u2192",
312
313
  blocks: [
313
314
  { label: "\u2192", latex: "\\rightarrow" },
@@ -322,7 +323,7 @@ var MATH_CATEGORIES = [
322
323
  ]
323
324
  },
324
325
  {
325
- name: "Funciones",
326
+ name: "Functions",
326
327
  icon: "f(x)",
327
328
  blocks: [
328
329
  { label: "sin", latex: "\\sin{\u25A2}", cursor: 5 },
@@ -338,7 +339,7 @@ var MATH_CATEGORIES = [
338
339
  ]
339
340
  },
340
341
  {
341
- name: "Delimitadores",
342
+ name: "Delimiters",
342
343
  icon: "()",
343
344
  blocks: [
344
345
  { label: "(\u2026)", latex: "\\left( \u25A2 \\right)", cursor: 7 },
@@ -351,9 +352,12 @@ var MATH_CATEGORIES = [
351
352
  ]
352
353
  }
353
354
  ];
355
+
356
+ // src/components/MathEditor.tsx
357
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
354
358
  function renderLatexPreview(latex) {
355
359
  const clean = latex.replace(/^\$\$\s*/, "").replace(/\s*\$\$$/, "").trim();
356
- if (!clean) return '<span class="sci-nb-math-preview-empty">Formula vacia</span>';
360
+ if (!clean) return '<span class="sci-nb-math-preview-empty">Empty formula</span>';
357
361
  if (typeof globalThis !== "undefined" && globalThis.katex) {
358
362
  try {
359
363
  return globalThis.katex.renderToString(clean, {
@@ -363,14 +367,13 @@ function renderLatexPreview(latex) {
363
367
  } catch {
364
368
  }
365
369
  }
366
- return `<code class="sci-nb-math-preview-code">${escapeHtml(clean)}</code>`;
367
- }
368
- function escapeHtml(s) {
369
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
370
+ const escaped = clean.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
371
+ return `<code class="sci-nb-math-preview-code">${escaped}</code>`;
370
372
  }
371
373
  var MathEditor = ({ cellId, source, onExit }) => {
372
374
  const engine = useSciNotebook();
373
375
  const textareaRef = useRef2(null);
376
+ const containerRef = useRef2(null);
374
377
  const [activeCategory, setActiveCategory] = useState3(0);
375
378
  const [showRaw, setShowRaw] = useState3(false);
376
379
  const innerLatex = source.replace(/^\$\$\s*/, "").replace(/\s*\$\$$/, "").trim();
@@ -407,15 +410,42 @@ $$`);
407
410
  }
408
411
  });
409
412
  }, [innerLatex, updateSource]);
413
+ const exitAndNext = useCallback2(() => {
414
+ onExit();
415
+ const cells = engine.getCells();
416
+ const idx = cells.findIndex((c) => c.id === cellId);
417
+ if (idx < cells.length - 1) {
418
+ engine.focusCell(cells[idx + 1].id);
419
+ engine.setEditMode(cells[idx + 1].id);
420
+ }
421
+ }, [engine, cellId, onExit]);
410
422
  const handleKeyDown = useCallback2((e) => {
411
423
  if (e.key === "Escape") {
412
424
  e.preventDefault();
425
+ e.stopPropagation();
413
426
  onExit();
414
427
  } else if (e.key === "Enter" && e.shiftKey) {
415
428
  e.preventDefault();
429
+ e.stopPropagation();
430
+ exitAndNext();
431
+ } else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
432
+ e.preventDefault();
433
+ e.stopPropagation();
416
434
  onExit();
417
435
  }
418
- }, [onExit]);
436
+ }, [onExit, exitAndNext]);
437
+ useEffect3(() => {
438
+ if (showRaw && textareaRef.current) {
439
+ textareaRef.current.focus();
440
+ } else if (containerRef.current) {
441
+ containerRef.current.focus();
442
+ }
443
+ }, [showRaw]);
444
+ useEffect3(() => {
445
+ if (containerRef.current) {
446
+ containerRef.current.focus();
447
+ }
448
+ }, []);
419
449
  useEffect3(() => {
420
450
  if (showRaw && textareaRef.current) {
421
451
  const ta = textareaRef.current;
@@ -424,82 +454,97 @@ $$`);
424
454
  }
425
455
  }, [innerLatex, showRaw]);
426
456
  const category = MATH_CATEGORIES[activeCategory];
427
- return /* @__PURE__ */ jsxs("div", { className: "sci-nb-math-editor", onKeyDown: handleKeyDown, children: [
428
- /* @__PURE__ */ jsx2("div", { className: "sci-nb-math-tabs", children: MATH_CATEGORIES.map((cat, i) => /* @__PURE__ */ jsxs(
429
- "button",
430
- {
431
- className: `sci-nb-math-tab ${i === activeCategory ? "sci-nb-math-tab--active" : ""}`,
432
- onClick: () => setActiveCategory(i),
433
- title: cat.name,
434
- children: [
435
- /* @__PURE__ */ jsx2("span", { className: "sci-nb-math-tab-icon", children: cat.icon }),
436
- /* @__PURE__ */ jsx2("span", { className: "sci-nb-math-tab-label", children: cat.name })
437
- ]
438
- },
439
- cat.name
440
- )) }),
441
- /* @__PURE__ */ jsx2("div", { className: "sci-nb-math-palette", children: category.blocks.map((block, i) => /* @__PURE__ */ jsx2(
442
- "button",
443
- {
444
- className: "sci-nb-math-block",
445
- onClick: () => insertBlock(block),
446
- title: block.latex,
447
- children: block.label
448
- },
449
- i
450
- )) }),
451
- /* @__PURE__ */ jsxs("div", { className: "sci-nb-math-editor-area", children: [
452
- /* @__PURE__ */ jsxs("div", { className: "sci-nb-math-mode-toggle", children: [
453
- /* @__PURE__ */ jsx2(
457
+ return /* @__PURE__ */ jsxs(
458
+ "div",
459
+ {
460
+ ref: containerRef,
461
+ className: "sci-nb-math-editor",
462
+ onKeyDown: handleKeyDown,
463
+ tabIndex: -1,
464
+ children: [
465
+ /* @__PURE__ */ jsx2("div", { className: "sci-nb-math-tabs", children: MATH_CATEGORIES.map((cat, i) => /* @__PURE__ */ jsxs(
454
466
  "button",
455
467
  {
456
- className: `sci-nb-math-mode-btn ${!showRaw ? "sci-nb-math-mode-btn--active" : ""}`,
457
- onClick: () => setShowRaw(false),
458
- children: "Preview"
459
- }
460
- ),
461
- /* @__PURE__ */ jsx2(
468
+ className: `sci-nb-math-tab ${i === activeCategory ? "sci-nb-math-tab--active" : ""}`,
469
+ onClick: () => setActiveCategory(i),
470
+ title: cat.name,
471
+ tabIndex: -1,
472
+ children: [
473
+ /* @__PURE__ */ jsx2("span", { className: "sci-nb-math-tab-icon", children: cat.icon }),
474
+ /* @__PURE__ */ jsx2("span", { className: "sci-nb-math-tab-label", children: cat.name })
475
+ ]
476
+ },
477
+ cat.name
478
+ )) }),
479
+ /* @__PURE__ */ jsx2("div", { className: "sci-nb-math-palette", children: category.blocks.map((block, i) => /* @__PURE__ */ jsx2(
462
480
  "button",
463
481
  {
464
- className: `sci-nb-math-mode-btn ${showRaw ? "sci-nb-math-mode-btn--active" : ""}`,
465
- onClick: () => setShowRaw(true),
466
- children: "LaTeX"
467
- }
468
- )
469
- ] }),
470
- showRaw ? /* @__PURE__ */ jsx2(
471
- "textarea",
472
- {
473
- ref: textareaRef,
474
- className: "sci-nb-math-raw",
475
- value: innerLatex,
476
- onChange: handleRawChange,
477
- placeholder: "Escribe LaTeX aqui...",
478
- spellCheck: false,
479
- autoFocus: true
480
- }
481
- ) : /* @__PURE__ */ jsxs("div", { className: "sci-nb-math-visual", children: [
482
- /* @__PURE__ */ jsx2(
483
- "div",
484
- {
485
- className: "sci-nb-math-preview",
486
- dangerouslySetInnerHTML: { __html: renderLatexPreview(source) }
487
- }
488
- ),
489
- /* @__PURE__ */ jsxs("p", { className: "sci-nb-math-visual-hint", children: [
490
- "Haz click en los bloques de arriba para construir tu formula. Cambia a modo ",
491
- /* @__PURE__ */ jsx2("strong", { children: "LaTeX" }),
492
- " para editar directamente."
482
+ className: "sci-nb-math-block",
483
+ onClick: () => insertBlock(block),
484
+ title: block.latex,
485
+ tabIndex: -1,
486
+ children: block.label
487
+ },
488
+ i
489
+ )) }),
490
+ /* @__PURE__ */ jsxs("div", { className: "sci-nb-math-editor-area", children: [
491
+ /* @__PURE__ */ jsxs("div", { className: "sci-nb-math-mode-toggle", children: [
492
+ /* @__PURE__ */ jsx2(
493
+ "button",
494
+ {
495
+ className: `sci-nb-math-mode-btn ${!showRaw ? "sci-nb-math-mode-btn--active" : ""}`,
496
+ onClick: () => setShowRaw(false),
497
+ tabIndex: -1,
498
+ children: "Preview"
499
+ }
500
+ ),
501
+ /* @__PURE__ */ jsx2(
502
+ "button",
503
+ {
504
+ className: `sci-nb-math-mode-btn ${showRaw ? "sci-nb-math-mode-btn--active" : ""}`,
505
+ onClick: () => setShowRaw(true),
506
+ tabIndex: -1,
507
+ children: "LaTeX"
508
+ }
509
+ )
510
+ ] }),
511
+ showRaw ? /* @__PURE__ */ jsx2(
512
+ "textarea",
513
+ {
514
+ ref: textareaRef,
515
+ className: "sci-nb-math-raw",
516
+ value: innerLatex,
517
+ onChange: handleRawChange,
518
+ placeholder: "Type LaTeX here...",
519
+ spellCheck: false,
520
+ autoFocus: true
521
+ }
522
+ ) : /* @__PURE__ */ jsxs("div", { className: "sci-nb-math-visual", children: [
523
+ /* @__PURE__ */ jsx2(
524
+ "div",
525
+ {
526
+ className: "sci-nb-math-preview",
527
+ dangerouslySetInnerHTML: { __html: renderLatexPreview(source) }
528
+ }
529
+ ),
530
+ /* @__PURE__ */ jsxs("p", { className: "sci-nb-math-visual-hint", children: [
531
+ "Click the blocks above to build your formula. Switch to ",
532
+ /* @__PURE__ */ jsx2("strong", { children: "LaTeX" }),
533
+ " mode to edit directly."
534
+ ] })
535
+ ] })
536
+ ] }),
537
+ /* @__PURE__ */ jsxs("div", { className: "sci-nb-cell-hint", children: [
538
+ /* @__PURE__ */ jsx2("kbd", { children: "Esc" }),
539
+ " exit \xB7 ",
540
+ /* @__PURE__ */ jsx2("kbd", { children: "Shift+Enter" }),
541
+ " next \xB7 ",
542
+ /* @__PURE__ */ jsx2("kbd", { children: "Ctrl+Enter" }),
543
+ " render"
493
544
  ] })
494
- ] })
495
- ] }),
496
- /* @__PURE__ */ jsxs("div", { className: "sci-nb-cell-hint", children: [
497
- /* @__PURE__ */ jsx2("kbd", { children: "Esc" }),
498
- " salir \xB7 ",
499
- /* @__PURE__ */ jsx2("kbd", { children: "Shift+Enter" }),
500
- " siguiente"
501
- ] })
502
- ] });
545
+ ]
546
+ }
547
+ );
503
548
  };
504
549
 
505
550
  // src/components/ImageCell.tsx
@@ -597,7 +642,7 @@ var ImageCell = ({ cellId, source, metadata, onExit }) => {
597
642
  /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "2.5" }),
598
643
  /* @__PURE__ */ jsx3("path", { d: "M4 22l6-6 4 4 4-4 10 10", strokeLinejoin: "round" })
599
644
  ] }),
600
- /* @__PURE__ */ jsx3("p", { children: "Arrastra, pega (Ctrl+V) o haz click para seleccionar" }),
645
+ /* @__PURE__ */ jsx3("p", { children: "Drag, paste (Ctrl+V) or click to select" }),
601
646
  /* @__PURE__ */ jsx3(
602
647
  "input",
603
648
  {
@@ -636,7 +681,7 @@ var ImageCell = ({ cellId, source, metadata, onExit }) => {
636
681
  type: "text",
637
682
  value: data.alt,
638
683
  onChange: (e) => save({ alt: e.target.value }),
639
- placeholder: "Descripcion de la imagen"
684
+ placeholder: "Image description"
640
685
  }
641
686
  )
642
687
  ] }),
@@ -648,13 +693,13 @@ var ImageCell = ({ cellId, source, metadata, onExit }) => {
648
693
  type: "text",
649
694
  value: data.caption,
650
695
  onChange: (e) => save({ caption: e.target.value }),
651
- placeholder: "Pie de imagen (opcional)"
696
+ placeholder: "Caption (optional)"
652
697
  }
653
698
  )
654
699
  ] }),
655
700
  /* @__PURE__ */ jsxs2("div", { className: "sci-nb-image-row", children: [
656
701
  /* @__PURE__ */ jsxs2("div", { className: "sci-nb-image-field sci-nb-image-field--small", children: [
657
- /* @__PURE__ */ jsx3("label", { children: "Ancho" }),
702
+ /* @__PURE__ */ jsx3("label", { children: "Width" }),
658
703
  /* @__PURE__ */ jsxs2("select", { value: data.width, onChange: (e) => save({ width: e.target.value }), children: [
659
704
  /* @__PURE__ */ jsx3("option", { value: "25%", children: "25%" }),
660
705
  /* @__PURE__ */ jsx3("option", { value: "50%", children: "50%" }),
@@ -664,38 +709,38 @@ var ImageCell = ({ cellId, source, metadata, onExit }) => {
664
709
  ] })
665
710
  ] }),
666
711
  /* @__PURE__ */ jsxs2("div", { className: "sci-nb-image-field sci-nb-image-field--small", children: [
667
- /* @__PURE__ */ jsx3("label", { children: "Alinear" }),
712
+ /* @__PURE__ */ jsx3("label", { children: "Align" }),
668
713
  /* @__PURE__ */ jsxs2("select", { value: data.align, onChange: (e) => save({ align: e.target.value }), children: [
669
- /* @__PURE__ */ jsx3("option", { value: "left", children: "Izquierda" }),
670
- /* @__PURE__ */ jsx3("option", { value: "center", children: "Centro" }),
671
- /* @__PURE__ */ jsx3("option", { value: "right", children: "Derecha" })
714
+ /* @__PURE__ */ jsx3("option", { value: "left", children: "Left" }),
715
+ /* @__PURE__ */ jsx3("option", { value: "center", children: "Center" }),
716
+ /* @__PURE__ */ jsx3("option", { value: "right", children: "Right" })
672
717
  ] })
673
718
  ] }),
674
- hasSrc && /* @__PURE__ */ jsx3("button", { className: "sci-nb-image-clear", onClick: () => save({ src: "" }), children: "Quitar imagen" })
719
+ hasSrc && /* @__PURE__ */ jsx3("button", { className: "sci-nb-image-clear", onClick: () => save({ src: "" }), children: "Remove image" })
675
720
  ] })
676
721
  ] }),
677
722
  /* @__PURE__ */ jsxs2("div", { className: "sci-nb-cell-hint", children: [
678
723
  /* @__PURE__ */ jsx3("kbd", { children: "Esc" }),
679
- " salir"
724
+ " exit"
680
725
  ] })
681
726
  ] });
682
727
  };
683
728
  function renderImagePreview(source, metadata) {
684
729
  const data = parseImageSource(source, metadata);
685
730
  if (!data.src) {
686
- return '<div class="sci-nb-image-empty"><span class="sci-nb-placeholder">Click para agregar imagen</span></div>';
731
+ return '<div class="sci-nb-image-empty"><span class="sci-nb-placeholder">Click to add image</span></div>';
687
732
  }
688
733
  const alignStyle = `text-align:${data.align}`;
689
734
  const widthStyle = `max-width:${data.width};width:auto;max-height:400px`;
690
735
  let html = `<div class="sci-nb-image-view" style="${alignStyle}">`;
691
736
  html += `<img src="${escapeAttr(data.src)}" alt="${escapeAttr(data.alt)}" style="${widthStyle}" />`;
692
737
  if (data.caption) {
693
- html += `<p class="sci-nb-image-caption">${escapeHtml2(data.caption)}</p>`;
738
+ html += `<p class="sci-nb-image-caption">${escapeHtml(data.caption)}</p>`;
694
739
  }
695
740
  html += `</div>`;
696
741
  return html;
697
742
  }
698
- function escapeHtml2(s) {
743
+ function escapeHtml(s) {
699
744
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
700
745
  }
701
746
  function escapeAttr(s) {
@@ -821,22 +866,22 @@ var EmbedCell = ({ cellId, source, metadata, onExit }) => {
821
866
  /* @__PURE__ */ jsx4("label", { children: "Sandbox" }),
822
867
  /* @__PURE__ */ jsxs3("select", { value: data.sandbox, onChange: (e) => save({ sandbox: e.target.value }), children: [
823
868
  /* @__PURE__ */ jsx4("option", { value: "allow-scripts allow-same-origin allow-popups", children: "Standard" }),
824
- /* @__PURE__ */ jsx4("option", { value: "allow-scripts", children: "Solo scripts" }),
825
- /* @__PURE__ */ jsx4("option", { value: "", children: "Restringido" })
869
+ /* @__PURE__ */ jsx4("option", { value: "allow-scripts", children: "Scripts only" }),
870
+ /* @__PURE__ */ jsx4("option", { value: "", children: "Restricted" })
826
871
  ] })
827
872
  ] })
828
873
  ] })
829
874
  ] }),
830
875
  /* @__PURE__ */ jsxs3("div", { className: "sci-nb-cell-hint", children: [
831
876
  /* @__PURE__ */ jsx4("kbd", { children: "Esc" }),
832
- " salir"
877
+ " exit"
833
878
  ] })
834
879
  ] });
835
880
  };
836
881
  function renderEmbedPreview(source, metadata) {
837
882
  const data = parseEmbedSource(source, metadata);
838
883
  if (!data.url) {
839
- return '<div class="sci-nb-embed-empty"><span class="sci-nb-placeholder">Click para agregar contenido embebido</span></div>';
884
+ return '<div class="sci-nb-embed-empty"><span class="sci-nb-placeholder">Click to add embedded content</span></div>';
840
885
  }
841
886
  const titleAttr = data.title ? ` title="${escapeAttr2(data.title)}"` : "";
842
887
  return `<div class="sci-nb-embed-view" style="height:${data.height}">
@@ -851,14 +896,14 @@ function escapeAttr2(s) {
851
896
  import { useState as useState6, useEffect as useEffect5, useRef as useRef4 } from "react";
852
897
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
853
898
  var DEFAULT_COMMANDS = [
854
- { type: "markdown", label: "Texto", description: "Bloque de texto con formato Markdown", icon: "M", keywords: ["text", "markdown", "paragraph", "texto"] },
855
- { type: "code", label: "C\xF3digo", description: "Bloque de c\xF3digo con syntax highlighting", icon: "</>", keywords: ["code", "codigo", "script", "program"] },
856
- { type: "latex", label: "F\xF3rmula", description: "Editor visual de f\xF3rmulas LaTeX", icon: "\u2211", keywords: ["latex", "math", "formula", "ecuacion", "equation"] },
857
- { type: "image", label: "Imagen", description: "Imagen con drag & drop, URL, caption", icon: "\u{1F5BC}", keywords: ["image", "imagen", "foto", "picture", "img"] },
899
+ { type: "markdown", label: "Text", description: "Markdown formatted text block", icon: "M", keywords: ["text", "markdown", "paragraph"] },
900
+ { type: "code", label: "Code", description: "Code block with syntax highlighting", icon: "</>", keywords: ["code", "script", "program"] },
901
+ { type: "latex", label: "Formula", description: "Visual LaTeX formula editor", icon: "\u2211", keywords: ["latex", "math", "formula", "equation"] },
902
+ { type: "image", label: "Image", description: "Image with drag & drop, URL, caption", icon: "\u{1F5BC}", keywords: ["image", "picture", "photo", "img"] },
858
903
  { type: "embed", label: "Embed", description: "YouTube, CodePen, Desmos, iframe", icon: "\u29C9", keywords: ["embed", "iframe", "youtube", "video", "codepen"] },
859
- { type: "table", label: "Tabla", description: "Tabla editable con filas y columnas", icon: "\u25A6", keywords: ["table", "tabla", "grid", "spreadsheet"] },
860
- { type: "mermaid", label: "Diagrama", description: "Diagrama Mermaid (flowchart, sequence, etc.)", icon: "\u25C7", keywords: ["mermaid", "diagram", "diagrama", "flowchart", "chart"] },
861
- { type: "raw", label: "Raw", description: "Texto sin formato", icon: "T", keywords: ["raw", "plain", "text", "crudo"] }
904
+ { type: "table", label: "Table", description: "Editable table with rows and columns", icon: "\u25A6", keywords: ["table", "grid", "spreadsheet"] },
905
+ { type: "mermaid", label: "Diagram", description: "Mermaid diagram (flowchart, sequence, etc.)", icon: "\u25C7", keywords: ["mermaid", "diagram", "flowchart", "chart"] },
906
+ { type: "raw", label: "Raw", description: "Plain unformatted text", icon: "T", keywords: ["raw", "plain", "text"] }
862
907
  ];
863
908
  var SlashCommand = ({
864
909
  position,
@@ -913,7 +958,7 @@ var SlashCommand = ({
913
958
  className: "sci-nb-slash-menu",
914
959
  style: { top: position.top, left: position.left },
915
960
  children: /* @__PURE__ */ jsxs4("div", { className: "sci-nb-slash-empty", children: [
916
- 'Sin resultados para "/',
961
+ 'No results for "/',
917
962
  query,
918
963
  '"'
919
964
  ] })
@@ -927,7 +972,7 @@ var SlashCommand = ({
927
972
  className: "sci-nb-slash-menu",
928
973
  style: { top: position.top, left: position.left },
929
974
  children: [
930
- /* @__PURE__ */ jsx5("div", { className: "sci-nb-slash-header", children: "Insertar bloque" }),
975
+ /* @__PURE__ */ jsx5("div", { className: "sci-nb-slash-header", children: "Insert block" }),
931
976
  filtered.map((cmd, i) => /* @__PURE__ */ jsxs4(
932
977
  "button",
933
978
  {
@@ -980,6 +1025,8 @@ function toMarkdownTable(data) {
980
1025
  var TableCell = ({ cellId, source, onExit }) => {
981
1026
  const engine = useSciNotebook();
982
1027
  const [data, setData] = useState7(() => parseMarkdownTable(source));
1028
+ const [hoverCol, setHoverCol] = useState7(null);
1029
+ const [hoverRow, setHoverRow] = useState7(null);
983
1030
  const syncToEngine = useCallback6((newData) => {
984
1031
  setData(newData);
985
1032
  engine.updateCellSource(cellId, toMarkdownTable(newData));
@@ -1018,142 +1065,104 @@ var TableCell = ({ cellId, source, onExit }) => {
1018
1065
  if (e.key === "Escape") {
1019
1066
  e.preventDefault();
1020
1067
  onExit();
1021
- } else if (e.key === "Tab" && !e.shiftKey) {
1022
1068
  }
1023
1069
  }, [onExit]);
1024
1070
  return /* @__PURE__ */ jsxs5("div", { className: "sci-nb-table-editor", onKeyDown: handleKeyDown, children: [
1025
1071
  /* @__PURE__ */ jsxs5("div", { className: "sci-nb-table-toolbar", children: [
1026
- /* @__PURE__ */ jsx6("button", { onClick: addRow, children: "+ Fila" }),
1027
- /* @__PURE__ */ jsx6("button", { onClick: addColumn, children: "+ Columna" })
1072
+ /* @__PURE__ */ jsx6("button", { onClick: addRow, children: "+ Row" }),
1073
+ /* @__PURE__ */ jsx6("button", { onClick: addColumn, children: "+ Column" })
1028
1074
  ] }),
1029
1075
  /* @__PURE__ */ jsxs5("table", { children: [
1030
- /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsxs5("tr", { children: [
1031
- data.headers.map((h, ci) => /* @__PURE__ */ jsx6("th", { children: /* @__PURE__ */ jsx6(
1032
- "input",
1033
- {
1034
- value: h,
1035
- onChange: (e) => updateHeader(ci, e.target.value),
1036
- placeholder: `Col ${ci + 1}`
1037
- }
1038
- ) }, ci)),
1039
- /* @__PURE__ */ jsx6("th", { style: { width: 30, padding: 0 } })
1040
- ] }) }),
1041
- /* @__PURE__ */ jsx6("tbody", { children: data.rows.map((row, ri) => /* @__PURE__ */ jsxs5("tr", { children: [
1042
- row.map((cell, ci) => /* @__PURE__ */ jsx6("td", { children: /* @__PURE__ */ jsx6(
1043
- "input",
1044
- {
1045
- value: cell,
1046
- onChange: (e) => updateCell(ri, ci, e.target.value),
1047
- placeholder: "..."
1048
- }
1049
- ) }, ci)),
1050
- /* @__PURE__ */ jsx6("td", { style: { width: 30, padding: 0, textAlign: "center" }, children: /* @__PURE__ */ jsx6(
1051
- "button",
1052
- {
1053
- className: "sci-nb-btn sci-nb-btn--danger",
1054
- onClick: () => removeRow(ri),
1055
- title: "Eliminar fila",
1056
- style: { padding: "2px 4px", fontSize: 10, border: "none", background: "transparent" },
1057
- children: "\u2715"
1058
- }
1059
- ) })
1060
- ] }, ri)) })
1076
+ /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsx6("tr", { children: data.headers.map((h, ci) => /* @__PURE__ */ jsxs5(
1077
+ "th",
1078
+ {
1079
+ className: "sci-nb-table-header-cell",
1080
+ onMouseEnter: () => setHoverCol(ci),
1081
+ onMouseLeave: () => setHoverCol(null),
1082
+ children: [
1083
+ /* @__PURE__ */ jsx6(
1084
+ "input",
1085
+ {
1086
+ value: h,
1087
+ onChange: (e) => updateHeader(ci, e.target.value),
1088
+ placeholder: `Col ${ci + 1}`
1089
+ }
1090
+ ),
1091
+ data.headers.length > 1 && hoverCol === ci && /* @__PURE__ */ jsx6(
1092
+ "button",
1093
+ {
1094
+ className: "sci-nb-table-delete-btn",
1095
+ onClick: () => removeColumn(ci),
1096
+ title: "Delete column",
1097
+ children: "\u2715"
1098
+ }
1099
+ )
1100
+ ]
1101
+ },
1102
+ ci
1103
+ )) }) }),
1104
+ /* @__PURE__ */ jsx6("tbody", { children: data.rows.map((row, ri) => /* @__PURE__ */ jsx6(
1105
+ "tr",
1106
+ {
1107
+ onMouseEnter: () => setHoverRow(ri),
1108
+ onMouseLeave: () => setHoverRow(null),
1109
+ children: row.map((cell, ci) => {
1110
+ const isLastCol = ci === row.length - 1;
1111
+ return /* @__PURE__ */ jsxs5(
1112
+ "td",
1113
+ {
1114
+ className: isLastCol ? "sci-nb-table-row-end" : "",
1115
+ children: [
1116
+ /* @__PURE__ */ jsx6(
1117
+ "input",
1118
+ {
1119
+ value: cell,
1120
+ onChange: (e) => updateCell(ri, ci, e.target.value),
1121
+ placeholder: "..."
1122
+ }
1123
+ ),
1124
+ isLastCol && data.rows.length > 1 && hoverRow === ri && /* @__PURE__ */ jsx6(
1125
+ "button",
1126
+ {
1127
+ className: "sci-nb-table-delete-btn",
1128
+ onClick: () => removeRow(ri),
1129
+ title: "Delete row",
1130
+ children: "\u2715"
1131
+ }
1132
+ )
1133
+ ]
1134
+ },
1135
+ ci
1136
+ );
1137
+ })
1138
+ },
1139
+ ri
1140
+ )) })
1061
1141
  ] }),
1062
1142
  /* @__PURE__ */ jsxs5("div", { className: "sci-nb-cell-hint", children: [
1063
1143
  /* @__PURE__ */ jsx6("kbd", { children: "Tab" }),
1064
- " siguiente celda \xB7 ",
1144
+ " next cell \xB7 ",
1065
1145
  /* @__PURE__ */ jsx6("kbd", { children: "Esc" }),
1066
- " salir"
1146
+ " exit"
1067
1147
  ] })
1068
1148
  ] });
1069
1149
  };
1070
1150
  function renderTablePreview(source) {
1071
1151
  const data = parseMarkdownTable(source);
1072
- if (data.headers.length === 0) return "<p>Tabla vac\xEDa</p>";
1073
- const ths = data.headers.map((h) => `<th>${escapeHtml3(h)}</th>`).join("");
1152
+ if (data.headers.length === 0) return "<p>Empty table</p>";
1153
+ const ths = data.headers.map((h) => `<th>${escapeHtml2(h)}</th>`).join("");
1074
1154
  const trs = data.rows.map(
1075
- (row) => `<tr>${row.map((c) => `<td>${escapeHtml3(c)}</td>`).join("")}</tr>`
1155
+ (row) => `<tr>${row.map((c) => `<td>${escapeHtml2(c)}</td>`).join("")}</tr>`
1076
1156
  ).join("");
1077
1157
  return `<table class="sci-nb-rendered-table"><thead><tr>${ths}</tr></thead><tbody>${trs}</tbody></table>`;
1078
1158
  }
1079
- function escapeHtml3(s) {
1159
+ function escapeHtml2(s) {
1080
1160
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1081
1161
  }
1082
1162
 
1083
- // src/components/CellOutput.tsx
1084
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1085
- var CellOutputDisplay = ({ outputs }) => {
1086
- if (!outputs || outputs.length === 0) return null;
1087
- return /* @__PURE__ */ jsx7("div", { className: "sci-nb-cell-outputs", children: outputs.map((output, i) => /* @__PURE__ */ jsx7("div", { className: `sci-nb-output sci-nb-output--${output.outputType}`, children: renderOutput(output) }, i)) });
1088
- };
1089
- function renderOutput(output) {
1090
- switch (output.outputType) {
1091
- case "stream":
1092
- return /* @__PURE__ */ jsx7("pre", { className: `sci-nb-output-stream sci-nb-output-stream--${output.name}`, children: output.text });
1093
- case "display": {
1094
- if (output.data["text/html"]) {
1095
- return /* @__PURE__ */ jsx7(
1096
- "div",
1097
- {
1098
- className: "sci-nb-output-html",
1099
- dangerouslySetInnerHTML: { __html: output.data["text/html"] }
1100
- }
1101
- );
1102
- }
1103
- if (output.data["image/svg+xml"]) {
1104
- return /* @__PURE__ */ jsx7(
1105
- "div",
1106
- {
1107
- className: "sci-nb-output-svg",
1108
- dangerouslySetInnerHTML: { __html: output.data["image/svg+xml"] }
1109
- }
1110
- );
1111
- }
1112
- if (output.data["image/png"]) {
1113
- return /* @__PURE__ */ jsx7(
1114
- "img",
1115
- {
1116
- className: "sci-nb-output-image",
1117
- src: `data:image/png;base64,${output.data["image/png"]}`,
1118
- alt: "Output"
1119
- }
1120
- );
1121
- }
1122
- if (output.data["image/jpeg"]) {
1123
- return /* @__PURE__ */ jsx7(
1124
- "img",
1125
- {
1126
- className: "sci-nb-output-image",
1127
- src: `data:image/jpeg;base64,${output.data["image/jpeg"]}`,
1128
- alt: "Output"
1129
- }
1130
- );
1131
- }
1132
- if (output.data["application/json"]) {
1133
- return /* @__PURE__ */ jsx7("pre", { className: "sci-nb-output-json", children: JSON.stringify(JSON.parse(output.data["application/json"]), null, 2) });
1134
- }
1135
- if (output.data["text/plain"]) {
1136
- return /* @__PURE__ */ jsx7("pre", { className: "sci-nb-output-text", children: output.data["text/plain"] });
1137
- }
1138
- return /* @__PURE__ */ jsx7("pre", { className: "sci-nb-output-text", children: "[Display output]" });
1139
- }
1140
- case "error":
1141
- return /* @__PURE__ */ jsxs6("div", { className: "sci-nb-output-error", children: [
1142
- /* @__PURE__ */ jsxs6("strong", { className: "sci-nb-output-error-name", children: [
1143
- output.name,
1144
- ": "
1145
- ] }),
1146
- /* @__PURE__ */ jsx7("span", { className: "sci-nb-output-error-msg", children: output.message }),
1147
- output.traceback && output.traceback.length > 0 && /* @__PURE__ */ jsx7("pre", { className: "sci-nb-output-traceback", children: output.traceback.join("\n") })
1148
- ] });
1149
- default:
1150
- return null;
1151
- }
1152
- }
1153
-
1154
1163
  // src/components/MermaidCell.tsx
1155
1164
  import { useState as useState8, useEffect as useEffect6, useRef as useRef5 } from "react";
1156
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1165
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1157
1166
  var mermaidIdCounter = 0;
1158
1167
  var MermaidPreview = ({ source, onClick }) => {
1159
1168
  const [svg, setSvg] = useState8(null);
@@ -1196,29 +1205,29 @@ var MermaidPreview = ({ source, onClick }) => {
1196
1205
  }, [source]);
1197
1206
  const mermaid = globalThis.mermaid;
1198
1207
  if (!source.trim()) {
1199
- return /* @__PURE__ */ jsx8("div", { className: "sci-nb-mermaid-preview", onClick, children: /* @__PURE__ */ jsx8("span", { className: "sci-nb-placeholder", children: "Diagrama vacio \u2014 escribe sintaxis Mermaid" }) });
1208
+ return /* @__PURE__ */ jsx7("div", { className: "sci-nb-mermaid-preview", onClick, children: /* @__PURE__ */ jsx7("span", { className: "sci-nb-placeholder", children: "Empty diagram \u2014 write Mermaid syntax" }) });
1200
1209
  }
1201
1210
  if (!mermaid) {
1202
- return /* @__PURE__ */ jsxs7("div", { className: "sci-nb-mermaid-preview", onClick, children: [
1203
- /* @__PURE__ */ jsx8("pre", { className: "sci-nb-code", children: /* @__PURE__ */ jsx8("code", { className: "language-mermaid", children: source }) }),
1204
- /* @__PURE__ */ jsxs7("div", { style: { fontSize: 11, color: "#94a3b8", textAlign: "center", padding: 4 }, children: [
1205
- "Mermaid no disponible. Importa ",
1206
- /* @__PURE__ */ jsx8("code", { children: "mermaid" }),
1207
- " y exponlo como ",
1208
- /* @__PURE__ */ jsx8("code", { children: "globalThis.mermaid" }),
1211
+ return /* @__PURE__ */ jsxs6("div", { className: "sci-nb-mermaid-preview", onClick, children: [
1212
+ /* @__PURE__ */ jsx7("pre", { className: "sci-nb-code", children: /* @__PURE__ */ jsx7("code", { className: "language-mermaid", children: source }) }),
1213
+ /* @__PURE__ */ jsxs6("div", { style: { fontSize: 11, color: "#94a3b8", textAlign: "center", padding: 4 }, children: [
1214
+ "Mermaid not available. Import ",
1215
+ /* @__PURE__ */ jsx7("code", { children: "mermaid" }),
1216
+ " and expose it as ",
1217
+ /* @__PURE__ */ jsx7("code", { children: "globalThis.mermaid" }),
1209
1218
  "."
1210
1219
  ] })
1211
1220
  ] });
1212
1221
  }
1213
1222
  if (error) {
1214
- return /* @__PURE__ */ jsxs7("div", { className: "sci-nb-mermaid-error", onClick, children: [
1215
- /* @__PURE__ */ jsx8("strong", { children: "Mermaid error:" }),
1223
+ return /* @__PURE__ */ jsxs6("div", { className: "sci-nb-mermaid-error", onClick, children: [
1224
+ /* @__PURE__ */ jsx7("strong", { children: "Mermaid error:" }),
1216
1225
  " ",
1217
1226
  error
1218
1227
  ] });
1219
1228
  }
1220
1229
  if (svg) {
1221
- return /* @__PURE__ */ jsx8(
1230
+ return /* @__PURE__ */ jsx7(
1222
1231
  "div",
1223
1232
  {
1224
1233
  ref: containerRef,
@@ -1226,125 +1235,361 @@ var MermaidPreview = ({ source, onClick }) => {
1226
1235
  onClick,
1227
1236
  dangerouslySetInnerHTML: { __html: svg }
1228
1237
  }
1229
- );
1238
+ );
1239
+ }
1240
+ return /* @__PURE__ */ jsx7("div", { className: "sci-nb-mermaid-preview", onClick, children: /* @__PURE__ */ jsx7("span", { className: "sci-nb-placeholder", children: "Rendering diagram..." }) });
1241
+ };
1242
+ function initMermaid(mermaidLib, config) {
1243
+ globalThis.mermaid = mermaidLib;
1244
+ mermaidLib.initialize({
1245
+ startOnLoad: false,
1246
+ theme: "default",
1247
+ securityLevel: "loose",
1248
+ ...config
1249
+ });
1250
+ }
1251
+
1252
+ // src/components/CodeEditor.tsx
1253
+ import { useRef as useRef6, useEffect as useEffect7, useCallback as useCallback8, useState as useState9 } from "react";
1254
+ import { highlightCodeTokens } from "@velo-sci/notebook-renderer";
1255
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1256
+ var CodeEditor = ({
1257
+ source,
1258
+ language,
1259
+ onChange,
1260
+ onKeyDown,
1261
+ placeholder
1262
+ }) => {
1263
+ const textareaRef = useRef6(null);
1264
+ const preRef = useRef6(null);
1265
+ const [highlighted, setHighlighted] = useState9("");
1266
+ useEffect7(() => {
1267
+ const html = highlightCodeTokens(source, language || "text");
1268
+ const match = html.match(/<code[^>]*>([\s\S]*)<\/code>/);
1269
+ setHighlighted(match ? match[1] : html);
1270
+ }, [source, language]);
1271
+ const syncScroll = useCallback8(() => {
1272
+ if (textareaRef.current && preRef.current) {
1273
+ preRef.current.scrollTop = textareaRef.current.scrollTop;
1274
+ preRef.current.scrollLeft = textareaRef.current.scrollLeft;
1275
+ }
1276
+ }, []);
1277
+ useEffect7(() => {
1278
+ if (textareaRef.current) {
1279
+ const ta = textareaRef.current;
1280
+ ta.style.height = "auto";
1281
+ ta.style.height = `${Math.max(40, ta.scrollHeight)}px`;
1282
+ }
1283
+ }, [source]);
1284
+ useEffect7(() => {
1285
+ textareaRef.current?.focus();
1286
+ }, []);
1287
+ const handleChange = useCallback8((e) => {
1288
+ onChange(e.target.value);
1289
+ }, [onChange]);
1290
+ return /* @__PURE__ */ jsxs7("div", { className: "sci-nb-code-editor-wrap", children: [
1291
+ /* @__PURE__ */ jsx8(
1292
+ "pre",
1293
+ {
1294
+ ref: preRef,
1295
+ className: "sci-nb-code-editor-highlight sci-nb-code--highlighted",
1296
+ "aria-hidden": "true",
1297
+ children: /* @__PURE__ */ jsxs7("code", { className: `language-${language || "text"}`, children: [
1298
+ /* @__PURE__ */ jsx8("span", { dangerouslySetInnerHTML: { __html: highlighted || "&nbsp;" } }),
1299
+ "\n"
1300
+ ] })
1301
+ }
1302
+ ),
1303
+ /* @__PURE__ */ jsx8(
1304
+ "textarea",
1305
+ {
1306
+ ref: textareaRef,
1307
+ className: "sci-nb-code-editor-input",
1308
+ value: source,
1309
+ onChange: handleChange,
1310
+ onKeyDown,
1311
+ onScroll: syncScroll,
1312
+ placeholder,
1313
+ spellCheck: false,
1314
+ autoComplete: "off",
1315
+ autoCapitalize: "off",
1316
+ rows: 1
1317
+ }
1318
+ )
1319
+ ] });
1320
+ };
1321
+
1322
+ // src/components/CellRenderers.tsx
1323
+ import { Fragment, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1324
+ function renderEditMode(cell, cellId, engine, textareaRef, handleSourceChange, handleKeyDown, placeholder, exitEdit, slashState, onSlashSelect, onSlashClose) {
1325
+ if (cell.type === "latex") {
1326
+ return /* @__PURE__ */ jsx9(MathEditor, { cellId, source: cell.source, onExit: exitEdit });
1327
+ }
1328
+ if (cell.type === "image") {
1329
+ return /* @__PURE__ */ jsx9(ImageCell, { cellId, source: cell.source, metadata: cell.metadata, onExit: exitEdit });
1330
+ }
1331
+ if (cell.type === "embed") {
1332
+ return /* @__PURE__ */ jsx9(EmbedCell, { cellId, source: cell.source, metadata: cell.metadata, onExit: exitEdit });
1333
+ }
1334
+ if (cell.type === "table") {
1335
+ return /* @__PURE__ */ jsx9(TableCell, { cellId, source: cell.source, metadata: cell.metadata, onExit: exitEdit });
1336
+ }
1337
+ if (cell.type === "code") {
1338
+ const lang = cell.metadata.language || "javascript";
1339
+ return /* @__PURE__ */ jsxs8(Fragment, { children: [
1340
+ /* @__PURE__ */ jsx9(
1341
+ CodeEditor,
1342
+ {
1343
+ cellId,
1344
+ source: cell.source,
1345
+ language: lang,
1346
+ onChange: (val) => engine.updateCellSource(cellId, val),
1347
+ onKeyDown: handleKeyDown,
1348
+ placeholder
1349
+ }
1350
+ ),
1351
+ /* @__PURE__ */ jsxs8("div", { className: "sci-nb-cell-hint", children: [
1352
+ /* @__PURE__ */ jsx9("kbd", { children: "Shift+Enter" }),
1353
+ " next \xB7 ",
1354
+ /* @__PURE__ */ jsx9("kbd", { children: "Esc" }),
1355
+ " exit"
1356
+ ] })
1357
+ ] });
1358
+ }
1359
+ return /* @__PURE__ */ jsxs8(Fragment, { children: [
1360
+ cell.type === "markdown" && /* @__PURE__ */ jsx9(FloatingToolbar, { cellId, textareaRef }),
1361
+ /* @__PURE__ */ jsx9(
1362
+ "textarea",
1363
+ {
1364
+ ref: textareaRef,
1365
+ className: "sci-nb-editor",
1366
+ value: cell.source,
1367
+ onChange: handleSourceChange,
1368
+ onKeyDown: handleKeyDown,
1369
+ placeholder,
1370
+ spellCheck: cell.type === "markdown",
1371
+ rows: 1
1372
+ }
1373
+ ),
1374
+ slashState && /* @__PURE__ */ jsx9(
1375
+ SlashCommand,
1376
+ {
1377
+ position: slashState.pos,
1378
+ query: slashState.query,
1379
+ onSelect: onSlashSelect,
1380
+ onClose: onSlashClose
1381
+ }
1382
+ ),
1383
+ /* @__PURE__ */ jsxs8("div", { className: "sci-nb-cell-hint", children: [
1384
+ /* @__PURE__ */ jsx9("kbd", { children: "/" }),
1385
+ " commands \xB7 ",
1386
+ /* @__PURE__ */ jsx9("kbd", { children: "Shift+Enter" }),
1387
+ " next \xB7 ",
1388
+ /* @__PURE__ */ jsx9("kbd", { children: "Esc" }),
1389
+ " exit"
1390
+ ] })
1391
+ ] });
1392
+ }
1393
+ function renderViewMode(cell, renderedHtml, isEmpty, placeholder, enterEdit) {
1394
+ if (cell.type === "image") {
1395
+ const html = renderImagePreview(cell.source, cell.metadata);
1396
+ return /* @__PURE__ */ jsx9("div", { className: "sci-nb-preview", onClick: enterEdit, dangerouslySetInnerHTML: { __html: html } });
1397
+ }
1398
+ if (cell.type === "embed") {
1399
+ const html = renderEmbedPreview(cell.source, cell.metadata);
1400
+ return /* @__PURE__ */ jsx9("div", { className: "sci-nb-preview sci-nb-preview--embed", onClick: enterEdit, dangerouslySetInnerHTML: { __html: html } });
1401
+ }
1402
+ if (cell.type === "table") {
1403
+ const html = renderTablePreview(cell.source);
1404
+ return /* @__PURE__ */ jsx9("div", { className: "sci-nb-preview", onClick: enterEdit, dangerouslySetInnerHTML: { __html: html } });
1405
+ }
1406
+ if (cell.type === "mermaid") {
1407
+ return /* @__PURE__ */ jsx9(MermaidPreview, { source: cell.source, onClick: enterEdit });
1408
+ }
1409
+ return /* @__PURE__ */ jsx9(
1410
+ "div",
1411
+ {
1412
+ className: `sci-nb-preview ${isEmpty ? "sci-nb-preview--empty" : ""}`,
1413
+ onClick: enterEdit,
1414
+ dangerouslySetInnerHTML: isEmpty ? { __html: `<span class="sci-nb-placeholder">${placeholder}</span>` } : { __html: renderedHtml }
1415
+ }
1416
+ );
1417
+ }
1418
+
1419
+ // src/components/CellOutput.tsx
1420
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1421
+ var CellOutputDisplay = ({ outputs }) => {
1422
+ if (!outputs || outputs.length === 0) return null;
1423
+ return /* @__PURE__ */ jsx10("div", { className: "sci-nb-cell-outputs", children: outputs.map((output, i) => /* @__PURE__ */ jsx10("div", { className: `sci-nb-output sci-nb-output--${output.outputType}`, children: renderOutput(output) }, i)) });
1424
+ };
1425
+ function renderOutput(output) {
1426
+ switch (output.outputType) {
1427
+ case "stream":
1428
+ return /* @__PURE__ */ jsx10("pre", { className: `sci-nb-output-stream sci-nb-output-stream--${output.name}`, children: output.text });
1429
+ case "display": {
1430
+ if (output.data["text/html"]) {
1431
+ return /* @__PURE__ */ jsx10(
1432
+ "div",
1433
+ {
1434
+ className: "sci-nb-output-html",
1435
+ dangerouslySetInnerHTML: { __html: output.data["text/html"] }
1436
+ }
1437
+ );
1438
+ }
1439
+ if (output.data["image/svg+xml"]) {
1440
+ return /* @__PURE__ */ jsx10(
1441
+ "div",
1442
+ {
1443
+ className: "sci-nb-output-svg",
1444
+ dangerouslySetInnerHTML: { __html: output.data["image/svg+xml"] }
1445
+ }
1446
+ );
1447
+ }
1448
+ if (output.data["image/png"]) {
1449
+ return /* @__PURE__ */ jsx10(
1450
+ "img",
1451
+ {
1452
+ className: "sci-nb-output-image",
1453
+ src: `data:image/png;base64,${output.data["image/png"]}`,
1454
+ alt: "Output"
1455
+ }
1456
+ );
1457
+ }
1458
+ if (output.data["image/jpeg"]) {
1459
+ return /* @__PURE__ */ jsx10(
1460
+ "img",
1461
+ {
1462
+ className: "sci-nb-output-image",
1463
+ src: `data:image/jpeg;base64,${output.data["image/jpeg"]}`,
1464
+ alt: "Output"
1465
+ }
1466
+ );
1467
+ }
1468
+ if (output.data["application/json"]) {
1469
+ return /* @__PURE__ */ jsx10("pre", { className: "sci-nb-output-json", children: JSON.stringify(JSON.parse(output.data["application/json"]), null, 2) });
1470
+ }
1471
+ if (output.data["text/plain"]) {
1472
+ return /* @__PURE__ */ jsx10("pre", { className: "sci-nb-output-text", children: output.data["text/plain"] });
1473
+ }
1474
+ return /* @__PURE__ */ jsx10("pre", { className: "sci-nb-output-text", children: "[Display output]" });
1475
+ }
1476
+ case "error":
1477
+ return /* @__PURE__ */ jsxs9("div", { className: "sci-nb-output-error", children: [
1478
+ /* @__PURE__ */ jsxs9("strong", { className: "sci-nb-output-error-name", children: [
1479
+ output.name,
1480
+ ": "
1481
+ ] }),
1482
+ /* @__PURE__ */ jsx10("span", { className: "sci-nb-output-error-msg", children: output.message }),
1483
+ output.traceback && output.traceback.length > 0 && /* @__PURE__ */ jsx10("pre", { className: "sci-nb-output-traceback", children: output.traceback.join("\n") })
1484
+ ] });
1485
+ default:
1486
+ return null;
1230
1487
  }
1231
- return /* @__PURE__ */ jsx8("div", { className: "sci-nb-mermaid-preview", onClick, children: /* @__PURE__ */ jsx8("span", { className: "sci-nb-placeholder", children: "Renderizando diagrama..." }) });
1232
- };
1233
- function initMermaid(mermaidLib, config) {
1234
- globalThis.mermaid = mermaidLib;
1235
- mermaidLib.initialize({
1236
- startOnLoad: false,
1237
- theme: "default",
1238
- securityLevel: "loose",
1239
- ...config
1240
- });
1241
1488
  }
1242
1489
 
1243
1490
  // src/components/Cell.tsx
1244
- import { Fragment, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1491
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1245
1492
  var CELL_TYPES = [
1246
1493
  { value: "markdown", label: "Markdown", icon: "M" },
1247
1494
  { value: "code", label: "Code", icon: "</>" },
1248
1495
  { value: "raw", label: "Raw", icon: "T" },
1249
1496
  { value: "latex", label: "LaTeX", icon: "\u2211" },
1250
- { value: "image", label: "Imagen", icon: "\u{1F5BC}" },
1497
+ { value: "image", label: "Image", icon: "\u{1F5BC}" },
1251
1498
  { value: "embed", label: "Embed", icon: "\u29C9" }
1252
1499
  ];
1253
1500
  var PLACEHOLDERS = {
1254
- markdown: "Escribe markdown aqui... (click para editar)",
1255
- code: "Escribe codigo aqui...",
1256
- raw: "Texto raw...",
1257
- latex: "Escribe LaTeX aqui... e.g. \\int_0^1 x^2 dx",
1258
- image: "Click para agregar imagen",
1259
- embed: "Click para agregar contenido embebido"
1501
+ markdown: "Write markdown here... (click to edit)",
1502
+ code: "Write code here...",
1503
+ raw: "Raw text...",
1504
+ latex: "Write LaTeX here... e.g. \\int_0^1 x^2 dx",
1505
+ image: "Click to add image",
1506
+ embed: "Click to add embedded content"
1260
1507
  };
1261
1508
  var Cell = ({ cellId, pipeline, index, totalCells }) => {
1262
1509
  const cell = useCell(cellId);
1263
1510
  const engine = useSciNotebook();
1264
- const textareaRef = useRef6(null);
1265
- const cellRef = useRef6(null);
1266
- const [showTypeMenu, setShowTypeMenu] = useState9(false);
1267
- const [hovered, setHovered] = useState9(false);
1268
- const [slashState, setSlashState] = useState9(null);
1269
- const [dragOver, setDragOver] = useState9(null);
1270
- const [isDragging, setIsDragging] = useState9(false);
1271
- const rendered = useMemo3(() => {
1511
+ const textareaRef = useRef7(null);
1512
+ const cellRef = useRef7(null);
1513
+ const [showTypeMenu, setShowTypeMenu] = useState10(false);
1514
+ const [hovered, setHovered] = useState10(false);
1515
+ const [slashState, setSlashState] = useState10(null);
1516
+ const [dragOver, setDragOver] = useState10(null);
1517
+ const [isDragging, setIsDragging] = useState10(false);
1518
+ const rendered = useMemo2(() => {
1272
1519
  if (!cell) return { html: "", cellId: "", renderTime: 0, cached: false };
1273
1520
  return pipeline.render(cell);
1274
1521
  }, [cell?.source, cell?.type, cell?.metadata, pipeline]);
1275
- useEffect7(() => {
1522
+ useEffect8(() => {
1276
1523
  if (cell?.editing && textareaRef.current) {
1277
1524
  const ta = textareaRef.current;
1278
1525
  ta.style.height = "auto";
1279
1526
  ta.style.height = `${Math.max(40, ta.scrollHeight)}px`;
1280
1527
  }
1281
1528
  }, [cell?.source, cell?.editing]);
1282
- useEffect7(() => {
1283
- if (cell?.editing && textareaRef.current) {
1284
- textareaRef.current.focus();
1285
- }
1529
+ useEffect8(() => {
1530
+ if (cell?.editing && textareaRef.current) textareaRef.current.focus();
1286
1531
  }, [cell?.editing]);
1287
- useEffect7(() => {
1532
+ useEffect8(() => {
1288
1533
  if (!showTypeMenu) return;
1289
1534
  const handler = (e) => {
1290
- if (cellRef.current && !cellRef.current.contains(e.target)) {
1291
- setShowTypeMenu(false);
1292
- }
1535
+ if (cellRef.current && !cellRef.current.contains(e.target)) setShowTypeMenu(false);
1293
1536
  };
1294
1537
  document.addEventListener("mousedown", handler);
1295
1538
  return () => document.removeEventListener("mousedown", handler);
1296
1539
  }, [showTypeMenu]);
1297
- const handleSourceChange = useCallback8((e) => {
1540
+ const handleSourceChange = useCallback9((e) => {
1298
1541
  const val = e.target.value;
1299
1542
  engine.updateCellSource(cellId, val);
1300
1543
  const ta = e.target;
1301
1544
  const cursor = ta.selectionStart;
1302
1545
  const textBefore = val.slice(0, cursor);
1303
1546
  const lastNewline = textBefore.lastIndexOf("\n");
1304
- const lineStart = lastNewline + 1;
1305
- const currentLine = textBefore.slice(lineStart);
1547
+ const currentLine = textBefore.slice(lastNewline + 1);
1306
1548
  if (currentLine.startsWith("/")) {
1307
- const query = currentLine.slice(1);
1308
1549
  const rect = ta.getBoundingClientRect();
1309
- const lineHeight = 22;
1310
1550
  const lines = textBefore.split("\n").length;
1311
- setSlashState({
1312
- query,
1313
- pos: { top: rect.top + lines * lineHeight + 4 - ta.scrollTop, left: rect.left + 8 }
1314
- });
1551
+ setSlashState({ query: currentLine.slice(1), pos: { top: rect.top + lines * 22 + 4 - ta.scrollTop, left: rect.left + 8 } });
1315
1552
  } else {
1316
1553
  setSlashState(null);
1317
1554
  }
1318
1555
  }, [engine, cellId]);
1319
- const enterEdit = useCallback8(() => {
1556
+ const enterEdit = useCallback9(() => {
1320
1557
  engine.setEditMode(cellId);
1321
1558
  engine.focusCell(cellId);
1322
1559
  }, [engine, cellId]);
1323
- const exitEdit = useCallback8(() => {
1560
+ const exitEdit = useCallback9(() => {
1324
1561
  engine.setViewMode(cellId);
1325
1562
  }, [engine, cellId]);
1326
- const handleSlashSelect = useCallback8((type) => {
1563
+ const handleSlashSelect = useCallback9((type) => {
1327
1564
  const val = cell?.source || "";
1328
1565
  const ta = textareaRef.current;
1329
1566
  if (ta) {
1330
1567
  const cursor = ta.selectionStart;
1331
1568
  const textBefore = val.slice(0, cursor);
1332
- const lastNewline = textBefore.lastIndexOf("\n");
1333
- const lineStart = lastNewline + 1;
1334
- const cleaned = val.slice(0, lineStart) + val.slice(cursor);
1335
- engine.updateCellSource(cellId, cleaned.trim());
1569
+ const lineStart = textBefore.lastIndexOf("\n") + 1;
1570
+ engine.updateCellSource(cellId, (val.slice(0, lineStart) + val.slice(cursor)).trim());
1336
1571
  }
1337
1572
  engine.setCellType(cellId, type);
1338
1573
  setSlashState(null);
1339
1574
  }, [engine, cellId, cell?.source]);
1340
- const handleKeyDown = useCallback8((e) => {
1341
- if (slashState) {
1342
- if (["ArrowDown", "ArrowUp", "Enter"].includes(e.key)) return;
1343
- if (e.key === "Escape") {
1344
- e.preventDefault();
1345
- setSlashState(null);
1346
- return;
1575
+ const wrapSelection = useCallback9((before, after) => {
1576
+ const ta = textareaRef.current;
1577
+ if (!ta) return;
1578
+ const { selectionStart: start, selectionEnd: end, value: val } = ta;
1579
+ engine.updateCellSource(cellId, val.substring(0, start) + before + val.substring(start, end) + after + val.substring(end));
1580
+ requestAnimationFrame(() => {
1581
+ if (textareaRef.current) {
1582
+ textareaRef.current.selectionStart = start + before.length;
1583
+ textareaRef.current.selectionEnd = end + before.length;
1347
1584
  }
1585
+ });
1586
+ }, [engine, cellId]);
1587
+ const handleKeyDown = useCallback9((e) => {
1588
+ if (slashState && ["ArrowDown", "ArrowUp", "Enter"].includes(e.key)) return;
1589
+ if (slashState && e.key === "Escape") {
1590
+ e.preventDefault();
1591
+ setSlashState(null);
1592
+ return;
1348
1593
  }
1349
1594
  if (e.key === "Escape") {
1350
1595
  e.preventDefault();
@@ -1365,30 +1610,24 @@ var Cell = ({ cellId, pipeline, index, totalCells }) => {
1365
1610
  e.preventDefault();
1366
1611
  const ta = e.currentTarget;
1367
1612
  const start = ta.selectionStart;
1368
- const end = ta.selectionEnd;
1369
- const val = ta.value;
1370
- const newVal = val.substring(0, start) + " " + val.substring(end);
1371
- engine.updateCellSource(cellId, newVal);
1613
+ engine.updateCellSource(cellId, ta.value.substring(0, start) + " " + ta.value.substring(ta.selectionEnd));
1372
1614
  requestAnimationFrame(() => {
1373
1615
  if (textareaRef.current) {
1374
- textareaRef.current.selectionStart = start + 2;
1375
- textareaRef.current.selectionEnd = start + 2;
1616
+ textareaRef.current.selectionStart = textareaRef.current.selectionEnd = start + 2;
1376
1617
  }
1377
1618
  });
1378
1619
  } else if (e.key === "Tab" && e.shiftKey) {
1379
1620
  e.preventDefault();
1380
1621
  const ta = e.currentTarget;
1381
1622
  const start = ta.selectionStart;
1382
- const val = ta.value;
1383
- const before = val.substring(0, start);
1623
+ const before = ta.value.substring(0, start);
1384
1624
  const trimmed = before.replace(/ $/, "");
1385
1625
  if (trimmed !== before) {
1386
- engine.updateCellSource(cellId, trimmed + val.substring(start));
1387
1626
  const diff = before.length - trimmed.length;
1627
+ engine.updateCellSource(cellId, trimmed + ta.value.substring(start));
1388
1628
  requestAnimationFrame(() => {
1389
1629
  if (textareaRef.current) {
1390
- textareaRef.current.selectionStart = start - diff;
1391
- textareaRef.current.selectionEnd = start - diff;
1630
+ textareaRef.current.selectionStart = textareaRef.current.selectionEnd = start - diff;
1392
1631
  }
1393
1632
  });
1394
1633
  }
@@ -1399,27 +1638,12 @@ var Cell = ({ cellId, pipeline, index, totalCells }) => {
1399
1638
  e.preventDefault();
1400
1639
  wrapSelection("*", "*");
1401
1640
  }
1402
- }, [engine, cellId, exitEdit]);
1403
- const wrapSelection = useCallback8((before, after) => {
1404
- const ta = textareaRef.current;
1405
- if (!ta) return;
1406
- const start = ta.selectionStart;
1407
- const end = ta.selectionEnd;
1408
- const val = ta.value;
1409
- const newVal = val.substring(0, start) + before + val.substring(start, end) + after + val.substring(end);
1410
- engine.updateCellSource(cellId, newVal);
1411
- requestAnimationFrame(() => {
1412
- if (textareaRef.current) {
1413
- textareaRef.current.selectionStart = start + before.length;
1414
- textareaRef.current.selectionEnd = end + before.length;
1415
- }
1416
- });
1417
- }, [engine, cellId]);
1641
+ }, [engine, cellId, exitEdit, slashState, wrapSelection]);
1418
1642
  if (!cell) return null;
1419
1643
  const isEditing = !!cell.editing;
1420
1644
  const isEmpty = !cell.source.trim();
1421
1645
  const placeholder = PLACEHOLDERS[cell.type] || "Click to edit...";
1422
- return /* @__PURE__ */ jsxs8(
1646
+ return /* @__PURE__ */ jsxs10(
1423
1647
  "div",
1424
1648
  {
1425
1649
  ref: cellRef,
@@ -1446,18 +1670,14 @@ var Cell = ({ cellId, pipeline, index, totalCells }) => {
1446
1670
  e.preventDefault();
1447
1671
  e.dataTransfer.dropEffect = "move";
1448
1672
  const rect = e.currentTarget.getBoundingClientRect();
1449
- const midY = rect.top + rect.height / 2;
1450
- setDragOver(e.clientY < midY ? "top" : "bottom");
1673
+ setDragOver(e.clientY < rect.top + rect.height / 2 ? "top" : "bottom");
1451
1674
  },
1452
1675
  onDragLeave: () => setDragOver(null),
1453
1676
  onDrop: (e) => {
1454
1677
  e.preventDefault();
1455
- const draggedId = e.dataTransfer.getData("text/plain");
1678
+ const did = e.dataTransfer.getData("text/plain");
1456
1679
  setDragOver(null);
1457
- if (draggedId && draggedId !== cellId) {
1458
- const targetIdx = dragOver === "top" ? index : index + 1;
1459
- engine.moveCell(draggedId, targetIdx);
1460
- }
1680
+ if (did && did !== cellId) engine.moveCell(did, dragOver === "top" ? index : index + 1);
1461
1681
  },
1462
1682
  "data-testid": `cell-${cell.id}`,
1463
1683
  "data-editing": String(isEditing),
@@ -1470,35 +1690,27 @@ var Cell = ({ cellId, pipeline, index, totalCells }) => {
1470
1690
  onMouseLeave: () => setHovered(false),
1471
1691
  onClick: () => engine.focusCell(cellId),
1472
1692
  children: [
1473
- /* @__PURE__ */ jsxs8("div", { className: "sci-nb-cell-gutter", children: [
1474
- /* @__PURE__ */ jsx9("div", { className: "sci-nb-cell-handle", title: "Drag to reorder", children: /* @__PURE__ */ jsxs8("svg", { width: "12", height: "20", viewBox: "0 0 12 20", fill: "currentColor", children: [
1475
- /* @__PURE__ */ jsx9("circle", { cx: "3", cy: "4", r: "1.5" }),
1476
- /* @__PURE__ */ jsx9("circle", { cx: "9", cy: "4", r: "1.5" }),
1477
- /* @__PURE__ */ jsx9("circle", { cx: "3", cy: "10", r: "1.5" }),
1478
- /* @__PURE__ */ jsx9("circle", { cx: "9", cy: "10", r: "1.5" }),
1479
- /* @__PURE__ */ jsx9("circle", { cx: "3", cy: "16", r: "1.5" }),
1480
- /* @__PURE__ */ jsx9("circle", { cx: "9", cy: "16", r: "1.5" })
1693
+ /* @__PURE__ */ jsxs10("div", { className: "sci-nb-cell-gutter", children: [
1694
+ /* @__PURE__ */ jsx11("div", { className: "sci-nb-cell-handle", title: "Drag to reorder", children: /* @__PURE__ */ jsxs10("svg", { width: "12", height: "20", viewBox: "0 0 12 20", fill: "currentColor", children: [
1695
+ /* @__PURE__ */ jsx11("circle", { cx: "3", cy: "4", r: "1.5" }),
1696
+ /* @__PURE__ */ jsx11("circle", { cx: "9", cy: "4", r: "1.5" }),
1697
+ /* @__PURE__ */ jsx11("circle", { cx: "3", cy: "10", r: "1.5" }),
1698
+ /* @__PURE__ */ jsx11("circle", { cx: "9", cy: "10", r: "1.5" }),
1699
+ /* @__PURE__ */ jsx11("circle", { cx: "3", cy: "16", r: "1.5" }),
1700
+ /* @__PURE__ */ jsx11("circle", { cx: "9", cy: "16", r: "1.5" })
1481
1701
  ] }) }),
1482
- /* @__PURE__ */ jsxs8("span", { className: "sci-nb-cell-index", children: [
1702
+ /* @__PURE__ */ jsxs10("span", { className: "sci-nb-cell-index", children: [
1483
1703
  "[",
1484
1704
  index + 1,
1485
1705
  "]"
1486
1706
  ] })
1487
1707
  ] }),
1488
- /* @__PURE__ */ jsxs8("div", { className: "sci-nb-cell-badge-wrap", children: [
1489
- /* @__PURE__ */ jsx9(
1490
- "button",
1491
- {
1492
- className: "sci-nb-cell-badge",
1493
- onClick: (e) => {
1494
- e.stopPropagation();
1495
- setShowTypeMenu(!showTypeMenu);
1496
- },
1497
- title: "Change cell type",
1498
- children: CELL_TYPES.find((ct) => ct.value === cell.type)?.icon || cell.type.slice(0, 2).toUpperCase()
1499
- }
1500
- ),
1501
- showTypeMenu && /* @__PURE__ */ jsx9("div", { className: "sci-nb-type-menu", children: CELL_TYPES.map((ct) => /* @__PURE__ */ jsxs8(
1708
+ /* @__PURE__ */ jsxs10("div", { className: "sci-nb-cell-badge-wrap", children: [
1709
+ /* @__PURE__ */ jsx11("button", { className: "sci-nb-cell-badge", onClick: (e) => {
1710
+ e.stopPropagation();
1711
+ setShowTypeMenu(!showTypeMenu);
1712
+ }, title: "Change cell type", children: CELL_TYPES.find((ct) => ct.value === cell.type)?.icon || cell.type.slice(0, 2).toUpperCase() }),
1713
+ showTypeMenu && /* @__PURE__ */ jsx11("div", { className: "sci-nb-type-menu", children: CELL_TYPES.map((ct) => /* @__PURE__ */ jsxs10(
1502
1714
  "button",
1503
1715
  {
1504
1716
  className: `sci-nb-type-option ${cell.type === ct.value ? "sci-nb-type-option--active" : ""}`,
@@ -1508,173 +1720,46 @@ var Cell = ({ cellId, pipeline, index, totalCells }) => {
1508
1720
  setShowTypeMenu(false);
1509
1721
  },
1510
1722
  children: [
1511
- /* @__PURE__ */ jsx9("span", { className: "sci-nb-type-option-icon", children: ct.icon }),
1723
+ /* @__PURE__ */ jsx11("span", { className: "sci-nb-type-option-icon", children: ct.icon }),
1512
1724
  ct.label
1513
1725
  ]
1514
1726
  },
1515
1727
  ct.value
1516
1728
  )) })
1517
1729
  ] }),
1518
- /* @__PURE__ */ jsxs8("div", { className: "sci-nb-cell-content", children: [
1519
- isEditing ? renderEditMode(cell, cellId, textareaRef, handleSourceChange, handleKeyDown, placeholder, exitEdit, slashState, handleSlashSelect, () => setSlashState(null)) : renderViewMode(cell, rendered.html, isEmpty, placeholder, enterEdit),
1520
- cell.outputs && cell.outputs.length > 0 && /* @__PURE__ */ jsx9(CellOutputDisplay, { outputs: cell.outputs })
1730
+ /* @__PURE__ */ jsxs10("div", { className: "sci-nb-cell-content", children: [
1731
+ isEditing ? renderEditMode(cell, cellId, engine, textareaRef, handleSourceChange, handleKeyDown, placeholder, exitEdit, slashState, handleSlashSelect, () => setSlashState(null)) : renderViewMode(cell, rendered.html, isEmpty, placeholder, enterEdit),
1732
+ cell.outputs && cell.outputs.length > 0 && /* @__PURE__ */ jsx11(CellOutputDisplay, { outputs: cell.outputs })
1521
1733
  ] }),
1522
- /* @__PURE__ */ jsxs8("div", { className: "sci-nb-cell-actions", children: [
1523
- /* @__PURE__ */ jsx9(
1524
- "button",
1525
- {
1526
- className: "sci-nb-btn",
1527
- onClick: (e) => {
1528
- e.stopPropagation();
1529
- engine.moveCell(cellId, index - 1);
1530
- },
1531
- disabled: index === 0,
1532
- title: "Move up",
1533
- children: /* @__PURE__ */ jsx9("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx9("path", { d: "M7 11V3M7 3L3 7M7 3l4 4", strokeLinecap: "round", strokeLinejoin: "round" }) })
1534
- }
1535
- ),
1536
- /* @__PURE__ */ jsx9(
1537
- "button",
1538
- {
1539
- className: "sci-nb-btn",
1540
- onClick: (e) => {
1541
- e.stopPropagation();
1542
- engine.moveCell(cellId, index + 1);
1543
- },
1544
- disabled: index >= totalCells - 1,
1545
- title: "Move down",
1546
- children: /* @__PURE__ */ jsx9("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx9("path", { d: "M7 3v8M7 11l-4-4M7 11l4-4", strokeLinecap: "round", strokeLinejoin: "round" }) })
1547
- }
1548
- ),
1549
- /* @__PURE__ */ jsx9(
1550
- "button",
1551
- {
1552
- className: "sci-nb-btn",
1553
- onClick: (e) => {
1554
- e.stopPropagation();
1555
- engine.duplicateCell(cellId);
1556
- },
1557
- title: "Duplicate cell",
1558
- children: /* @__PURE__ */ jsxs8("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
1559
- /* @__PURE__ */ jsx9("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5" }),
1560
- /* @__PURE__ */ jsx9("path", { d: "M10 2H3.5A1.5 1.5 0 002 3.5V10" })
1561
- ] })
1562
- }
1563
- ),
1564
- /* @__PURE__ */ jsx9(
1565
- "button",
1566
- {
1567
- className: "sci-nb-btn sci-nb-btn--danger",
1568
- onClick: (e) => {
1569
- e.stopPropagation();
1570
- engine.deleteCell(cellId);
1571
- },
1572
- title: "Delete cell",
1573
- children: /* @__PURE__ */ jsx9("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx9("path", { d: "M3 4h8M5.5 4V3a1 1 0 011-1h1a1 1 0 011 1v1M6 6.5v3M8 6.5v3M4 4l.5 7a1.5 1.5 0 001.5 1.5h2A1.5 1.5 0 0010 11l.5-7", strokeLinecap: "round", strokeLinejoin: "round" }) })
1574
- }
1575
- )
1734
+ /* @__PURE__ */ jsxs10("div", { className: "sci-nb-cell-actions", children: [
1735
+ /* @__PURE__ */ jsx11("button", { className: "sci-nb-btn", onClick: (e) => {
1736
+ e.stopPropagation();
1737
+ engine.moveCell(cellId, index - 1);
1738
+ }, disabled: index === 0, title: "Move up", children: /* @__PURE__ */ jsx11("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx11("path", { d: "M7 11V3M7 3L3 7M7 3l4 4", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
1739
+ /* @__PURE__ */ jsx11("button", { className: "sci-nb-btn", onClick: (e) => {
1740
+ e.stopPropagation();
1741
+ engine.moveCell(cellId, index + 1);
1742
+ }, disabled: index >= totalCells - 1, title: "Move down", children: /* @__PURE__ */ jsx11("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx11("path", { d: "M7 3v8M7 11l-4-4M7 11l4-4", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
1743
+ /* @__PURE__ */ jsx11("button", { className: "sci-nb-btn", onClick: (e) => {
1744
+ e.stopPropagation();
1745
+ engine.duplicateCell(cellId);
1746
+ }, title: "Duplicate cell", children: /* @__PURE__ */ jsxs10("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
1747
+ /* @__PURE__ */ jsx11("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5" }),
1748
+ /* @__PURE__ */ jsx11("path", { d: "M10 2H3.5A1.5 1.5 0 002 3.5V10" })
1749
+ ] }) }),
1750
+ /* @__PURE__ */ jsx11("button", { className: "sci-nb-btn sci-nb-btn--danger", onClick: (e) => {
1751
+ e.stopPropagation();
1752
+ engine.deleteCell(cellId);
1753
+ }, title: "Delete cell", children: /* @__PURE__ */ jsx11("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx11("path", { d: "M3 4h8M5.5 4V3a1 1 0 011-1h1a1 1 0 011 1v1M6 6.5v3M8 6.5v3M4 4l.5 7a1.5 1.5 0 001.5 1.5h2A1.5 1.5 0 0010 11l.5-7", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
1576
1754
  ] })
1577
1755
  ]
1578
1756
  }
1579
1757
  );
1580
1758
  };
1581
- function renderEditMode(cell, cellId, textareaRef, handleSourceChange, handleKeyDown, placeholder, exitEdit, slashState, onSlashSelect, onSlashClose) {
1582
- if (cell.type === "latex") {
1583
- return /* @__PURE__ */ jsx9(MathEditor, { cellId, source: cell.source, onExit: exitEdit });
1584
- }
1585
- if (cell.type === "image") {
1586
- return /* @__PURE__ */ jsx9(ImageCell, { cellId, source: cell.source, metadata: cell.metadata, onExit: exitEdit });
1587
- }
1588
- if (cell.type === "embed") {
1589
- return /* @__PURE__ */ jsx9(EmbedCell, { cellId, source: cell.source, metadata: cell.metadata, onExit: exitEdit });
1590
- }
1591
- if (cell.type === "table") {
1592
- return /* @__PURE__ */ jsx9(TableCell, { cellId, source: cell.source, metadata: cell.metadata, onExit: exitEdit });
1593
- }
1594
- return /* @__PURE__ */ jsxs8(Fragment, { children: [
1595
- cell.type === "markdown" && /* @__PURE__ */ jsx9(FloatingToolbar, { cellId, textareaRef }),
1596
- /* @__PURE__ */ jsx9(
1597
- "textarea",
1598
- {
1599
- ref: textareaRef,
1600
- className: "sci-nb-editor",
1601
- value: cell.source,
1602
- onChange: handleSourceChange,
1603
- onKeyDown: handleKeyDown,
1604
- placeholder,
1605
- spellCheck: cell.type === "markdown",
1606
- rows: 1
1607
- }
1608
- ),
1609
- slashState && /* @__PURE__ */ jsx9(
1610
- SlashCommand,
1611
- {
1612
- position: slashState.pos,
1613
- query: slashState.query,
1614
- onSelect: onSlashSelect,
1615
- onClose: onSlashClose
1616
- }
1617
- ),
1618
- /* @__PURE__ */ jsxs8("div", { className: "sci-nb-cell-hint", children: [
1619
- /* @__PURE__ */ jsx9("kbd", { children: "/" }),
1620
- " comandos \xB7 ",
1621
- /* @__PURE__ */ jsx9("kbd", { children: "Shift+Enter" }),
1622
- " siguiente \xB7 ",
1623
- /* @__PURE__ */ jsx9("kbd", { children: "Esc" }),
1624
- " salir"
1625
- ] })
1626
- ] });
1627
- }
1628
- function renderViewMode(cell, renderedHtml, isEmpty, placeholder, enterEdit) {
1629
- if (cell.type === "image") {
1630
- const html = renderImagePreview(cell.source, cell.metadata);
1631
- return /* @__PURE__ */ jsx9(
1632
- "div",
1633
- {
1634
- className: "sci-nb-preview",
1635
- onClick: enterEdit,
1636
- dangerouslySetInnerHTML: { __html: html }
1637
- }
1638
- );
1639
- }
1640
- if (cell.type === "embed") {
1641
- const html = renderEmbedPreview(cell.source, cell.metadata);
1642
- return /* @__PURE__ */ jsx9(
1643
- "div",
1644
- {
1645
- className: "sci-nb-preview sci-nb-preview--embed",
1646
- onClick: enterEdit,
1647
- dangerouslySetInnerHTML: { __html: html }
1648
- }
1649
- );
1650
- }
1651
- if (cell.type === "table") {
1652
- const html = renderTablePreview(cell.source);
1653
- return /* @__PURE__ */ jsx9(
1654
- "div",
1655
- {
1656
- className: "sci-nb-preview",
1657
- onClick: enterEdit,
1658
- dangerouslySetInnerHTML: { __html: html }
1659
- }
1660
- );
1661
- }
1662
- if (cell.type === "mermaid") {
1663
- return /* @__PURE__ */ jsx9(MermaidPreview, { source: cell.source, onClick: enterEdit });
1664
- }
1665
- return /* @__PURE__ */ jsx9(
1666
- "div",
1667
- {
1668
- className: `sci-nb-preview ${isEmpty ? "sci-nb-preview--empty" : ""}`,
1669
- onClick: enterEdit,
1670
- dangerouslySetInnerHTML: isEmpty ? { __html: `<span class="sci-nb-placeholder">${placeholder}</span>` } : { __html: renderedHtml }
1671
- }
1672
- );
1673
- }
1674
1759
 
1675
1760
  // src/components/InsertHandle.tsx
1676
- import { useState as useState10, useRef as useRef7, useEffect as useEffect8 } from "react";
1677
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1761
+ import { useState as useState11, useRef as useRef8, useEffect as useEffect9 } from "react";
1762
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1678
1763
  var INSERT_TYPES = [
1679
1764
  { type: "markdown", label: "Markdown", icon: "M" },
1680
1765
  { type: "code", label: "Code", icon: "</>" },
@@ -1685,9 +1770,9 @@ var INSERT_TYPES = [
1685
1770
  ];
1686
1771
  var InsertHandle = ({ index }) => {
1687
1772
  const engine = useSciNotebook();
1688
- const [open, setOpen] = useState10(false);
1689
- const menuRef = useRef7(null);
1690
- useEffect8(() => {
1773
+ const [open, setOpen] = useState11(false);
1774
+ const menuRef = useRef8(null);
1775
+ useEffect9(() => {
1691
1776
  if (!open) return;
1692
1777
  const onClickOutside = (e) => {
1693
1778
  if (menuRef.current && !menuRef.current.contains(e.target)) {
@@ -1708,27 +1793,27 @@ var InsertHandle = ({ index }) => {
1708
1793
  }
1709
1794
  });
1710
1795
  };
1711
- return /* @__PURE__ */ jsxs9("div", { className: "sci-nb-insert-handle", ref: menuRef, children: [
1712
- /* @__PURE__ */ jsx10("div", { className: "sci-nb-insert-line", children: /* @__PURE__ */ jsx10(
1796
+ return /* @__PURE__ */ jsxs11("div", { className: "sci-nb-insert-handle", ref: menuRef, children: [
1797
+ /* @__PURE__ */ jsx12("div", { className: "sci-nb-insert-line", children: /* @__PURE__ */ jsx12(
1713
1798
  "button",
1714
1799
  {
1715
1800
  className: "sci-nb-insert-btn",
1716
1801
  onClick: () => setOpen(!open),
1717
1802
  title: "Insert cell",
1718
- children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
1719
- /* @__PURE__ */ jsx10("line", { x1: "8", y1: "3", x2: "8", y2: "13", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1720
- /* @__PURE__ */ jsx10("line", { x1: "3", y1: "8", x2: "13", y2: "8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
1803
+ children: /* @__PURE__ */ jsxs11("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
1804
+ /* @__PURE__ */ jsx12("line", { x1: "8", y1: "3", x2: "8", y2: "13", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1805
+ /* @__PURE__ */ jsx12("line", { x1: "3", y1: "8", x2: "13", y2: "8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
1721
1806
  ] })
1722
1807
  }
1723
1808
  ) }),
1724
- open && /* @__PURE__ */ jsx10("div", { className: "sci-nb-insert-menu", children: INSERT_TYPES.map((ct) => /* @__PURE__ */ jsxs9(
1809
+ open && /* @__PURE__ */ jsx12("div", { className: "sci-nb-insert-menu", children: INSERT_TYPES.map((ct) => /* @__PURE__ */ jsxs11(
1725
1810
  "button",
1726
1811
  {
1727
1812
  className: "sci-nb-insert-option",
1728
1813
  onClick: () => handleInsert(ct.type),
1729
1814
  children: [
1730
- /* @__PURE__ */ jsx10("span", { className: "sci-nb-insert-option-icon", children: ct.icon }),
1731
- /* @__PURE__ */ jsx10("span", { children: ct.label })
1815
+ /* @__PURE__ */ jsx12("span", { className: "sci-nb-insert-option-icon", children: ct.icon }),
1816
+ /* @__PURE__ */ jsx12("span", { children: ct.label })
1732
1817
  ]
1733
1818
  },
1734
1819
  ct.type
@@ -1737,12 +1822,12 @@ var InsertHandle = ({ index }) => {
1737
1822
  };
1738
1823
 
1739
1824
  // src/components/TOCSidebar.tsx
1740
- import { useMemo as useMemo4, useCallback as useCallback9 } from "react";
1741
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1825
+ import { useMemo as useMemo3, useCallback as useCallback10 } from "react";
1826
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
1742
1827
  var TOCSidebar = ({ focusedCellId }) => {
1743
1828
  const notebook = useNotebook();
1744
1829
  const engine = useSciNotebook();
1745
- const items = useMemo4(() => {
1830
+ const items = useMemo3(() => {
1746
1831
  if (!notebook) return [];
1747
1832
  const result = [];
1748
1833
  for (const cell of notebook.cells) {
@@ -1761,16 +1846,16 @@ var TOCSidebar = ({ focusedCellId }) => {
1761
1846
  }
1762
1847
  return result;
1763
1848
  }, [notebook]);
1764
- const handleClick = useCallback9((cellId) => {
1849
+ const handleClick = useCallback10((cellId) => {
1765
1850
  engine.focusCell(cellId);
1766
1851
  engine.setEditMode(cellId);
1767
1852
  const el = document.querySelector(`[data-testid="cell-${cellId}"]`);
1768
1853
  if (el) el.scrollIntoView({ behavior: "smooth", block: "center" });
1769
1854
  }, [engine]);
1770
1855
  if (items.length === 0) return null;
1771
- return /* @__PURE__ */ jsxs10("nav", { className: "sci-nb-toc", children: [
1772
- /* @__PURE__ */ jsx11("div", { className: "sci-nb-toc-title", children: "Contenido" }),
1773
- items.map((item, i) => /* @__PURE__ */ jsx11(
1856
+ return /* @__PURE__ */ jsxs12("nav", { className: "sci-nb-toc", children: [
1857
+ /* @__PURE__ */ jsx13("div", { className: "sci-nb-toc-title", children: "Contenido" }),
1858
+ items.map((item, i) => /* @__PURE__ */ jsx13(
1774
1859
  "button",
1775
1860
  {
1776
1861
  className: [
@@ -1788,21 +1873,21 @@ var TOCSidebar = ({ focusedCellId }) => {
1788
1873
  };
1789
1874
 
1790
1875
  // src/components/FindReplace.tsx
1791
- import { useState as useState11, useCallback as useCallback10, useMemo as useMemo5, useEffect as useEffect9, useRef as useRef8 } from "react";
1792
- import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1876
+ import { useState as useState12, useCallback as useCallback11, useMemo as useMemo4, useEffect as useEffect10, useRef as useRef9 } from "react";
1877
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
1793
1878
  var FindReplace = ({ onClose }) => {
1794
1879
  const notebook = useNotebook();
1795
1880
  const engine = useSciNotebook();
1796
- const [query, setQuery] = useState11("");
1797
- const [replacement, setReplacement] = useState11("");
1798
- const [showReplace, setShowReplace] = useState11(false);
1799
- const [caseSensitive, setCaseSensitive] = useState11(false);
1800
- const [currentIdx, setCurrentIdx] = useState11(0);
1801
- const inputRef = useRef8(null);
1802
- useEffect9(() => {
1881
+ const [query, setQuery] = useState12("");
1882
+ const [replacement, setReplacement] = useState12("");
1883
+ const [showReplace, setShowReplace] = useState12(false);
1884
+ const [caseSensitive, setCaseSensitive] = useState12(false);
1885
+ const [currentIdx, setCurrentIdx] = useState12(0);
1886
+ const inputRef = useRef9(null);
1887
+ useEffect10(() => {
1803
1888
  inputRef.current?.focus();
1804
1889
  }, []);
1805
- const matches = useMemo5(() => {
1890
+ const matches = useMemo4(() => {
1806
1891
  if (!query || !notebook) return [];
1807
1892
  const result = [];
1808
1893
  const q = caseSensitive ? query : query.toLowerCase();
@@ -1818,27 +1903,27 @@ var FindReplace = ({ onClose }) => {
1818
1903
  }
1819
1904
  return result;
1820
1905
  }, [query, notebook, caseSensitive]);
1821
- useEffect9(() => {
1906
+ useEffect10(() => {
1822
1907
  setCurrentIdx(0);
1823
1908
  }, [query, caseSensitive]);
1824
- const navigateToMatch = useCallback10((match) => {
1909
+ const navigateToMatch = useCallback11((match) => {
1825
1910
  engine.focusCell(match.cellId);
1826
1911
  const el = document.querySelector(`[data-testid="cell-${match.cellId}"]`);
1827
1912
  if (el) el.scrollIntoView({ behavior: "smooth", block: "center" });
1828
1913
  }, [engine]);
1829
- const goNext = useCallback10(() => {
1914
+ const goNext = useCallback11(() => {
1830
1915
  if (matches.length === 0) return;
1831
1916
  const next = (currentIdx + 1) % matches.length;
1832
1917
  setCurrentIdx(next);
1833
1918
  navigateToMatch(matches[next]);
1834
1919
  }, [matches, currentIdx, navigateToMatch]);
1835
- const goPrev = useCallback10(() => {
1920
+ const goPrev = useCallback11(() => {
1836
1921
  if (matches.length === 0) return;
1837
1922
  const prev = (currentIdx - 1 + matches.length) % matches.length;
1838
1923
  setCurrentIdx(prev);
1839
1924
  navigateToMatch(matches[prev]);
1840
1925
  }, [matches, currentIdx, navigateToMatch]);
1841
- const replaceCurrent = useCallback10(() => {
1926
+ const replaceCurrent = useCallback11(() => {
1842
1927
  if (matches.length === 0) return;
1843
1928
  const match = matches[currentIdx];
1844
1929
  if (!match) return;
@@ -1847,7 +1932,7 @@ var FindReplace = ({ onClose }) => {
1847
1932
  const newSource = cell.source.slice(0, match.index) + replacement + cell.source.slice(match.index + match.length);
1848
1933
  engine.updateCellSource(match.cellId, newSource);
1849
1934
  }, [matches, currentIdx, replacement, notebook, engine]);
1850
- const replaceAll = useCallback10(() => {
1935
+ const replaceAll = useCallback11(() => {
1851
1936
  if (matches.length === 0 || !notebook) return;
1852
1937
  const byCellId = /* @__PURE__ */ new Map();
1853
1938
  for (const m of matches) {
@@ -1866,7 +1951,7 @@ var FindReplace = ({ onClose }) => {
1866
1951
  engine.updateCellSource(cellId, src);
1867
1952
  }
1868
1953
  }, [matches, replacement, notebook, engine]);
1869
- const handleKeyDown = useCallback10((e) => {
1954
+ const handleKeyDown = useCallback11((e) => {
1870
1955
  if (e.key === "Escape") {
1871
1956
  e.preventDefault();
1872
1957
  onClose();
@@ -1879,21 +1964,21 @@ var FindReplace = ({ onClose }) => {
1879
1964
  setShowReplace((v) => !v);
1880
1965
  }
1881
1966
  }, [onClose, goNext, goPrev]);
1882
- return /* @__PURE__ */ jsxs11("div", { className: "sci-nb-find-bar", onKeyDown: handleKeyDown, children: [
1883
- /* @__PURE__ */ jsx12(
1967
+ return /* @__PURE__ */ jsxs13("div", { className: "sci-nb-find-bar", onKeyDown: handleKeyDown, children: [
1968
+ /* @__PURE__ */ jsx14(
1884
1969
  "input",
1885
1970
  {
1886
1971
  ref: inputRef,
1887
1972
  type: "text",
1888
1973
  value: query,
1889
1974
  onChange: (e) => setQuery(e.target.value),
1890
- placeholder: "Buscar..."
1975
+ placeholder: "Search..."
1891
1976
  }
1892
1977
  ),
1893
- /* @__PURE__ */ jsx12("span", { className: "sci-nb-find-count", children: matches.length > 0 ? `${currentIdx + 1}/${matches.length}` : query ? "0" : "" }),
1894
- /* @__PURE__ */ jsx12("button", { onClick: goPrev, title: "Anterior (Shift+Enter)", children: "\u25B2" }),
1895
- /* @__PURE__ */ jsx12("button", { onClick: goNext, title: "Siguiente (Enter)", children: "\u25BC" }),
1896
- /* @__PURE__ */ jsx12(
1978
+ /* @__PURE__ */ jsx14("span", { className: "sci-nb-find-count", children: matches.length > 0 ? `${currentIdx + 1}/${matches.length}` : query ? "0" : "" }),
1979
+ /* @__PURE__ */ jsx14("button", { onClick: goPrev, title: "Previous (Shift+Enter)", children: "\u25B2" }),
1980
+ /* @__PURE__ */ jsx14("button", { onClick: goNext, title: "Next (Enter)", children: "\u25BC" }),
1981
+ /* @__PURE__ */ jsx14(
1897
1982
  "button",
1898
1983
  {
1899
1984
  onClick: () => setCaseSensitive((v) => !v),
@@ -1902,29 +1987,29 @@ var FindReplace = ({ onClose }) => {
1902
1987
  children: "Aa"
1903
1988
  }
1904
1989
  ),
1905
- /* @__PURE__ */ jsxs11("button", { onClick: () => setShowReplace((v) => !v), title: "Reemplazar (Ctrl+H)", children: [
1990
+ /* @__PURE__ */ jsxs13("button", { onClick: () => setShowReplace((v) => !v), title: "Replace (Ctrl+H)", children: [
1906
1991
  showReplace ? "\u25BE" : "\u25B8",
1907
- " Reemplazar"
1992
+ " Replace"
1908
1993
  ] }),
1909
- showReplace && /* @__PURE__ */ jsxs11(Fragment2, { children: [
1910
- /* @__PURE__ */ jsx12(
1994
+ showReplace && /* @__PURE__ */ jsxs13(Fragment2, { children: [
1995
+ /* @__PURE__ */ jsx14(
1911
1996
  "input",
1912
1997
  {
1913
1998
  type: "text",
1914
1999
  value: replacement,
1915
2000
  onChange: (e) => setReplacement(e.target.value),
1916
- placeholder: "Reemplazar con..."
2001
+ placeholder: "Replace with..."
1917
2002
  }
1918
2003
  ),
1919
- /* @__PURE__ */ jsx12("button", { onClick: replaceCurrent, title: "Reemplazar actual", children: "1" }),
1920
- /* @__PURE__ */ jsx12("button", { onClick: replaceAll, title: "Reemplazar todos", children: "\u2200" })
2004
+ /* @__PURE__ */ jsx14("button", { onClick: replaceCurrent, title: "Replace current", children: "1" }),
2005
+ /* @__PURE__ */ jsx14("button", { onClick: replaceAll, title: "Replace all", children: "\u2200" })
1921
2006
  ] }),
1922
- /* @__PURE__ */ jsx12("button", { onClick: onClose, title: "Cerrar (Esc)", children: "\u2715" })
2007
+ /* @__PURE__ */ jsx14("button", { onClick: onClose, title: "Close (Esc)", children: "\u2715" })
1923
2008
  ] });
1924
2009
  };
1925
2010
 
1926
2011
  // src/components/SciNotebook.tsx
1927
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2012
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1928
2013
  var SciNotebook = ({
1929
2014
  notebook: initialNotebook,
1930
2015
  engine: providedEngine,
@@ -1940,7 +2025,7 @@ var SciNotebook = ({
1940
2025
  engineRef,
1941
2026
  showTOC: showTOCProp = false
1942
2027
  }) => {
1943
- const engine = useMemo6(() => {
2028
+ const engine = useMemo5(() => {
1944
2029
  if (providedEngine) return providedEngine;
1945
2030
  if (initialContent && !initialNotebook) {
1946
2031
  const cells2 = parseInitialContent(initialContent);
@@ -1959,37 +2044,37 @@ var SciNotebook = ({
1959
2044
  }
1960
2045
  return createNotebook({ notebook: initialNotebook, config: { plugins } });
1961
2046
  }, [providedEngine]);
1962
- useEffect10(() => {
2047
+ useEffect11(() => {
1963
2048
  if (engineRef) engineRef.current = engine;
1964
2049
  return () => {
1965
2050
  if (engineRef) engineRef.current = null;
1966
2051
  };
1967
2052
  }, [engine, engineRef]);
1968
- const [notebook, setNotebook] = useState12(initialNotebook || engine.getNotebook());
1969
- useEffect10(() => {
2053
+ const [notebook, setNotebook] = useState13(initialNotebook || engine.getNotebook());
2054
+ useEffect11(() => {
1970
2055
  const unsub = engine.on("notebook:updated", (payload) => {
1971
2056
  setNotebook(payload.data.notebook);
1972
2057
  if (onChange) onChange(payload.data.notebook);
1973
2058
  });
1974
2059
  return unsub;
1975
2060
  }, [engine, onChange]);
1976
- useEffect10(() => {
2061
+ useEffect11(() => {
1977
2062
  if (!onCellFocus) return;
1978
2063
  return engine.on("cell:focused", (payload) => {
1979
2064
  onCellFocus(payload.data.cellId);
1980
2065
  });
1981
2066
  }, [engine, onCellFocus]);
1982
- const pipeline = useMemo6(() => new RenderPipeline(), []);
2067
+ const pipeline = useMemo5(() => new RenderPipeline(), []);
1983
2068
  const cells = notebook.cells;
1984
- const [showFind, setShowFind] = useState12(false);
1985
- const [showTOC, setShowTOC] = useState12(showTOCProp);
1986
- const [focusedCellId, setFocusedCellId] = useState12(null);
1987
- useEffect10(() => {
2069
+ const [showFind, setShowFind] = useState13(false);
2070
+ const [showTOC, setShowTOC] = useState13(showTOCProp);
2071
+ const [focusedCellId, setFocusedCellId] = useState13(null);
2072
+ useEffect11(() => {
1988
2073
  return engine.on("cell:focused", (payload) => {
1989
2074
  setFocusedCellId(payload.data.cellId);
1990
2075
  });
1991
2076
  }, [engine]);
1992
- const handleGlobalKeyDown = useCallback11((e) => {
2077
+ const handleGlobalKeyDown = useCallback12((e) => {
1993
2078
  if (readOnly) return;
1994
2079
  if ((e.ctrlKey || e.metaKey) && e.key === "f") {
1995
2080
  e.preventDefault();
@@ -1998,7 +2083,7 @@ var SciNotebook = ({
1998
2083
  }
1999
2084
  engine.handleKeyDown(e.nativeEvent);
2000
2085
  }, [engine, readOnly]);
2001
- return /* @__PURE__ */ jsx13(NotebookContext.Provider, { value: engine, children: /* @__PURE__ */ jsxs12(
2086
+ return /* @__PURE__ */ jsx15(NotebookContext.Provider, { value: engine, children: /* @__PURE__ */ jsxs14(
2002
2087
  "div",
2003
2088
  {
2004
2089
  className: `sci-nb ${className || ""}`,
@@ -2007,10 +2092,10 @@ var SciNotebook = ({
2007
2092
  onKeyDown: handleGlobalKeyDown,
2008
2093
  tabIndex: 0,
2009
2094
  children: [
2010
- showToolbar && /* @__PURE__ */ jsxs12("div", { className: "sci-nb-toolbar", children: [
2011
- /* @__PURE__ */ jsx13("div", { className: "sci-nb-toolbar-group", children: /* @__PURE__ */ jsx13("span", { className: "sci-nb-toolbar-title", children: notebook.title }) }),
2012
- /* @__PURE__ */ jsxs12("div", { className: "sci-nb-toolbar-group", children: [
2013
- /* @__PURE__ */ jsxs12(
2095
+ showToolbar && /* @__PURE__ */ jsxs14("div", { className: "sci-nb-toolbar", children: [
2096
+ /* @__PURE__ */ jsx15("div", { className: "sci-nb-toolbar-group", children: /* @__PURE__ */ jsx15("span", { className: "sci-nb-toolbar-title", children: notebook.title }) }),
2097
+ /* @__PURE__ */ jsxs14("div", { className: "sci-nb-toolbar-group", children: [
2098
+ /* @__PURE__ */ jsxs14(
2014
2099
  "button",
2015
2100
  {
2016
2101
  className: "sci-nb-toolbar-btn",
@@ -2018,12 +2103,12 @@ var SciNotebook = ({
2018
2103
  disabled: !engine.canUndo(),
2019
2104
  title: "Undo (Ctrl+Z)",
2020
2105
  children: [
2021
- /* @__PURE__ */ jsx13("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx13("path", { d: "M3 7h6a3 3 0 010 6H7M3 7l3-3M3 7l3 3", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2106
+ /* @__PURE__ */ jsx15("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx15("path", { d: "M3 7h6a3 3 0 010 6H7M3 7l3-3M3 7l3 3", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2022
2107
  "Undo"
2023
2108
  ]
2024
2109
  }
2025
2110
  ),
2026
- /* @__PURE__ */ jsxs12(
2111
+ /* @__PURE__ */ jsxs14(
2027
2112
  "button",
2028
2113
  {
2029
2114
  className: "sci-nb-toolbar-btn",
@@ -2032,12 +2117,12 @@ var SciNotebook = ({
2032
2117
  title: "Redo (Ctrl+Shift+Z)",
2033
2118
  children: [
2034
2119
  "Redo",
2035
- /* @__PURE__ */ jsx13("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx13("path", { d: "M11 7H5a3 3 0 000 6h2M11 7l-3-3M11 7l-3 3", strokeLinecap: "round", strokeLinejoin: "round" }) })
2120
+ /* @__PURE__ */ jsx15("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx15("path", { d: "M11 7H5a3 3 0 000 6h2M11 7l-3-3M11 7l-3 3", strokeLinecap: "round", strokeLinejoin: "round" }) })
2036
2121
  ]
2037
2122
  }
2038
2123
  ),
2039
- /* @__PURE__ */ jsx13("span", { className: "sci-nb-toolbar-sep" }),
2040
- /* @__PURE__ */ jsx13(
2124
+ /* @__PURE__ */ jsx15("span", { className: "sci-nb-toolbar-sep" }),
2125
+ /* @__PURE__ */ jsx15(
2041
2126
  "button",
2042
2127
  {
2043
2128
  className: "sci-nb-toolbar-btn",
@@ -2046,7 +2131,7 @@ var SciNotebook = ({
2046
2131
  children: "Edit All"
2047
2132
  }
2048
2133
  ),
2049
- /* @__PURE__ */ jsx13(
2134
+ /* @__PURE__ */ jsx15(
2050
2135
  "button",
2051
2136
  {
2052
2137
  className: "sci-nb-toolbar-btn",
@@ -2055,17 +2140,17 @@ var SciNotebook = ({
2055
2140
  children: "View All"
2056
2141
  }
2057
2142
  ),
2058
- /* @__PURE__ */ jsx13("span", { className: "sci-nb-toolbar-sep" }),
2059
- /* @__PURE__ */ jsx13(
2143
+ /* @__PURE__ */ jsx15("span", { className: "sci-nb-toolbar-sep" }),
2144
+ /* @__PURE__ */ jsx15(
2060
2145
  "button",
2061
2146
  {
2062
2147
  className: "sci-nb-toolbar-btn",
2063
2148
  onClick: () => setShowFind((v) => !v),
2064
2149
  title: "Find & Replace (Ctrl+F)",
2065
- children: "Buscar"
2150
+ children: "Find"
2066
2151
  }
2067
2152
  ),
2068
- /* @__PURE__ */ jsx13(
2153
+ /* @__PURE__ */ jsx15(
2069
2154
  "button",
2070
2155
  {
2071
2156
  className: `sci-nb-toolbar-btn ${showTOC ? "sci-nb-toolbar-btn--active" : ""}`,
@@ -2076,23 +2161,23 @@ var SciNotebook = ({
2076
2161
  )
2077
2162
  ] })
2078
2163
  ] }),
2079
- showFind && /* @__PURE__ */ jsx13(FindReplace, { onClose: () => setShowFind(false) }),
2080
- /* @__PURE__ */ jsxs12("div", { className: "sci-nb-layout", style: { display: "flex", gap: 16 }, children: [
2081
- showTOC && /* @__PURE__ */ jsx13(TOCSidebar, { focusedCellId }),
2082
- /* @__PURE__ */ jsxs12("div", { className: "sci-nb-cells", style: { flex: 1 }, children: [
2083
- cells.length === 0 && /* @__PURE__ */ jsxs12("div", { className: "sci-nb-empty", children: [
2084
- /* @__PURE__ */ jsx13("div", { className: "sci-nb-empty-icon", children: /* @__PURE__ */ jsxs12("svg", { width: "48", height: "48", viewBox: "0 0 48 48", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
2085
- /* @__PURE__ */ jsx13("rect", { x: "8", y: "6", width: "32", height: "36", rx: "4" }),
2086
- /* @__PURE__ */ jsx13("line", { x1: "14", y1: "14", x2: "34", y2: "14" }),
2087
- /* @__PURE__ */ jsx13("line", { x1: "14", y1: "22", x2: "28", y2: "22" }),
2088
- /* @__PURE__ */ jsx13("line", { x1: "14", y1: "30", x2: "22", y2: "30" })
2164
+ showFind && /* @__PURE__ */ jsx15(FindReplace, { onClose: () => setShowFind(false) }),
2165
+ /* @__PURE__ */ jsxs14("div", { className: "sci-nb-layout", style: { display: "flex", gap: 16 }, children: [
2166
+ showTOC && /* @__PURE__ */ jsx15(TOCSidebar, { focusedCellId }),
2167
+ /* @__PURE__ */ jsxs14("div", { className: "sci-nb-cells", style: { flex: 1 }, children: [
2168
+ cells.length === 0 && /* @__PURE__ */ jsxs14("div", { className: "sci-nb-empty", children: [
2169
+ /* @__PURE__ */ jsx15("div", { className: "sci-nb-empty-icon", children: /* @__PURE__ */ jsxs14("svg", { width: "48", height: "48", viewBox: "0 0 48 48", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
2170
+ /* @__PURE__ */ jsx15("rect", { x: "8", y: "6", width: "32", height: "36", rx: "4" }),
2171
+ /* @__PURE__ */ jsx15("line", { x1: "14", y1: "14", x2: "34", y2: "14" }),
2172
+ /* @__PURE__ */ jsx15("line", { x1: "14", y1: "22", x2: "28", y2: "22" }),
2173
+ /* @__PURE__ */ jsx15("line", { x1: "14", y1: "30", x2: "22", y2: "30" })
2089
2174
  ] }) }),
2090
- /* @__PURE__ */ jsx13("p", { children: "Notebook vacio. Agrega una celda para comenzar." }),
2091
- /* @__PURE__ */ jsx13(InsertHandle, { index: 0 })
2175
+ /* @__PURE__ */ jsx15("p", { children: "Empty notebook. Add a cell to get started." }),
2176
+ /* @__PURE__ */ jsx15(InsertHandle, { index: 0 })
2092
2177
  ] }),
2093
- cells.length > 0 && /* @__PURE__ */ jsx13(InsertHandle, { index: 0 }),
2094
- cells.map((cell, idx) => /* @__PURE__ */ jsxs12(React12.Fragment, { children: [
2095
- /* @__PURE__ */ jsx13(
2178
+ cells.length > 0 && /* @__PURE__ */ jsx15(InsertHandle, { index: 0 }),
2179
+ cells.map((cell, idx) => /* @__PURE__ */ jsxs14(React13.Fragment, { children: [
2180
+ /* @__PURE__ */ jsx15(
2096
2181
  Cell,
2097
2182
  {
2098
2183
  cellId: cell.id,
@@ -2101,7 +2186,7 @@ var SciNotebook = ({
2101
2186
  totalCells: cells.length
2102
2187
  }
2103
2188
  ),
2104
- /* @__PURE__ */ jsx13(InsertHandle, { index: idx + 1 })
2189
+ /* @__PURE__ */ jsx15(InsertHandle, { index: idx + 1 })
2105
2190
  ] }, cell.id))
2106
2191
  ] })
2107
2192
  ] })
@@ -2123,8 +2208,8 @@ function parseInitialContent(content) {
2123
2208
  }
2124
2209
 
2125
2210
  // src/components/LatexAutocomplete.tsx
2126
- import { useState as useState13, useEffect as useEffect11, useRef as useRef9, useMemo as useMemo7 } from "react";
2127
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2211
+ import { useState as useState14, useEffect as useEffect12, useRef as useRef10, useMemo as useMemo6 } from "react";
2212
+ import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
2128
2213
  var LATEX_COMMANDS = [
2129
2214
  // Structures
2130
2215
  { cmd: "\\frac{}{}", desc: "Fracci\xF3n", category: "struct" },
@@ -2256,19 +2341,19 @@ var LatexAutocomplete = ({
2256
2341
  onSelect,
2257
2342
  onClose
2258
2343
  }) => {
2259
- const [selectedIndex, setSelectedIndex] = useState13(0);
2260
- const menuRef = useRef9(null);
2261
- const filtered = useMemo7(() => {
2344
+ const [selectedIndex, setSelectedIndex] = useState14(0);
2345
+ const menuRef = useRef10(null);
2346
+ const filtered = useMemo6(() => {
2262
2347
  if (!query) return LATEX_COMMANDS.slice(0, 12);
2263
2348
  const q = query.toLowerCase();
2264
2349
  return LATEX_COMMANDS.filter(
2265
2350
  (c) => c.cmd.toLowerCase().includes(q) || c.desc.toLowerCase().includes(q)
2266
2351
  ).slice(0, 10);
2267
2352
  }, [query]);
2268
- useEffect11(() => {
2353
+ useEffect12(() => {
2269
2354
  setSelectedIndex(0);
2270
2355
  }, [query]);
2271
- useEffect11(() => {
2356
+ useEffect12(() => {
2272
2357
  const handleKey = (e) => {
2273
2358
  if (e.key === "ArrowDown") {
2274
2359
  e.preventDefault();
@@ -2293,23 +2378,23 @@ var LatexAutocomplete = ({
2293
2378
  return () => document.removeEventListener("keydown", handleKey, true);
2294
2379
  }, [filtered, selectedIndex, onSelect, onClose]);
2295
2380
  if (filtered.length === 0) return null;
2296
- return /* @__PURE__ */ jsx14(
2381
+ return /* @__PURE__ */ jsx16(
2297
2382
  "div",
2298
2383
  {
2299
2384
  ref: menuRef,
2300
2385
  className: "sci-nb-slash-menu",
2301
2386
  style: { top: position.top, left: position.left, minWidth: 220 },
2302
- children: filtered.map((item, i) => /* @__PURE__ */ jsxs13(
2387
+ children: filtered.map((item, i) => /* @__PURE__ */ jsxs15(
2303
2388
  "button",
2304
2389
  {
2305
2390
  className: `sci-nb-slash-item ${i === selectedIndex ? "sci-nb-slash-item--active" : ""}`,
2306
2391
  onMouseEnter: () => setSelectedIndex(i),
2307
2392
  onClick: () => onSelect(item.cmd),
2308
2393
  children: [
2309
- /* @__PURE__ */ jsx14("span", { className: "sci-nb-slash-icon", style: { fontFamily: "monospace", fontSize: 11 }, children: item.desc.length <= 2 ? item.desc : item.cmd.slice(0, 4) }),
2310
- /* @__PURE__ */ jsxs13("div", { className: "sci-nb-slash-text", children: [
2311
- /* @__PURE__ */ jsx14("span", { className: "sci-nb-slash-label", style: { fontFamily: "monospace", fontSize: 12 }, children: item.cmd }),
2312
- /* @__PURE__ */ jsx14("span", { className: "sci-nb-slash-desc", children: item.desc })
2394
+ /* @__PURE__ */ jsx16("span", { className: "sci-nb-slash-icon", style: { fontFamily: "monospace", fontSize: 11 }, children: item.desc.length <= 2 ? item.desc : item.cmd.slice(0, 4) }),
2395
+ /* @__PURE__ */ jsxs15("div", { className: "sci-nb-slash-text", children: [
2396
+ /* @__PURE__ */ jsx16("span", { className: "sci-nb-slash-label", style: { fontFamily: "monospace", fontSize: 12 }, children: item.cmd }),
2397
+ /* @__PURE__ */ jsx16("span", { className: "sci-nb-slash-desc", children: item.desc })
2313
2398
  ] })
2314
2399
  ]
2315
2400
  },
@@ -2320,15 +2405,15 @@ var LatexAutocomplete = ({
2320
2405
  };
2321
2406
 
2322
2407
  // src/components/GhostText.tsx
2323
- import { useEffect as useEffect12, useCallback as useCallback13 } from "react";
2324
- import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
2408
+ import { useEffect as useEffect13, useCallback as useCallback14 } from "react";
2409
+ import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
2325
2410
  var GhostText = ({
2326
2411
  text,
2327
2412
  textareaRef,
2328
2413
  onAccept,
2329
2414
  onDismiss
2330
2415
  }) => {
2331
- const handleKeyDown = useCallback13((e) => {
2416
+ const handleKeyDown = useCallback14((e) => {
2332
2417
  if (e.key === "Tab" && !e.shiftKey) {
2333
2418
  e.preventDefault();
2334
2419
  e.stopPropagation();
@@ -2338,7 +2423,7 @@ var GhostText = ({
2338
2423
  onDismiss();
2339
2424
  }
2340
2425
  }, [onAccept, onDismiss]);
2341
- useEffect12(() => {
2426
+ useEffect13(() => {
2342
2427
  const ta2 = textareaRef.current;
2343
2428
  if (!ta2) return;
2344
2429
  ta2.addEventListener("keydown", handleKeyDown, true);
@@ -2356,7 +2441,7 @@ var GhostText = ({
2356
2441
  const left = lines[lines.length - 1].length * charWidth;
2357
2442
  const firstLine = text.split("\n")[0];
2358
2443
  const hasMore = text.includes("\n");
2359
- return /* @__PURE__ */ jsxs14(
2444
+ return /* @__PURE__ */ jsxs16(
2360
2445
  "div",
2361
2446
  {
2362
2447
  className: "sci-nb-ghost-text",
@@ -2374,15 +2459,15 @@ var GhostText = ({
2374
2459
  children: [
2375
2460
  firstLine,
2376
2461
  hasMore ? "..." : "",
2377
- /* @__PURE__ */ jsx15("span", { style: { fontSize: 10, opacity: 0.5, marginLeft: 8 }, children: "Tab \u21B9" })
2462
+ /* @__PURE__ */ jsx17("span", { style: { fontSize: 10, opacity: 0.5, marginLeft: 8 }, children: "Tab \u21B9" })
2378
2463
  ]
2379
2464
  }
2380
2465
  );
2381
2466
  };
2382
2467
 
2383
2468
  // src/components/ChatSidebar.tsx
2384
- import { useState as useState14, useCallback as useCallback14, useRef as useRef10, useEffect as useEffect13 } from "react";
2385
- import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
2469
+ import { useState as useState15, useCallback as useCallback15, useRef as useRef11, useEffect as useEffect14 } from "react";
2470
+ import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
2386
2471
  var ChatSidebar = ({
2387
2472
  onSend,
2388
2473
  systemPrompt,
@@ -2390,23 +2475,23 @@ var ChatSidebar = ({
2390
2475
  onClose
2391
2476
  }) => {
2392
2477
  const engine = useSciNotebook();
2393
- const [messages, setMessages] = useState14(() => {
2478
+ const [messages, setMessages] = useState15(() => {
2394
2479
  if (systemPrompt) {
2395
2480
  return [{ role: "system", content: systemPrompt, timestamp: Date.now() }];
2396
2481
  }
2397
2482
  return [];
2398
2483
  });
2399
- const [input, setInput] = useState14("");
2400
- const [loading, setLoading] = useState14(false);
2401
- const messagesEndRef = useRef10(null);
2402
- const inputRef = useRef10(null);
2403
- useEffect13(() => {
2484
+ const [input, setInput] = useState15("");
2485
+ const [loading, setLoading] = useState15(false);
2486
+ const messagesEndRef = useRef11(null);
2487
+ const inputRef = useRef11(null);
2488
+ useEffect14(() => {
2404
2489
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
2405
2490
  }, [messages]);
2406
- useEffect13(() => {
2491
+ useEffect14(() => {
2407
2492
  inputRef.current?.focus();
2408
2493
  }, []);
2409
- const handleSend = useCallback14(async () => {
2494
+ const handleSend = useCallback15(async () => {
2410
2495
  const text = input.trim();
2411
2496
  if (!text || loading) return;
2412
2497
  const userMsg = { role: "user", content: text, timestamp: Date.now() };
@@ -2444,17 +2529,17 @@ var ChatSidebar = ({
2444
2529
  setLoading(false);
2445
2530
  }
2446
2531
  }, [input, messages, loading, onSend]);
2447
- const handleKeyDown = useCallback14((e) => {
2532
+ const handleKeyDown = useCallback15((e) => {
2448
2533
  if (e.key === "Enter" && !e.shiftKey) {
2449
2534
  e.preventDefault();
2450
2535
  handleSend();
2451
2536
  }
2452
2537
  }, [handleSend]);
2453
2538
  const visibleMessages = messages.filter((m) => m.role !== "system");
2454
- return /* @__PURE__ */ jsxs15("div", { className: "sci-nb-chat-sidebar", children: [
2455
- /* @__PURE__ */ jsxs15("div", { className: "sci-nb-chat-header", children: [
2456
- /* @__PURE__ */ jsx16("span", { children: "AI Assistant" }),
2457
- onClose && /* @__PURE__ */ jsx16(
2539
+ return /* @__PURE__ */ jsxs17("div", { className: "sci-nb-chat-sidebar", children: [
2540
+ /* @__PURE__ */ jsxs17("div", { className: "sci-nb-chat-header", children: [
2541
+ /* @__PURE__ */ jsx18("span", { children: "AI Assistant" }),
2542
+ onClose && /* @__PURE__ */ jsx18(
2458
2543
  "button",
2459
2544
  {
2460
2545
  onClick: onClose,
@@ -2463,11 +2548,11 @@ var ChatSidebar = ({
2463
2548
  }
2464
2549
  )
2465
2550
  ] }),
2466
- /* @__PURE__ */ jsxs15("div", { className: "sci-nb-chat-messages", children: [
2467
- visibleMessages.length === 0 && /* @__PURE__ */ jsx16("div", { style: { textAlign: "center", color: "#94a3b8", padding: 24 }, children: "Ask me anything about your notebook..." }),
2468
- visibleMessages.map((msg, i) => /* @__PURE__ */ jsxs15("div", { className: `sci-nb-chat-msg sci-nb-chat-msg--${msg.role}`, children: [
2469
- /* @__PURE__ */ jsx16("div", { children: msg.content }),
2470
- msg.role === "assistant" && onApply && /* @__PURE__ */ jsx16(
2551
+ /* @__PURE__ */ jsxs17("div", { className: "sci-nb-chat-messages", children: [
2552
+ visibleMessages.length === 0 && /* @__PURE__ */ jsx18("div", { style: { textAlign: "center", color: "#94a3b8", padding: 24 }, children: "Ask me anything about your notebook..." }),
2553
+ visibleMessages.map((msg, i) => /* @__PURE__ */ jsxs17("div", { className: `sci-nb-chat-msg sci-nb-chat-msg--${msg.role}`, children: [
2554
+ /* @__PURE__ */ jsx18("div", { children: msg.content }),
2555
+ msg.role === "assistant" && onApply && /* @__PURE__ */ jsx18(
2471
2556
  "button",
2472
2557
  {
2473
2558
  onClick: () => onApply(msg.content),
@@ -2484,11 +2569,11 @@ var ChatSidebar = ({
2484
2569
  }
2485
2570
  )
2486
2571
  ] }, i)),
2487
- loading && /* @__PURE__ */ jsx16("div", { className: "sci-nb-chat-msg sci-nb-chat-msg--assistant", style: { opacity: 0.6 }, children: "Thinking..." }),
2488
- /* @__PURE__ */ jsx16("div", { ref: messagesEndRef })
2572
+ loading && /* @__PURE__ */ jsx18("div", { className: "sci-nb-chat-msg sci-nb-chat-msg--assistant", style: { opacity: 0.6 }, children: "Thinking..." }),
2573
+ /* @__PURE__ */ jsx18("div", { ref: messagesEndRef })
2489
2574
  ] }),
2490
- /* @__PURE__ */ jsxs15("div", { className: "sci-nb-chat-input", children: [
2491
- /* @__PURE__ */ jsx16(
2575
+ /* @__PURE__ */ jsxs17("div", { className: "sci-nb-chat-input", children: [
2576
+ /* @__PURE__ */ jsx18(
2492
2577
  "input",
2493
2578
  {
2494
2579
  ref: inputRef,
@@ -2500,14 +2585,14 @@ var ChatSidebar = ({
2500
2585
  disabled: loading
2501
2586
  }
2502
2587
  ),
2503
- /* @__PURE__ */ jsx16("button", { onClick: handleSend, disabled: loading || !input.trim(), children: "Send" })
2588
+ /* @__PURE__ */ jsx18("button", { onClick: handleSend, disabled: loading || !input.trim(), children: "Send" })
2504
2589
  ] })
2505
2590
  ] });
2506
2591
  };
2507
2592
 
2508
2593
  // src/components/ImageResize.tsx
2509
- import { useState as useState15, useCallback as useCallback15, useRef as useRef11, useEffect as useEffect14 } from "react";
2510
- import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
2594
+ import { useState as useState16, useCallback as useCallback16, useRef as useRef12, useEffect as useEffect15 } from "react";
2595
+ import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
2511
2596
  var ImageResize = ({
2512
2597
  src,
2513
2598
  alt = "",
@@ -2516,12 +2601,12 @@ var ImageResize = ({
2516
2601
  onResize,
2517
2602
  children
2518
2603
  }) => {
2519
- const containerRef = useRef11(null);
2520
- const imgRef = useRef11(null);
2521
- const [dragging, setDragging] = useState15(false);
2522
- const [width, setWidth] = useState15(null);
2523
- const startRef = useRef11({ x: 0, w: 0 });
2524
- const handleMouseDown = useCallback15((e) => {
2604
+ const containerRef = useRef12(null);
2605
+ const imgRef = useRef12(null);
2606
+ const [dragging, setDragging] = useState16(false);
2607
+ const [width, setWidth] = useState16(null);
2608
+ const startRef = useRef12({ x: 0, w: 0 });
2609
+ const handleMouseDown = useCallback16((e) => {
2525
2610
  e.preventDefault();
2526
2611
  e.stopPropagation();
2527
2612
  const img = imgRef.current;
@@ -2529,7 +2614,7 @@ var ImageResize = ({
2529
2614
  startRef.current = { x: e.clientX, w: img.offsetWidth };
2530
2615
  setDragging(true);
2531
2616
  }, []);
2532
- useEffect14(() => {
2617
+ useEffect15(() => {
2533
2618
  if (!dragging) return;
2534
2619
  const handleMouseMove = (e) => {
2535
2620
  const dx = e.clientX - startRef.current.x;
@@ -2557,8 +2642,8 @@ var ImageResize = ({
2557
2642
  position: "relative",
2558
2643
  display: "inline-block"
2559
2644
  };
2560
- return /* @__PURE__ */ jsxs16("div", { ref: containerRef, className: "sci-nb-image-resizable", style, children: [
2561
- /* @__PURE__ */ jsx17(
2645
+ return /* @__PURE__ */ jsxs18("div", { ref: containerRef, className: "sci-nb-image-resizable", style, children: [
2646
+ /* @__PURE__ */ jsx19(
2562
2647
  "img",
2563
2648
  {
2564
2649
  ref: imgRef,
@@ -2569,7 +2654,7 @@ var ImageResize = ({
2569
2654
  }
2570
2655
  ),
2571
2656
  children,
2572
- /* @__PURE__ */ jsx17(
2657
+ /* @__PURE__ */ jsx19(
2573
2658
  "div",
2574
2659
  {
2575
2660
  className: "sci-nb-image-resize-handle sci-nb-image-resize-handle--se",
@@ -2580,28 +2665,28 @@ var ImageResize = ({
2580
2665
  };
2581
2666
 
2582
2667
  // src/components/VirtualRenderer.tsx
2583
- import { useState as useState16, useEffect as useEffect15, useRef as useRef12, useMemo as useMemo8, useCallback as useCallback16 } from "react";
2584
- import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
2668
+ import { useState as useState17, useEffect as useEffect16, useRef as useRef13, useMemo as useMemo7, useCallback as useCallback17 } from "react";
2669
+ import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
2585
2670
  var VirtualRenderer = ({
2586
2671
  cells,
2587
2672
  pipeline,
2588
2673
  estimatedHeight = 120,
2589
2674
  overscan = 5
2590
2675
  }) => {
2591
- const containerRef = useRef12(null);
2592
- const [visibleRange, setVisibleRange] = useState16({ start: 0, end: 20 });
2593
- const cellHeights = useRef12(/* @__PURE__ */ new Map());
2594
- const getHeight = useCallback16((index) => {
2676
+ const containerRef = useRef13(null);
2677
+ const [visibleRange, setVisibleRange] = useState17({ start: 0, end: 20 });
2678
+ const cellHeights = useRef13(/* @__PURE__ */ new Map());
2679
+ const getHeight = useCallback17((index) => {
2595
2680
  return cellHeights.current.get(index) ?? estimatedHeight;
2596
2681
  }, [estimatedHeight]);
2597
- const totalHeight = useMemo8(() => {
2682
+ const totalHeight = useMemo7(() => {
2598
2683
  let h = 0;
2599
2684
  for (let i = 0; i < cells.length; i++) {
2600
2685
  h += getHeight(i) + 32;
2601
2686
  }
2602
2687
  return h;
2603
2688
  }, [cells.length, getHeight]);
2604
- useEffect15(() => {
2689
+ useEffect16(() => {
2605
2690
  const container = containerRef.current;
2606
2691
  if (!container) return;
2607
2692
  const handleScroll = () => {
@@ -2630,7 +2715,7 @@ var VirtualRenderer = ({
2630
2715
  container.addEventListener("scroll", handleScroll, { passive: true });
2631
2716
  return () => container.removeEventListener("scroll", handleScroll);
2632
2717
  }, [cells.length, getHeight, overscan]);
2633
- const measureRef = useCallback16((index) => {
2718
+ const measureRef = useCallback17((index) => {
2634
2719
  return (el) => {
2635
2720
  if (!el) return;
2636
2721
  const observer = new ResizeObserver((entries) => {
@@ -2644,7 +2729,7 @@ var VirtualRenderer = ({
2644
2729
  observer.observe(el);
2645
2730
  };
2646
2731
  }, []);
2647
- const topOffset = useMemo8(() => {
2732
+ const topOffset = useMemo7(() => {
2648
2733
  let h = 0;
2649
2734
  for (let i = 0; i < visibleRange.start; i++) {
2650
2735
  h += getHeight(i) + 32;
@@ -2652,18 +2737,18 @@ var VirtualRenderer = ({
2652
2737
  return h;
2653
2738
  }, [visibleRange.start, getHeight]);
2654
2739
  const visibleCells = cells.slice(visibleRange.start, visibleRange.end);
2655
- return /* @__PURE__ */ jsx18(
2740
+ return /* @__PURE__ */ jsx20(
2656
2741
  "div",
2657
2742
  {
2658
2743
  ref: containerRef,
2659
2744
  className: "sci-nb-virtual-container",
2660
2745
  style: { height: "100%", overflow: "auto", position: "relative" },
2661
- children: /* @__PURE__ */ jsx18("div", { style: { height: totalHeight, position: "relative" }, children: /* @__PURE__ */ jsxs17("div", { style: { position: "absolute", top: topOffset, left: 0, right: 0 }, children: [
2662
- visibleRange.start === 0 && /* @__PURE__ */ jsx18(InsertHandle, { index: 0 }),
2746
+ children: /* @__PURE__ */ jsx20("div", { style: { height: totalHeight, position: "relative" }, children: /* @__PURE__ */ jsxs19("div", { style: { position: "absolute", top: topOffset, left: 0, right: 0 }, children: [
2747
+ visibleRange.start === 0 && /* @__PURE__ */ jsx20(InsertHandle, { index: 0 }),
2663
2748
  visibleCells.map((cell, i) => {
2664
2749
  const realIndex = visibleRange.start + i;
2665
- return /* @__PURE__ */ jsxs17("div", { ref: measureRef(realIndex), children: [
2666
- /* @__PURE__ */ jsx18(
2750
+ return /* @__PURE__ */ jsxs19("div", { ref: measureRef(realIndex), children: [
2751
+ /* @__PURE__ */ jsx20(
2667
2752
  Cell,
2668
2753
  {
2669
2754
  cellId: cell.id,
@@ -2672,7 +2757,7 @@ var VirtualRenderer = ({
2672
2757
  totalCells: cells.length
2673
2758
  }
2674
2759
  ),
2675
- /* @__PURE__ */ jsx18(InsertHandle, { index: realIndex + 1 })
2760
+ /* @__PURE__ */ jsx20(InsertHandle, { index: realIndex + 1 })
2676
2761
  ] }, cell.id);
2677
2762
  })
2678
2763
  ] }) })
@@ -2681,8 +2766,8 @@ var VirtualRenderer = ({
2681
2766
  };
2682
2767
 
2683
2768
  // src/components/AIRewrite.tsx
2684
- import { useState as useState17, useCallback as useCallback17, useRef as useRef13, useEffect as useEffect16 } from "react";
2685
- import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
2769
+ import { useState as useState18, useCallback as useCallback18, useRef as useRef14, useEffect as useEffect17 } from "react";
2770
+ import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
2686
2771
  var AIRewrite = ({
2687
2772
  selectedText,
2688
2773
  position,
@@ -2690,15 +2775,15 @@ var AIRewrite = ({
2690
2775
  onAccept,
2691
2776
  onReject
2692
2777
  }) => {
2693
- const [state, setState] = useState17("prompt");
2694
- const [instruction, setInstruction] = useState17("");
2695
- const [result, setResult] = useState17("");
2696
- const [error, setError] = useState17(null);
2697
- const inputRef = useRef13(null);
2698
- useEffect16(() => {
2778
+ const [state, setState] = useState18("prompt");
2779
+ const [instruction, setInstruction] = useState18("");
2780
+ const [result, setResult] = useState18("");
2781
+ const [error, setError] = useState18(null);
2782
+ const inputRef = useRef14(null);
2783
+ useEffect17(() => {
2699
2784
  inputRef.current?.focus();
2700
2785
  }, []);
2701
- const handleSubmit = useCallback17(async () => {
2786
+ const handleSubmit = useCallback18(async () => {
2702
2787
  if (!instruction.trim()) return;
2703
2788
  setState("loading");
2704
2789
  setError(null);
@@ -2711,7 +2796,7 @@ var AIRewrite = ({
2711
2796
  setState("prompt");
2712
2797
  }
2713
2798
  }, [instruction, selectedText, onRewrite]);
2714
- const handleKeyDown = useCallback17((e) => {
2799
+ const handleKeyDown = useCallback18((e) => {
2715
2800
  if (e.key === "Enter" && !e.shiftKey) {
2716
2801
  e.preventDefault();
2717
2802
  handleSubmit();
@@ -2720,15 +2805,15 @@ var AIRewrite = ({
2720
2805
  onReject();
2721
2806
  }
2722
2807
  }, [handleSubmit, onReject]);
2723
- const handleAccept = useCallback17(() => {
2808
+ const handleAccept = useCallback18(() => {
2724
2809
  onAccept(result);
2725
2810
  }, [result, onAccept]);
2726
- const handleRetry = useCallback17(() => {
2811
+ const handleRetry = useCallback18(() => {
2727
2812
  setState("prompt");
2728
2813
  setResult("");
2729
2814
  inputRef.current?.focus();
2730
2815
  }, []);
2731
- return /* @__PURE__ */ jsxs18(
2816
+ return /* @__PURE__ */ jsxs20(
2732
2817
  "div",
2733
2818
  {
2734
2819
  className: "sci-nb-ai-rewrite",
@@ -2739,13 +2824,13 @@ var AIRewrite = ({
2739
2824
  zIndex: 100
2740
2825
  },
2741
2826
  children: [
2742
- state === "prompt" && /* @__PURE__ */ jsxs18("div", { className: "sci-nb-ai-rewrite-prompt", children: [
2743
- /* @__PURE__ */ jsxs18("div", { className: "sci-nb-ai-rewrite-selected", children: [
2744
- /* @__PURE__ */ jsx19("span", { className: "sci-nb-ai-rewrite-label", children: "Selected:" }),
2745
- /* @__PURE__ */ jsx19("span", { className: "sci-nb-ai-rewrite-text", children: selectedText.length > 80 ? selectedText.slice(0, 80) + "..." : selectedText })
2827
+ state === "prompt" && /* @__PURE__ */ jsxs20("div", { className: "sci-nb-ai-rewrite-prompt", children: [
2828
+ /* @__PURE__ */ jsxs20("div", { className: "sci-nb-ai-rewrite-selected", children: [
2829
+ /* @__PURE__ */ jsx21("span", { className: "sci-nb-ai-rewrite-label", children: "Selected:" }),
2830
+ /* @__PURE__ */ jsx21("span", { className: "sci-nb-ai-rewrite-text", children: selectedText.length > 80 ? selectedText.slice(0, 80) + "..." : selectedText })
2746
2831
  ] }),
2747
- /* @__PURE__ */ jsxs18("div", { className: "sci-nb-ai-rewrite-input-row", children: [
2748
- /* @__PURE__ */ jsx19(
2832
+ /* @__PURE__ */ jsxs20("div", { className: "sci-nb-ai-rewrite-input-row", children: [
2833
+ /* @__PURE__ */ jsx21(
2749
2834
  "input",
2750
2835
  {
2751
2836
  ref: inputRef,
@@ -2757,7 +2842,7 @@ var AIRewrite = ({
2757
2842
  className: "sci-nb-ai-rewrite-input"
2758
2843
  }
2759
2844
  ),
2760
- /* @__PURE__ */ jsx19(
2845
+ /* @__PURE__ */ jsx21(
2761
2846
  "button",
2762
2847
  {
2763
2848
  onClick: handleSubmit,
@@ -2766,24 +2851,24 @@ var AIRewrite = ({
2766
2851
  children: "Rewrite"
2767
2852
  }
2768
2853
  ),
2769
- /* @__PURE__ */ jsx19("button", { onClick: onReject, className: "sci-nb-ai-rewrite-btn", children: "Cancel" })
2854
+ /* @__PURE__ */ jsx21("button", { onClick: onReject, className: "sci-nb-ai-rewrite-btn", children: "Cancel" })
2770
2855
  ] }),
2771
- error && /* @__PURE__ */ jsx19("div", { className: "sci-nb-ai-rewrite-error", children: error })
2856
+ error && /* @__PURE__ */ jsx21("div", { className: "sci-nb-ai-rewrite-error", children: error })
2772
2857
  ] }),
2773
- state === "loading" && /* @__PURE__ */ jsx19("div", { className: "sci-nb-ai-rewrite-loading", children: /* @__PURE__ */ jsx19("span", { children: "Rewriting..." }) }),
2774
- state === "preview" && /* @__PURE__ */ jsxs18("div", { className: "sci-nb-ai-rewrite-preview", children: [
2775
- /* @__PURE__ */ jsxs18("div", { className: "sci-nb-ai-rewrite-diff", children: [
2776
- /* @__PURE__ */ jsxs18("div", { className: "sci-nb-ai-rewrite-diff-old", children: [
2777
- /* @__PURE__ */ jsx19("span", { className: "sci-nb-ai-rewrite-diff-label", children: "Original:" }),
2778
- /* @__PURE__ */ jsx19("pre", { children: selectedText })
2858
+ state === "loading" && /* @__PURE__ */ jsx21("div", { className: "sci-nb-ai-rewrite-loading", children: /* @__PURE__ */ jsx21("span", { children: "Rewriting..." }) }),
2859
+ state === "preview" && /* @__PURE__ */ jsxs20("div", { className: "sci-nb-ai-rewrite-preview", children: [
2860
+ /* @__PURE__ */ jsxs20("div", { className: "sci-nb-ai-rewrite-diff", children: [
2861
+ /* @__PURE__ */ jsxs20("div", { className: "sci-nb-ai-rewrite-diff-old", children: [
2862
+ /* @__PURE__ */ jsx21("span", { className: "sci-nb-ai-rewrite-diff-label", children: "Original:" }),
2863
+ /* @__PURE__ */ jsx21("pre", { children: selectedText })
2779
2864
  ] }),
2780
- /* @__PURE__ */ jsxs18("div", { className: "sci-nb-ai-rewrite-diff-new", children: [
2781
- /* @__PURE__ */ jsx19("span", { className: "sci-nb-ai-rewrite-diff-label", children: "Rewritten:" }),
2782
- /* @__PURE__ */ jsx19("pre", { children: result })
2865
+ /* @__PURE__ */ jsxs20("div", { className: "sci-nb-ai-rewrite-diff-new", children: [
2866
+ /* @__PURE__ */ jsx21("span", { className: "sci-nb-ai-rewrite-diff-label", children: "Rewritten:" }),
2867
+ /* @__PURE__ */ jsx21("pre", { children: result })
2783
2868
  ] })
2784
2869
  ] }),
2785
- /* @__PURE__ */ jsxs18("div", { className: "sci-nb-ai-rewrite-actions", children: [
2786
- /* @__PURE__ */ jsx19(
2870
+ /* @__PURE__ */ jsxs20("div", { className: "sci-nb-ai-rewrite-actions", children: [
2871
+ /* @__PURE__ */ jsx21(
2787
2872
  "button",
2788
2873
  {
2789
2874
  onClick: handleAccept,
@@ -2791,8 +2876,8 @@ var AIRewrite = ({
2791
2876
  children: "Accept"
2792
2877
  }
2793
2878
  ),
2794
- /* @__PURE__ */ jsx19("button", { onClick: handleRetry, className: "sci-nb-ai-rewrite-btn", children: "Retry" }),
2795
- /* @__PURE__ */ jsx19("button", { onClick: onReject, className: "sci-nb-ai-rewrite-btn", children: "Reject" })
2879
+ /* @__PURE__ */ jsx21("button", { onClick: handleRetry, className: "sci-nb-ai-rewrite-btn", children: "Retry" }),
2880
+ /* @__PURE__ */ jsx21("button", { onClick: onReject, className: "sci-nb-ai-rewrite-btn", children: "Reject" })
2796
2881
  ] })
2797
2882
  ] })
2798
2883
  ]
@@ -2801,22 +2886,22 @@ var AIRewrite = ({
2801
2886
  };
2802
2887
 
2803
2888
  // src/components/AICellGenerate.tsx
2804
- import { useState as useState18, useCallback as useCallback18, useRef as useRef14, useEffect as useEffect17 } from "react";
2805
- import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
2889
+ import { useState as useState19, useCallback as useCallback19, useRef as useRef15, useEffect as useEffect18 } from "react";
2890
+ import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
2806
2891
  var AICellGenerate = ({
2807
2892
  onGenerate,
2808
2893
  onAccept,
2809
2894
  onCancel
2810
2895
  }) => {
2811
- const [state, setState] = useState18("prompt");
2812
- const [prompt, setPrompt] = useState18("");
2813
- const [cells, setCells] = useState18([]);
2814
- const [error, setError] = useState18(null);
2815
- const inputRef = useRef14(null);
2816
- useEffect17(() => {
2896
+ const [state, setState] = useState19("prompt");
2897
+ const [prompt, setPrompt] = useState19("");
2898
+ const [cells, setCells] = useState19([]);
2899
+ const [error, setError] = useState19(null);
2900
+ const inputRef = useRef15(null);
2901
+ useEffect18(() => {
2817
2902
  inputRef.current?.focus();
2818
2903
  }, []);
2819
- const handleGenerate = useCallback18(async () => {
2904
+ const handleGenerate = useCallback19(async () => {
2820
2905
  if (!prompt.trim()) return;
2821
2906
  setState("loading");
2822
2907
  setError(null);
@@ -2829,7 +2914,7 @@ var AICellGenerate = ({
2829
2914
  setState("prompt");
2830
2915
  }
2831
2916
  }, [prompt, onGenerate]);
2832
- const handleKeyDown = useCallback18((e) => {
2917
+ const handleKeyDown = useCallback19((e) => {
2833
2918
  if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
2834
2919
  e.preventDefault();
2835
2920
  handleGenerate();
@@ -2838,10 +2923,10 @@ var AICellGenerate = ({
2838
2923
  onCancel();
2839
2924
  }
2840
2925
  }, [handleGenerate, onCancel]);
2841
- const handleAccept = useCallback18(() => {
2926
+ const handleAccept = useCallback19(() => {
2842
2927
  onAccept(cells);
2843
2928
  }, [cells, onAccept]);
2844
- const handleRegenerate = useCallback18(() => {
2929
+ const handleRegenerate = useCallback19(() => {
2845
2930
  setState("prompt");
2846
2931
  setCells([]);
2847
2932
  inputRef.current?.focus();
@@ -2854,13 +2939,13 @@ var AICellGenerate = ({
2854
2939
  mermaid: "Mermaid",
2855
2940
  raw: "Raw"
2856
2941
  };
2857
- return /* @__PURE__ */ jsxs19("div", { className: "sci-nb-ai-generate", children: [
2858
- state === "prompt" && /* @__PURE__ */ jsxs19("div", { className: "sci-nb-ai-generate-prompt", children: [
2859
- /* @__PURE__ */ jsxs19("div", { className: "sci-nb-ai-generate-header", children: [
2860
- /* @__PURE__ */ jsx20("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx20("path", { d: "M8 1v14M1 8h14", strokeLinecap: "round" }) }),
2861
- /* @__PURE__ */ jsx20("span", { children: "Generate cells with AI" })
2942
+ return /* @__PURE__ */ jsxs21("div", { className: "sci-nb-ai-generate", children: [
2943
+ state === "prompt" && /* @__PURE__ */ jsxs21("div", { className: "sci-nb-ai-generate-prompt", children: [
2944
+ /* @__PURE__ */ jsxs21("div", { className: "sci-nb-ai-generate-header", children: [
2945
+ /* @__PURE__ */ jsx22("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx22("path", { d: "M8 1v14M1 8h14", strokeLinecap: "round" }) }),
2946
+ /* @__PURE__ */ jsx22("span", { children: "Generate cells with AI" })
2862
2947
  ] }),
2863
- /* @__PURE__ */ jsx20(
2948
+ /* @__PURE__ */ jsx22(
2864
2949
  "textarea",
2865
2950
  {
2866
2951
  ref: inputRef,
@@ -2872,8 +2957,8 @@ var AICellGenerate = ({
2872
2957
  rows: 3
2873
2958
  }
2874
2959
  ),
2875
- /* @__PURE__ */ jsxs19("div", { className: "sci-nb-ai-generate-actions", children: [
2876
- /* @__PURE__ */ jsx20(
2960
+ /* @__PURE__ */ jsxs21("div", { className: "sci-nb-ai-generate-actions", children: [
2961
+ /* @__PURE__ */ jsx22(
2877
2962
  "button",
2878
2963
  {
2879
2964
  onClick: handleGenerate,
@@ -2882,24 +2967,24 @@ var AICellGenerate = ({
2882
2967
  children: "Generate (Ctrl+Enter)"
2883
2968
  }
2884
2969
  ),
2885
- /* @__PURE__ */ jsx20("button", { onClick: onCancel, className: "sci-nb-ai-rewrite-btn", children: "Cancel" })
2970
+ /* @__PURE__ */ jsx22("button", { onClick: onCancel, className: "sci-nb-ai-rewrite-btn", children: "Cancel" })
2886
2971
  ] }),
2887
- error && /* @__PURE__ */ jsx20("div", { className: "sci-nb-ai-rewrite-error", children: error })
2972
+ error && /* @__PURE__ */ jsx22("div", { className: "sci-nb-ai-rewrite-error", children: error })
2888
2973
  ] }),
2889
- state === "loading" && /* @__PURE__ */ jsx20("div", { className: "sci-nb-ai-generate-loading", children: /* @__PURE__ */ jsx20("span", { children: "Generating cells..." }) }),
2890
- state === "preview" && /* @__PURE__ */ jsxs19("div", { className: "sci-nb-ai-generate-preview", children: [
2891
- /* @__PURE__ */ jsx20("div", { className: "sci-nb-ai-generate-header", children: /* @__PURE__ */ jsxs19("span", { children: [
2974
+ state === "loading" && /* @__PURE__ */ jsx22("div", { className: "sci-nb-ai-generate-loading", children: /* @__PURE__ */ jsx22("span", { children: "Generating cells..." }) }),
2975
+ state === "preview" && /* @__PURE__ */ jsxs21("div", { className: "sci-nb-ai-generate-preview", children: [
2976
+ /* @__PURE__ */ jsx22("div", { className: "sci-nb-ai-generate-header", children: /* @__PURE__ */ jsxs21("span", { children: [
2892
2977
  "Generated ",
2893
2978
  cells.length,
2894
2979
  " cell",
2895
2980
  cells.length !== 1 ? "s" : ""
2896
2981
  ] }) }),
2897
- /* @__PURE__ */ jsx20("div", { className: "sci-nb-ai-generate-cells", children: cells.map((cell, i) => /* @__PURE__ */ jsxs19("div", { className: "sci-nb-ai-generate-cell", children: [
2898
- /* @__PURE__ */ jsx20("div", { className: "sci-nb-ai-generate-cell-badge", children: CELL_TYPE_LABELS[cell.type] || cell.type }),
2899
- /* @__PURE__ */ jsx20("pre", { className: "sci-nb-ai-generate-cell-source", children: cell.source.length > 200 ? cell.source.slice(0, 200) + "..." : cell.source })
2982
+ /* @__PURE__ */ jsx22("div", { className: "sci-nb-ai-generate-cells", children: cells.map((cell, i) => /* @__PURE__ */ jsxs21("div", { className: "sci-nb-ai-generate-cell", children: [
2983
+ /* @__PURE__ */ jsx22("div", { className: "sci-nb-ai-generate-cell-badge", children: CELL_TYPE_LABELS[cell.type] || cell.type }),
2984
+ /* @__PURE__ */ jsx22("pre", { className: "sci-nb-ai-generate-cell-source", children: cell.source.length > 200 ? cell.source.slice(0, 200) + "..." : cell.source })
2900
2985
  ] }, i)) }),
2901
- /* @__PURE__ */ jsxs19("div", { className: "sci-nb-ai-generate-actions", children: [
2902
- /* @__PURE__ */ jsxs19(
2986
+ /* @__PURE__ */ jsxs21("div", { className: "sci-nb-ai-generate-actions", children: [
2987
+ /* @__PURE__ */ jsxs21(
2903
2988
  "button",
2904
2989
  {
2905
2990
  onClick: handleAccept,
@@ -2912,8 +2997,8 @@ var AICellGenerate = ({
2912
2997
  ]
2913
2998
  }
2914
2999
  ),
2915
- /* @__PURE__ */ jsx20("button", { onClick: handleRegenerate, className: "sci-nb-ai-rewrite-btn", children: "Regenerate" }),
2916
- /* @__PURE__ */ jsx20("button", { onClick: onCancel, className: "sci-nb-ai-rewrite-btn", children: "Cancel" })
3000
+ /* @__PURE__ */ jsx22("button", { onClick: handleRegenerate, className: "sci-nb-ai-rewrite-btn", children: "Regenerate" }),
3001
+ /* @__PURE__ */ jsx22("button", { onClick: onCancel, className: "sci-nb-ai-rewrite-btn", children: "Cancel" })
2917
3002
  ] })
2918
3003
  ] })
2919
3004
  ] });