- added spreadsheet form element;

This commit is contained in:
Vitalii Kiiko
2026-03-25 12:28:34 +01:00
parent d36f73a068
commit 61e03f304b
16 changed files with 382 additions and 11 deletions

View File

@@ -0,0 +1,84 @@
import React, { useEffect, useRef } from 'react';
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets';
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core';
import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US';
import '@univerjs/preset-sheets-core/lib/index.css';
const parseWorkbook = (val) => {
if (!val) return null;
if (typeof val === 'object' && val.sheets) return val;
if (typeof val === 'string') {
try {
const parsed = JSON.parse(val);
return parsed && parsed.sheets ? parsed : null;
} catch {
return null;
}
}
return null;
};
const Spreadsheet = ({ fieldName, defaultValue, setDataFn, template }) => {
const containerRef = useRef(null);
const univerRef = useRef(null);
const univerAPIRef = useRef(null);
const saveTimerRef = useRef(null);
useEffect(() => {
if (!containerRef.current) return;
const { univer, univerAPI } = createUniver({
locale: LocaleType.EN_US,
locales: {
[LocaleType.EN_US]: mergeLocales(UniverPresetSheetsCoreEnUS),
},
presets: [
UniverSheetsCorePreset({
container: containerRef.current,
}),
],
});
univerRef.current = univer;
univerAPIRef.current = univerAPI;
const initialData = parseWorkbook(defaultValue) || parseWorkbook(template) || { name: 'Sheet' };
univerAPI.createWorkbook(initialData);
univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, () => {
clearTimeout(saveTimerRef.current);
saveTimerRef.current = setTimeout(() => {
const wb = univerAPIRef.current?.getActiveWorkbook();
if (wb) {
setDataFn(fieldName, wb.save());
}
}, 300);
});
return () => {
clearTimeout(saveTimerRef.current);
if (univerRef.current) {
univerRef.current.dispose();
univerRef.current = null;
univerAPIRef.current = null;
}
};
}, []); // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => {
const el = containerRef.current;
if (!el) return;
const handler = (e) => { e.stopPropagation(); e.preventDefault(); };
el.addEventListener('wheel', handler, { passive: false });
return () => el.removeEventListener('wheel', handler);
}, []);
return (
<div
ref={containerRef}
style={{ width: '100%', height: '500px' }}
/>
);
};
export default Spreadsheet;

View File

@@ -19,6 +19,7 @@ import Table from './components/Table';
import PasswordField from './components/PasswordField';
import CriteriaTable from './components/CriteriaTable';
import FileSelect from './components/FileSelect';
import Spreadsheet from './components/Spreadsheet';
const FormField = (props) => {
const fields = {
@@ -38,6 +39,7 @@ const FormField = (props) => {
criteria_table: CriteriaTable,
password: PasswordField,
fileselect: FileSelect,
spreadsheet: Spreadsheet,
}
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;