@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.
- package/dist/index.cjs +826 -741
- package/dist/index.js +825 -740
- 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
|
|
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
|
|
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
|
-
|
|
195
|
+
|
|
196
|
+
// src/components/math-categories.ts
|
|
196
197
|
var MATH_CATEGORIES = [
|
|
197
198
|
{
|
|
198
|
-
name: "
|
|
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: "
|
|
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: "
|
|
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{
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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">
|
|
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
|
-
|
|
367
|
-
}
|
|
368
|
-
function escapeHtml(s) {
|
|
369
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
370
|
+
const escaped = clean.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
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(
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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-
|
|
457
|
-
onClick: () =>
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
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:
|
|
465
|
-
onClick: () =>
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
{
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
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
|
-
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
670
|
-
/* @__PURE__ */ jsx3("option", { value: "center", children: "
|
|
671
|
-
/* @__PURE__ */ jsx3("option", { value: "right", children: "
|
|
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: "
|
|
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
|
-
"
|
|
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
|
|
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">${
|
|
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
|
|
743
|
+
function escapeHtml(s) {
|
|
699
744
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
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: "
|
|
825
|
-
/* @__PURE__ */ jsx4("option", { value: "", children: "
|
|
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
|
-
"
|
|
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
|
|
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: "
|
|
855
|
-
{ type: "code", label: "
|
|
856
|
-
{ type: "latex", label: "
|
|
857
|
-
{ type: "image", label: "
|
|
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: "
|
|
860
|
-
{ type: "mermaid", label: "
|
|
861
|
-
{ type: "raw", label: "Raw", description: "
|
|
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
|
-
'
|
|
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: "
|
|
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: "+
|
|
1027
|
-
/* @__PURE__ */ jsx6("button", { onClick: addColumn, children: "+
|
|
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__ */
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
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
|
-
"
|
|
1144
|
+
" next cell \xB7 ",
|
|
1065
1145
|
/* @__PURE__ */ jsx6("kbd", { children: "Esc" }),
|
|
1066
|
-
"
|
|
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>
|
|
1073
|
-
const ths = data.headers.map((h) => `<th>${
|
|
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>${
|
|
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
|
|
1159
|
+
function escapeHtml2(s) {
|
|
1080
1160
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1203
|
-
/* @__PURE__ */
|
|
1204
|
-
/* @__PURE__ */
|
|
1205
|
-
"Mermaid
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
"
|
|
1208
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1215
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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 || " " } }),
|
|
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 {
|
|
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: "
|
|
1497
|
+
{ value: "image", label: "Image", icon: "\u{1F5BC}" },
|
|
1251
1498
|
{ value: "embed", label: "Embed", icon: "\u29C9" }
|
|
1252
1499
|
];
|
|
1253
1500
|
var PLACEHOLDERS = {
|
|
1254
|
-
markdown: "
|
|
1255
|
-
code: "
|
|
1256
|
-
raw: "
|
|
1257
|
-
latex: "
|
|
1258
|
-
image: "Click
|
|
1259
|
-
embed: "Click
|
|
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 =
|
|
1265
|
-
const cellRef =
|
|
1266
|
-
const [showTypeMenu, setShowTypeMenu] =
|
|
1267
|
-
const [hovered, setHovered] =
|
|
1268
|
-
const [slashState, setSlashState] =
|
|
1269
|
-
const [dragOver, setDragOver] =
|
|
1270
|
-
const [isDragging, setIsDragging] =
|
|
1271
|
-
const rendered =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
1556
|
+
const enterEdit = useCallback9(() => {
|
|
1320
1557
|
engine.setEditMode(cellId);
|
|
1321
1558
|
engine.focusCell(cellId);
|
|
1322
1559
|
}, [engine, cellId]);
|
|
1323
|
-
const exitEdit =
|
|
1560
|
+
const exitEdit = useCallback9(() => {
|
|
1324
1561
|
engine.setViewMode(cellId);
|
|
1325
1562
|
}, [engine, cellId]);
|
|
1326
|
-
const handleSlashSelect =
|
|
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
|
|
1333
|
-
|
|
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
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
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
|
-
|
|
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
|
|
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__ */
|
|
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
|
-
|
|
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
|
|
1678
|
+
const did = e.dataTransfer.getData("text/plain");
|
|
1456
1679
|
setDragOver(null);
|
|
1457
|
-
if (
|
|
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__ */
|
|
1474
|
-
/* @__PURE__ */
|
|
1475
|
-
/* @__PURE__ */
|
|
1476
|
-
/* @__PURE__ */
|
|
1477
|
-
/* @__PURE__ */
|
|
1478
|
-
/* @__PURE__ */
|
|
1479
|
-
/* @__PURE__ */
|
|
1480
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1702
|
+
/* @__PURE__ */ jsxs10("span", { className: "sci-nb-cell-index", children: [
|
|
1483
1703
|
"[",
|
|
1484
1704
|
index + 1,
|
|
1485
1705
|
"]"
|
|
1486
1706
|
] })
|
|
1487
1707
|
] }),
|
|
1488
|
-
/* @__PURE__ */
|
|
1489
|
-
/* @__PURE__ */
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
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
|
|
1677
|
-
import { jsx as
|
|
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] =
|
|
1689
|
-
const menuRef =
|
|
1690
|
-
|
|
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__ */
|
|
1712
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1719
|
-
/* @__PURE__ */
|
|
1720
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1731
|
-
/* @__PURE__ */
|
|
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
|
|
1741
|
-
import { jsx as
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
1772
|
-
/* @__PURE__ */
|
|
1773
|
-
items.map((item, i) => /* @__PURE__ */
|
|
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
|
|
1792
|
-
import { Fragment as Fragment2, jsx as
|
|
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] =
|
|
1797
|
-
const [replacement, setReplacement] =
|
|
1798
|
-
const [showReplace, setShowReplace] =
|
|
1799
|
-
const [caseSensitive, setCaseSensitive] =
|
|
1800
|
-
const [currentIdx, setCurrentIdx] =
|
|
1801
|
-
const inputRef =
|
|
1802
|
-
|
|
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 =
|
|
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
|
-
|
|
1906
|
+
useEffect10(() => {
|
|
1822
1907
|
setCurrentIdx(0);
|
|
1823
1908
|
}, [query, caseSensitive]);
|
|
1824
|
-
const navigateToMatch =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
1883
|
-
/* @__PURE__ */
|
|
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: "
|
|
1975
|
+
placeholder: "Search..."
|
|
1891
1976
|
}
|
|
1892
1977
|
),
|
|
1893
|
-
/* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
1895
|
-
/* @__PURE__ */
|
|
1896
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1990
|
+
/* @__PURE__ */ jsxs13("button", { onClick: () => setShowReplace((v) => !v), title: "Replace (Ctrl+H)", children: [
|
|
1906
1991
|
showReplace ? "\u25BE" : "\u25B8",
|
|
1907
|
-
"
|
|
1992
|
+
" Replace"
|
|
1908
1993
|
] }),
|
|
1909
|
-
showReplace && /* @__PURE__ */
|
|
1910
|
-
/* @__PURE__ */
|
|
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: "
|
|
2001
|
+
placeholder: "Replace with..."
|
|
1917
2002
|
}
|
|
1918
2003
|
),
|
|
1919
|
-
/* @__PURE__ */
|
|
1920
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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] =
|
|
1969
|
-
|
|
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
|
-
|
|
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 =
|
|
2067
|
+
const pipeline = useMemo5(() => new RenderPipeline(), []);
|
|
1983
2068
|
const cells = notebook.cells;
|
|
1984
|
-
const [showFind, setShowFind] =
|
|
1985
|
-
const [showTOC, setShowTOC] =
|
|
1986
|
-
const [focusedCellId, setFocusedCellId] =
|
|
1987
|
-
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
2011
|
-
/* @__PURE__ */
|
|
2012
|
-
/* @__PURE__ */
|
|
2013
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2040
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2059
|
-
/* @__PURE__ */
|
|
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: "
|
|
2150
|
+
children: "Find"
|
|
2066
2151
|
}
|
|
2067
2152
|
),
|
|
2068
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2080
|
-
/* @__PURE__ */
|
|
2081
|
-
showTOC && /* @__PURE__ */
|
|
2082
|
-
/* @__PURE__ */
|
|
2083
|
-
cells.length === 0 && /* @__PURE__ */
|
|
2084
|
-
/* @__PURE__ */
|
|
2085
|
-
/* @__PURE__ */
|
|
2086
|
-
/* @__PURE__ */
|
|
2087
|
-
/* @__PURE__ */
|
|
2088
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2091
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2094
|
-
cells.map((cell, idx) => /* @__PURE__ */
|
|
2095
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
2127
|
-
import { jsx as
|
|
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] =
|
|
2260
|
-
const menuRef =
|
|
2261
|
-
const filtered =
|
|
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
|
-
|
|
2353
|
+
useEffect12(() => {
|
|
2269
2354
|
setSelectedIndex(0);
|
|
2270
2355
|
}, [query]);
|
|
2271
|
-
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2310
|
-
/* @__PURE__ */
|
|
2311
|
-
/* @__PURE__ */
|
|
2312
|
-
/* @__PURE__ */
|
|
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
|
|
2324
|
-
import { jsx as
|
|
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 =
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
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
|
|
2385
|
-
import { jsx as
|
|
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] =
|
|
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] =
|
|
2400
|
-
const [loading, setLoading] =
|
|
2401
|
-
const messagesEndRef =
|
|
2402
|
-
const inputRef =
|
|
2403
|
-
|
|
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
|
-
|
|
2491
|
+
useEffect14(() => {
|
|
2407
2492
|
inputRef.current?.focus();
|
|
2408
2493
|
}, []);
|
|
2409
|
-
const handleSend =
|
|
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 =
|
|
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__ */
|
|
2455
|
-
/* @__PURE__ */
|
|
2456
|
-
/* @__PURE__ */
|
|
2457
|
-
onClose && /* @__PURE__ */
|
|
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__ */
|
|
2467
|
-
visibleMessages.length === 0 && /* @__PURE__ */
|
|
2468
|
-
visibleMessages.map((msg, i) => /* @__PURE__ */
|
|
2469
|
-
/* @__PURE__ */
|
|
2470
|
-
msg.role === "assistant" && onApply && /* @__PURE__ */
|
|
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__ */
|
|
2488
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2491
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
2510
|
-
import { jsx as
|
|
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 =
|
|
2520
|
-
const imgRef =
|
|
2521
|
-
const [dragging, setDragging] =
|
|
2522
|
-
const [width, setWidth] =
|
|
2523
|
-
const startRef =
|
|
2524
|
-
const handleMouseDown =
|
|
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
|
-
|
|
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__ */
|
|
2561
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
2584
|
-
import { jsx as
|
|
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 =
|
|
2592
|
-
const [visibleRange, setVisibleRange] =
|
|
2593
|
-
const cellHeights =
|
|
2594
|
-
const getHeight =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
2662
|
-
visibleRange.start === 0 && /* @__PURE__ */
|
|
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__ */
|
|
2666
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
2685
|
-
import { jsx as
|
|
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] =
|
|
2694
|
-
const [instruction, setInstruction] =
|
|
2695
|
-
const [result, setResult] =
|
|
2696
|
-
const [error, setError] =
|
|
2697
|
-
const inputRef =
|
|
2698
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
2808
|
+
const handleAccept = useCallback18(() => {
|
|
2724
2809
|
onAccept(result);
|
|
2725
2810
|
}, [result, onAccept]);
|
|
2726
|
-
const handleRetry =
|
|
2811
|
+
const handleRetry = useCallback18(() => {
|
|
2727
2812
|
setState("prompt");
|
|
2728
2813
|
setResult("");
|
|
2729
2814
|
inputRef.current?.focus();
|
|
2730
2815
|
}, []);
|
|
2731
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
2743
|
-
/* @__PURE__ */
|
|
2744
|
-
/* @__PURE__ */
|
|
2745
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2748
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2854
|
+
/* @__PURE__ */ jsx21("button", { onClick: onReject, className: "sci-nb-ai-rewrite-btn", children: "Cancel" })
|
|
2770
2855
|
] }),
|
|
2771
|
-
error && /* @__PURE__ */
|
|
2856
|
+
error && /* @__PURE__ */ jsx21("div", { className: "sci-nb-ai-rewrite-error", children: error })
|
|
2772
2857
|
] }),
|
|
2773
|
-
state === "loading" && /* @__PURE__ */
|
|
2774
|
-
state === "preview" && /* @__PURE__ */
|
|
2775
|
-
/* @__PURE__ */
|
|
2776
|
-
/* @__PURE__ */
|
|
2777
|
-
/* @__PURE__ */
|
|
2778
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2781
|
-
/* @__PURE__ */
|
|
2782
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2786
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2795
|
-
/* @__PURE__ */
|
|
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
|
|
2805
|
-
import { jsx as
|
|
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] =
|
|
2812
|
-
const [prompt, setPrompt] =
|
|
2813
|
-
const [cells, setCells] =
|
|
2814
|
-
const [error, setError] =
|
|
2815
|
-
const inputRef =
|
|
2816
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
2926
|
+
const handleAccept = useCallback19(() => {
|
|
2842
2927
|
onAccept(cells);
|
|
2843
2928
|
}, [cells, onAccept]);
|
|
2844
|
-
const handleRegenerate =
|
|
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__ */
|
|
2858
|
-
state === "prompt" && /* @__PURE__ */
|
|
2859
|
-
/* @__PURE__ */
|
|
2860
|
-
/* @__PURE__ */
|
|
2861
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2876
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2970
|
+
/* @__PURE__ */ jsx22("button", { onClick: onCancel, className: "sci-nb-ai-rewrite-btn", children: "Cancel" })
|
|
2886
2971
|
] }),
|
|
2887
|
-
error && /* @__PURE__ */
|
|
2972
|
+
error && /* @__PURE__ */ jsx22("div", { className: "sci-nb-ai-rewrite-error", children: error })
|
|
2888
2973
|
] }),
|
|
2889
|
-
state === "loading" && /* @__PURE__ */
|
|
2890
|
-
state === "preview" && /* @__PURE__ */
|
|
2891
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2898
|
-
/* @__PURE__ */
|
|
2899
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2902
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2916
|
-
/* @__PURE__ */
|
|
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
|
] });
|