Skip to content

Commit

Permalink
add min rows/cols
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyphilemon committed Jan 30, 2025
1 parent c35e7df commit 796c9c0
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 160 deletions.
3 changes: 2 additions & 1 deletion blocks/sheet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Block } from '@/components/create-block';
import {
DownloadIcon,
MessageIcon,
RedoIcon,
SparklesIcon,
Expand Down Expand Up @@ -72,7 +73,7 @@ export const sheetBlock = new Block<'sheet', Metadata>({
},
},
{
icon: <SparklesIcon />,
icon: <DownloadIcon />,
description: 'Export',
onClick: ({ content }) => {
try {
Expand Down
20 changes: 10 additions & 10 deletions components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1119,20 +1119,20 @@ export const FullscreenIcon = ({ size = 16 }: { size?: number }) => (
></path>
</svg>
);

export const DownloadIcon = ({ size = 16 }: { size?: number }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
viewBox="0 0 16 16"
width={size}
style={{ color: 'currentcolor' }}
>
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<polyline points="7 10 12 15 17 10" />
<line x1="12" x2="12" y1="15" y2="3" />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8.75 1V1.75V8.68934L10.7197 6.71967L11.25 6.18934L12.3107 7.25L11.7803 7.78033L8.70711 10.8536C8.31658 11.2441 7.68342 11.2441 7.29289 10.8536L4.21967 7.78033L3.68934 7.25L4.75 6.18934L5.28033 6.71967L7.25 8.68934V1.75V1H8.75ZM13.5 9.25V13.5H2.5V9.25V8.5H1V9.25V14C1 14.5523 1.44771 15 2 15H14C14.5523 15 15 14.5523 15 14V9.25V8.5H13.5V9.25Z"
fill="currentColor"
></path>
</svg>
);
128 changes: 78 additions & 50 deletions components/sheet-editor.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
'use client';

import React, { memo } from 'react';
import 'handsontable/styles/handsontable.min.css';
import 'handsontable/styles/ht-theme-main.min.css';
import { registerAllModules } from 'handsontable/registry';
import React, { memo, useMemo } from 'react';
import DataGrid from 'react-data-grid';
import 'react-data-grid/lib/styles.css';
import { parse, unparse } from 'papaparse';

registerAllModules();

import { HotTable } from '@handsontable/react-wrapper';

interface SpreadsheetData {
headers: string[];
rows: string[][];
}

interface SpreadsheetEditorProps {
interface SheetEditorProps {
content: string;
saveContent: (updatedContent: string, debounce: boolean) => void;
status: 'streaming' | 'idle';
Expand All @@ -28,53 +18,91 @@ const PureSpreadsheetEditor = ({
saveContent,
status,
isCurrentVersion,
}: SpreadsheetEditorProps) => {
const parseData = (csvContent: string): string[][] | null => {
}: SheetEditorProps) => {
const parseData = (csvContent: string) => {
if (!csvContent) return null;

const result = parse<string[]>(csvContent, { skipEmptyLines: true });
return result.data;
};

const generateCsv = (data: string[][]) => {
const generateCsv = (data: any[][]) => {
return unparse(data);
};

const data = parseData(content);

return data ? (
<HotTable
data={data}
rowHeaders={true}
colHeaders={true}
height="auto"
autoWrapRow={true}
autoWrapCol={true}
themeName="ht-theme-main-dark-auto"
licenseKey="non-commercial-and-evaluation"
customBorders={false}
afterChange={(changes) => {
if (changes && isCurrentVersion) {
const newData: string[][] = data.map((row) => [...row]);

changes.forEach(([row, prop, _, newValue]) => {
if (typeof row === 'number' && typeof prop === 'number') {
newData[row][prop] = String(newValue);
}
});

const updatedCsv = generateCsv(newData);
saveContent(updatedCsv, true);
}
}}
/>
const rawData = parseData(content);

const columns = useMemo(() => {
if (!rawData || rawData.length === 0) return [];

const columnCount = Math.max(...rawData.map((row) => row.length));
return Array.from({ length: columnCount }, (_, i) => ({
key: i.toString(),
name: String.fromCharCode(65 + i),
editor: 'textEditor',
editable: true,
}));
}, [rawData]);

const rows = useMemo(() => {
if (!rawData) return [];

return rawData.map((row, rowIndex) => {
const rowData: any = { id: rowIndex };

columns.forEach((col, colIndex) => {
rowData[col.key] = row[colIndex] || '';
});

return rowData;
});
}, [rawData, columns]);

function onCellEdit(rowIndex: number, columnKey: string, newValue: string) {
if (!isCurrentVersion) return;

const newRows = [...rows];
newRows[rowIndex] = { ...newRows[rowIndex], [columnKey]: newValue };

// Convert the rows back to 2D array format
const newData = newRows.map((row) =>
columns.map((col) => row[col.key] || ''),
);

const updatedCsv = generateCsv(newData);
saveContent(updatedCsv, true);
}

return rawData ? (
<div style={{ height: '100%', width: '100%' }}>
<DataGrid
columns={columns}
rows={rows}
onCellClick={(args) => {
args.selectCell();
}}
onCellKeyDown={(args) => {
if (args.mode !== 'EDIT' && args.row.id !== undefined) {
args.enableEditMode();
}
}}
onRowsChange={(newRows, { indexes, column }) => {
if (indexes.length === 1) {
const rowIndex = indexes[0];
const newValue = newRows[rowIndex][column.key];
onCellEdit(rowIndex, column.key, newValue);
}
}}
style={{ height: '100%' }}
defaultColumnOptions={{
resizable: true,
sortable: true,
}}
/>
</div>
) : null;
};

function areEqual(
prevProps: SpreadsheetEditorProps,
nextProps: SpreadsheetEditorProps,
) {
function areEqual(prevProps: SheetEditorProps, nextProps: SheetEditorProps) {
return (
prevProps.currentVersionIndex === nextProps.currentVersionIndex &&
prevProps.isCurrentVersion === nextProps.isCurrentVersion &&
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"@codemirror/state": "^6.5.0",
"@codemirror/theme-one-dark": "^6.1.2",
"@codemirror/view": "^6.35.3",
"@handsontable/react-wrapper": "^15.0.0",
"@radix-ui/react-alert-dialog": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
Expand All @@ -51,7 +50,6 @@
"fast-deep-equal": "^3.1.3",
"framer-motion": "^11.3.19",
"geist": "^1.3.1",
"handsontable": "^15.0.0",
"lucide-react": "^0.446.0",
"nanoid": "^5.0.8",
"next": "15.0.3-canary.2",
Expand All @@ -69,6 +67,7 @@
"prosemirror-state": "^1.4.3",
"prosemirror-view": "^1.34.3",
"react": "19.0.0-rc-45804af1-20241021",
"react-data-grid": "7.0.0-beta.47",
"react-dom": "19.0.0-rc-45804af1-20241021",
"react-markdown": "^9.0.1",
"react-resizable-panels": "^2.1.7",
Expand Down
Loading

0 comments on commit 796c9c0

Please sign in to comment.