pixel-react 1.5.5 → 1.5.6
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/lib/components/DatePicker/types.d.ts +4 -0
- package/lib/components/Excel/ExcelContextMenu/ExcelContextMenu.d.ts +1 -7
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/DataViewer.d.ts +1 -1
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.d.ts +1 -0
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/reducerFunctions.d.ts +1 -0
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/types.d.ts +5 -0
- package/lib/components/FileDropzone/types.d.ts +3 -0
- package/lib/components/StateDropdown/StateDropdown.d.ts +1 -1
- package/lib/components/StateDropdown/StateDropdownTypes.d.ts +3 -0
- package/lib/index.d.ts +49 -2
- package/lib/index.esm.js +899 -550
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +899 -549
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/assets/icons/dashboard_icon.svg +31 -0
- package/src/assets/styles/_colors.scss +1 -0
- package/src/components/AllProjectsDropdown/AllProjectsDropdown.scss +1 -1
- package/src/components/DatePicker/DatePicker.scss +4 -3
- package/src/components/DatePicker/DatePicker.stories.tsx +27 -14
- package/src/components/DatePicker/DatePicker.tsx +62 -49
- package/src/components/DatePicker/types.ts +5 -0
- package/src/components/Excel/ColorBarSelector/ColorBarSelector.scss +8 -4
- package/src/components/Excel/ColorBarSelector/ColorBarSelector.tsx +2 -2
- package/src/components/Excel/ExcelContextMenu/ExcelContextMenu.scss +23 -35
- package/src/components/Excel/ExcelContextMenu/ExcelContextMenu.tsx +3 -12
- package/src/components/Excel/ExcelFile/ExcelFile.scss +31 -25
- package/src/components/Excel/ExcelFile/ExcelFile.tsx +157 -47
- package/src/components/Excel/ExcelFile/ExcelFileComponents/Cell.tsx +5 -4
- package/src/components/Excel/ExcelFile/ExcelFileComponents/ColumnIndicator.tsx +3 -3
- package/src/components/Excel/ExcelFile/ExcelFileComponents/DataViewer.tsx +40 -1
- package/src/components/Excel/ExcelFile/ExcelFileComponents/RowIndicator.tsx +3 -3
- package/src/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.scss +10 -0
- package/src/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.tsx +9 -45
- package/src/components/Excel/ExcelFile/ExcelFileComponents/reducer.ts +43 -2
- package/src/components/Excel/ExcelFile/ExcelFileComponents/reducerFunctions.ts +40 -5
- package/src/components/Excel/ExcelFile/ExcelFileComponents/types.ts +3 -1
- package/src/components/Excel/ExcelFile.stories.tsx +42 -43
- package/src/components/Excel/ExcelToolBar/ExcelToolBar.scss +80 -20
- package/src/components/Excel/ExcelToolBar/ExcelToolBar.tsx +171 -159
- package/src/components/FileDropzone/Dropzone.tsx +2 -0
- package/src/components/FileDropzone/FileDropzone.scss +1 -2
- package/src/components/FileDropzone/FileDropzone.stories.tsx +3 -0
- package/src/components/FileDropzone/FileDropzone.tsx +11 -3
- package/src/components/FileDropzone/types.ts +5 -0
- package/src/components/Icon/Icon.stories.tsx +5 -4
- package/src/components/Icon/iconList.ts +2 -0
- package/src/components/MultiSelect/MultiSelect.scss +41 -50
- package/src/components/MultiSelect/MultiSelect.tsx +48 -48
- package/src/components/Select/Select.scss +11 -1
- package/src/components/Select/Select.tsx +2 -2
- package/src/components/StateDropdown/StateDropdown.stories.tsx +5 -0
- package/src/components/StateDropdown/StateDropdown.tsx +27 -12
- package/src/components/StateDropdown/StateDropdownTypes.tsx +6 -0
- package/src/components/TableTree/TableTree.scss +17 -15
- package/src/components/TableTree/TableTree.tsx +42 -40
- package/src/index.ts +2 -0
@@ -2,11 +2,13 @@ import React, { useState, useRef, useEffect } from 'react';
|
|
2
2
|
import Spreadsheet, { CellBase } from './ExcelFileComponents/index';
|
3
3
|
import * as Matrix from './ExcelFileComponents/matrix';
|
4
4
|
import './ExcelFile.scss';
|
5
|
-
import { Col, Row } from '../../GridLayout/GridLayout';
|
6
5
|
import Tooltip from '../../Tooltip';
|
7
6
|
import Icon from '../../Icon';
|
8
7
|
import Toastify from '../../Toastify';
|
9
8
|
import { toast } from '../../Toastify/Toastify';
|
9
|
+
import { ContextMenuState } from './ExcelFileComponents/types';
|
10
|
+
import ExcelContextMenu from '../ExcelContextMenu/ExcelContextMenu';
|
11
|
+
import Typography from '../../Typography';
|
10
12
|
|
11
13
|
interface ExcelFileProps {
|
12
14
|
/** The Excel data containing sheets and their content */
|
@@ -33,6 +35,12 @@ const ExcelFile: React.FC<ExcelFileProps> = ({
|
|
33
35
|
onSave = () => {},
|
34
36
|
}) => {
|
35
37
|
const [sheetNames, setSheetNames] = useState<string[]>([]);
|
38
|
+
const [contextMenu, setContextMenu] = React.useState<ContextMenuState>({
|
39
|
+
open: false,
|
40
|
+
position: { x: 0, y: 0 },
|
41
|
+
options: [{ label: '', value: '', iconName: '', action: () => {} }],
|
42
|
+
});
|
43
|
+
|
36
44
|
const EmptyRow: CellBase = {
|
37
45
|
value: '',
|
38
46
|
style: {
|
@@ -41,6 +49,7 @@ const ExcelFile: React.FC<ExcelFileProps> = ({
|
|
41
49
|
borderColor: 'var(--toggle-strip-color)',
|
42
50
|
},
|
43
51
|
};
|
52
|
+
|
44
53
|
const [selectedSheet, setSelectedSheet] = useState<{
|
45
54
|
name: string;
|
46
55
|
index: number;
|
@@ -54,15 +63,37 @@ const ExcelFile: React.FC<ExcelFileProps> = ({
|
|
54
63
|
Matrix.Matrix<CellBase>
|
55
64
|
>([[EmptyRow]]);
|
56
65
|
|
57
|
-
|
66
|
+
const pageRef = useRef<string>('');
|
58
67
|
const sheetRef = useRef<HTMLDivElement | null>(null);
|
59
68
|
|
60
|
-
|
69
|
+
const checkVal = (val: any) => {
|
61
70
|
if (val === undefined || val === null) {
|
62
71
|
return null;
|
63
72
|
}
|
64
73
|
return val;
|
65
74
|
};
|
75
|
+
|
76
|
+
const options = [
|
77
|
+
{
|
78
|
+
label: 'Add Sheet',
|
79
|
+
value: 'Add Sheet',
|
80
|
+
iconName: 'plus_icon',
|
81
|
+
action: () => {
|
82
|
+
handleAddSheet();
|
83
|
+
},
|
84
|
+
disable: false,
|
85
|
+
},
|
86
|
+
{
|
87
|
+
label: 'Delete Sheet',
|
88
|
+
value: 'Delete Sheet',
|
89
|
+
iconName: 'delete',
|
90
|
+
action: () => {
|
91
|
+
handleDeleteSheet();
|
92
|
+
},
|
93
|
+
disable: false,
|
94
|
+
},
|
95
|
+
];
|
96
|
+
|
66
97
|
useEffect(() => {
|
67
98
|
const payload = excelData;
|
68
99
|
const sheetNames = payload.sheets.map((e) => e.sheetName);
|
@@ -111,7 +142,7 @@ const ExcelFile: React.FC<ExcelFileProps> = ({
|
|
111
142
|
|
112
143
|
const onEvaluateChange = (data: Matrix.Matrix<CellBase>) => {
|
113
144
|
setWorksheetsData((prev) => ({ ...prev, [pageRef.current]: data }));
|
114
|
-
onSave()
|
145
|
+
onSave();
|
115
146
|
};
|
116
147
|
|
117
148
|
const [editingSheet, setEditingSheet] = useState<number | null>(null);
|
@@ -142,6 +173,38 @@ const ExcelFile: React.FC<ExcelFileProps> = ({
|
|
142
173
|
pageRef.current = newSheetName;
|
143
174
|
};
|
144
175
|
|
176
|
+
useEffect(() => {
|
177
|
+
const selectedData = worksheetsData[selectedSheet.name];
|
178
|
+
if (selectedData !== undefined) {
|
179
|
+
setSelectedSheetData(selectedData);
|
180
|
+
} else {
|
181
|
+
setSelectedSheetData([]);
|
182
|
+
}
|
183
|
+
}, [selectedSheet.name, worksheetsData]);
|
184
|
+
|
185
|
+
const handleDeleteSheet = () => {
|
186
|
+
const { index, name } = selectedSheet;
|
187
|
+
|
188
|
+
if (sheetNames.length > 1) {
|
189
|
+
let updatedSheetNames = sheetNames.slice();
|
190
|
+
updatedSheetNames.splice(index, 1);
|
191
|
+
|
192
|
+
const updatedWorksheetsData = { ...worksheetsData };
|
193
|
+
|
194
|
+
delete updatedWorksheetsData[name];
|
195
|
+
const newIndex = Math.min(index, updatedSheetNames.length - 1);
|
196
|
+
|
197
|
+
setSheetNames(updatedSheetNames);
|
198
|
+
setWorksheetsData(updatedWorksheetsData);
|
199
|
+
setSelectedSheet({
|
200
|
+
index: newIndex,
|
201
|
+
name: updatedSheetNames[newIndex] ? updatedSheetNames[newIndex] : '',
|
202
|
+
});
|
203
|
+
} else {
|
204
|
+
toast.warning('Cannot delete the last sheet.');
|
205
|
+
}
|
206
|
+
};
|
207
|
+
|
145
208
|
const handleNameChange = (
|
146
209
|
event: React.SyntheticEvent<HTMLDivElement>,
|
147
210
|
index: number,
|
@@ -214,6 +277,9 @@ const ExcelFile: React.FC<ExcelFileProps> = ({
|
|
214
277
|
}
|
215
278
|
|
216
279
|
const handleSheetChange = (name: string, index: number) => {
|
280
|
+
if (name === selectedSheet.name || index === selectedSheet.index) {
|
281
|
+
return;
|
282
|
+
}
|
217
283
|
setSelectedSheet({ index, name });
|
218
284
|
setSheetNames((prev: string[]) => {
|
219
285
|
const updatedSheetNames = [...prev];
|
@@ -239,18 +305,63 @@ const ExcelFile: React.FC<ExcelFileProps> = ({
|
|
239
305
|
selection?.addRange(range);
|
240
306
|
};
|
241
307
|
|
308
|
+
const handleClickOutside = React.useCallback(
|
309
|
+
(event: MouseEvent) => {
|
310
|
+
if (contextMenu.open) {
|
311
|
+
event.preventDefault();
|
312
|
+
event.stopPropagation();
|
313
|
+
setContextMenu({
|
314
|
+
open: false,
|
315
|
+
position: { x: 0, y: 0 },
|
316
|
+
options: [{ label: '', value: '', iconName: '', action: () => {} }],
|
317
|
+
});
|
318
|
+
}
|
319
|
+
},
|
320
|
+
[contextMenu.open]
|
321
|
+
);
|
322
|
+
|
323
|
+
React.useEffect(() => {
|
324
|
+
document.addEventListener('click', handleClickOutside);
|
325
|
+
return () => {
|
326
|
+
document.removeEventListener('click', handleClickOutside);
|
327
|
+
};
|
328
|
+
}, [handleClickOutside]);
|
329
|
+
|
330
|
+
const contextClick = (event: React.MouseEvent) => {
|
331
|
+
event.preventDefault();
|
332
|
+
const target = event.target as HTMLElement;
|
333
|
+
const selectedSheetName = target.innerText;
|
334
|
+
|
335
|
+
sheetNames.map((name, index) => {
|
336
|
+
if (selectedSheetName === name) {
|
337
|
+
handleSheetChange(name, index);
|
338
|
+
}
|
339
|
+
});
|
340
|
+
|
341
|
+
setContextMenu({
|
342
|
+
open: true,
|
343
|
+
position: {
|
344
|
+
x: event.pageX - 50,
|
345
|
+
y: event.pageY - 350,
|
346
|
+
},
|
347
|
+
options: options,
|
348
|
+
});
|
349
|
+
};
|
350
|
+
|
242
351
|
return (
|
243
|
-
<div className="excel-page">
|
352
|
+
<div className="ff-excel-page">
|
244
353
|
{sheetNames.length > 0 && (
|
245
|
-
<div className="excel-book">
|
246
|
-
<
|
354
|
+
<div className="ff-excel-book">
|
355
|
+
{contextMenu.open && <ExcelContextMenu contextMenu={contextMenu} />}
|
356
|
+
<div ref={sheetRef} className="ff-excel-sheet">
|
247
357
|
<Spreadsheet
|
358
|
+
setContextMenu={setContextMenu}
|
248
359
|
data={selectedSheetData}
|
249
360
|
onEvaluatedDataChange={onEvaluateChange}
|
250
361
|
/>
|
251
362
|
</div>
|
252
|
-
<
|
253
|
-
<
|
363
|
+
<div className="ff-excel-sheet-bar">
|
364
|
+
<div className="ff-excel-add-sheet-icon">
|
254
365
|
<Tooltip title="Add Sheet" placement="top">
|
255
366
|
<Icon
|
256
367
|
className="cursor-pointer ml-1"
|
@@ -263,45 +374,44 @@ const ExcelFile: React.FC<ExcelFileProps> = ({
|
|
263
374
|
width={20}
|
264
375
|
/>
|
265
376
|
</Tooltip>
|
266
|
-
</
|
267
|
-
<
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
377
|
+
</div>
|
378
|
+
<div className="ff-excel-tab-container">
|
379
|
+
{sheetNames.map((name, index) => (
|
380
|
+
<div
|
381
|
+
key={name}
|
382
|
+
onContextMenu={contextClick}
|
383
|
+
className={`ff-excel-tab-list ${
|
384
|
+
name === selectedSheet.name ? 'active' : ''
|
385
|
+
}`}
|
386
|
+
onClick={() => {
|
387
|
+
handleSheetChange(name, index);
|
388
|
+
}}
|
389
|
+
suppressContentEditableWarning={editingSheet === index}
|
390
|
+
onDoubleClick={(e) => {
|
391
|
+
setEditingSheet(index);
|
392
|
+
if (editingSheet === null) {
|
393
|
+
setTimeout(
|
394
|
+
() => setCursorToEnd(e.target as HTMLDivElement),
|
395
|
+
0
|
396
|
+
);
|
397
|
+
}
|
398
|
+
}}
|
399
|
+
contentEditable={editingSheet === index}
|
400
|
+
onBlur={(e) => {
|
401
|
+
handleNameChange(e, index, name);
|
402
|
+
}}
|
403
|
+
onKeyDown={(e) => {
|
404
|
+
if (e.key === 'Enter') {
|
405
|
+
e.preventDefault();
|
290
406
|
handleNameChange(e, index, name);
|
291
|
-
}
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
{name}
|
300
|
-
</div>
|
301
|
-
))}
|
302
|
-
</div>
|
303
|
-
</Col>
|
304
|
-
</Row>
|
407
|
+
}
|
408
|
+
}}
|
409
|
+
>
|
410
|
+
<Typography>{name}</Typography>
|
411
|
+
</div>
|
412
|
+
))}
|
413
|
+
</div>
|
414
|
+
</div>
|
305
415
|
</div>
|
306
416
|
)}
|
307
417
|
<Toastify />
|
@@ -109,13 +109,13 @@ export const Cell: React.FC<Types.CellComponentProps> = ({
|
|
109
109
|
setContextMenu({
|
110
110
|
open: true,
|
111
111
|
position: {
|
112
|
-
x: event.
|
113
|
-
y: event.
|
112
|
+
x: event.pageX - 50,
|
113
|
+
y: event.pageY - 260,
|
114
114
|
},
|
115
115
|
options: options,
|
116
116
|
});
|
117
117
|
},
|
118
|
-
[setContextMenu]
|
118
|
+
[setContextMenu, select, point]
|
119
119
|
);
|
120
120
|
|
121
121
|
React.useEffect(() => {
|
@@ -147,13 +147,14 @@ export const Cell: React.FC<Types.CellComponentProps> = ({
|
|
147
147
|
>
|
148
148
|
<DataViewer
|
149
149
|
row={row}
|
150
|
+
setContextMenu={setContextMenu}
|
150
151
|
column={column}
|
151
152
|
cell={data}
|
152
153
|
evaluatedCell={evaluatedData}
|
153
154
|
setCellData={setCellData}
|
154
155
|
/>
|
155
156
|
<div
|
156
|
-
className="Selection_dot"
|
157
|
+
// className="Selection_dot" TODO
|
157
158
|
onMouseOver={handleDotOver}
|
158
159
|
onMouseDown={handleDotDown}
|
159
160
|
></div>
|
@@ -18,7 +18,7 @@ const ColumnIndicator: Types.ColumnIndicatorComponent = ({
|
|
18
18
|
}) => {
|
19
19
|
const dispatch = useDispatch();
|
20
20
|
const [width, setWidth] = React.useState(100);
|
21
|
-
|
21
|
+
const options = [
|
22
22
|
{
|
23
23
|
label: 'Add Column',
|
24
24
|
value: 'Add Column',
|
@@ -92,8 +92,8 @@ const ColumnIndicator: Types.ColumnIndicatorComponent = ({
|
|
92
92
|
setContextMenu({
|
93
93
|
open: true,
|
94
94
|
position: {
|
95
|
-
x: event.
|
96
|
-
y: event.
|
95
|
+
x: event.pageX - 50,
|
96
|
+
y: event.pageY - 260,
|
97
97
|
},
|
98
98
|
options: options,
|
99
99
|
});
|
@@ -10,15 +10,54 @@ export const FALSE_TEXT = 'FALSE';
|
|
10
10
|
const DataViewer = <Cell extends Types.CellBase<Value>, Value>({
|
11
11
|
cell,
|
12
12
|
evaluatedCell,
|
13
|
+
setContextMenu,//Todo
|
13
14
|
}: Types.DataViewerProps<Cell>): React.ReactElement => {
|
15
|
+
|
14
16
|
const value = getValue(cell, evaluatedCell);
|
15
17
|
|
18
|
+
const options = [
|
19
|
+
{
|
20
|
+
label: 'Dynamic Cell One',
|
21
|
+
value: 'Dynamic Cell One',
|
22
|
+
iconName: 'plus_icon',
|
23
|
+
action: () => {
|
24
|
+
},
|
25
|
+
disable: false,
|
26
|
+
},
|
27
|
+
{
|
28
|
+
label: 'Dynamic Cell Two',
|
29
|
+
value: 'Dynamic Cell Two',
|
30
|
+
iconName: 'plus_icon',
|
31
|
+
action: () => {
|
32
|
+
},
|
33
|
+
disable: false,
|
34
|
+
},
|
35
|
+
];
|
36
|
+
|
37
|
+
const contextClick = React.useCallback(
|
38
|
+
(event: React.MouseEvent) => {
|
39
|
+
event.preventDefault();
|
40
|
+
|
41
|
+
setContextMenu({
|
42
|
+
open: true,
|
43
|
+
position: {
|
44
|
+
x: event.pageX - 50,
|
45
|
+
y: event.pageY - 260,
|
46
|
+
},
|
47
|
+
options: options,
|
48
|
+
});
|
49
|
+
},
|
50
|
+
[ setContextMenu]
|
51
|
+
);
|
52
|
+
|
16
53
|
return typeof value === 'boolean' ? (
|
17
|
-
<span
|
54
|
+
<span
|
55
|
+
className="ff-spreadsheet-data-viewer ff-spreadsheet-data-viewer--boolean">
|
18
56
|
{convertBooleanToText(value)}
|
19
57
|
</span>
|
20
58
|
) : (
|
21
59
|
<span
|
60
|
+
onContextMenu={contextClick}
|
22
61
|
className={classNames('ff-spreadsheet-data-viewer', {
|
23
62
|
'ff-spreadsheet-data-viewer--preserve-breaks': hasLineBreaker(value),
|
24
63
|
})}
|
@@ -17,7 +17,7 @@ const RowIndicator: Types.RowIndicatorComponent = ({
|
|
17
17
|
}) => {
|
18
18
|
const [height, setHeight] = React.useState(0);
|
19
19
|
|
20
|
-
|
20
|
+
const options = [
|
21
21
|
{
|
22
22
|
label: 'Add Row',
|
23
23
|
value: 'Add Row',
|
@@ -86,8 +86,8 @@ const RowIndicator: Types.RowIndicatorComponent = ({
|
|
86
86
|
setContextMenu({
|
87
87
|
open: true,
|
88
88
|
position: {
|
89
|
-
x: event.
|
90
|
-
y: event.
|
89
|
+
x: event.pageX - 50,
|
90
|
+
y: event.pageY - 260,
|
91
91
|
},
|
92
92
|
options: options,
|
93
93
|
});
|
@@ -1,5 +1,10 @@
|
|
1
1
|
@use '../../../../assets/styles/fonts';
|
2
2
|
|
3
|
+
.ff-excel {
|
4
|
+
display: flex;
|
5
|
+
flex-direction: column;
|
6
|
+
}
|
7
|
+
|
3
8
|
.ff-spreadsheet {
|
4
9
|
--background-color: var(--drawer-footer-bg);
|
5
10
|
--text-color: var(--text-color);
|
@@ -29,6 +34,11 @@
|
|
29
34
|
}
|
30
35
|
|
31
36
|
.ff-spreadsheet-table {
|
37
|
+
overflow: scroll;
|
38
|
+
&::-webkit-scrollbar {
|
39
|
+
height: 0px;
|
40
|
+
}
|
41
|
+
|
32
42
|
margin-top: 20px;
|
33
43
|
border-collapse: collapse;
|
34
44
|
table-layout: fixed;
|
@@ -38,7 +38,6 @@ import Copied from './Copied';
|
|
38
38
|
import './Spreadsheet.scss';
|
39
39
|
import ExcelToolBar from '../../ExcelToolBar/ExcelToolBar';
|
40
40
|
import { hasKeyDownHandler } from './reducerFunctions';
|
41
|
-
import ExcelContextMenu from '../../ExcelContextMenu/ExcelContextMenu';
|
42
41
|
|
43
42
|
/** The Spreadsheet component props */
|
44
43
|
export type Props<CellType extends Types.CellBase> = {
|
@@ -98,6 +97,7 @@ export type Props<CellType extends Types.CellBase> = {
|
|
98
97
|
onActivate?: (active: Point.Point) => void;
|
99
98
|
/** Callback called when the Spreadsheet's evaluated data changes. */
|
100
99
|
onEvaluatedDataChange?: (data: Matrix.Matrix<CellType>) => void;
|
100
|
+
setContextMenu: React.Dispatch<React.SetStateAction<Types.ContextMenuState>>;
|
101
101
|
};
|
102
102
|
|
103
103
|
/**
|
@@ -106,12 +106,6 @@ export type Props<CellType extends Types.CellBase> = {
|
|
106
106
|
const Spreadsheet = <CellType extends Types.CellBase>(
|
107
107
|
props: Props<CellType>
|
108
108
|
): React.ReactElement => {
|
109
|
-
const [contextMenu, setContextMenu] = React.useState<Types.ContextMenuState>({
|
110
|
-
open: false,
|
111
|
-
position: { x: 0, y: 0 },
|
112
|
-
options: [{ label: '', value: '', iconName: '', action: () => {} }],
|
113
|
-
});
|
114
|
-
|
115
109
|
const {
|
116
110
|
className,
|
117
111
|
columnLabels,
|
@@ -287,30 +281,13 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
287
281
|
[mode, paste]
|
288
282
|
);
|
289
283
|
|
290
|
-
const handleClickOutside = React.useCallback(
|
291
|
-
(event: MouseEvent) => {
|
292
|
-
if (contextMenu.open) {
|
293
|
-
event.preventDefault();
|
294
|
-
event.stopPropagation();
|
295
|
-
setContextMenu({
|
296
|
-
open: false,
|
297
|
-
position: { x: 0, y: 0 },
|
298
|
-
options: [{ label: '', value: '', iconName: '', action: () => {} }],
|
299
|
-
});
|
300
|
-
}
|
301
|
-
},
|
302
|
-
[contextMenu.open]
|
303
|
-
);
|
304
|
-
|
305
284
|
const handleKeyDown = React.useCallback(
|
306
285
|
(event: React.KeyboardEvent) => {
|
307
286
|
event.persist();
|
308
287
|
if (onKeyDown) {
|
309
288
|
onKeyDown(event);
|
310
289
|
}
|
311
|
-
// Do not use event in case preventDefault() was called inside onKeyDown
|
312
290
|
if (!event.defaultPrevented) {
|
313
|
-
// Only disable default behavior if an handler exist
|
314
291
|
if (hasKeyDownHandler(state, event)) {
|
315
292
|
event.nativeEvent.preventDefault();
|
316
293
|
}
|
@@ -361,29 +338,17 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
361
338
|
document.addEventListener('cut', handleCut);
|
362
339
|
document.addEventListener('copy', handleCopy);
|
363
340
|
document.addEventListener('paste', handlePaste);
|
364
|
-
document.addEventListener('click', handleClickOutside);
|
365
341
|
|
366
342
|
return () => {
|
367
343
|
document.removeEventListener('cut', handleCut);
|
368
344
|
document.removeEventListener('copy', handleCopy);
|
369
345
|
document.removeEventListener('paste', handlePaste);
|
370
|
-
document.removeEventListener('click', handleClickOutside);
|
371
346
|
};
|
372
|
-
}, [handleCut, handleCopy, handlePaste
|
347
|
+
}, [handleCut, handleCopy, handlePaste]);
|
373
348
|
|
374
349
|
const tableNode = React.useMemo(
|
375
350
|
() => (
|
376
351
|
<Table columns={size.columns}>
|
377
|
-
{contextMenu.open && (
|
378
|
-
<ExcelContextMenu
|
379
|
-
contextMenu={contextMenu}
|
380
|
-
data={props.data}
|
381
|
-
addRowTop={addRowTop}
|
382
|
-
addColumnLeft={addColumnLeft}
|
383
|
-
deleteRow={deleteRow}
|
384
|
-
deleteColumn={deleteColumn}
|
385
|
-
/>
|
386
|
-
)}
|
387
352
|
<HeaderRow>
|
388
353
|
{<CornerIndicator />}
|
389
354
|
{range(size.columns).map((columnNumber) =>
|
@@ -391,7 +356,7 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
391
356
|
<ColumnIndicator
|
392
357
|
key={columnNumber}
|
393
358
|
column={columnNumber}
|
394
|
-
setContextMenu={setContextMenu}
|
359
|
+
setContextMenu={props.setContextMenu}
|
395
360
|
label={
|
396
361
|
columnNumber in columnLabels
|
397
362
|
? columnLabels[columnNumber]
|
@@ -405,7 +370,7 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
405
370
|
<ColumnIndicator
|
406
371
|
key={columnNumber}
|
407
372
|
column={columnNumber}
|
408
|
-
setContextMenu={setContextMenu}
|
373
|
+
setContextMenu={props.setContextMenu}
|
409
374
|
deleteColumn={deleteColumn}
|
410
375
|
addColumnLeft={addColumnLeft}
|
411
376
|
data={props.data}
|
@@ -421,7 +386,7 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
421
386
|
label={rowNumber in rowLabels ? rowLabels[rowNumber] : null}
|
422
387
|
row={rowNumber}
|
423
388
|
addRowTop={addRowTop}
|
424
|
-
setContextMenu={setContextMenu}
|
389
|
+
setContextMenu={props.setContextMenu}
|
425
390
|
deleteRow={deleteRow}
|
426
391
|
data={props.data}
|
427
392
|
/>
|
@@ -430,7 +395,7 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
430
395
|
key={rowNumber}
|
431
396
|
row={rowNumber}
|
432
397
|
addRowTop={addRowTop}
|
433
|
-
setContextMenu={setContextMenu}
|
398
|
+
setContextMenu={props.setContextMenu}
|
434
399
|
deleteRow={deleteRow}
|
435
400
|
data={props.data}
|
436
401
|
/>
|
@@ -440,7 +405,7 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
440
405
|
key={columnNumber}
|
441
406
|
row={rowNumber}
|
442
407
|
column={columnNumber}
|
443
|
-
setContextMenu={setContextMenu}
|
408
|
+
setContextMenu={props.setContextMenu}
|
444
409
|
// @ts-ignore
|
445
410
|
DataViewer={DataViewer}
|
446
411
|
/>
|
@@ -462,7 +427,6 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
462
427
|
RowIndicator,
|
463
428
|
Cell,
|
464
429
|
DataViewer,
|
465
|
-
contextMenu,
|
466
430
|
]
|
467
431
|
);
|
468
432
|
|
@@ -478,7 +442,7 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
478
442
|
|
479
443
|
const rootNode = React.useMemo(
|
480
444
|
() => (
|
481
|
-
|
445
|
+
<div className="ff-excel">
|
482
446
|
<ExcelToolBar
|
483
447
|
data={props.data}
|
484
448
|
onBold={onBold}
|
@@ -503,7 +467,7 @@ const Spreadsheet = <CellType extends Types.CellBase>(
|
|
503
467
|
<Selected />
|
504
468
|
<Copied />
|
505
469
|
</div>
|
506
|
-
|
470
|
+
</div>
|
507
471
|
),
|
508
472
|
[className, handleKeyDown, handleMouseMove, tableNode, activeCellNode]
|
509
473
|
);
|
@@ -19,6 +19,7 @@ import {
|
|
19
19
|
applyColorToCells,
|
20
20
|
applyFontFamily,
|
21
21
|
applyFontSize,
|
22
|
+
applyFormatePainter,
|
22
23
|
applyItalicToCells,
|
23
24
|
applyTextAlign,
|
24
25
|
applyUnderlineToCells,
|
@@ -47,6 +48,7 @@ export const INITIAL_STATE: Types.StoreState = {
|
|
47
48
|
lastCommit: null,
|
48
49
|
selectedColumn: null,
|
49
50
|
selectedRow: null,
|
51
|
+
formattedStyle: { open: false, style: undefined },
|
50
52
|
};
|
51
53
|
|
52
54
|
export default function reducer(
|
@@ -278,9 +280,10 @@ export default function reducer(
|
|
278
280
|
}
|
279
281
|
|
280
282
|
case Actions.FORMATE_PAINTER: {
|
283
|
+
const copiedStyle = applyFormatePainter(state.model.data, state.active);
|
281
284
|
return {
|
282
285
|
...state,
|
283
|
-
|
286
|
+
formattedStyle: { open: true, style: copiedStyle },
|
284
287
|
};
|
285
288
|
}
|
286
289
|
|
@@ -573,7 +576,45 @@ export default function reducer(
|
|
573
576
|
}
|
574
577
|
|
575
578
|
case Actions.DRAG_END: {
|
576
|
-
|
579
|
+
const selectedRange = state.selected.toRange(state.model.data);
|
580
|
+
let currentData = state.model.data;
|
581
|
+
|
582
|
+
if (!state.formattedStyle.open || !selectedRange) {
|
583
|
+
return {
|
584
|
+
...state,
|
585
|
+
dragging: false,
|
586
|
+
formattedStyle: { open: false, style: undefined },
|
587
|
+
};
|
588
|
+
}
|
589
|
+
|
590
|
+
const { start, end } = selectedRange;
|
591
|
+
|
592
|
+
let updatedData = currentData;
|
593
|
+
|
594
|
+
for (let row = start.row; row <= end.row; row++) {
|
595
|
+
for (let col = start.column; col <= end.column; col++) {
|
596
|
+
const currentCell = Matrix.get({ row, column: col }, updatedData);
|
597
|
+
if (!currentCell) {
|
598
|
+
continue;
|
599
|
+
}
|
600
|
+
const updatedCell = {
|
601
|
+
...currentCell,
|
602
|
+
style: state.formattedStyle.style,
|
603
|
+
};
|
604
|
+
|
605
|
+
updatedData = Matrix.set(
|
606
|
+
{ row, column: col },
|
607
|
+
updatedCell,
|
608
|
+
updatedData
|
609
|
+
);
|
610
|
+
}
|
611
|
+
}
|
612
|
+
return {
|
613
|
+
...state,
|
614
|
+
dragging: false,
|
615
|
+
formattedStyle: { open: false, style: undefined },
|
616
|
+
model: new Model(state.model.createFormulaParser, updatedData),
|
617
|
+
};
|
577
618
|
}
|
578
619
|
|
579
620
|
case Actions.COMMIT: {
|