@candidstartup/react-spreadsheet 0.7.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/LICENSE +29 -0
- package/README.md +4 -0
- package/dist/index.d.ts +149 -0
- package/dist/index.js +490 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
- package/src/VirtualSpreadsheet.css +124 -0
- package/src/VirtualSpreadsheet.module.css +2 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-2024, Tim Wiegand
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { SpreadsheetData } from '@candidstartup/infinisheet-types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Theme that defines class names for all DOM elements within {@link VirtualSpreadsheet}. Provide an appropriate
|
|
6
|
+
* theme to use VirtualSpreadsheet with whatever CSS management system you prefer.
|
|
7
|
+
*
|
|
8
|
+
* Properties are named using a BEM style with the form `ComponentName_ElementName__modifierName_modifierValue`
|
|
9
|
+
*/
|
|
10
|
+
interface VirtualSpreadsheetTheme {
|
|
11
|
+
/** Class applied to the overall component */
|
|
12
|
+
VirtualSpreadsheet: string;
|
|
13
|
+
/** Class applied to the input bar at the top of the component */
|
|
14
|
+
VirtualSpreadsheet_InputBar: string;
|
|
15
|
+
/** Class applied to the Name input on the left end of the input bar */
|
|
16
|
+
VirtualSpreadsheet_Name: string;
|
|
17
|
+
/** Class applied to the "fx" label in the input bar */
|
|
18
|
+
VirtualSpreadsheet_Fx: string;
|
|
19
|
+
/** Class applied to the Formula input on the right end of the input bar */
|
|
20
|
+
VirtualSpreadsheet_Formula: string;
|
|
21
|
+
/** Class applied to the grid of cells */
|
|
22
|
+
VirtualSpreadsheet_Grid: string;
|
|
23
|
+
/** Class applied to the top left corner where the row and column headers meet */
|
|
24
|
+
VirtualSpreadsheet_CornerHeader: string;
|
|
25
|
+
/** Class applied to the column header */
|
|
26
|
+
VirtualSpreadsheet_ColumnHeader: string;
|
|
27
|
+
/** Class applied to an individual column within the column header */
|
|
28
|
+
VirtualSpreadsheet_Column: string;
|
|
29
|
+
/** Modifier class applied to a column when it's selected */
|
|
30
|
+
VirtualSpreadsheet_Column__Selected: string;
|
|
31
|
+
/** Modifier class applied to a column when a cell in that column is selected */
|
|
32
|
+
VirtualSpreadsheet_Column__CellSelected: string;
|
|
33
|
+
/** Class applied to the row header */
|
|
34
|
+
VirtualSpreadsheet_RowHeader: string;
|
|
35
|
+
/** Class applied to an individual row within the row header */
|
|
36
|
+
VirtualSpreadsheet_Row: string;
|
|
37
|
+
/** Modifier class applied to a row when it's selected */
|
|
38
|
+
VirtualSpreadsheet_Row__Selected: string;
|
|
39
|
+
/** Modifier class applied to a row when a cell in that row is selected */
|
|
40
|
+
VirtualSpreadsheet_Row__CellSelected: string;
|
|
41
|
+
/** Class applied to a cell within the grid*/
|
|
42
|
+
VirtualSpreadsheet_Cell: string;
|
|
43
|
+
/** Modifier class applied to a cell when it contains a string value */
|
|
44
|
+
VirtualSpreadsheet_Cell__Type_string: string;
|
|
45
|
+
/** Modifier class applied to a cell when it contains a number value */
|
|
46
|
+
VirtualSpreadsheet_Cell__Type_number: string;
|
|
47
|
+
/** Modifier class applied to a cell when it contains a boolean value */
|
|
48
|
+
VirtualSpreadsheet_Cell__Type_boolean: string;
|
|
49
|
+
/** Modifier class applied to a cell when it contains a null value */
|
|
50
|
+
VirtualSpreadsheet_Cell__Type_null: string;
|
|
51
|
+
/** Modifier class applied to a cell when it contains an undefined value */
|
|
52
|
+
VirtualSpreadsheet_Cell__Type_undefined: string;
|
|
53
|
+
/** Modifier class applied to a cell when it contains an error value */
|
|
54
|
+
VirtualSpreadsheet_Cell__Type_CellError: string;
|
|
55
|
+
/** Modifier class applied to a cell when it has the focus */
|
|
56
|
+
VirtualSpreadsheet_Cell__Focus: string;
|
|
57
|
+
/** Modifier class applied to a cell when it's within a selected row */
|
|
58
|
+
VirtualSpreadsheet_Cell__RowSelected: string;
|
|
59
|
+
/** Modifier class applied to a cell when it's within a selected column */
|
|
60
|
+
VirtualSpreadsheet_Cell__ColumnSelected: string;
|
|
61
|
+
}
|
|
62
|
+
/** Default implementation of theme provided by `VirtualSpreadsheet.css` */
|
|
63
|
+
declare const VirtualSpreadsheetDefaultTheme: VirtualSpreadsheetTheme;
|
|
64
|
+
|
|
65
|
+
/** Extension of {@link SpreadsheetData} interface so that it's compatible with React's `useSyncExternalStore` hook
|
|
66
|
+
*
|
|
67
|
+
* Additional properties are optional, so anything that implements `SpreadsheetData` is compatible with something
|
|
68
|
+
* that accepts `ReactSpreadsheetData`.
|
|
69
|
+
*/
|
|
70
|
+
interface ReactSpreadsheetData<Snapshot> extends SpreadsheetData<Snapshot> {
|
|
71
|
+
/** Used by `useSyncExternalStore` to support server side rendering */
|
|
72
|
+
getServerSnapshot?: () => Snapshot;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Props for {@link VirtualSpreadsheet}
|
|
76
|
+
*/
|
|
77
|
+
interface VirtualSpreadsheetProps<Snapshot> {
|
|
78
|
+
/** The `className` applied to the spreadsheet as a whole */
|
|
79
|
+
className?: string;
|
|
80
|
+
/** Spreadsheet theme which defines the CSS classes to apply
|
|
81
|
+
*
|
|
82
|
+
* Defined as a union so that it supports both hand written themes
|
|
83
|
+
* defined as implementations of {@link VirtualSpreadsheetTheme} and themes
|
|
84
|
+
* implicitly defined by importing a CSS module.
|
|
85
|
+
*/
|
|
86
|
+
theme?: VirtualSpreadsheetTheme | Record<string, string>;
|
|
87
|
+
/** Component height */
|
|
88
|
+
height: number;
|
|
89
|
+
/** Component width */
|
|
90
|
+
width: number;
|
|
91
|
+
/** Height of input bar
|
|
92
|
+
* @defaultValue 30
|
|
93
|
+
*/
|
|
94
|
+
inputBarHeight?: number;
|
|
95
|
+
/** Height of column header
|
|
96
|
+
* @defaultValue 50
|
|
97
|
+
*/
|
|
98
|
+
columnHeaderHeight?: number;
|
|
99
|
+
/** Width of row header
|
|
100
|
+
* @defaultValue 100
|
|
101
|
+
*/
|
|
102
|
+
rowHeaderWidth?: number;
|
|
103
|
+
/** Data to display and edit */
|
|
104
|
+
data: ReactSpreadsheetData<Snapshot>;
|
|
105
|
+
/** Disables edit mode if true
|
|
106
|
+
* @defaultValue false
|
|
107
|
+
*/
|
|
108
|
+
readOnly?: boolean;
|
|
109
|
+
/** Minimum number of rows in the spreadsheet
|
|
110
|
+
* @defaultValue 100
|
|
111
|
+
*/
|
|
112
|
+
minRowCount?: number;
|
|
113
|
+
/** Maximum number of rows in the spreadsheet
|
|
114
|
+
* @defaultValue 1000000000000
|
|
115
|
+
*/
|
|
116
|
+
maxRowCount?: number;
|
|
117
|
+
/** Minimum number of columns in the grid
|
|
118
|
+
* @defaultValue 26
|
|
119
|
+
*/
|
|
120
|
+
minColumnCount?: number;
|
|
121
|
+
/** Maximum umber of columns in the grid
|
|
122
|
+
* @defaultValue 1000000000000
|
|
123
|
+
*/
|
|
124
|
+
maxColumnCount?: number;
|
|
125
|
+
/**
|
|
126
|
+
* Maximum size for CSS element beyond which layout breaks. You should never normally need to change this.
|
|
127
|
+
* The default value is compatible with all major browsers.
|
|
128
|
+
*
|
|
129
|
+
* @defaultValue 6000000
|
|
130
|
+
* */
|
|
131
|
+
maxCssSize?: number;
|
|
132
|
+
/**
|
|
133
|
+
* The minimum number of virtual pages to use when inner container would otherwise be more than {@link VirtualSpreadsheetProps.maxCssSize} big.
|
|
134
|
+
* You should never normally need to change this.
|
|
135
|
+
*
|
|
136
|
+
* @defaultValue 100
|
|
137
|
+
*/
|
|
138
|
+
minNumPages?: number;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Virtual Spreadsheet
|
|
142
|
+
*
|
|
143
|
+
* Accepts props defined by {@link VirtualSpreadsheetProps}.
|
|
144
|
+
* You must pass an instance of {@link SpreadsheetData} using the `data` prop.
|
|
145
|
+
* @group Components
|
|
146
|
+
*/
|
|
147
|
+
declare function VirtualSpreadsheet<Snapshot>(props: VirtualSpreadsheetProps<Snapshot>): react_jsx_runtime.JSX.Element;
|
|
148
|
+
|
|
149
|
+
export { type ReactSpreadsheetData, VirtualSpreadsheet, VirtualSpreadsheetDefaultTheme, type VirtualSpreadsheetProps, type VirtualSpreadsheetTheme };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { DisplayList, VirtualScroll, AutoSizer, DisplayGrid, getRangeToScroll, getOffsetToScrollRange } from '@candidstartup/react-virtual-scroll';
|
|
4
|
+
import { rowColRefToCoords, indexToColRef, rowColCoordsToRef } from '@candidstartup/infinisheet-types';
|
|
5
|
+
import * as numfmt from 'numfmt';
|
|
6
|
+
|
|
7
|
+
/** Default implementation of theme provided by `VirtualSpreadsheet.css` */
|
|
8
|
+
const VirtualSpreadsheetDefaultTheme = {
|
|
9
|
+
VirtualSpreadsheet: "VirtualSpreadsheet",
|
|
10
|
+
VirtualSpreadsheet_InputBar: "VirtualSpreadsheet_InputBar",
|
|
11
|
+
VirtualSpreadsheet_Name: "VirtualSpreadsheet_Name",
|
|
12
|
+
VirtualSpreadsheet_Fx: "VirtualSpreadsheet_Fx",
|
|
13
|
+
VirtualSpreadsheet_Formula: "VirtualSpreadsheet_Formula",
|
|
14
|
+
VirtualSpreadsheet_Grid: "VirtualSpreadsheet_Grid",
|
|
15
|
+
VirtualSpreadsheet_CornerHeader: "VirtualSpreadsheet_CornerHeader",
|
|
16
|
+
VirtualSpreadsheet_ColumnHeader: "VirtualSpreadsheet_ColumnHeader",
|
|
17
|
+
VirtualSpreadsheet_Column: "VirtualSpreadsheet_Column",
|
|
18
|
+
VirtualSpreadsheet_Column__Selected: "VirtualSpreadsheet_Column__Selected",
|
|
19
|
+
VirtualSpreadsheet_Column__CellSelected: "VirtualSpreadsheet_Column__CellSelected",
|
|
20
|
+
VirtualSpreadsheet_RowHeader: "VirtualSpreadsheet_RowHeader",
|
|
21
|
+
VirtualSpreadsheet_Row: "VirtualSpreadsheet_Row",
|
|
22
|
+
VirtualSpreadsheet_Row__Selected: "VirtualSpreadsheet_Row__Selected",
|
|
23
|
+
VirtualSpreadsheet_Row__CellSelected: "VirtualSpreadsheet_Row__CellSelected",
|
|
24
|
+
VirtualSpreadsheet_Cell: "VirtualSpreadsheet_Cell",
|
|
25
|
+
VirtualSpreadsheet_Cell__Type_string: "VirtualSpreadsheet_Cell__Type_string",
|
|
26
|
+
VirtualSpreadsheet_Cell__Type_number: "VirtualSpreadsheet_Cell__Type_number",
|
|
27
|
+
VirtualSpreadsheet_Cell__Type_boolean: "VirtualSpreadsheet_Cell__Type_boolean",
|
|
28
|
+
VirtualSpreadsheet_Cell__Type_null: "VirtualSpreadsheet_Cell__Type_null",
|
|
29
|
+
VirtualSpreadsheet_Cell__Type_undefined: "VirtualSpreadsheet_Cell__Type_undefined",
|
|
30
|
+
VirtualSpreadsheet_Cell__Type_CellError: "VirtualSpreadsheet_Cell__Type_CellError",
|
|
31
|
+
VirtualSpreadsheet_Cell__Focus: "VirtualSpreadsheet_Cell__Focus",
|
|
32
|
+
VirtualSpreadsheet_Cell__RowSelected: "VirtualSpreadsheet_Cell__RowSelected",
|
|
33
|
+
VirtualSpreadsheet_Cell__ColumnSelected: "VirtualSpreadsheet_Cell__ColumnSelected"
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function join(...v) {
|
|
37
|
+
let s = undefined;
|
|
38
|
+
v.forEach(a => {
|
|
39
|
+
if (s && a)
|
|
40
|
+
s = s + ' ' + a;
|
|
41
|
+
else if (a)
|
|
42
|
+
s = a;
|
|
43
|
+
});
|
|
44
|
+
return s;
|
|
45
|
+
}
|
|
46
|
+
function ifdef(b, s) { return (b) ? s : undefined; }
|
|
47
|
+
// Options for numfmt that match Google Sheets and ECMA-376 behavior. This is compatible with supported dates in Excel apart from Jan/Feb 1900.
|
|
48
|
+
// This is due to Excel's backwards compatibility support for the Lotus 1-2-3 leap year bug that incorrectly thinks 1900 is a leap year.
|
|
49
|
+
const numfmtOptions = {
|
|
50
|
+
leap1900: false,
|
|
51
|
+
dateSpanLarge: true
|
|
52
|
+
};
|
|
53
|
+
function formatContent(value, format) {
|
|
54
|
+
if (value === null || value === undefined)
|
|
55
|
+
return "";
|
|
56
|
+
if (typeof value === 'object')
|
|
57
|
+
return value.value;
|
|
58
|
+
if (typeof value === 'string' && value[0] == '\'') {
|
|
59
|
+
// Leading apostrophe means display rest of string as is
|
|
60
|
+
return value.substring(1);
|
|
61
|
+
}
|
|
62
|
+
if (format === undefined)
|
|
63
|
+
format = "";
|
|
64
|
+
return numfmt.format(format, value, numfmtOptions);
|
|
65
|
+
}
|
|
66
|
+
function classForType(value) {
|
|
67
|
+
if (value === null)
|
|
68
|
+
return 'VirtualSpreadsheet_Cell__Type_null';
|
|
69
|
+
if (value === undefined)
|
|
70
|
+
return 'VirtualSpreadsheet_Cell__Type_undefined';
|
|
71
|
+
const type = typeof value;
|
|
72
|
+
if (type === 'object')
|
|
73
|
+
return 'VirtualSpreadsheet_Cell__Type_CellError';
|
|
74
|
+
return 'VirtualSpreadsheet_Cell__Type_' + type;
|
|
75
|
+
}
|
|
76
|
+
function inRect(x, y, rect) {
|
|
77
|
+
return (x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom);
|
|
78
|
+
}
|
|
79
|
+
// Return mouse coordinates in space of current event target. Not directly available so we convert
|
|
80
|
+
// using client coordinates.
|
|
81
|
+
function getCurrentTargetXY(event) {
|
|
82
|
+
let clientX = event.clientX;
|
|
83
|
+
let clientY = event.clientY;
|
|
84
|
+
if (event.target !== event.currentTarget) {
|
|
85
|
+
const target = event.target;
|
|
86
|
+
const targetRect = target.getBoundingClientRect();
|
|
87
|
+
if (!inRect(clientX, clientY, targetRect)) {
|
|
88
|
+
// Sometimes get events with bogus client XY, often generated by some form of automation
|
|
89
|
+
// If this happens behave as if middle of target rect was clicked
|
|
90
|
+
clientX = (targetRect.left + targetRect.right) / 2;
|
|
91
|
+
clientY = (targetRect.top + targetRect.bottom) / 2;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const currentRect = event.currentTarget.getBoundingClientRect();
|
|
95
|
+
if (!inRect(clientX, clientY, currentRect)) {
|
|
96
|
+
// Somethings gone horribly wrong
|
|
97
|
+
return [0, 0];
|
|
98
|
+
}
|
|
99
|
+
return [clientX - currentRect.left, clientY - currentRect.top];
|
|
100
|
+
}
|
|
101
|
+
function HeaderItem({ index, data, style }) {
|
|
102
|
+
const itemRender = data;
|
|
103
|
+
return itemRender(index, style);
|
|
104
|
+
}
|
|
105
|
+
function Cell({ rowIndex, columnIndex, data, style }) {
|
|
106
|
+
const cellRender = data;
|
|
107
|
+
return cellRender(rowIndex, columnIndex, style);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Virtual Spreadsheet
|
|
111
|
+
*
|
|
112
|
+
* Accepts props defined by {@link VirtualSpreadsheetProps}.
|
|
113
|
+
* You must pass an instance of {@link SpreadsheetData} using the `data` prop.
|
|
114
|
+
* @group Components
|
|
115
|
+
*/
|
|
116
|
+
function VirtualSpreadsheet(props) {
|
|
117
|
+
const { width, height, inputBarHeight = 30, columnHeaderHeight = 50, rowHeaderWidth = 100, theme, data, readOnly = false, minRowCount = 100, minColumnCount = 26, maxRowCount = 1000000000000, maxColumnCount = 1000000000000 } = props;
|
|
118
|
+
const scrollRef = React.useRef(null);
|
|
119
|
+
const focusSinkRef = React.useRef(null);
|
|
120
|
+
// Originally passed data.subscribe.bind(data) to useCallback. It works but React hooks lint fails because it can only validate
|
|
121
|
+
// dependencies for an inline function.
|
|
122
|
+
const subscribeFn = React.useCallback((cb) => data.subscribe(cb), [data]);
|
|
123
|
+
const snapshot = React.useSyncExternalStore(subscribeFn, data.getSnapshot.bind(data), data.getServerSnapshot?.bind(data));
|
|
124
|
+
const [name, setName] = React.useState("");
|
|
125
|
+
const [formula, setFormula] = React.useState("");
|
|
126
|
+
const [cellValue, setCellValue] = React.useState("");
|
|
127
|
+
const [editMode, setEditMode] = React.useState(false);
|
|
128
|
+
const [hwmRowIndex, setHwmRowIndex] = React.useState(0);
|
|
129
|
+
const [hwmColumnIndex, setHwmColumnIndex] = React.useState(0);
|
|
130
|
+
const [selection, setSelection] = React.useState([undefined, undefined]);
|
|
131
|
+
const [focusCell, setFocusCell] = React.useState(null);
|
|
132
|
+
const [[gridRowOffset, gridColumnOffset], setGridScrollState] = React.useState([0, 0]);
|
|
133
|
+
const dataRowCount = data.getRowCount(snapshot);
|
|
134
|
+
const rowCount = Math.max(minRowCount, dataRowCount, hwmRowIndex + 1, focusCell ? focusCell[0] + 1 : 0);
|
|
135
|
+
const rowMapping = data.getRowItemOffsetMapping(snapshot);
|
|
136
|
+
const rowOffset = rowMapping.itemOffset(rowCount);
|
|
137
|
+
const dataColumnCount = data.getColumnCount(snapshot);
|
|
138
|
+
const columnCount = Math.max(minColumnCount, dataColumnCount, hwmColumnIndex + 1, focusCell ? focusCell[1] + 1 : 0);
|
|
139
|
+
const columnMapping = data.getColumnItemOffsetMapping(snapshot);
|
|
140
|
+
const columnOffset = columnMapping.itemOffset(columnCount);
|
|
141
|
+
React.useEffect(() => {
|
|
142
|
+
scrollRef.current?.scrollTo(gridRowOffset, gridColumnOffset);
|
|
143
|
+
}, [gridRowOffset, gridColumnOffset]);
|
|
144
|
+
React.useEffect(() => {
|
|
145
|
+
focusSinkRef.current?.focus({ preventScroll: true });
|
|
146
|
+
}, [focusCell]);
|
|
147
|
+
function onScroll(rowOffsetValue, columnOffsetValue) {
|
|
148
|
+
if (rowOffsetValue == gridRowOffset && columnOffsetValue == gridColumnOffset)
|
|
149
|
+
return;
|
|
150
|
+
if (rowOffsetValue == 0)
|
|
151
|
+
setHwmRowIndex(0);
|
|
152
|
+
else if (scrollRef.current && (rowOffsetValue + scrollRef.current.clientHeight == rowOffset)) {
|
|
153
|
+
// Infinite scrolling if we've reached the end
|
|
154
|
+
if (hwmRowIndex < rowCount && rowCount < maxRowCount)
|
|
155
|
+
setHwmRowIndex(rowCount);
|
|
156
|
+
}
|
|
157
|
+
if (columnOffsetValue == 0)
|
|
158
|
+
setHwmColumnIndex(0);
|
|
159
|
+
else if (scrollRef.current && (columnOffsetValue + scrollRef.current.clientWidth == columnOffset)) {
|
|
160
|
+
// Infinite scrolling if we've reached the end
|
|
161
|
+
if (hwmColumnIndex < columnCount && columnCount < maxColumnCount)
|
|
162
|
+
setHwmColumnIndex(columnCount);
|
|
163
|
+
}
|
|
164
|
+
setGridScrollState([rowOffsetValue, columnOffsetValue]);
|
|
165
|
+
}
|
|
166
|
+
function updateFormula(rowIndex, colIndex, editMode) {
|
|
167
|
+
if (rowIndex < dataRowCount && colIndex < dataColumnCount) {
|
|
168
|
+
const dataValue = data.getCellValue(snapshot, rowIndex, colIndex);
|
|
169
|
+
const format = data.getCellFormat(snapshot, rowIndex, colIndex);
|
|
170
|
+
const value = formatContent(dataValue, format);
|
|
171
|
+
setFormula(value);
|
|
172
|
+
setCellValue(editMode ? value : "");
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
setFormula("");
|
|
176
|
+
setCellValue("");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function updateFocus(rowIndex, colIndex) {
|
|
180
|
+
if (!focusCell || rowIndex != focusCell[0] || colIndex != focusCell[1]) {
|
|
181
|
+
// Reset formula and edit mode only if the focus cell is changing
|
|
182
|
+
updateFormula(rowIndex, colIndex, false);
|
|
183
|
+
setEditMode(false);
|
|
184
|
+
}
|
|
185
|
+
// We use change of focusCell state to trigger effect that gives focus to the focus sink
|
|
186
|
+
// Make sure we always change state, even if focus cell hasn't changed. Any click in grid
|
|
187
|
+
// removes focus from focus sink. Need to make sure it's always given back, even if user
|
|
188
|
+
// clicked on focus cell again.
|
|
189
|
+
setFocusCell([rowIndex, colIndex]);
|
|
190
|
+
}
|
|
191
|
+
function updateSelection(row, col) {
|
|
192
|
+
if (row === undefined && col === undefined) {
|
|
193
|
+
// Clear out and bail if nothing selected
|
|
194
|
+
setFocusCell(null);
|
|
195
|
+
setFormula("");
|
|
196
|
+
setCellValue("");
|
|
197
|
+
setEditMode(false);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (row !== selection[0] || col !== selection[1]) {
|
|
201
|
+
setSelection([row, col]);
|
|
202
|
+
setName(rowColCoordsToRef(row, col));
|
|
203
|
+
}
|
|
204
|
+
const rowIndex = row ? row : 0;
|
|
205
|
+
const colIndex = col ? col : 0;
|
|
206
|
+
updateFocus(rowIndex, colIndex);
|
|
207
|
+
}
|
|
208
|
+
function ensureVisible(row, col) {
|
|
209
|
+
const scroll = scrollRef.current;
|
|
210
|
+
if (!scroll)
|
|
211
|
+
return;
|
|
212
|
+
// Implements same logic as VirtualScrollProxy.scrollToArea so that we can directly update our grid scroll state.
|
|
213
|
+
// React 18+ gives scroll events a lower priority than discrete events like key and mouse clicks. If we use
|
|
214
|
+
// scrollToArea + OnScroll callback we can end up with other state changes being rendered immediately with the
|
|
215
|
+
// scroll related changes being rendered a frame later.
|
|
216
|
+
// Scroll bar position is synchronized with state in an effect post render.
|
|
217
|
+
const rowRange = getRangeToScroll(row, rowMapping);
|
|
218
|
+
const colRange = getRangeToScroll(col, columnMapping);
|
|
219
|
+
const newRowOffset = getOffsetToScrollRange(...rowRange, scroll.clientHeight, gridRowOffset, 'visible');
|
|
220
|
+
const newColOffset = getOffsetToScrollRange(...colRange, scroll.clientWidth, gridColumnOffset, 'visible');
|
|
221
|
+
if (newRowOffset !== undefined || newColOffset !== undefined) {
|
|
222
|
+
setGridScrollState([(newRowOffset === undefined) ? gridRowOffset : newRowOffset, (newColOffset === undefined) ? gridColumnOffset : newColOffset]);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Is cell in selected row or column?
|
|
226
|
+
function isInSelection(row, col) {
|
|
227
|
+
if (row === undefined || col === undefined)
|
|
228
|
+
return false;
|
|
229
|
+
return (selection[0] === undefined && col === selection[1]) ||
|
|
230
|
+
(selection[1] === undefined && row === selection[0]);
|
|
231
|
+
}
|
|
232
|
+
// Expands grid as needed for target cell
|
|
233
|
+
function selectItem(row, col, keepSelection) {
|
|
234
|
+
if (row !== undefined) {
|
|
235
|
+
if (row < 0)
|
|
236
|
+
return;
|
|
237
|
+
if (row >= maxRowCount)
|
|
238
|
+
row = maxRowCount - 1;
|
|
239
|
+
if (row > hwmRowIndex) {
|
|
240
|
+
setHwmRowIndex(row);
|
|
241
|
+
}
|
|
242
|
+
else if (row == 0)
|
|
243
|
+
setHwmRowIndex(0);
|
|
244
|
+
}
|
|
245
|
+
if (col !== undefined) {
|
|
246
|
+
if (col < 0)
|
|
247
|
+
return;
|
|
248
|
+
if (col >= maxColumnCount)
|
|
249
|
+
col = maxColumnCount - 1;
|
|
250
|
+
if (col > hwmColumnIndex) {
|
|
251
|
+
setHwmColumnIndex(col);
|
|
252
|
+
}
|
|
253
|
+
else if (col == 0)
|
|
254
|
+
setHwmColumnIndex(0);
|
|
255
|
+
}
|
|
256
|
+
// If desired and possible move focus within existing selection rather than changing selection
|
|
257
|
+
if (keepSelection && isInSelection(row, col)) {
|
|
258
|
+
const rowIndex = row ? row : 0;
|
|
259
|
+
const colIndex = col ? col : 0;
|
|
260
|
+
updateFocus(rowIndex, colIndex);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
updateSelection(row, col);
|
|
264
|
+
}
|
|
265
|
+
ensureVisible(row, col);
|
|
266
|
+
}
|
|
267
|
+
// Move on to next cell.
|
|
268
|
+
// Moves within selected row or column. If none moves vertically if isVertical otherwise horizontally.
|
|
269
|
+
// Move backwards (left/dup) if isBackwards, otherwise forwards
|
|
270
|
+
function nextCell(row, col, isVertical, isBackwards) {
|
|
271
|
+
if (selection[0] === undefined && selection[1] === undefined)
|
|
272
|
+
return;
|
|
273
|
+
const offset = isBackwards ? -1 : 1;
|
|
274
|
+
if (selection[0] === undefined) {
|
|
275
|
+
// Column selected - move vertically within existing selection
|
|
276
|
+
selectItem(row + offset, col, true);
|
|
277
|
+
}
|
|
278
|
+
else if (selection[1] === undefined) {
|
|
279
|
+
// Row selected - move horizontally within existing selection
|
|
280
|
+
selectItem(row, col + offset, true);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
// Cell selected
|
|
284
|
+
if (isVertical)
|
|
285
|
+
selectItem(row + offset, col);
|
|
286
|
+
else
|
|
287
|
+
selectItem(row, col + offset);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function onNameKeyUp(event) {
|
|
291
|
+
if (event.key !== "Enter")
|
|
292
|
+
return;
|
|
293
|
+
const [row, col] = rowColRefToCoords(name);
|
|
294
|
+
selectItem(row, col);
|
|
295
|
+
}
|
|
296
|
+
function CommitFormulaChange(rowIndex, colIndex) {
|
|
297
|
+
let value = undefined;
|
|
298
|
+
let format = undefined;
|
|
299
|
+
const parseData = numfmt.parseValue(formula);
|
|
300
|
+
if (parseData) {
|
|
301
|
+
// number or boolean
|
|
302
|
+
value = parseData.v;
|
|
303
|
+
format = parseData.z;
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
// string
|
|
307
|
+
value = formula;
|
|
308
|
+
}
|
|
309
|
+
data.setCellValueAndFormat(rowIndex, colIndex, value, format);
|
|
310
|
+
}
|
|
311
|
+
// Used by both formula and focus sink input fields
|
|
312
|
+
function onEditValueKeyDown(event) {
|
|
313
|
+
if (!focusCell)
|
|
314
|
+
return;
|
|
315
|
+
const row = focusCell[0];
|
|
316
|
+
const col = focusCell[1];
|
|
317
|
+
if (editMode) {
|
|
318
|
+
switch (event.key) {
|
|
319
|
+
case "Escape":
|
|
320
|
+
{
|
|
321
|
+
updateFormula(row, col, false);
|
|
322
|
+
setEditMode(false);
|
|
323
|
+
setFocusCell([row, col]);
|
|
324
|
+
}
|
|
325
|
+
break;
|
|
326
|
+
case "Enter":
|
|
327
|
+
{
|
|
328
|
+
CommitFormulaChange(row, col);
|
|
329
|
+
updateFormula(row, col, false);
|
|
330
|
+
setEditMode(false);
|
|
331
|
+
nextCell(row, col, true, event.shiftKey);
|
|
332
|
+
}
|
|
333
|
+
break;
|
|
334
|
+
case "Tab":
|
|
335
|
+
{
|
|
336
|
+
CommitFormulaChange(row, col);
|
|
337
|
+
updateFormula(row, col, false);
|
|
338
|
+
setEditMode(false);
|
|
339
|
+
nextCell(row, col, false, event.shiftKey);
|
|
340
|
+
event.preventDefault();
|
|
341
|
+
}
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
switch (event.key) {
|
|
347
|
+
case "ArrowDown":
|
|
348
|
+
{
|
|
349
|
+
selectItem(row + 1, col);
|
|
350
|
+
event.preventDefault();
|
|
351
|
+
}
|
|
352
|
+
break;
|
|
353
|
+
case "ArrowUp":
|
|
354
|
+
{
|
|
355
|
+
selectItem(row - 1, col);
|
|
356
|
+
event.preventDefault();
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
359
|
+
case "ArrowLeft":
|
|
360
|
+
{
|
|
361
|
+
selectItem(row, col - 1);
|
|
362
|
+
event.preventDefault();
|
|
363
|
+
}
|
|
364
|
+
break;
|
|
365
|
+
case "ArrowRight":
|
|
366
|
+
{
|
|
367
|
+
selectItem(row, col + 1);
|
|
368
|
+
event.preventDefault();
|
|
369
|
+
}
|
|
370
|
+
break;
|
|
371
|
+
case "Tab":
|
|
372
|
+
{
|
|
373
|
+
nextCell(row, col, false, event.shiftKey);
|
|
374
|
+
event.preventDefault();
|
|
375
|
+
}
|
|
376
|
+
break;
|
|
377
|
+
case "Enter":
|
|
378
|
+
{
|
|
379
|
+
if (isInSelection(row, col)) {
|
|
380
|
+
nextCell(row, col, true, event.shiftKey);
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
updateFormula(row, col, true);
|
|
384
|
+
if (readOnly)
|
|
385
|
+
nextCell(row, col, true, event.shiftKey);
|
|
386
|
+
else
|
|
387
|
+
setEditMode(true);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
function colSelected(index) { return (selection[0] == undefined && selection[1] == index); }
|
|
395
|
+
function colCellSelected(index) {
|
|
396
|
+
return (selection[0] != undefined) && (selection[1] == undefined || selection[1] == index);
|
|
397
|
+
}
|
|
398
|
+
function rowSelected(index) { return (selection[0] == index && selection[1] == undefined); }
|
|
399
|
+
function rowCellSelected(index) {
|
|
400
|
+
return (selection[1] != undefined) && (selection[0] == undefined || selection[0] == index);
|
|
401
|
+
}
|
|
402
|
+
const colHeaderRender = ({ ...rest }, ref) => (jsx("div", { ref: ref, onClick: (event) => {
|
|
403
|
+
const [x, _] = getCurrentTargetXY(event);
|
|
404
|
+
const colOffset = x + gridColumnOffset;
|
|
405
|
+
const [colIndex] = columnMapping.offsetToItem(colOffset);
|
|
406
|
+
updateSelection(undefined, colIndex);
|
|
407
|
+
}, ...rest }));
|
|
408
|
+
const rowHeaderRender = ({ ...rest }, ref) => (jsx("div", { ref: ref, onClick: (event) => {
|
|
409
|
+
const [_, y] = getCurrentTargetXY(event);
|
|
410
|
+
const rowOffset = y + gridRowOffset;
|
|
411
|
+
const [rowIndex] = rowMapping.offsetToItem(rowOffset);
|
|
412
|
+
updateSelection(rowIndex, undefined);
|
|
413
|
+
}, ...rest }));
|
|
414
|
+
const colRender = (index, style) => (jsx("div", { className: join(theme?.VirtualSpreadsheet_Column, ifdef(colSelected(index), theme?.VirtualSpreadsheet_Column__Selected), ifdef(colCellSelected(index), theme?.VirtualSpreadsheet_Column__CellSelected)), style: style, children: indexToColRef(index) }));
|
|
415
|
+
const rowRender = (index, style) => (jsx("div", { className: join(theme?.VirtualSpreadsheet_Row, ifdef(rowSelected(index), theme?.VirtualSpreadsheet_Row__Selected), ifdef(rowCellSelected(index), theme?.VirtualSpreadsheet_Row__CellSelected)), style: style, children: index + 1 }));
|
|
416
|
+
const outerGridRender = ({ children, ...rest }, ref) => {
|
|
417
|
+
let focusSink;
|
|
418
|
+
if (focusCell) {
|
|
419
|
+
const row = focusCell[0];
|
|
420
|
+
const col = focusCell[1];
|
|
421
|
+
// Position focus sink underneath focused cell. If outside viewport clamp position.
|
|
422
|
+
// Careful - focus cell might be bigger than the viewport!
|
|
423
|
+
const focusHeight = rowMapping.itemSize(row);
|
|
424
|
+
let focusTop = rowMapping.itemOffset(row) - gridRowOffset;
|
|
425
|
+
if (focusTop < -focusHeight)
|
|
426
|
+
focusTop = -focusHeight;
|
|
427
|
+
else if (focusTop > height)
|
|
428
|
+
focusTop = height;
|
|
429
|
+
const focusWidth = columnMapping.itemSize(col);
|
|
430
|
+
let focusLeft = columnMapping.itemOffset(col) - gridColumnOffset;
|
|
431
|
+
if (focusLeft < -focusWidth)
|
|
432
|
+
focusLeft = -focusWidth;
|
|
433
|
+
else if (focusLeft > width)
|
|
434
|
+
focusLeft = width;
|
|
435
|
+
// Browser will try and bring focus sink into view in various scenarios like text being typed or user
|
|
436
|
+
// giving it focus by tabbing between fields. All browsers I tested make a horrible mess of things
|
|
437
|
+
// due to the sticky positioning. Need to use my own ensureVisible method to clean up.
|
|
438
|
+
focusSink = jsx("input", { ref: focusSinkRef, className: join(theme?.VirtualSpreadsheet_Cell, theme?.VirtualSpreadsheet_Cell__Focus), type: "text", name: "edit", title: "Edit", readOnly: readOnly, value: cellValue, onChange: (event) => {
|
|
439
|
+
setCellValue(event.target?.value);
|
|
440
|
+
setEditMode(!readOnly);
|
|
441
|
+
setFormula(event.target?.value);
|
|
442
|
+
}, onFocus: () => { ensureVisible(row, col); }, onBeforeInput: () => { ensureVisible(row, col); }, onKeyDown: onEditValueKeyDown, style: { zIndex: editMode ? 1 : -1, position: "absolute", top: focusTop, height: focusHeight, left: focusLeft, width: focusWidth } });
|
|
443
|
+
}
|
|
444
|
+
return jsxs("div", { ref: ref, onClick: (event) => {
|
|
445
|
+
const [x, y] = getCurrentTargetXY(event);
|
|
446
|
+
const colOffset = x + gridColumnOffset;
|
|
447
|
+
const rowOffset = y + gridRowOffset;
|
|
448
|
+
const [rowIndex] = rowMapping.offsetToItem(rowOffset);
|
|
449
|
+
const [colIndex] = columnMapping.offsetToItem(colOffset);
|
|
450
|
+
updateSelection(rowIndex, colIndex);
|
|
451
|
+
}, onDoubleClick: (_event) => {
|
|
452
|
+
setCellValue(formula);
|
|
453
|
+
setEditMode(!readOnly);
|
|
454
|
+
}, ...rest, children: [children, focusSink] });
|
|
455
|
+
};
|
|
456
|
+
const cellRender = (rowIndex, columnIndex, style) => {
|
|
457
|
+
let dataValue = undefined;
|
|
458
|
+
let value = "";
|
|
459
|
+
if (rowIndex < dataRowCount && columnIndex < dataColumnCount) {
|
|
460
|
+
dataValue = data.getCellValue(snapshot, rowIndex, columnIndex);
|
|
461
|
+
const format = data.getCellFormat(snapshot, rowIndex, columnIndex);
|
|
462
|
+
value = formatContent(dataValue, format);
|
|
463
|
+
}
|
|
464
|
+
const focused = focusCell && rowIndex == focusCell[0] && columnIndex == focusCell[1];
|
|
465
|
+
const classNames = join(theme?.VirtualSpreadsheet_Cell, ifdef(rowSelected(rowIndex), theme?.VirtualSpreadsheet_Cell__RowSelected), ifdef(colSelected(columnIndex), theme?.VirtualSpreadsheet_Cell__ColumnSelected), classForType(dataValue), ifdef(focused, theme?.VirtualSpreadsheet_Cell__Focus));
|
|
466
|
+
return jsx("div", { className: classNames, style: style, children: value });
|
|
467
|
+
};
|
|
468
|
+
const columnTemplate = `${rowHeaderWidth}px 1fr`;
|
|
469
|
+
const rowTemplate = `${inputBarHeight}px ${columnHeaderHeight}px 1fr`;
|
|
470
|
+
const minWidth = rowHeaderWidth * 2;
|
|
471
|
+
const minHeight = inputBarHeight + columnHeaderHeight * 2;
|
|
472
|
+
const gridWidth = Math.max(width - rowHeaderWidth, rowHeaderWidth);
|
|
473
|
+
const gridHeight = Math.max(height - columnHeaderHeight - inputBarHeight, columnHeaderHeight);
|
|
474
|
+
return (jsxs("div", { className: join(props.className, theme?.VirtualSpreadsheet), style: { width, height, minWidth, minHeight, display: "grid", gridTemplateColumns: columnTemplate, gridTemplateRows: rowTemplate }, children: [jsxs("div", { className: theme?.VirtualSpreadsheet_InputBar, style: { overflow: 'hidden', display: 'flex', gridColumnStart: 1, gridColumnEnd: 3 }, children: [jsx("input", { className: theme?.VirtualSpreadsheet_Name, type: "text", name: "name", title: "Name", value: name, size: 20, onChange: (event) => {
|
|
475
|
+
setName(event.target?.value);
|
|
476
|
+
}, onKeyUp: onNameKeyUp }), jsx("label", { className: theme?.VirtualSpreadsheet_Fx, children: "fx" }), jsx("input", { className: theme?.VirtualSpreadsheet_Formula, style: { flexGrow: 1 }, type: "text", readOnly: readOnly, name: "formula", title: "Formula", value: formula, onChange: (event) => {
|
|
477
|
+
setFormula(event.target?.value);
|
|
478
|
+
setEditMode(!readOnly);
|
|
479
|
+
if (focusCell)
|
|
480
|
+
setCellValue(event.target?.value);
|
|
481
|
+
}, onFocus: () => {
|
|
482
|
+
if (focusCell) {
|
|
483
|
+
setCellValue(formula);
|
|
484
|
+
setEditMode(!readOnly);
|
|
485
|
+
}
|
|
486
|
+
}, onKeyDown: onEditValueKeyDown })] }), jsx("div", { className: theme?.VirtualSpreadsheet_CornerHeader }), jsx(DisplayList, { offset: gridColumnOffset, className: theme?.VirtualSpreadsheet_ColumnHeader, itemData: colRender, outerRender: colHeaderRender, height: columnHeaderHeight, itemCount: columnCount, itemOffsetMapping: columnMapping, layout: 'horizontal', width: gridWidth, children: HeaderItem }), jsx(DisplayList, { offset: gridRowOffset, className: theme?.VirtualSpreadsheet_RowHeader, itemData: rowRender, outerRender: rowHeaderRender, height: gridHeight, itemCount: rowCount, itemOffsetMapping: rowMapping, width: rowHeaderWidth, children: HeaderItem }), jsx(VirtualScroll, { className: theme?.VirtualSpreadsheet_Grid, ref: scrollRef, onScroll: onScroll, height: gridHeight, width: gridWidth, scrollHeight: rowOffset, scrollWidth: columnOffset, useOffsets: false, maxCssSize: props.maxCssSize, minNumPages: props.minNumPages, children: (_) => (jsx(AutoSizer, { style: { height: '100%', width: '100%' }, children: ({ height, width }) => (jsx(DisplayGrid, { rowOffset: gridRowOffset, columnOffset: gridColumnOffset, height: height, width: width, itemData: cellRender, outerRender: outerGridRender, rowCount: rowCount, rowOffsetMapping: rowMapping, columnCount: columnCount, columnOffsetMapping: columnMapping, children: Cell })) })) })] }));
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export { VirtualSpreadsheet, VirtualSpreadsheetDefaultTheme };
|
|
490
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/VirtualSpreadsheetTheme.ts","../src/VirtualSpreadsheet.tsx"],"sourcesContent":["/**\n * Theme that defines class names for all DOM elements within {@link VirtualSpreadsheet}. Provide an appropriate\n * theme to use VirtualSpreadsheet with whatever CSS management system you prefer.\n * \n * Properties are named using a BEM style with the form `ComponentName_ElementName__modifierName_modifierValue`\n */\nexport interface VirtualSpreadsheetTheme {\n /** Class applied to the overall component */\n VirtualSpreadsheet: string,\n\n /** Class applied to the input bar at the top of the component */\n VirtualSpreadsheet_InputBar: string,\n\n /** Class applied to the Name input on the left end of the input bar */\n VirtualSpreadsheet_Name: string,\n\n /** Class applied to the \"fx\" label in the input bar */\n VirtualSpreadsheet_Fx: string,\n\n /** Class applied to the Formula input on the right end of the input bar */\n VirtualSpreadsheet_Formula: string,\n\n /** Class applied to the grid of cells */\n VirtualSpreadsheet_Grid: string,\n\n /** Class applied to the top left corner where the row and column headers meet */\n VirtualSpreadsheet_CornerHeader: string,\n\n /** Class applied to the column header */\n VirtualSpreadsheet_ColumnHeader: string,\n\n /** Class applied to an individual column within the column header */\n VirtualSpreadsheet_Column: string,\n\n /** Modifier class applied to a column when it's selected */\n VirtualSpreadsheet_Column__Selected: string,\n\n /** Modifier class applied to a column when a cell in that column is selected */\n VirtualSpreadsheet_Column__CellSelected: string,\n\n /** Class applied to the row header */\n VirtualSpreadsheet_RowHeader: string,\n\n /** Class applied to an individual row within the row header */\n VirtualSpreadsheet_Row: string,\n\n /** Modifier class applied to a row when it's selected */\n VirtualSpreadsheet_Row__Selected: string,\n\n /** Modifier class applied to a row when a cell in that row is selected */\n VirtualSpreadsheet_Row__CellSelected: string,\n\n /** Class applied to a cell within the grid*/ \n VirtualSpreadsheet_Cell: string,\n\n /** Modifier class applied to a cell when it contains a string value */\n VirtualSpreadsheet_Cell__Type_string: string,\n\n /** Modifier class applied to a cell when it contains a number value */\n VirtualSpreadsheet_Cell__Type_number: string,\n\n /** Modifier class applied to a cell when it contains a boolean value */\n VirtualSpreadsheet_Cell__Type_boolean: string,\n\n /** Modifier class applied to a cell when it contains a null value */\n VirtualSpreadsheet_Cell__Type_null: string,\n\n /** Modifier class applied to a cell when it contains an undefined value */\n VirtualSpreadsheet_Cell__Type_undefined: string,\n\n /** Modifier class applied to a cell when it contains an error value */\n VirtualSpreadsheet_Cell__Type_CellError: string,\n\n /** Modifier class applied to a cell when it has the focus */\n VirtualSpreadsheet_Cell__Focus: string,\n\n /** Modifier class applied to a cell when it's within a selected row */\n VirtualSpreadsheet_Cell__RowSelected: string,\n\n /** Modifier class applied to a cell when it's within a selected column */\n VirtualSpreadsheet_Cell__ColumnSelected: string,\n}\n\n/** Default implementation of theme provided by `VirtualSpreadsheet.css` */\nexport const VirtualSpreadsheetDefaultTheme: VirtualSpreadsheetTheme = {\n VirtualSpreadsheet: \"VirtualSpreadsheet\",\n VirtualSpreadsheet_InputBar: \"VirtualSpreadsheet_InputBar\",\n VirtualSpreadsheet_Name: \"VirtualSpreadsheet_Name\",\n VirtualSpreadsheet_Fx: \"VirtualSpreadsheet_Fx\",\n VirtualSpreadsheet_Formula: \"VirtualSpreadsheet_Formula\",\n VirtualSpreadsheet_Grid: \"VirtualSpreadsheet_Grid\",\n VirtualSpreadsheet_CornerHeader: \"VirtualSpreadsheet_CornerHeader\",\n VirtualSpreadsheet_ColumnHeader: \"VirtualSpreadsheet_ColumnHeader\",\n VirtualSpreadsheet_Column: \"VirtualSpreadsheet_Column\",\n VirtualSpreadsheet_Column__Selected: \"VirtualSpreadsheet_Column__Selected\",\n VirtualSpreadsheet_Column__CellSelected: \"VirtualSpreadsheet_Column__CellSelected\",\n VirtualSpreadsheet_RowHeader: \"VirtualSpreadsheet_RowHeader\",\n VirtualSpreadsheet_Row: \"VirtualSpreadsheet_Row\",\n VirtualSpreadsheet_Row__Selected: \"VirtualSpreadsheet_Row__Selected\",\n VirtualSpreadsheet_Row__CellSelected: \"VirtualSpreadsheet_Row__CellSelected\",\n VirtualSpreadsheet_Cell: \"VirtualSpreadsheet_Cell\",\n VirtualSpreadsheet_Cell__Type_string: \"VirtualSpreadsheet_Cell__Type_string\",\n VirtualSpreadsheet_Cell__Type_number: \"VirtualSpreadsheet_Cell__Type_number\",\n VirtualSpreadsheet_Cell__Type_boolean: \"VirtualSpreadsheet_Cell__Type_boolean\",\n VirtualSpreadsheet_Cell__Type_null: \"VirtualSpreadsheet_Cell__Type_null\",\n VirtualSpreadsheet_Cell__Type_undefined: \"VirtualSpreadsheet_Cell__Type_undefined\",\n VirtualSpreadsheet_Cell__Type_CellError: \"VirtualSpreadsheet_Cell__Type_CellError\",\n VirtualSpreadsheet_Cell__Focus: \"VirtualSpreadsheet_Cell__Focus\",\n VirtualSpreadsheet_Cell__RowSelected: \"VirtualSpreadsheet_Cell__RowSelected\",\n VirtualSpreadsheet_Cell__ColumnSelected: \"VirtualSpreadsheet_Cell__ColumnSelected\"\n}\n","import React from 'react';\nimport { DisplayList, DisplayGrid, AutoSizer, VirtualContainerRender, VirtualScroll, VirtualScrollProxy,\n getRangeToScroll, getOffsetToScrollRange } from '@candidstartup/react-virtual-scroll';\nimport type { VirtualSpreadsheetTheme } from './VirtualSpreadsheetTheme';\nimport { SpreadsheetData, CellValue, indexToColRef, RowColCoords, rowColRefToCoords, rowColCoordsToRef } from '@candidstartup/infinisheet-types'\nimport * as numfmt from 'numfmt'\n\n/** Extension of {@link SpreadsheetData} interface so that it's compatible with React's `useSyncExternalStore` hook\n * \n * Additional properties are optional, so anything that implements `SpreadsheetData` is compatible with something\n * that accepts `ReactSpreadsheetData`.\n */\nexport interface ReactSpreadsheetData<Snapshot> extends SpreadsheetData<Snapshot> {\n /** Used by `useSyncExternalStore` to support server side rendering */\n getServerSnapshot?: () => Snapshot\n}\n\n/**\n * Props for {@link VirtualSpreadsheet}\n */\nexport interface VirtualSpreadsheetProps<Snapshot> {\n /** The `className` applied to the spreadsheet as a whole */\n className?: string,\n\n /** Spreadsheet theme which defines the CSS classes to apply\n * \n * Defined as a union so that it supports both hand written themes\n * defined as implementations of {@link VirtualSpreadsheetTheme} and themes\n * implicitly defined by importing a CSS module. \n */\n theme?: VirtualSpreadsheetTheme | Record<string, string>,\n\n /** Component height */\n height: number,\n\n /** Component width */\n width: number,\n\n /** Height of input bar\n * @defaultValue 30\n */\n inputBarHeight?: number,\n\n /** Height of column header\n * @defaultValue 50\n */\n columnHeaderHeight?: number,\n\n /** Width of row header\n * @defaultValue 100\n */\n rowHeaderWidth?: number,\n\n /** Data to display and edit */\n data: ReactSpreadsheetData<Snapshot>,\n\n /** Disables edit mode if true\n * @defaultValue false\n */\n readOnly?: boolean, \n\n /** Minimum number of rows in the spreadsheet \n * @defaultValue 100\n */\n minRowCount?: number,\n\n /** Maximum number of rows in the spreadsheet \n * @defaultValue 1000000000000\n */\n maxRowCount?: number,\n\n /** Minimum number of columns in the grid \n * @defaultValue 26\n */\n minColumnCount?: number,\n\n /** Maximum umber of columns in the grid \n * @defaultValue 1000000000000\n */\n maxColumnCount?: number,\n\n /** \n * Maximum size for CSS element beyond which layout breaks. You should never normally need to change this. \n * The default value is compatible with all major browsers.\n * \n * @defaultValue 6000000\n * */\n maxCssSize?: number,\n\n /**\n * The minimum number of virtual pages to use when inner container would otherwise be more than {@link VirtualSpreadsheetProps.maxCssSize} big.\n * You should never normally need to change this.\n * \n * @defaultValue 100\n */\n minNumPages?: number\n}\n\nfunction join(...v: (string|undefined)[]) {\n let s: string|undefined = undefined;\n v.forEach(a => {\n if (s && a)\n s = s + ' ' + a;\n else if (a)\n s = a;\n });\n return s;\n}\n\nfunction ifdef(b: boolean|null, s: string|undefined) { return (b) ? s : undefined }\n\n// Options for numfmt that match Google Sheets and ECMA-376 behavior. This is compatible with supported dates in Excel apart from Jan/Feb 1900. \n// This is due to Excel's backwards compatibility support for the Lotus 1-2-3 leap year bug that incorrectly thinks 1900 is a leap year.\nconst numfmtOptions = {\n leap1900: false,\n dateSpanLarge: true\n}\n\nfunction formatContent(value: CellValue, format: string | undefined): string {\n if (value === null || value === undefined)\n return \"\";\n\n if (typeof value === 'object')\n return value.value;\n\n if (typeof value === 'string' && value[0] == '\\'') {\n // Leading apostrophe means display rest of string as is\n return value.substring(1);\n }\n\n if (format === undefined)\n format = \"\";\n\n return numfmt.format(format, value, numfmtOptions);\n}\n\nfunction classForType(value: CellValue) {\n if (value === null)\n return 'VirtualSpreadsheet_Cell__Type_null';\n if (value === undefined)\n return 'VirtualSpreadsheet_Cell__Type_undefined';\n\n const type = typeof value;\n if (type === 'object')\n return 'VirtualSpreadsheet_Cell__Type_CellError';\n\n return 'VirtualSpreadsheet_Cell__Type_' + type;\n}\n\nfunction inRect(x: number, y: number, rect: DOMRect) {\n return (x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom);\n}\n\n// Return mouse coordinates in space of current event target. Not directly available so we convert\n// using client coordinates.\nfunction getCurrentTargetXY(event: React.MouseEvent<HTMLDivElement>): [number,number] {\n let clientX = event.clientX;\n let clientY = event.clientY;\n if (event.target !== event.currentTarget) {\n const target = event.target as Element;\n const targetRect = target.getBoundingClientRect();\n if (!inRect(clientX, clientY, targetRect))\n {\n // Sometimes get events with bogus client XY, often generated by some form of automation\n // If this happens behave as if middle of target rect was clicked\n clientX = (targetRect.left + targetRect.right) / 2;\n clientY = (targetRect.top + targetRect.bottom) / 2;\n }\n }\n\n const currentRect = event.currentTarget.getBoundingClientRect();\n if (!inRect(clientX, clientY, currentRect)) {\n // Somethings gone horribly wrong\n return [0,0];\n }\n\n return [clientX - currentRect.left, clientY - currentRect.top];\n}\n\ntype HeaderItemRender = (index: number, style: React.CSSProperties) => JSX.Element;\nfunction HeaderItem({ index, data, style }: { index: number, data:unknown, style: React.CSSProperties }) {\n const itemRender = data as HeaderItemRender;\n return itemRender(index, style);\n}\n\ntype CellRender = (rowIndex: number, columnIndex: number, style: React.CSSProperties) => JSX.Element;\nfunction Cell({ rowIndex, columnIndex, data, style }: { rowIndex: number, columnIndex: number, data: unknown, style: React.CSSProperties }) {\n const cellRender = data as CellRender;\n return cellRender(rowIndex, columnIndex, style);\n}\n\n/**\n * Virtual Spreadsheet\n * \n * Accepts props defined by {@link VirtualSpreadsheetProps}. \n * You must pass an instance of {@link SpreadsheetData} using the `data` prop. \n * @group Components\n */\nexport function VirtualSpreadsheet<Snapshot>(props: VirtualSpreadsheetProps<Snapshot>) {\n const { width, height, inputBarHeight=30, columnHeaderHeight=50, rowHeaderWidth=100,\n theme, data, readOnly=false, minRowCount=100, minColumnCount=26, maxRowCount=1000000000000, maxColumnCount=1000000000000 } = props;\n const scrollRef = React.useRef<VirtualScrollProxy>(null);\n const focusSinkRef = React.useRef<HTMLInputElement>(null);\n\n // Originally passed data.subscribe.bind(data) to useCallback. It works but React hooks lint fails because it can only validate\n // dependencies for an inline function.\n const subscribeFn = React.useCallback((cb: () => void) => data.subscribe(cb), [data]); \n const snapshot = React.useSyncExternalStore<Snapshot>(subscribeFn, data.getSnapshot.bind(data), data.getServerSnapshot?.bind(data));\n\n const [name, setName] = React.useState(\"\");\n const [formula, setFormula] = React.useState(\"\");\n const [cellValue, setCellValue] = React.useState(\"\");\n const [editMode, setEditMode] = React.useState(false);\n const [hwmRowIndex, setHwmRowIndex] = React.useState(0);\n const [hwmColumnIndex, setHwmColumnIndex] = React.useState(0);\n const [selection, setSelection] = React.useState<RowColCoords>([undefined,undefined]);\n const [focusCell, setFocusCell] = React.useState<[number,number]|null>(null);\n const [[gridRowOffset, gridColumnOffset], setGridScrollState] = React.useState<[number,number]>([0, 0]);\n\n const dataRowCount = data.getRowCount(snapshot);\n const rowCount = Math.max(minRowCount, dataRowCount, hwmRowIndex+1, focusCell ? focusCell[0]+1 : 0);\n const rowMapping = data.getRowItemOffsetMapping(snapshot);\n const rowOffset = rowMapping.itemOffset(rowCount);\n const dataColumnCount = data.getColumnCount(snapshot);\n const columnCount = Math.max(minColumnCount, dataColumnCount, hwmColumnIndex+1, focusCell ? focusCell[1]+1 : 0);\n const columnMapping = data.getColumnItemOffsetMapping(snapshot);\n const columnOffset = columnMapping.itemOffset(columnCount);\n\n React.useEffect(() => {\n scrollRef.current?.scrollTo(gridRowOffset, gridColumnOffset);\n }, [gridRowOffset, gridColumnOffset])\n\n React.useEffect(() => {\n focusSinkRef.current?.focus({preventScroll: true})\n }, [focusCell])\n\n function onScroll(rowOffsetValue: number, columnOffsetValue: number) {\n if (rowOffsetValue == gridRowOffset && columnOffsetValue == gridColumnOffset)\n return;\n\n if (rowOffsetValue == 0)\n setHwmRowIndex(0);\n else if (scrollRef.current && (rowOffsetValue + scrollRef.current.clientHeight == rowOffset)) {\n // Infinite scrolling if we've reached the end\n if (hwmRowIndex < rowCount && rowCount < maxRowCount)\n setHwmRowIndex(rowCount);\n }\n\n if (columnOffsetValue == 0)\n setHwmColumnIndex(0);\n else if (scrollRef.current && (columnOffsetValue + scrollRef.current.clientWidth == columnOffset)) {\n // Infinite scrolling if we've reached the end\n if (hwmColumnIndex < columnCount && columnCount < maxColumnCount)\n setHwmColumnIndex(columnCount);\n }\n\n setGridScrollState([rowOffsetValue, columnOffsetValue]);\n }\n\n function updateFormula(rowIndex: number, colIndex: number, editMode: boolean) {\n if (rowIndex < dataRowCount && colIndex < dataColumnCount) {\n const dataValue = data.getCellValue(snapshot, rowIndex, colIndex);\n const format = data.getCellFormat(snapshot, rowIndex, colIndex);\n const value = formatContent(dataValue, format);\n setFormula(value);\n setCellValue(editMode ? value : \"\");\n } else {\n setFormula(\"\");\n setCellValue(\"\");\n }\n }\n\n function updateFocus(rowIndex: number, colIndex: number) {\n if (!focusCell || rowIndex != focusCell[0] || colIndex != focusCell[1]) {\n // Reset formula and edit mode only if the focus cell is changing\n updateFormula(rowIndex, colIndex, false);\n setEditMode(false);\n }\n\n // We use change of focusCell state to trigger effect that gives focus to the focus sink\n // Make sure we always change state, even if focus cell hasn't changed. Any click in grid\n // removes focus from focus sink. Need to make sure it's always given back, even if user\n // clicked on focus cell again. \n setFocusCell([rowIndex, colIndex]);\n }\n\n function updateSelection(row: number|undefined, col: number|undefined) {\n if (row === undefined && col === undefined) {\n // Clear out and bail if nothing selected\n setFocusCell(null);\n setFormula(\"\");\n setCellValue(\"\");\n setEditMode(false);\n return;\n }\n\n if (row !== selection[0] || col !== selection[1]) {\n setSelection([row,col]);\n setName(rowColCoordsToRef(row,col));\n }\n\n const rowIndex = row ? row : 0;\n const colIndex = col ? col : 0;\n updateFocus(rowIndex, colIndex);\n }\n\n function ensureVisible(row: number|undefined, col: number|undefined) {\n const scroll = scrollRef.current;\n if (!scroll)\n return;\n\n // Implements same logic as VirtualScrollProxy.scrollToArea so that we can directly update our grid scroll state.\n // React 18+ gives scroll events a lower priority than discrete events like key and mouse clicks. If we use\n // scrollToArea + OnScroll callback we can end up with other state changes being rendered immediately with the\n // scroll related changes being rendered a frame later. \n // Scroll bar position is synchronized with state in an effect post render.\n const rowRange = getRangeToScroll(row, rowMapping);\n const colRange = getRangeToScroll(col, columnMapping);\n\n const newRowOffset = getOffsetToScrollRange(...rowRange, scroll.clientHeight, gridRowOffset, 'visible');\n const newColOffset = getOffsetToScrollRange(...colRange, scroll.clientWidth, gridColumnOffset, 'visible');\n if (newRowOffset !== undefined || newColOffset !== undefined) {\n setGridScrollState([(newRowOffset === undefined) ? gridRowOffset : newRowOffset, (newColOffset === undefined) ? gridColumnOffset : newColOffset]);\n }\n }\n\n // Is cell in selected row or column?\n function isInSelection(row: number|undefined, col: number|undefined): boolean {\n if (row === undefined || col === undefined)\n return false;\n\n return (selection[0] === undefined && col === selection[1]) ||\n (selection[1] === undefined && row === selection[0]);\n }\n\n // Expands grid as needed for target cell\n function selectItem(row: number|undefined, col: number|undefined, keepSelection?: boolean) {\n if (row !== undefined) {\n if (row < 0)\n return;\n if (row >= maxRowCount)\n row = maxRowCount - 1;\n if (row > hwmRowIndex) {\n setHwmRowIndex(row);\n } else if (row == 0)\n setHwmRowIndex(0);\n }\n\n if (col !== undefined) {\n if (col < 0)\n return;\n if (col >= maxColumnCount)\n col = maxColumnCount - 1;\n if (col > hwmColumnIndex) {\n setHwmColumnIndex(col);\n } else if (col == 0)\n setHwmColumnIndex(0);\n }\n\n // If desired and possible move focus within existing selection rather than changing selection\n if (keepSelection && isInSelection(row,col)) {\n const rowIndex = row ? row : 0;\n const colIndex = col ? col : 0;\n updateFocus(rowIndex, colIndex);\n } else {\n updateSelection(row,col);\n }\n ensureVisible(row,col);\n }\n\n // Move on to next cell. \n // Moves within selected row or column. If none moves vertically if isVertical otherwise horizontally. \n // Move backwards (left/dup) if isBackwards, otherwise forwards\n function nextCell(row: number, col: number, isVertical: boolean, isBackwards: boolean) {\n if (selection[0] === undefined && selection[1] === undefined)\n return;\n\n const offset = isBackwards ? -1 : 1;\n\n if (selection[0] === undefined) {\n // Column selected - move vertically within existing selection\n selectItem(row+offset, col, true);\n } else if (selection[1] === undefined) {\n // Row selected - move horizontally within existing selection\n selectItem(row, col+offset, true);\n } else {\n // Cell selected\n if (isVertical)\n selectItem(row+offset,col);\n else\n selectItem(row,col+offset);\n }\n }\n\n function onNameKeyUp(event: React.KeyboardEvent<HTMLInputElement>) {\n if (event.key !== \"Enter\")\n return;\n\n const [row, col] = rowColRefToCoords(name);\n selectItem(row,col);\n }\n\n function CommitFormulaChange(rowIndex: number, colIndex: number) {\n let value: CellValue = undefined;\n let format: string | undefined = undefined;\n const parseData = numfmt.parseValue(formula);\n if (parseData) {\n // number or boolean\n value = parseData.v;\n format = parseData.z;\n } else {\n // string\n value = formula;\n }\n\n data.setCellValueAndFormat(rowIndex, colIndex, value, format);\n }\n\n // Used by both formula and focus sink input fields\n function onEditValueKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {\n if (!focusCell)\n return;\n\n const row = focusCell[0];\n const col = focusCell[1];\n\n if (editMode) {\n switch (event.key) {\n case \"Escape\": { \n updateFormula(row, col, false); \n setEditMode(false); \n setFocusCell([row, col]); \n } \n break;\n\n case \"Enter\": { \n CommitFormulaChange(row, col); \n updateFormula(row, col, false); \n setEditMode(false);\n nextCell(row,col,true,event.shiftKey);\n } \n break;\n\n case \"Tab\": { \n CommitFormulaChange(row, col); \n updateFormula(row, col, false); \n setEditMode(false);\n nextCell(row,col,false,event.shiftKey);\n event.preventDefault();\n } \n break;\n }\n } else {\n switch (event.key) {\n case \"ArrowDown\": { selectItem(row+1,col); event.preventDefault(); } break;\n case \"ArrowUp\": { selectItem(row-1,col); event.preventDefault(); } break;\n case \"ArrowLeft\": { selectItem(row,col-1); event.preventDefault(); } break;\n case \"ArrowRight\": { selectItem(row,col+1); event.preventDefault(); } break;\n case \"Tab\": { nextCell(row,col,false,event.shiftKey); event.preventDefault(); } break;\n case \"Enter\": { \n if (isInSelection(row,col)) {\n nextCell(row,col,true,event.shiftKey);\n } else {\n updateFormula(row, col, true); \n if (readOnly)\n nextCell(row,col,true,event.shiftKey);\n else\n setEditMode(true);\n }\n } \n break;\n }\n }\n }\n\n function colSelected(index: number) { return (selection[0] == undefined && selection[1] == index) }\n function colCellSelected(index: number) { \n return (selection[0] != undefined) && (selection[1] == undefined || selection[1] == index)\n }\n function rowSelected(index: number) { return (selection[0] == index && selection[1] == undefined) }\n function rowCellSelected(index: number) { \n return (selection[1] != undefined) && (selection[0] == undefined || selection[0] == index)\n }\n\n const colHeaderRender: VirtualContainerRender = ({...rest}, ref) => (\n <div ref={ref}\n onClick={(event) => {\n const [x,_] = getCurrentTargetXY(event);\n const colOffset = x + gridColumnOffset;\n const [colIndex] = columnMapping.offsetToItem(colOffset);\n updateSelection(undefined,colIndex);\n }} \n {...rest}/>\n )\n\n const rowHeaderRender: VirtualContainerRender = ({...rest}, ref) => (\n <div ref={ref}\n onClick={(event) => {\n const [_,y] = getCurrentTargetXY(event);\n const rowOffset = y + gridRowOffset;\n const [rowIndex] = rowMapping.offsetToItem(rowOffset);\n updateSelection(rowIndex, undefined);\n }} \n {...rest}/>\n )\n \n const colRender: HeaderItemRender = (index, style ) => (\n <div className={join(theme?.VirtualSpreadsheet_Column, \n ifdef(colSelected(index), theme?.VirtualSpreadsheet_Column__Selected),\n ifdef(colCellSelected(index), theme?.VirtualSpreadsheet_Column__CellSelected))} \n style={style}>\n { indexToColRef(index) }\n </div>\n );\n \n const rowRender: HeaderItemRender = (index, style) => (\n <div className={join(theme?.VirtualSpreadsheet_Row, \n ifdef(rowSelected(index), theme?.VirtualSpreadsheet_Row__Selected),\n ifdef(rowCellSelected(index), theme?.VirtualSpreadsheet_Row__CellSelected))}\n style={style}>\n { index+1 }\n </div>\n );\n \n const outerGridRender: VirtualContainerRender = ({children, ...rest}, ref) => {\n let focusSink;\n if (focusCell) {\n const row = focusCell[0];\n const col = focusCell[1];\n\n // Position focus sink underneath focused cell. If outside viewport clamp position.\n // Careful - focus cell might be bigger than the viewport!\n const focusHeight = rowMapping.itemSize(row);\n let focusTop = rowMapping.itemOffset(row) - gridRowOffset;\n if (focusTop < -focusHeight)\n focusTop = -focusHeight;\n else if (focusTop > height)\n focusTop = height;\n\n const focusWidth = columnMapping.itemSize(col);\n let focusLeft = columnMapping.itemOffset(col) - gridColumnOffset;\n if (focusLeft < -focusWidth)\n focusLeft = -focusWidth;\n else if (focusLeft > width)\n focusLeft = width;\n\n // Browser will try and bring focus sink into view in various scenarios like text being typed or user\n // giving it focus by tabbing between fields. All browsers I tested make a horrible mess of things\n // due to the sticky positioning. Need to use my own ensureVisible method to clean up.\n focusSink = <input\n ref={focusSinkRef}\n className={join(theme?.VirtualSpreadsheet_Cell, theme?.VirtualSpreadsheet_Cell__Focus)}\n type={\"text\"}\n name={\"edit\"}\n title={\"Edit\"}\n readOnly={readOnly}\n value={cellValue}\n onChange={(event) => {\n setCellValue(event.target?.value);\n setEditMode(!readOnly);\n setFormula(event.target?.value);\n }}\n onFocus={() => { ensureVisible(row,col) }}\n onBeforeInput={() => { ensureVisible(row,col) }}\n onKeyDown={onEditValueKeyDown}\n style={{ zIndex: editMode ? 1 : -1, position: \"absolute\", top: focusTop, height: focusHeight, left: focusLeft, width: focusWidth }}\n />\n }\n return <div ref={ref}\n onClick={(event) => {\n const [x,y] = getCurrentTargetXY(event);\n const colOffset = x + gridColumnOffset;\n const rowOffset = y + gridRowOffset;\n const [rowIndex] = rowMapping.offsetToItem(rowOffset);\n const [colIndex] = columnMapping.offsetToItem(colOffset);\n updateSelection(rowIndex,colIndex);\n }} \n onDoubleClick={(_event) => {\n setCellValue(formula);\n setEditMode(!readOnly);\n }} \n {...rest}>\n {children}\n {focusSink}\n </div>\n }\n\n const cellRender: CellRender = (rowIndex, columnIndex, style) => {\n let dataValue: CellValue = undefined;\n let value:string = \"\";\n if (rowIndex < dataRowCount && columnIndex < dataColumnCount) {\n dataValue = data.getCellValue(snapshot, rowIndex, columnIndex);\n const format = data.getCellFormat(snapshot, rowIndex, columnIndex);\n value = formatContent(dataValue, format);\n }\n\n const focused = focusCell && rowIndex == focusCell[0] && columnIndex == focusCell[1];\n const classNames = join(theme?.VirtualSpreadsheet_Cell,\n ifdef(rowSelected(rowIndex), theme?.VirtualSpreadsheet_Cell__RowSelected),\n ifdef(colSelected(columnIndex), theme?.VirtualSpreadsheet_Cell__ColumnSelected),\n classForType(dataValue),\n ifdef(focused, theme?.VirtualSpreadsheet_Cell__Focus));\n\n return <div className={classNames} style={style}>\n { value }\n </div>\n };\n\n const columnTemplate = `${rowHeaderWidth}px 1fr`;\n const rowTemplate = `${inputBarHeight}px ${columnHeaderHeight}px 1fr`;\n const minWidth = rowHeaderWidth * 2;\n const minHeight = inputBarHeight + columnHeaderHeight * 2;\n const gridWidth = Math.max(width - rowHeaderWidth, rowHeaderWidth);\n const gridHeight = Math.max(height - columnHeaderHeight - inputBarHeight, columnHeaderHeight);\n\n return (\n <div className={join(props.className, theme?.VirtualSpreadsheet)} \n style={{ width, height, minWidth, minHeight, display: \"grid\", gridTemplateColumns: columnTemplate, gridTemplateRows: rowTemplate }}>\n <div className={theme?.VirtualSpreadsheet_InputBar} style={{overflow: 'hidden', display: 'flex', gridColumnStart: 1, gridColumnEnd: 3}}>\n <input className={theme?.VirtualSpreadsheet_Name}\n type={\"text\"}\n name={\"name\"}\n title={\"Name\"}\n value={name}\n size={20}\n onChange={(event) => {\n setName(event.target?.value);\n }}\n onKeyUp={onNameKeyUp}\n />\n <label className={theme?.VirtualSpreadsheet_Fx}>fx</label>\n <input className={theme?.VirtualSpreadsheet_Formula}\n style={{flexGrow: 1}}\n type={\"text\"}\n readOnly={readOnly}\n name={\"formula\"}\n title={\"Formula\"}\n value={formula}\n onChange={(event) => {\n setFormula(event.target?.value);\n setEditMode(!readOnly);\n if (focusCell)\n setCellValue(event.target?.value);\n }}\n onFocus={() => {\n if (focusCell) {\n setCellValue(formula);\n setEditMode(!readOnly);\n }\n }}\n onKeyDown={onEditValueKeyDown}\n />\n </div>\n\n <div className={theme?.VirtualSpreadsheet_CornerHeader}></div>\n\n <DisplayList\n offset={gridColumnOffset}\n className={theme?.VirtualSpreadsheet_ColumnHeader}\n itemData={colRender}\n outerRender={colHeaderRender}\n height={columnHeaderHeight}\n itemCount={columnCount}\n itemOffsetMapping={columnMapping}\n layout={'horizontal'}\n width={gridWidth}>\n {HeaderItem}\n </DisplayList>\n\n <DisplayList\n offset={gridRowOffset}\n className={theme?.VirtualSpreadsheet_RowHeader}\n itemData={rowRender}\n outerRender={rowHeaderRender}\n height={gridHeight}\n itemCount={rowCount}\n itemOffsetMapping={rowMapping}\n width={rowHeaderWidth}>\n {HeaderItem}\n </DisplayList>\n\n <VirtualScroll\n className={theme?.VirtualSpreadsheet_Grid}\n ref={scrollRef}\n onScroll={onScroll}\n height={gridHeight}\n width={gridWidth}\n scrollHeight={rowOffset}\n scrollWidth={columnOffset}\n useOffsets={false}\n maxCssSize={props.maxCssSize}\n minNumPages={props.minNumPages}>\n {(_) => (\n <AutoSizer style={{ height: '100%', width: '100%' }}>\n {({height,width}) => (\n <DisplayGrid\n rowOffset={gridRowOffset}\n columnOffset={gridColumnOffset}\n height={height}\n width={width}\n itemData={cellRender}\n outerRender={outerGridRender}\n rowCount={rowCount}\n rowOffsetMapping={rowMapping}\n columnCount={columnCount}\n columnOffsetMapping={columnMapping}>\n {Cell}\n </DisplayGrid>\n )}\n </AutoSizer>\n )}\n </VirtualScroll>\n </div>\n )\n}\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@candidstartup/react-spreadsheet",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.7.0",
|
|
5
|
+
"description": "Modern React Spreadsheet Frontend",
|
|
6
|
+
"author": "Tim Wiegand <tim.wiegand@thecandidstartup.org>",
|
|
7
|
+
"license": "BSD-3-Clause",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/TheCandidStartup/infinisheet.git",
|
|
11
|
+
"directory": "packages/react-spreadsheet"
|
|
12
|
+
},
|
|
13
|
+
"bugs": "https://github.com/TheCandidStartup/infinisheet/issues",
|
|
14
|
+
"homepage": "https://github.com/TheCandidStartup/infinisheet/blob/main/packages/react-spreadsheet/README.md",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"react",
|
|
17
|
+
"reactjs",
|
|
18
|
+
"spreadsheet",
|
|
19
|
+
"virtualized",
|
|
20
|
+
"modern",
|
|
21
|
+
"scalable",
|
|
22
|
+
"infinisheet"
|
|
23
|
+
],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"type": "module",
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"src/VirtualSpreadsheet.css",
|
|
31
|
+
"src/VirtualSpreadsheet.module.css"
|
|
32
|
+
],
|
|
33
|
+
"module": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"import": "./dist/index.js"
|
|
39
|
+
},
|
|
40
|
+
"./VirtualSpreadsheet.css": "./src/VirtualSpreadsheet.css",
|
|
41
|
+
"./VirtualSpreadsheet.module.css": "./src/VirtualSpreadsheet.module.css"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"dev": "vite",
|
|
45
|
+
"clean": "rimraf {dist,temp}",
|
|
46
|
+
"prebuild": "npm run clean",
|
|
47
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
48
|
+
"build-tsc": "tsc -p tsconfig.build.json",
|
|
49
|
+
"build-rollup": "rollup -c ../rollup.config.mjs",
|
|
50
|
+
"build": "npm run build-rollup",
|
|
51
|
+
"lint": "eslint . --report-unused-disable-directives --max-warnings 0",
|
|
52
|
+
"devapi": "api-extractor run --local",
|
|
53
|
+
"prodapi": "api-extractor run",
|
|
54
|
+
"devbuild": "npm run build && npm run lint && npm run devapi",
|
|
55
|
+
"test": "vitest"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"react": "^18.2.0"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@candidstartup/infinisheet-types": "^0.7.0",
|
|
62
|
+
"@candidstartup/react-virtual-scroll": "^0.7.0",
|
|
63
|
+
"numfmt": "^3.1.2"
|
|
64
|
+
},
|
|
65
|
+
"gitHead": "5ea8ee7cef0e539dd15b844bd074a745d08b6ba6"
|
|
66
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* Example global style sheet that works with default theme */
|
|
2
|
+
|
|
3
|
+
.VirtualSpreadsheet_InputBar {
|
|
4
|
+
margin-bottom: 2px;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.VirtualSpreadsheet_Fx {
|
|
8
|
+
margin-left: 5px;
|
|
9
|
+
margin-right: 2px;
|
|
10
|
+
margin-top: auto;
|
|
11
|
+
margin-bottom: auto;
|
|
12
|
+
color: darkgrey;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.VirtualSpreadsheet_CornerHeader {
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
border: 1px solid grey;
|
|
18
|
+
background-color: whitesmoke;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.VirtualSpreadsheet_ColumnHeader {
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
border: 1px solid grey;
|
|
24
|
+
border-left: 1px solid transparent;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.VirtualSpreadsheet_Column {
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
border-right: 1px solid lightgrey;
|
|
30
|
+
text-align: center;
|
|
31
|
+
background-color: white;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.VirtualSpreadsheet_Column__Selected {
|
|
35
|
+
color: white;
|
|
36
|
+
background-color: darkblue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.VirtualSpreadsheet_Column__CellSelected {
|
|
40
|
+
background-color: lightblue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.VirtualSpreadsheet_RowHeader {
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
border: 1px solid grey;
|
|
46
|
+
border-top: 1px solid transparent;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.VirtualSpreadsheet_Row {
|
|
50
|
+
box-sizing: border-box;
|
|
51
|
+
border-bottom: 1px solid lightgrey;
|
|
52
|
+
text-align: center;
|
|
53
|
+
background-color: white;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.VirtualSpreadsheet_Row__Selected {
|
|
57
|
+
color: white;
|
|
58
|
+
background-color: darkblue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.VirtualSpreadsheet_Row__CellSelected {
|
|
62
|
+
background-color: lightblue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.VirtualSpreadsheet_Grid {
|
|
66
|
+
box-sizing: border-box;
|
|
67
|
+
border-left: 1px solid transparent;
|
|
68
|
+
border-top: 1px solid transparent;
|
|
69
|
+
border-right: 1px solid grey;
|
|
70
|
+
border-bottom: 1px solid grey;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.VirtualSpreadsheet_Cell {
|
|
74
|
+
box-sizing: border-box;
|
|
75
|
+
border-left: 1px solid transparent;
|
|
76
|
+
border-top: 1px solid transparent;
|
|
77
|
+
border-right: 1px solid lightgrey;
|
|
78
|
+
border-bottom: 1px solid lightgrey;
|
|
79
|
+
resize: none;
|
|
80
|
+
background-color: white;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.VirtualSpreadsheet_Cell__Type_string {
|
|
84
|
+
text-align: left;
|
|
85
|
+
padding-left: 2px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.VirtualSpreadsheet_Cell__Type_number {
|
|
89
|
+
text-align: right;
|
|
90
|
+
padding-right: 2px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.VirtualSpreadsheet_Cell__Type_boolean {
|
|
94
|
+
text-align: center;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.VirtualSpreadsheet_Cell__Type_null {
|
|
98
|
+
text-align: center;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.VirtualSpreadsheet_Cell__Type_undefined {
|
|
102
|
+
text-align: center;
|
|
103
|
+
background-color: whitesmoke;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.VirtualSpreadsheet_Cell__Type_CellError {
|
|
107
|
+
text-align: center;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.VirtualSpreadsheet_Cell__RowSelected {
|
|
111
|
+
background-color: lightblue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.VirtualSpreadsheet_Cell__ColumnSelected {
|
|
115
|
+
background-color: lightblue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.VirtualSpreadsheet_Cell__Focus {
|
|
119
|
+
border: 2px solid darkblue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.VirtualSpreadsheet_Cell__Focus:focus {
|
|
123
|
+
outline: none;
|
|
124
|
+
}
|