"use client";
import { useState, useRef, useEffect } from 'react';
import {
Bold, Italic, Underline as UnderlineIcon, AlignLeft, AlignCenter,
AlignRight, AlignJustify,
Table as TableIcon, Plus, Minus,
Trash2, Palette, Highlighter,
ChevronDown, Search, Copy,
PieChart, BarChart3, LineChart, Sigma, Filter, DollarSign,
Percent,
WrapText, Merge, Split,
Grid, List, Columns,
Rows,
PlusSquare, MinusSquare, Table2,
ZoomIn as ZoomInIcon,
ZoomOut as ZoomOutIcon,
Cat as CatIcon,
TextIcon,
CpuIcon,
IceCreamCone,
DnaIcon
} from 'lucide-react';
import { createUniver, defaultTheme, LocaleType, merge } from '@univerjs/presets';
import { UniverSheetsCorePreset } from '@univerjs/presets/preset-sheets-core';
import UniverPresetSheetsCoreEnUS from '@univerjs/presets/preset-sheets-core/locales/en-US';
import '@univerjs/presets/lib/styles/preset-sheets-core.css';
import './styles.css'; // Import your custom styles
const RibbonTab = ({ label, isActive, onClick, children }) => (
{isActive &&
{children}
}
);
const RibbonGroup = ({ title, children }) => (
);
// @ts-ignore
const RibbonButton = ({ icon: Icon, label, onClick, isActive = undefined, size = 'medium', dropdown = false }) => (
);
// @ts-ignore
const RibbonDropdownButton = ({ icon: Icon, label, onClick, isActive = undefined, children }) => (
);
// @ts-ignore
const RibbonSplitButton = ({ icon: Icon, label, onClick, dropdownOnClick, isActive }) => (
);
export default function Lotus123Clone() {
// @ts-ignore
const [fileName, setFileName] = useState('Sales Report');
const [activeTab, setActiveTab] = useState('home');
// @ts-ignore
const [formulaMode, setFormulaMode] = useState('@');
const [commandMode, setCommandMode] = useState(false);
// @ts-ignore
const [currentCell, setCurrentCell] = useState('A1');
const [cellContent, setCellContent] = useState('');
const [zoomLevel, setZoomLevel] = useState(100);
const [showSampleData, setShowSampleData] = useState(false);
const univerRef = useRef(null);
const containerRef = useRef(null);
useEffect(() => {
const { univerAPI } = createUniver({
locale: LocaleType.EN_US,
locales: {
[LocaleType.EN_US]: merge(
{},
UniverPresetSheetsCoreEnUS,
),
},
theme: defaultTheme,
presets: [
UniverSheetsCorePreset({
container: containerRef.current,
}),
],
});
// Create a sample workbook with some data
const workbook = univerAPI.createWorkbook({
name: fileName,
styles: {
1: { // Style ID 1 for header
bl: 1, // bold
bg: { rgb: 'f2f2f2' } // background color
},
2: { // Style ID 2 for currency
ff: '$#,##0' // currency format
},
3: { // Style ID 3 for percentages
ff: '0.00%' // percentage format
}
}
});
// Add a worksheet
// @ts-ignore
const worksheet = workbook.create('Sales Data');
// Set sample data if enabled
if (showSampleData) {
// Merge cells for title
const titleRange = worksheet.getRange('A1:F1');
titleRange.merge();
// Set title
titleRange.setValue('Sales Report');
// @ts-ignore
titleRange.setStyle({ fs: 16, bl: 1 }); // font size 16, bold
// Set headers
const headers = ['Region', 'Q1', 'Q2', 'Q3', 'Q4', 'Total'];
const headerRange = worksheet.getRange(1, 0, 1, headers.length - 1);
headerRange.setValues([headers]);
// @ts-ignore
headerRange.setStyle(1); // Apply header style
// Set data rows
const data = [
['North', 12500, 15000, 14200, 16800, '=SUM(B3:E3)'],
['South', 9800, 11200, 10800, 12400, '=SUM(B4:E4)'],
['East', 15300, 16800, 17500, 19200, '=SUM(B5:E5)'],
['West', 11800, 13200, 12800, 14500, '=SUM(B6:E6)']
];
const dataRange = worksheet.getRange(2, 0, data.length, data[0].length);
dataRange.setValues(data);
// Apply currency format to Q1-Q4 and Total columns
const currencyRange = worksheet.getRange(2, 1, data.length, 5);
// @ts-ignore
currencyRange.setStyle(2);
// Set totals row
const totalsRow = 2 + data.length;
worksheet.getRange(totalsRow, 0).setValue('Total');
for (let col = 1; col <= 5; col++) {
const colLetter = String.fromCharCode(64 + col); // A=65, B=66, etc.
const formula = col === 5
? `=SUM(F3:F6)`
: `=SUM(${colLetter}3:${colLetter}6)`;
worksheet.getRange(totalsRow, col).setValue(formula);
// @ts-ignore
worksheet.getRange(totalsRow, col).setStyle({ bl: 1 }); // bold
}
// Set growth rate section
const growthTitleRow = totalsRow + 2;
worksheet.getRange(growthTitleRow, 0).setValue('Growth Rate');
// @ts-ignore
worksheet.getRange(growthTitleRow, 0).setStyle({ fs: 14, bl: 1 });
const growthRates = [
['Q1 to Q2', '=C3/B3-1', '=C4/B4-1', '=C5/B5-1', '=C6/B6-1', '=C7/B7-1'],
['Q2 to Q3', '=D3/C3-1', '=D4/C4-1', '=D5/C5-1', '=D6/C6-1', '=D7/C7-1'],
['Q3 to Q4', '=E3/D3-1', '=E4/D4-1', '=E5/D5-1', '=E6/D6-1', '=E7/D7-1']
];
const growthRange = worksheet.getRange(growthTitleRow + 1, 0, growthRates.length, growthRates[0].length);
growthRange.setValues(growthRates);
// Apply styles to growth rates
const growthLabelRange = worksheet.getRange(growthTitleRow + 1, 0, growthRates.length, 1);
// @ts-ignore
growthLabelRange.setStyle({ bg: { rgb: 'f2f2f2' } });
const growthValueRange = worksheet.getRange(growthTitleRow + 1, 1, growthRates.length, growthRates[0].length - 1);
// @ts-ignore
growthValueRange.setStyle(3); // percentage format
// Adjust column widths
worksheet.setColumnWidth(0, 120);
for (let col = 1; col <= 5; col++) {
worksheet.setColumnWidth(col, 80);
}
// Adjust row heights
worksheet.setRowHeight(0, 30); // title row
worksheet.setRowHeight(1, 22); // header row
worksheet.setRowHeight(totalsRow, 22); // totals row
worksheet.setRowHeight(growthTitleRow, 24); // growth rate title
}
univerRef.current = univerAPI;
return () => {
univerAPI.dispose();
};
}, [fileName, showSampleData]);
// Get the active range from selection
const getActiveRange = () => {
const workbook = univerRef.current?.getActiveWorkbook();
if (!workbook) return null;
const worksheet = workbook.getActiveSheet();
if (!worksheet) return null;
const selection = worksheet.getSelection();
if (!selection) return null;
return worksheet.getRange(selection.getRange());
};
const handleCopy = () => {
const range = getActiveRange();
if (range) {
const values = range.getValues();
navigator.clipboard.writeText(JSON.stringify(values));
}
};
const handlePaste = async () => {
try {
const text = await navigator.clipboard.readText();
const range = getActiveRange();
if (range) {
try {
const values = JSON.parse(text);
range.setValues(values);
} catch {
range.setValue(text);
}
}
} catch (error) {
console.error('Paste failed:', error);
}
};
const handleInsertRow = () => {
const range = getActiveRange();
if (range) {
range.insertCells(univerRef.current.Enum.Dimension.ROWS);
}
};
// @ts-ignore
const handleInsertColumn = () => {
const range = getActiveRange();
if (range) {
range.insertCells(univerRef.current.Enum.Dimension.COLUMNS);
}
};
const handleDeleteRow = () => {
const range = getActiveRange();
if (range) {
range.deleteCells(univerRef.current.Enum.Dimension.ROWS);
}
};
// @ts-ignore
const handleDeleteColumn = () => {
const range = getActiveRange();
if (range) {
range.deleteCells(univerRef.current.Enum.Dimension.COLUMNS);
}
};
const handleBold = () => {
const range = getActiveRange();
if (range) {
const isBold = range.getCellStyle()?.bl === 1;
range.setFontWeight(isBold ? null : 'bold');
}
};
const handleItalic = () => {
const range = getActiveRange();
if (range) {
const isItalic = range.getCellStyle()?.it === 1;
range.setFontLine(isItalic ? null : 'italic');
}
};
const handleUnderline = () => {
const range = getActiveRange();
if (range) {
const isUnderlined = range.getCellStyle()?.ul === 1;
range.setFontLine(isUnderlined ? null : 'underline');
}
};
const handleAlignment = (alignment) => {
const range = getActiveRange();
if (range) {
range.setTextAlignment(alignment);
}
};
const handleSort = () => {
const range = getActiveRange();
if (range) {
const worksheet = range.getWorksheet();
worksheet.sort(range, { column: range.getColumn(), ascending: true });
}
};
// @ts-ignore
const handleFillDown = () => {
const range = getActiveRange();
if (range && range.getRowCount() > 1) {
const sourceValue = range.getValue();
const values = Array(range.getRowCount()).fill(sourceValue);
range.setValues(values);
}
};
// @ts-ignore
const handleFillRight = () => {
const range = getActiveRange();
if (range && range.getColumnCount() > 1) {
const sourceValue = range.getValue();
const values = Array(range.getColumnCount()).fill(sourceValue);
range.setValues([values]);
}
};
// @ts-ignore
const handleUndo = () => {
univerRef.current?.undo();
};
// @ts-ignore
const handleRedo = () => {
univerRef.current?.redo();
};
// @ts-ignore
const handleSave = () => {
const workbook = univerRef.current?.getActiveWorkbook();
if (workbook) {
const data = workbook.save();
const blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${fileName}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
};
const handleZoomIn = () => {
setZoomLevel(prev => Math.min(prev + 10, 200));
univerRef.current?.setZoomLevel(zoomLevel / 100 + 0.1);
};
const handleZoomOut = () => {
setZoomLevel(prev => Math.max(prev - 10, 50));
univerRef.current?.setZoomLevel(zoomLevel / 100 - 0.1);
};
const handleSlashCommand = (e) => {
if (e.key === '/') {
setCommandMode(true);
} else if (e.key === 'Escape') {
setCommandMode(false);
}
};
// @ts-ignore
const handleLoadSampleData = () => {
setShowSampleData(true);
};
const handleMergeCells = () => {
const range = getActiveRange();
if (range) {
if (range.isMerged()) {
range.breakApart();
} else {
range.merge();
}
}
};
const handleClearFormat = () => {
const range = getActiveRange();
if (range) {
range.clearFormat();
}
};
const handleClearContent = () => {
const range = getActiveRange();
if (range) {
range.clearContent();
}
};
const handleHighlightRange = () => {
const range = getActiveRange();
if (range) {
const highlightDisposable = range.highlight({
stroke: 'red',
fill: 'rgba(255, 255, 0, 0.3)'
});
// Remove highlight after 5 seconds
setTimeout(() => {
highlightDisposable.dispose();
}, 5000);
}
};
const handleSplitText = () => {
const range = getActiveRange();
if (range) {
range.splitTextToColumns(true); // Split with default delimiter (comma)
}
};
return (
{/* ... (keep all the existing JSX and styles the same) ... */}
setActiveTab('home')}>
{}} />
{}} />
handleAlignment('left')} />
handleAlignment('center')} />
handleAlignment('right')} />
{}} />
{}} />
{}} />
{}} />
{}} />
{}} />
{}} />
setActiveTab('home')}>
handleAlignment('left')} />
handleAlignment('center')} />
handleAlignment('right')} />
handleAlignment('justify')} />
{}} />
{}} />
{}} />
{}} />
{}} />
{}} />
{}} />
{}} />
{}} />
{}} />
{}} />
setActiveTab('insert')}>
{}} />
{}} />
{}} />
{}} />
{}} />
{}} />
setActiveTab('data')}>
{}} />
{}} />
{}} />
{}} />
setActiveTab('view')}>
{}} />
{}} />
{}} />
{}} />
{currentCell}
setCellContent(e.target.value)}
onKeyDown={handleSlashCommand}
placeholder="Enter formula or value"
/>
{commandMode && (
/Worksheet - Manage worksheets
/Range - Format range
/File - Save or open files
/Print - Print options
/Graph - Create charts
/Data - Sort and filter
/System - Settings
/Quit - Exit application
)}
{formulaMode === '@' ? 'READY' : 'EDIT'}
For help, press F1
);
}