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.
Files changed (57) hide show
  1. package/lib/components/DatePicker/types.d.ts +4 -0
  2. package/lib/components/Excel/ExcelContextMenu/ExcelContextMenu.d.ts +1 -7
  3. package/lib/components/Excel/ExcelFile/ExcelFileComponents/DataViewer.d.ts +1 -1
  4. package/lib/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.d.ts +1 -0
  5. package/lib/components/Excel/ExcelFile/ExcelFileComponents/reducerFunctions.d.ts +1 -0
  6. package/lib/components/Excel/ExcelFile/ExcelFileComponents/types.d.ts +5 -0
  7. package/lib/components/FileDropzone/types.d.ts +3 -0
  8. package/lib/components/StateDropdown/StateDropdown.d.ts +1 -1
  9. package/lib/components/StateDropdown/StateDropdownTypes.d.ts +3 -0
  10. package/lib/index.d.ts +49 -2
  11. package/lib/index.esm.js +899 -550
  12. package/lib/index.esm.js.map +1 -1
  13. package/lib/index.js +899 -549
  14. package/lib/index.js.map +1 -1
  15. package/package.json +1 -1
  16. package/src/assets/icons/dashboard_icon.svg +31 -0
  17. package/src/assets/styles/_colors.scss +1 -0
  18. package/src/components/AllProjectsDropdown/AllProjectsDropdown.scss +1 -1
  19. package/src/components/DatePicker/DatePicker.scss +4 -3
  20. package/src/components/DatePicker/DatePicker.stories.tsx +27 -14
  21. package/src/components/DatePicker/DatePicker.tsx +62 -49
  22. package/src/components/DatePicker/types.ts +5 -0
  23. package/src/components/Excel/ColorBarSelector/ColorBarSelector.scss +8 -4
  24. package/src/components/Excel/ColorBarSelector/ColorBarSelector.tsx +2 -2
  25. package/src/components/Excel/ExcelContextMenu/ExcelContextMenu.scss +23 -35
  26. package/src/components/Excel/ExcelContextMenu/ExcelContextMenu.tsx +3 -12
  27. package/src/components/Excel/ExcelFile/ExcelFile.scss +31 -25
  28. package/src/components/Excel/ExcelFile/ExcelFile.tsx +157 -47
  29. package/src/components/Excel/ExcelFile/ExcelFileComponents/Cell.tsx +5 -4
  30. package/src/components/Excel/ExcelFile/ExcelFileComponents/ColumnIndicator.tsx +3 -3
  31. package/src/components/Excel/ExcelFile/ExcelFileComponents/DataViewer.tsx +40 -1
  32. package/src/components/Excel/ExcelFile/ExcelFileComponents/RowIndicator.tsx +3 -3
  33. package/src/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.scss +10 -0
  34. package/src/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.tsx +9 -45
  35. package/src/components/Excel/ExcelFile/ExcelFileComponents/reducer.ts +43 -2
  36. package/src/components/Excel/ExcelFile/ExcelFileComponents/reducerFunctions.ts +40 -5
  37. package/src/components/Excel/ExcelFile/ExcelFileComponents/types.ts +3 -1
  38. package/src/components/Excel/ExcelFile.stories.tsx +42 -43
  39. package/src/components/Excel/ExcelToolBar/ExcelToolBar.scss +80 -20
  40. package/src/components/Excel/ExcelToolBar/ExcelToolBar.tsx +171 -159
  41. package/src/components/FileDropzone/Dropzone.tsx +2 -0
  42. package/src/components/FileDropzone/FileDropzone.scss +1 -2
  43. package/src/components/FileDropzone/FileDropzone.stories.tsx +3 -0
  44. package/src/components/FileDropzone/FileDropzone.tsx +11 -3
  45. package/src/components/FileDropzone/types.ts +5 -0
  46. package/src/components/Icon/Icon.stories.tsx +5 -4
  47. package/src/components/Icon/iconList.ts +2 -0
  48. package/src/components/MultiSelect/MultiSelect.scss +41 -50
  49. package/src/components/MultiSelect/MultiSelect.tsx +48 -48
  50. package/src/components/Select/Select.scss +11 -1
  51. package/src/components/Select/Select.tsx +2 -2
  52. package/src/components/StateDropdown/StateDropdown.stories.tsx +5 -0
  53. package/src/components/StateDropdown/StateDropdown.tsx +27 -12
  54. package/src/components/StateDropdown/StateDropdownTypes.tsx +6 -0
  55. package/src/components/TableTree/TableTree.scss +17 -15
  56. package/src/components/TableTree/TableTree.tsx +42 -40
  57. 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
- let pageRef = useRef<string>('');
66
+ const pageRef = useRef<string>('');
58
67
  const sheetRef = useRef<HTMLDivElement | null>(null);
59
68
 
60
- let checkVal = (val: any) => {
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
- <div ref={sheetRef} className="excel-sheet">
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
- <Row className="sheet-bar">
253
- <Col size={0} className="add-sheet-icon">
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
- </Col>
267
- <Col size={10}>
268
- <div className="excel-tab-container">
269
- {sheetNames.map((name, index) => (
270
- <div
271
- key={name}
272
- className={`excel-tab-list ${
273
- name === selectedSheet.name ? 'active' : ''
274
- }`}
275
- onClick={() => {
276
- handleSheetChange(name, index);
277
- }}
278
- suppressContentEditableWarning={editingSheet === index}
279
- onDoubleClick={(e) => {
280
- setEditingSheet(index);
281
- if (editingSheet === null) {
282
- setTimeout(
283
- () => setCursorToEnd(e.target as HTMLDivElement),
284
- 0
285
- );
286
- }
287
- }}
288
- contentEditable={editingSheet === index}
289
- onBlur={(e) => {
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
- onKeyDown={(e) => {
293
- if (e.key === 'Enter') {
294
- e.preventDefault();
295
- handleNameChange(e, index, name);
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.clientX,
113
- y: event.clientY - 50,
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
- let options = [
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.clientX,
96
- y: event.clientY - 50,
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 className="ff-spreadsheet-data-viewer ff-spreadsheet-data-viewer--boolean">
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
- let options = [
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.clientX,
90
- y: event.clientY,
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, handleClickOutside]);
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
- model: new Model(state.model.createFormulaParser, state.model.data),
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
- return { ...state, dragging: false };
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: {