@pixerate/editor-react 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +406 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -7
- package/dist/index.d.ts +52 -7
- package/dist/index.js +407 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as _tiptap_core from '@tiptap/core';
|
|
2
2
|
import { Editor } from '@tiptap/core';
|
|
3
|
-
import
|
|
3
|
+
import * as _pixerate_editor from '@pixerate/editor';
|
|
4
|
+
import { Template, ColorGradient, RichTextPresetOptions, SpreadsheetControllerOptions, SpreadsheetDocument, CellCoordinate, CellRange, SpreadsheetController, SpreadsheetColumn, SpreadsheetRow, SpreadsheetDataSource, CellData } from '@pixerate/editor';
|
|
4
5
|
export { ColorGradient, RichTextPresetOptions, Template, TemplateVersion, Token, TokenType } from '@pixerate/editor';
|
|
5
6
|
import { UseEditorOptions, EditorContentProps as EditorContentProps$1 } from '@tiptap/react';
|
|
6
|
-
import React from 'react';
|
|
7
|
+
import * as React from 'react';
|
|
8
|
+
import React__default from 'react';
|
|
7
9
|
import { BubbleMenuPluginProps } from '@tiptap/extension-bubble-menu';
|
|
8
10
|
|
|
9
11
|
interface UsePromptEditorProps {
|
|
@@ -61,18 +63,18 @@ declare function useEditor(options?: UseRichEditorProps): _tiptap_core.Editor |
|
|
|
61
63
|
interface EditorContentProps extends EditorContentProps$1 {
|
|
62
64
|
className?: string;
|
|
63
65
|
}
|
|
64
|
-
declare const EditorContent:
|
|
66
|
+
declare const EditorContent: React__default.FC<EditorContentProps>;
|
|
65
67
|
|
|
66
68
|
interface BubbleMenuProps {
|
|
67
69
|
editor: Editor | null;
|
|
68
70
|
className?: string;
|
|
69
|
-
children:
|
|
71
|
+
children: React__default.ReactNode;
|
|
70
72
|
tippyOptions?: BubbleMenuPluginProps["tippyOptions"];
|
|
71
73
|
shouldShow?: BubbleMenuPluginProps["shouldShow"];
|
|
72
74
|
pluginKey?: BubbleMenuPluginProps["pluginKey"];
|
|
73
75
|
updateDelay?: BubbleMenuPluginProps["updateDelay"];
|
|
74
76
|
}
|
|
75
|
-
declare const BubbleMenu:
|
|
77
|
+
declare const BubbleMenu: React__default.FC<BubbleMenuProps>;
|
|
76
78
|
|
|
77
79
|
interface TemplateRendererProps {
|
|
78
80
|
/** Raw prompt or text string to render */
|
|
@@ -90,6 +92,49 @@ interface TemplateRendererProps {
|
|
|
90
92
|
/** Click callback for variable badges */
|
|
91
93
|
onVariableClick?: (variableName: string) => void;
|
|
92
94
|
}
|
|
93
|
-
declare const TemplateRenderer:
|
|
95
|
+
declare const TemplateRenderer: React__default.FC<TemplateRendererProps>;
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
declare function useSpreadsheetEditor(options?: SpreadsheetControllerOptions): {
|
|
98
|
+
document: SpreadsheetDocument;
|
|
99
|
+
activeCell: CellCoordinate | null;
|
|
100
|
+
selectedRange: CellRange | null;
|
|
101
|
+
editingCell: CellCoordinate | null;
|
|
102
|
+
draftValue: string;
|
|
103
|
+
setDraftValue: React.Dispatch<React.SetStateAction<string>>;
|
|
104
|
+
controller: SpreadsheetController;
|
|
105
|
+
getCell: (rowId: string, colId: string) => _pixerate_editor.CellData;
|
|
106
|
+
setCellValue: (rowId: string, colId: string, raw: string) => void;
|
|
107
|
+
selectCell: (row: number, col: number, extendSelection?: boolean) => void;
|
|
108
|
+
selectRange: (range: CellRange) => void;
|
|
109
|
+
startEditing: (row?: number, col?: number, initialVal?: string) => void;
|
|
110
|
+
commitEditing: (val?: string) => void;
|
|
111
|
+
cancelEditing: () => void;
|
|
112
|
+
moveCursor: (dir: "up" | "down" | "left" | "right", extend?: boolean) => void;
|
|
113
|
+
insertColumn: (index: number, config?: Partial<SpreadsheetColumn>) => void;
|
|
114
|
+
deleteColumn: (colId: string) => void;
|
|
115
|
+
insertRow: (index: number, config?: Partial<SpreadsheetRow>) => void;
|
|
116
|
+
deleteRow: (rowId: string) => void;
|
|
117
|
+
setColumnWidth: (colId: string, width: number) => void;
|
|
118
|
+
registerDataSource: (ds: SpreadsheetDataSource) => void;
|
|
119
|
+
setPrimaryDataSource: (id: string | undefined) => void;
|
|
120
|
+
recalculateAll: () => void;
|
|
121
|
+
exportToTsv: () => string;
|
|
122
|
+
importFromTsv: (data: string) => void;
|
|
123
|
+
undo: () => void;
|
|
124
|
+
redo: () => void;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
interface SpreadsheetEditorProps {
|
|
128
|
+
state?: ReturnType<typeof useSpreadsheetEditor>;
|
|
129
|
+
readOnly?: boolean;
|
|
130
|
+
customCellRenderer?: (props: {
|
|
131
|
+
row: SpreadsheetRow;
|
|
132
|
+
col: SpreadsheetColumn;
|
|
133
|
+
cell: CellData;
|
|
134
|
+
}) => React__default.ReactNode;
|
|
135
|
+
onAddColumnClick?: () => void;
|
|
136
|
+
onColumnHeaderClick?: (col: SpreadsheetColumn) => void;
|
|
137
|
+
}
|
|
138
|
+
declare const SpreadsheetEditor: React__default.FC<SpreadsheetEditorProps>;
|
|
139
|
+
|
|
140
|
+
export { BubbleMenu, type BubbleMenuProps, EditorContent, type EditorContentProps, SpreadsheetEditor, type SpreadsheetEditorProps, TemplateRenderer, type TemplateRendererProps, type UsePromptEditorProps, type UseRichEditorProps, useEditor, usePromptEditor, useSpreadsheetEditor };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as _tiptap_core from '@tiptap/core';
|
|
2
2
|
import { Editor } from '@tiptap/core';
|
|
3
|
-
import
|
|
3
|
+
import * as _pixerate_editor from '@pixerate/editor';
|
|
4
|
+
import { Template, ColorGradient, RichTextPresetOptions, SpreadsheetControllerOptions, SpreadsheetDocument, CellCoordinate, CellRange, SpreadsheetController, SpreadsheetColumn, SpreadsheetRow, SpreadsheetDataSource, CellData } from '@pixerate/editor';
|
|
4
5
|
export { ColorGradient, RichTextPresetOptions, Template, TemplateVersion, Token, TokenType } from '@pixerate/editor';
|
|
5
6
|
import { UseEditorOptions, EditorContentProps as EditorContentProps$1 } from '@tiptap/react';
|
|
6
|
-
import React from 'react';
|
|
7
|
+
import * as React from 'react';
|
|
8
|
+
import React__default from 'react';
|
|
7
9
|
import { BubbleMenuPluginProps } from '@tiptap/extension-bubble-menu';
|
|
8
10
|
|
|
9
11
|
interface UsePromptEditorProps {
|
|
@@ -61,18 +63,18 @@ declare function useEditor(options?: UseRichEditorProps): _tiptap_core.Editor |
|
|
|
61
63
|
interface EditorContentProps extends EditorContentProps$1 {
|
|
62
64
|
className?: string;
|
|
63
65
|
}
|
|
64
|
-
declare const EditorContent:
|
|
66
|
+
declare const EditorContent: React__default.FC<EditorContentProps>;
|
|
65
67
|
|
|
66
68
|
interface BubbleMenuProps {
|
|
67
69
|
editor: Editor | null;
|
|
68
70
|
className?: string;
|
|
69
|
-
children:
|
|
71
|
+
children: React__default.ReactNode;
|
|
70
72
|
tippyOptions?: BubbleMenuPluginProps["tippyOptions"];
|
|
71
73
|
shouldShow?: BubbleMenuPluginProps["shouldShow"];
|
|
72
74
|
pluginKey?: BubbleMenuPluginProps["pluginKey"];
|
|
73
75
|
updateDelay?: BubbleMenuPluginProps["updateDelay"];
|
|
74
76
|
}
|
|
75
|
-
declare const BubbleMenu:
|
|
77
|
+
declare const BubbleMenu: React__default.FC<BubbleMenuProps>;
|
|
76
78
|
|
|
77
79
|
interface TemplateRendererProps {
|
|
78
80
|
/** Raw prompt or text string to render */
|
|
@@ -90,6 +92,49 @@ interface TemplateRendererProps {
|
|
|
90
92
|
/** Click callback for variable badges */
|
|
91
93
|
onVariableClick?: (variableName: string) => void;
|
|
92
94
|
}
|
|
93
|
-
declare const TemplateRenderer:
|
|
95
|
+
declare const TemplateRenderer: React__default.FC<TemplateRendererProps>;
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
declare function useSpreadsheetEditor(options?: SpreadsheetControllerOptions): {
|
|
98
|
+
document: SpreadsheetDocument;
|
|
99
|
+
activeCell: CellCoordinate | null;
|
|
100
|
+
selectedRange: CellRange | null;
|
|
101
|
+
editingCell: CellCoordinate | null;
|
|
102
|
+
draftValue: string;
|
|
103
|
+
setDraftValue: React.Dispatch<React.SetStateAction<string>>;
|
|
104
|
+
controller: SpreadsheetController;
|
|
105
|
+
getCell: (rowId: string, colId: string) => _pixerate_editor.CellData;
|
|
106
|
+
setCellValue: (rowId: string, colId: string, raw: string) => void;
|
|
107
|
+
selectCell: (row: number, col: number, extendSelection?: boolean) => void;
|
|
108
|
+
selectRange: (range: CellRange) => void;
|
|
109
|
+
startEditing: (row?: number, col?: number, initialVal?: string) => void;
|
|
110
|
+
commitEditing: (val?: string) => void;
|
|
111
|
+
cancelEditing: () => void;
|
|
112
|
+
moveCursor: (dir: "up" | "down" | "left" | "right", extend?: boolean) => void;
|
|
113
|
+
insertColumn: (index: number, config?: Partial<SpreadsheetColumn>) => void;
|
|
114
|
+
deleteColumn: (colId: string) => void;
|
|
115
|
+
insertRow: (index: number, config?: Partial<SpreadsheetRow>) => void;
|
|
116
|
+
deleteRow: (rowId: string) => void;
|
|
117
|
+
setColumnWidth: (colId: string, width: number) => void;
|
|
118
|
+
registerDataSource: (ds: SpreadsheetDataSource) => void;
|
|
119
|
+
setPrimaryDataSource: (id: string | undefined) => void;
|
|
120
|
+
recalculateAll: () => void;
|
|
121
|
+
exportToTsv: () => string;
|
|
122
|
+
importFromTsv: (data: string) => void;
|
|
123
|
+
undo: () => void;
|
|
124
|
+
redo: () => void;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
interface SpreadsheetEditorProps {
|
|
128
|
+
state?: ReturnType<typeof useSpreadsheetEditor>;
|
|
129
|
+
readOnly?: boolean;
|
|
130
|
+
customCellRenderer?: (props: {
|
|
131
|
+
row: SpreadsheetRow;
|
|
132
|
+
col: SpreadsheetColumn;
|
|
133
|
+
cell: CellData;
|
|
134
|
+
}) => React__default.ReactNode;
|
|
135
|
+
onAddColumnClick?: () => void;
|
|
136
|
+
onColumnHeaderClick?: (col: SpreadsheetColumn) => void;
|
|
137
|
+
}
|
|
138
|
+
declare const SpreadsheetEditor: React__default.FC<SpreadsheetEditorProps>;
|
|
139
|
+
|
|
140
|
+
export { BubbleMenu, type BubbleMenuProps, EditorContent, type EditorContentProps, SpreadsheetEditor, type SpreadsheetEditorProps, TemplateRenderer, type TemplateRendererProps, type UsePromptEditorProps, type UseRichEditorProps, useEditor, usePromptEditor, useSpreadsheetEditor };
|
package/dist/index.js
CHANGED
|
@@ -361,11 +361,417 @@ var TemplateRenderer = ({
|
|
|
361
361
|
return /* @__PURE__ */ jsx2("span", { children: token.value }, index);
|
|
362
362
|
}) });
|
|
363
363
|
};
|
|
364
|
+
|
|
365
|
+
// src/spreadsheet/useSpreadsheetEditor.ts
|
|
366
|
+
import { useState as useState2, useMemo as useMemo3, useCallback } from "react";
|
|
367
|
+
import {
|
|
368
|
+
SpreadsheetController
|
|
369
|
+
} from "@pixerate/editor";
|
|
370
|
+
function useSpreadsheetEditor(options = {}) {
|
|
371
|
+
const [doc, setDoc] = useState2(() => ({
|
|
372
|
+
id: options.document?.id || `sheet_${Date.now()}`,
|
|
373
|
+
name: options.document?.name || "Sheet 1",
|
|
374
|
+
columns: options.document?.columns || [],
|
|
375
|
+
rows: options.document?.rows || [],
|
|
376
|
+
cells: options.document?.cells || {},
|
|
377
|
+
createdAt: options.document?.createdAt || Date.now(),
|
|
378
|
+
updatedAt: options.document?.updatedAt || Date.now()
|
|
379
|
+
}));
|
|
380
|
+
const [activeCell, setActiveCell] = useState2(null);
|
|
381
|
+
const [selectedRange, setSelectedRange] = useState2(null);
|
|
382
|
+
const [editingCell, setEditingCell] = useState2(null);
|
|
383
|
+
const [draftValue, setDraftValue] = useState2("");
|
|
384
|
+
const controller = useMemo3(() => {
|
|
385
|
+
return new SpreadsheetController({
|
|
386
|
+
...options,
|
|
387
|
+
onDocumentChange: (updated) => {
|
|
388
|
+
setDoc({ ...updated });
|
|
389
|
+
options.onDocumentChange?.(updated);
|
|
390
|
+
},
|
|
391
|
+
onSelectionChange: (active, range) => {
|
|
392
|
+
setActiveCell(active);
|
|
393
|
+
setSelectedRange(range);
|
|
394
|
+
options.onSelectionChange?.(active, range);
|
|
395
|
+
},
|
|
396
|
+
onCellCommit: (rowId, colId, raw, value) => {
|
|
397
|
+
options.onCellCommit?.(rowId, colId, raw, value);
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
}, []);
|
|
401
|
+
const setCellValue = useCallback((rowId, colId, raw) => {
|
|
402
|
+
controller.setCellValue(rowId, colId, raw);
|
|
403
|
+
setDoc({ ...controller.document });
|
|
404
|
+
}, [controller]);
|
|
405
|
+
const selectCell = useCallback((row, col, extendSelection = false) => {
|
|
406
|
+
controller.selectCell(row, col, extendSelection);
|
|
407
|
+
setActiveCell(controller.activeCell);
|
|
408
|
+
setSelectedRange(controller.selectedRange);
|
|
409
|
+
}, [controller]);
|
|
410
|
+
const selectRange = useCallback((range) => {
|
|
411
|
+
controller.selectRange(range);
|
|
412
|
+
setSelectedRange(controller.selectedRange);
|
|
413
|
+
}, [controller]);
|
|
414
|
+
const startEditing = useCallback((row, col, initialVal) => {
|
|
415
|
+
controller.startEditing(row, col, initialVal);
|
|
416
|
+
setActiveCell(controller.activeCell);
|
|
417
|
+
setEditingCell(controller.editingCell);
|
|
418
|
+
setDraftValue(controller.draftValue);
|
|
419
|
+
}, [controller]);
|
|
420
|
+
const commitEditing = useCallback((val) => {
|
|
421
|
+
controller.commitEditing(val);
|
|
422
|
+
setEditingCell(null);
|
|
423
|
+
setDraftValue("");
|
|
424
|
+
setDoc({ ...controller.document });
|
|
425
|
+
}, [controller]);
|
|
426
|
+
const cancelEditing = useCallback(() => {
|
|
427
|
+
controller.cancelEditing();
|
|
428
|
+
setEditingCell(null);
|
|
429
|
+
setDraftValue("");
|
|
430
|
+
}, [controller]);
|
|
431
|
+
const moveCursor = useCallback((dir, extend = false) => {
|
|
432
|
+
controller.moveCursor(dir, extend);
|
|
433
|
+
setActiveCell(controller.activeCell);
|
|
434
|
+
setSelectedRange(controller.selectedRange);
|
|
435
|
+
}, [controller]);
|
|
436
|
+
const insertColumn = useCallback((index, config) => {
|
|
437
|
+
controller.insertColumn(index, config);
|
|
438
|
+
setDoc({ ...controller.document });
|
|
439
|
+
}, [controller]);
|
|
440
|
+
const deleteColumn = useCallback((colId) => {
|
|
441
|
+
controller.deleteColumn(colId);
|
|
442
|
+
setDoc({ ...controller.document });
|
|
443
|
+
}, [controller]);
|
|
444
|
+
const insertRow = useCallback((index, config) => {
|
|
445
|
+
controller.insertRow(index, config);
|
|
446
|
+
setDoc({ ...controller.document });
|
|
447
|
+
}, [controller]);
|
|
448
|
+
const deleteRow = useCallback((rowId) => {
|
|
449
|
+
controller.deleteRow(rowId);
|
|
450
|
+
setDoc({ ...controller.document });
|
|
451
|
+
}, [controller]);
|
|
452
|
+
const setColumnWidth = useCallback((colId, width) => {
|
|
453
|
+
controller.setColumnWidth(colId, width);
|
|
454
|
+
setDoc({ ...controller.document });
|
|
455
|
+
}, [controller]);
|
|
456
|
+
const registerDataSource = useCallback((ds) => {
|
|
457
|
+
controller.registerDataSource(ds);
|
|
458
|
+
setDoc({ ...controller.document });
|
|
459
|
+
}, [controller]);
|
|
460
|
+
const setPrimaryDataSource = useCallback((id) => {
|
|
461
|
+
controller.setPrimaryDataSource(id);
|
|
462
|
+
setDoc({ ...controller.document });
|
|
463
|
+
}, [controller]);
|
|
464
|
+
const recalculateAll = useCallback(() => {
|
|
465
|
+
controller.recalculateAll();
|
|
466
|
+
setDoc({ ...controller.document });
|
|
467
|
+
}, [controller]);
|
|
468
|
+
const undo = useCallback(() => {
|
|
469
|
+
controller.undo();
|
|
470
|
+
setDoc({ ...controller.document });
|
|
471
|
+
}, [controller]);
|
|
472
|
+
const redo = useCallback(() => {
|
|
473
|
+
controller.redo();
|
|
474
|
+
setDoc({ ...controller.document });
|
|
475
|
+
}, [controller]);
|
|
476
|
+
return {
|
|
477
|
+
document: doc,
|
|
478
|
+
activeCell,
|
|
479
|
+
selectedRange,
|
|
480
|
+
editingCell,
|
|
481
|
+
draftValue,
|
|
482
|
+
setDraftValue,
|
|
483
|
+
controller,
|
|
484
|
+
getCell: (rowId, colId) => controller.getCell(rowId, colId),
|
|
485
|
+
setCellValue,
|
|
486
|
+
selectCell,
|
|
487
|
+
selectRange,
|
|
488
|
+
startEditing,
|
|
489
|
+
commitEditing,
|
|
490
|
+
cancelEditing,
|
|
491
|
+
moveCursor,
|
|
492
|
+
insertColumn,
|
|
493
|
+
deleteColumn,
|
|
494
|
+
insertRow,
|
|
495
|
+
deleteRow,
|
|
496
|
+
setColumnWidth,
|
|
497
|
+
registerDataSource,
|
|
498
|
+
setPrimaryDataSource,
|
|
499
|
+
recalculateAll,
|
|
500
|
+
exportToTsv: () => controller.exportToTsv(),
|
|
501
|
+
importFromTsv: (data) => {
|
|
502
|
+
controller.importFromTsv(data);
|
|
503
|
+
setDoc({ ...controller.document });
|
|
504
|
+
},
|
|
505
|
+
undo,
|
|
506
|
+
redo
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// src/spreadsheet/SpreadsheetEditor.tsx
|
|
511
|
+
import { useState as useState3, useMemo as useMemo4, useEffect as useEffect3, useCallback as useCallback2 } from "react";
|
|
512
|
+
import {
|
|
513
|
+
indexToColName
|
|
514
|
+
} from "@pixerate/editor";
|
|
515
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
516
|
+
var SpreadsheetEditor = ({
|
|
517
|
+
state: externalState,
|
|
518
|
+
readOnly = false,
|
|
519
|
+
customCellRenderer,
|
|
520
|
+
onAddColumnClick,
|
|
521
|
+
onColumnHeaderClick
|
|
522
|
+
}) => {
|
|
523
|
+
const defaultState = useSpreadsheetEditor();
|
|
524
|
+
const state = externalState || defaultState;
|
|
525
|
+
const [resizingColId, setResizingColId] = useState3(null);
|
|
526
|
+
const [resizeStartX, setResizeStartX] = useState3(0);
|
|
527
|
+
const [resizeStartWidth, setResizeStartWidth] = useState3(0);
|
|
528
|
+
const activeRawValue = useMemo4(() => {
|
|
529
|
+
if (!state.activeCell) return "";
|
|
530
|
+
const row = state.document.rows[state.activeCell.row];
|
|
531
|
+
const col = state.document.columns[state.activeCell.col];
|
|
532
|
+
if (!row || !col) return "";
|
|
533
|
+
return state.getCell(row.id, col.id).raw;
|
|
534
|
+
}, [state.activeCell, state.document]);
|
|
535
|
+
const coordLabel = useMemo4(() => {
|
|
536
|
+
if (!state.activeCell) return "--";
|
|
537
|
+
const colName = indexToColName(state.activeCell.col);
|
|
538
|
+
return `${colName}${state.activeCell.row + 1}`;
|
|
539
|
+
}, [state.activeCell]);
|
|
540
|
+
const handleCellClick = useCallback2((rIdx, cIdx, e) => {
|
|
541
|
+
if (state.editingCell && (state.editingCell.row !== rIdx || state.editingCell.col !== cIdx)) {
|
|
542
|
+
state.commitEditing();
|
|
543
|
+
}
|
|
544
|
+
state.selectCell(rIdx, cIdx, e.shiftKey);
|
|
545
|
+
}, [state]);
|
|
546
|
+
const handleCellDblClick = useCallback2((rIdx, cIdx) => {
|
|
547
|
+
if (readOnly) return;
|
|
548
|
+
const col = state.document.columns[cIdx];
|
|
549
|
+
if (col?.readOnly) return;
|
|
550
|
+
state.startEditing(rIdx, cIdx);
|
|
551
|
+
}, [readOnly, state]);
|
|
552
|
+
const handleKeyDown = useCallback2((e) => {
|
|
553
|
+
if (state.editingCell) {
|
|
554
|
+
if (e.key === "Enter") {
|
|
555
|
+
e.preventDefault();
|
|
556
|
+
state.commitEditing();
|
|
557
|
+
state.moveCursor("down");
|
|
558
|
+
} else if (e.key === "Escape") {
|
|
559
|
+
e.preventDefault();
|
|
560
|
+
state.cancelEditing();
|
|
561
|
+
} else if (e.key === "Tab") {
|
|
562
|
+
e.preventDefault();
|
|
563
|
+
state.commitEditing();
|
|
564
|
+
state.moveCursor(e.shiftKey ? "left" : "right");
|
|
565
|
+
}
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
if (!state.activeCell) return;
|
|
569
|
+
if (e.key === "ArrowUp") {
|
|
570
|
+
e.preventDefault();
|
|
571
|
+
state.moveCursor("up", e.shiftKey);
|
|
572
|
+
} else if (e.key === "ArrowDown") {
|
|
573
|
+
e.preventDefault();
|
|
574
|
+
state.moveCursor("down", e.shiftKey);
|
|
575
|
+
} else if (e.key === "ArrowLeft") {
|
|
576
|
+
e.preventDefault();
|
|
577
|
+
state.moveCursor("left", e.shiftKey);
|
|
578
|
+
} else if (e.key === "ArrowRight") {
|
|
579
|
+
e.preventDefault();
|
|
580
|
+
state.moveCursor("right", e.shiftKey);
|
|
581
|
+
} else if (e.key === "Tab") {
|
|
582
|
+
e.preventDefault();
|
|
583
|
+
state.moveCursor(e.shiftKey ? "left" : "right");
|
|
584
|
+
} else if (e.key === "Enter") {
|
|
585
|
+
e.preventDefault();
|
|
586
|
+
const col = state.document.columns[state.activeCell.col];
|
|
587
|
+
if (!readOnly && !col?.readOnly) {
|
|
588
|
+
state.startEditing();
|
|
589
|
+
}
|
|
590
|
+
} else if (e.key === "Backspace" || e.key === "Delete") {
|
|
591
|
+
if (readOnly) return;
|
|
592
|
+
const row = state.document.rows[state.activeCell.row];
|
|
593
|
+
const col = state.document.columns[state.activeCell.col];
|
|
594
|
+
if (row && col && !col.readOnly) {
|
|
595
|
+
e.preventDefault();
|
|
596
|
+
state.setCellValue(row.id, col.id, "");
|
|
597
|
+
}
|
|
598
|
+
} else if ((e.metaKey || e.ctrlKey) && e.key === "z") {
|
|
599
|
+
e.preventDefault();
|
|
600
|
+
if (e.shiftKey) {
|
|
601
|
+
state.redo();
|
|
602
|
+
} else {
|
|
603
|
+
state.undo();
|
|
604
|
+
}
|
|
605
|
+
} else if ((e.metaKey || e.ctrlKey) && e.key === "c") {
|
|
606
|
+
e.preventDefault();
|
|
607
|
+
const tsv = state.exportToTsv();
|
|
608
|
+
navigator.clipboard?.writeText(tsv);
|
|
609
|
+
} else if (!readOnly && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
610
|
+
const col = state.document.columns[state.activeCell.col];
|
|
611
|
+
if (!col?.readOnly) {
|
|
612
|
+
state.startEditing(state.activeCell.row, state.activeCell.col, e.key);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}, [readOnly, state]);
|
|
616
|
+
useEffect3(() => {
|
|
617
|
+
if (!resizingColId) return;
|
|
618
|
+
const handleMouseMove = (e) => {
|
|
619
|
+
const delta = e.clientX - resizeStartX;
|
|
620
|
+
state.setColumnWidth(resizingColId, Math.max(60, resizeStartWidth + delta));
|
|
621
|
+
};
|
|
622
|
+
const handleMouseUp = () => {
|
|
623
|
+
setResizingColId(null);
|
|
624
|
+
};
|
|
625
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
626
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
627
|
+
return () => {
|
|
628
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
629
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
630
|
+
};
|
|
631
|
+
}, [resizingColId, resizeStartX, resizeStartWidth, state]);
|
|
632
|
+
const isCellSelected = (rIdx, cIdx) => {
|
|
633
|
+
if (!state.selectedRange) return false;
|
|
634
|
+
const minR = Math.min(state.selectedRange.startRow, state.selectedRange.endRow);
|
|
635
|
+
const maxR = Math.max(state.selectedRange.startRow, state.selectedRange.endRow);
|
|
636
|
+
const minC = Math.min(state.selectedRange.startCol, state.selectedRange.endCol);
|
|
637
|
+
const maxC = Math.max(state.selectedRange.startCol, state.selectedRange.endCol);
|
|
638
|
+
return rIdx >= minR && rIdx <= maxR && cIdx >= minC && cIdx <= maxC;
|
|
639
|
+
};
|
|
640
|
+
const isActiveCell = (rIdx, cIdx) => {
|
|
641
|
+
return state.activeCell?.row === rIdx && state.activeCell?.col === cIdx;
|
|
642
|
+
};
|
|
643
|
+
return /* @__PURE__ */ jsxs(
|
|
644
|
+
"div",
|
|
645
|
+
{
|
|
646
|
+
className: "flex flex-col h-full w-full overflow-hidden border border-border bg-background select-none outline-none text-foreground font-sans text-xs",
|
|
647
|
+
tabIndex: 0,
|
|
648
|
+
onKeyDown: handleKeyDown,
|
|
649
|
+
role: "grid",
|
|
650
|
+
"aria-label": "Spreadsheet",
|
|
651
|
+
children: [
|
|
652
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-border bg-muted/20 px-3 py-1.5 text-xs font-mono", children: [
|
|
653
|
+
/* @__PURE__ */ jsx3("div", { className: "flex h-6 min-w-[3rem] items-center justify-center rounded border border-border bg-background px-1.5 font-semibold text-foreground", children: coordLabel }),
|
|
654
|
+
/* @__PURE__ */ jsx3("div", { className: "flex items-center text-muted-foreground select-none", children: /* @__PURE__ */ jsx3("span", { className: "italic font-serif font-bold text-sm text-primary", children: "fx" }) }),
|
|
655
|
+
/* @__PURE__ */ jsx3(
|
|
656
|
+
"input",
|
|
657
|
+
{
|
|
658
|
+
type: "text",
|
|
659
|
+
className: "flex-1 bg-transparent px-2 py-0.5 outline-none font-sans text-xs text-foreground placeholder:text-muted-foreground/60 focus:bg-background focus:ring-1 focus:ring-primary rounded",
|
|
660
|
+
placeholder: "Enter a value or formula (e.g. =SUM(A1:A5))",
|
|
661
|
+
value: state.editingCell ? state.draftValue : activeRawValue,
|
|
662
|
+
onChange: (e) => {
|
|
663
|
+
if (state.activeCell) {
|
|
664
|
+
state.setDraftValue(e.target.value);
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
onKeyDown: (e) => {
|
|
668
|
+
if (e.key === "Enter") {
|
|
669
|
+
e.preventDefault();
|
|
670
|
+
if (state.activeCell) {
|
|
671
|
+
const row = state.document.rows[state.activeCell.row];
|
|
672
|
+
const col = state.document.columns[state.activeCell.col];
|
|
673
|
+
if (row && col) {
|
|
674
|
+
state.setCellValue(row.id, col.id, e.target.value);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
} else if (e.key === "Escape") {
|
|
678
|
+
e.preventDefault();
|
|
679
|
+
state.cancelEditing();
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
)
|
|
684
|
+
] }),
|
|
685
|
+
/* @__PURE__ */ jsx3("div", { className: "relative flex-1 overflow-auto", children: /* @__PURE__ */ jsxs("table", { className: "border-collapse table-fixed w-max min-w-full", children: [
|
|
686
|
+
/* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "h-7 bg-muted/60 sticky top-0 z-20 border-b border-border shadow-xs", children: [
|
|
687
|
+
/* @__PURE__ */ jsx3("th", { className: "w-12 min-w-[3rem] sticky left-0 z-30 bg-muted/90 border-r border-border text-center text-[10px] text-muted-foreground font-medium", children: "#" }),
|
|
688
|
+
state.document.columns.map((col, cIdx) => /* @__PURE__ */ jsxs(
|
|
689
|
+
"th",
|
|
690
|
+
{
|
|
691
|
+
className: "relative border-r border-border px-2 text-left font-medium text-muted-foreground hover:bg-muted/90 transition-colors group cursor-pointer",
|
|
692
|
+
style: { width: col.width || 130, minWidth: col.width || 130, maxWidth: col.width || 130 },
|
|
693
|
+
onClick: () => onColumnHeaderClick?.(col),
|
|
694
|
+
children: [
|
|
695
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-1 truncate", children: [
|
|
696
|
+
/* @__PURE__ */ jsx3("span", { className: "truncate font-semibold text-foreground text-xs", children: col.title }),
|
|
697
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground/70 font-mono font-normal", children: [
|
|
698
|
+
"(",
|
|
699
|
+
col.key,
|
|
700
|
+
")"
|
|
701
|
+
] })
|
|
702
|
+
] }),
|
|
703
|
+
/* @__PURE__ */ jsx3(
|
|
704
|
+
"div",
|
|
705
|
+
{
|
|
706
|
+
className: "absolute right-0 top-0 bottom-0 w-1.5 cursor-col-resize hover:bg-primary/50 group-hover:bg-primary/20 z-10",
|
|
707
|
+
onMouseDown: (e) => {
|
|
708
|
+
e.preventDefault();
|
|
709
|
+
e.stopPropagation();
|
|
710
|
+
setResizingColId(col.id);
|
|
711
|
+
setResizeStartX(e.clientX);
|
|
712
|
+
setResizeStartWidth(col.width || 130);
|
|
713
|
+
},
|
|
714
|
+
role: "separator",
|
|
715
|
+
"aria-orientation": "vertical"
|
|
716
|
+
}
|
|
717
|
+
)
|
|
718
|
+
]
|
|
719
|
+
},
|
|
720
|
+
col.id
|
|
721
|
+
)),
|
|
722
|
+
onAddColumnClick && /* @__PURE__ */ jsx3(
|
|
723
|
+
"th",
|
|
724
|
+
{
|
|
725
|
+
className: "w-10 min-w-[2.5rem] px-1 text-center bg-muted/40 hover:bg-muted cursor-pointer transition-colors",
|
|
726
|
+
onClick: onAddColumnClick,
|
|
727
|
+
title: "Add Column",
|
|
728
|
+
children: /* @__PURE__ */ jsx3("span", { className: "text-xs font-bold text-muted-foreground", children: "+" })
|
|
729
|
+
}
|
|
730
|
+
)
|
|
731
|
+
] }) }),
|
|
732
|
+
/* @__PURE__ */ jsx3("tbody", { children: state.document.rows.map((row, rIdx) => /* @__PURE__ */ jsxs("tr", { className: "border-b border-border hover:bg-muted/10 transition-colors", style: { height: row.height || 32 }, children: [
|
|
733
|
+
/* @__PURE__ */ jsx3("td", { className: "w-12 min-w-[3rem] sticky left-0 z-10 bg-muted/50 border-r border-border text-center text-[10px] text-muted-foreground font-mono select-none", children: rIdx + 1 }),
|
|
734
|
+
state.document.columns.map((col, cIdx) => {
|
|
735
|
+
const cell = state.getCell(row.id, col.id);
|
|
736
|
+
const selected = isCellSelected(rIdx, cIdx);
|
|
737
|
+
const active = isActiveCell(rIdx, cIdx);
|
|
738
|
+
const isEditing = state.editingCell?.row === rIdx && state.editingCell?.col === cIdx;
|
|
739
|
+
return /* @__PURE__ */ jsx3(
|
|
740
|
+
"td",
|
|
741
|
+
{
|
|
742
|
+
className: `relative border-r border-border px-2 py-1 truncate text-foreground transition-all ${selected ? "bg-primary/10" : ""} ${active ? "ring-2 ring-primary ring-inset z-10" : ""}`,
|
|
743
|
+
style: { width: col.width || 130, minWidth: col.width || 130, maxWidth: col.width || 130 },
|
|
744
|
+
onClick: (e) => handleCellClick(rIdx, cIdx, e),
|
|
745
|
+
onDoubleClick: () => handleCellDblClick(rIdx, cIdx),
|
|
746
|
+
children: isEditing ? /* @__PURE__ */ jsx3(
|
|
747
|
+
"input",
|
|
748
|
+
{
|
|
749
|
+
type: "text",
|
|
750
|
+
className: "absolute inset-0 w-full h-full px-2 py-1 bg-background text-foreground outline-none font-sans text-xs border-2 border-primary z-20",
|
|
751
|
+
value: state.draftValue,
|
|
752
|
+
onChange: (e) => state.setDraftValue(e.target.value),
|
|
753
|
+
onBlur: () => state.commitEditing(),
|
|
754
|
+
autoFocus: true
|
|
755
|
+
}
|
|
756
|
+
) : customCellRenderer ? customCellRenderer({ row, col, cell }) : /* @__PURE__ */ jsx3("span", { className: `truncate block ${cell.error ? "text-destructive font-semibold" : ""}`, children: cell.error || (cell.value ?? "") })
|
|
757
|
+
},
|
|
758
|
+
col.id
|
|
759
|
+
);
|
|
760
|
+
}),
|
|
761
|
+
onAddColumnClick && /* @__PURE__ */ jsx3("td", { className: "w-10 min-w-[2.5rem] bg-muted/10 border-r border-border" })
|
|
762
|
+
] }, row.id)) })
|
|
763
|
+
] }) })
|
|
764
|
+
]
|
|
765
|
+
}
|
|
766
|
+
);
|
|
767
|
+
};
|
|
364
768
|
export {
|
|
365
769
|
BubbleMenu,
|
|
366
770
|
EditorContent,
|
|
771
|
+
SpreadsheetEditor,
|
|
367
772
|
TemplateRenderer,
|
|
368
773
|
useEditor2 as useEditor,
|
|
369
|
-
usePromptEditor
|
|
774
|
+
usePromptEditor,
|
|
775
|
+
useSpreadsheetEditor
|
|
370
776
|
};
|
|
371
777
|
//# sourceMappingURL=index.js.map
|