@atlaskit/editor-plugin-table 7.16.11 → 7.16.13
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/.eslintrc.js +3 -3
- package/CHANGELOG.md +16 -0
- package/dist/cjs/commands/misc.js +3 -3
- package/dist/cjs/nodeviews/TableCell.js +10 -10
- package/dist/cjs/nodeviews/TableContainer.js +83 -27
- package/dist/cjs/nodeviews/TableResizer.js +40 -19
- package/dist/cjs/nodeviews/TableRow.js +23 -23
- package/dist/cjs/pm-plugins/table-resizing/plugin.js +3 -3
- package/dist/cjs/pm-plugins/table-resizing/utils/resize-state.js +4 -4
- package/dist/cjs/pm-plugins/table-resizing/utils/scale-table.js +3 -3
- package/dist/cjs/ui/FloatingContextualMenu/styles.js +1 -1
- package/dist/cjs/ui/FloatingDragMenu/styles.js +1 -1
- package/dist/cjs/ui/common-styles.js +13 -13
- package/dist/cjs/ui/ui-styles.js +25 -25
- package/dist/cjs/utils/guidelines.js +7 -4
- package/dist/cjs/utils/merged-cells.js +3 -3
- package/dist/cjs/utils/snapping.js +7 -8
- package/dist/es2019/commands/misc.js +3 -3
- package/dist/es2019/nodeviews/TableContainer.js +70 -9
- package/dist/es2019/nodeviews/TableResizer.js +42 -21
- package/dist/es2019/nodeviews/TableRow.js +21 -21
- package/dist/es2019/pm-plugins/table-resizing/plugin.js +3 -3
- package/dist/es2019/pm-plugins/table-resizing/utils/resize-state.js +4 -4
- package/dist/es2019/pm-plugins/table-resizing/utils/scale-table.js +3 -3
- package/dist/es2019/ui/FloatingContextualMenu/styles.js +47 -47
- package/dist/es2019/ui/FloatingDragMenu/styles.js +30 -30
- package/dist/es2019/ui/common-styles.js +802 -816
- package/dist/es2019/ui/ui-styles.js +665 -678
- package/dist/es2019/utils/guidelines.js +5 -2
- package/dist/es2019/utils/merged-cells.js +3 -3
- package/dist/es2019/utils/snapping.js +5 -6
- package/dist/esm/commands/misc.js +3 -3
- package/dist/esm/nodeviews/TableCell.js +10 -10
- package/dist/esm/nodeviews/TableContainer.js +85 -29
- package/dist/esm/nodeviews/TableResizer.js +42 -21
- package/dist/esm/nodeviews/TableRow.js +23 -23
- package/dist/esm/pm-plugins/table-resizing/plugin.js +3 -3
- package/dist/esm/pm-plugins/table-resizing/utils/resize-state.js +4 -4
- package/dist/esm/pm-plugins/table-resizing/utils/scale-table.js +3 -3
- package/dist/esm/ui/FloatingContextualMenu/styles.js +1 -1
- package/dist/esm/ui/FloatingDragMenu/styles.js +1 -1
- package/dist/esm/ui/common-styles.js +13 -13
- package/dist/esm/ui/ui-styles.js +25 -25
- package/dist/esm/utils/guidelines.js +6 -3
- package/dist/esm/utils/merged-cells.js +3 -3
- package/dist/esm/utils/snapping.js +6 -7
- package/dist/types/nodeviews/TableResizer.d.ts +2 -1
- package/dist/types/pm-plugins/decorations/utils/index.d.ts +1 -1
- package/dist/types/pm-plugins/drag-and-drop/utils/autoscrollers.d.ts +1 -1
- package/dist/types/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +1 -1
- package/dist/types/pm-plugins/table-resizing/utils/index.d.ts +1 -1
- package/dist/types/ui/ColumnResizeWidget/index.d.ts +1 -1
- package/dist/types/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.d.ts +1 -1
- package/dist/types/ui/FloatingToolbarLabel/FloatingToolbarLabel.d.ts +1 -1
- package/dist/types/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.d.ts +1 -1
- package/dist/types/ui/TableFloatingControls/CornerControls/index.d.ts +1 -1
- package/dist/types/ui/icons/DragHandleDisabledIcon.d.ts +1 -1
- package/dist/types/utils/guidelines.d.ts +2 -1
- package/dist/types/utils/snapping.d.ts +3 -2
- package/dist/types-ts4.5/nodeviews/TableResizer.d.ts +2 -1
- package/dist/types-ts4.5/pm-plugins/decorations/utils/index.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/drag-and-drop/utils/autoscrollers.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/drag-and-drop/utils/getDragBehaviour.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/table-resizing/utils/index.d.ts +1 -1
- package/dist/types-ts4.5/ui/ColumnResizeWidget/index.d.ts +1 -1
- package/dist/types-ts4.5/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.d.ts +1 -1
- package/dist/types-ts4.5/ui/FloatingToolbarLabel/FloatingToolbarLabel.d.ts +1 -1
- package/dist/types-ts4.5/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.d.ts +1 -1
- package/dist/types-ts4.5/ui/TableFloatingControls/CornerControls/index.d.ts +1 -1
- package/dist/types-ts4.5/ui/icons/DragHandleDisabledIcon.d.ts +1 -1
- package/dist/types-ts4.5/utils/guidelines.d.ts +2 -1
- package/dist/types-ts4.5/utils/snapping.d.ts +3 -2
- package/docs/0-intro.tsx +9 -7
- package/package.json +3 -3
- package/report.api.md +67 -66
- package/src/commands/clear.ts +36 -44
- package/src/commands/collapse.ts +8 -8
- package/src/commands/column-resize.ts +412 -452
- package/src/commands/delete.ts +14 -14
- package/src/commands/display-mode.ts +10 -11
- package/src/commands/go-to-next-cell.ts +48 -54
- package/src/commands/hover.ts +210 -227
- package/src/commands/index.ts +35 -35
- package/src/commands/insert.ts +208 -235
- package/src/commands/misc.ts +655 -748
- package/src/commands/referentiality.ts +9 -9
- package/src/commands/selection.ts +433 -563
- package/src/commands/sort.ts +68 -86
- package/src/commands/split-cell.ts +14 -14
- package/src/commands/toggle.ts +69 -67
- package/src/commands-with-analytics.ts +570 -639
- package/src/create-plugin-config.ts +13 -13
- package/src/event-handlers.ts +513 -612
- package/src/handlers.ts +120 -133
- package/src/nodeviews/ExternalDropTargets.tsx +68 -73
- package/src/nodeviews/OverflowShadowsObserver.ts +148 -157
- package/src/nodeviews/TableCell.ts +47 -54
- package/src/nodeviews/TableComponent.tsx +1018 -1112
- package/src/nodeviews/TableComponentWithSharedState.tsx +91 -94
- package/src/nodeviews/TableContainer.tsx +384 -340
- package/src/nodeviews/TableNodeViewBase.ts +19 -24
- package/src/nodeviews/TableResizer.tsx +642 -653
- package/src/nodeviews/TableRow.ts +580 -629
- package/src/nodeviews/TableStickyScrollbar.ts +173 -190
- package/src/nodeviews/__mocks__/OverflowShadowsObserver.ts +8 -8
- package/src/nodeviews/__mocks__/OverridableMock.ts +14 -15
- package/src/nodeviews/table.tsx +345 -375
- package/src/nodeviews/types.ts +21 -24
- package/src/nodeviews/update-overflow-shadows.ts +8 -14
- package/src/plugin.tsx +578 -603
- package/src/pm-plugins/analytics/actions.ts +10 -12
- package/src/pm-plugins/analytics/commands.ts +31 -37
- package/src/pm-plugins/analytics/plugin-factory.ts +4 -2
- package/src/pm-plugins/analytics/plugin-key.ts +1 -3
- package/src/pm-plugins/analytics/plugin.ts +60 -70
- package/src/pm-plugins/analytics/reducer.ts +19 -19
- package/src/pm-plugins/analytics/types.ts +10 -10
- package/src/pm-plugins/analytics/utils/moved-event.ts +38 -38
- package/src/pm-plugins/decorations/plugin.ts +58 -77
- package/src/pm-plugins/decorations/utils/column-controls.ts +59 -71
- package/src/pm-plugins/decorations/utils/column-resizing.ts +50 -57
- package/src/pm-plugins/decorations/utils/compose-decorations.ts +6 -6
- package/src/pm-plugins/decorations/utils/index.ts +3 -6
- package/src/pm-plugins/decorations/utils/types.ts +7 -12
- package/src/pm-plugins/default-table-selection.ts +3 -3
- package/src/pm-plugins/drag-and-drop/actions.ts +25 -25
- package/src/pm-plugins/drag-and-drop/commands-with-analytics.ts +158 -190
- package/src/pm-plugins/drag-and-drop/commands.ts +154 -170
- package/src/pm-plugins/drag-and-drop/consts.ts +4 -5
- package/src/pm-plugins/drag-and-drop/plugin-factory.ts +23 -20
- package/src/pm-plugins/drag-and-drop/plugin-key.ts +1 -3
- package/src/pm-plugins/drag-and-drop/plugin.ts +329 -383
- package/src/pm-plugins/drag-and-drop/reducer.ts +30 -30
- package/src/pm-plugins/drag-and-drop/types.ts +8 -8
- package/src/pm-plugins/drag-and-drop/utils/autoscrollers.ts +38 -41
- package/src/pm-plugins/drag-and-drop/utils/getDragBehaviour.ts +3 -6
- package/src/pm-plugins/drag-and-drop/utils/monitor.ts +57 -70
- package/src/pm-plugins/keymap.ts +208 -220
- package/src/pm-plugins/main.ts +348 -400
- package/src/pm-plugins/plugin-factory.ts +32 -34
- package/src/pm-plugins/safari-delete-composition-text-issue-workaround.ts +83 -97
- package/src/pm-plugins/sticky-headers/commands.ts +2 -6
- package/src/pm-plugins/sticky-headers/plugin-key.ts +1 -3
- package/src/pm-plugins/sticky-headers/plugin-state.ts +41 -44
- package/src/pm-plugins/sticky-headers/plugin.ts +4 -4
- package/src/pm-plugins/sticky-headers/types.ts +8 -8
- package/src/pm-plugins/sticky-headers/util.ts +10 -10
- package/src/pm-plugins/table-analytics.ts +70 -72
- package/src/pm-plugins/table-local-id.ts +180 -184
- package/src/pm-plugins/table-resizing/commands.ts +72 -85
- package/src/pm-plugins/table-resizing/event-handlers.ts +298 -317
- package/src/pm-plugins/table-resizing/plugin-factory.ts +10 -10
- package/src/pm-plugins/table-resizing/plugin-key.ts +1 -3
- package/src/pm-plugins/table-resizing/plugin.ts +61 -68
- package/src/pm-plugins/table-resizing/reducer.ts +30 -33
- package/src/pm-plugins/table-resizing/utils/colgroup.ts +84 -84
- package/src/pm-plugins/table-resizing/utils/column-state.ts +78 -81
- package/src/pm-plugins/table-resizing/utils/content-width.ts +94 -114
- package/src/pm-plugins/table-resizing/utils/dom.ts +93 -110
- package/src/pm-plugins/table-resizing/utils/index.ts +29 -34
- package/src/pm-plugins/table-resizing/utils/misc.ts +94 -119
- package/src/pm-plugins/table-resizing/utils/resize-column.ts +93 -106
- package/src/pm-plugins/table-resizing/utils/resize-logic.ts +240 -257
- package/src/pm-plugins/table-resizing/utils/resize-state.ts +343 -372
- package/src/pm-plugins/table-resizing/utils/scale-table.ts +202 -207
- package/src/pm-plugins/table-resizing/utils/types.ts +17 -17
- package/src/pm-plugins/table-resizing/utils/unit-to-number.ts +1 -2
- package/src/pm-plugins/table-selection-keymap.ts +25 -51
- package/src/pm-plugins/table-width.ts +191 -204
- package/src/pm-plugins/view-mode-sort/index.ts +223 -227
- package/src/pm-plugins/view-mode-sort/plugin-key.ts +3 -2
- package/src/pm-plugins/view-mode-sort/types.ts +12 -12
- package/src/pm-plugins/view-mode-sort/utils.ts +108 -117
- package/src/reducer.ts +139 -155
- package/src/toolbar.tsx +815 -905
- package/src/transforms/column-width.ts +186 -213
- package/src/transforms/delete-columns.ts +208 -222
- package/src/transforms/delete-rows.ts +117 -121
- package/src/transforms/fix-tables.ts +190 -215
- package/src/transforms/merge.ts +263 -269
- package/src/transforms/replace-table.ts +27 -43
- package/src/transforms/split.ts +65 -75
- package/src/types.ts +421 -427
- package/src/ui/ColumnResizeWidget/index.tsx +40 -47
- package/src/ui/DragHandle/HandleIconComponent.tsx +9 -13
- package/src/ui/DragHandle/index.tsx +221 -250
- package/src/ui/DragPreview/index.tsx +35 -35
- package/src/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.tsx +33 -41
- package/src/ui/FloatingContextualButton/FixedButton.tsx +154 -157
- package/src/ui/FloatingContextualButton/index.tsx +109 -115
- package/src/ui/FloatingContextualButton/styles.ts +43 -46
- package/src/ui/FloatingContextualMenu/ContextualMenu.tsx +634 -694
- package/src/ui/FloatingContextualMenu/index.tsx +83 -101
- package/src/ui/FloatingContextualMenu/styles.ts +57 -65
- package/src/ui/FloatingDeleteButton/DeleteButton.tsx +37 -37
- package/src/ui/FloatingDeleteButton/getPopUpOptions.ts +47 -57
- package/src/ui/FloatingDeleteButton/index.tsx +319 -350
- package/src/ui/FloatingDragMenu/DragMenu.tsx +555 -596
- package/src/ui/FloatingDragMenu/DropdownMenu.tsx +152 -162
- package/src/ui/FloatingDragMenu/index.tsx +88 -102
- package/src/ui/FloatingDragMenu/styles.ts +51 -54
- package/src/ui/FloatingInsertButton/InsertButton.tsx +204 -217
- package/src/ui/FloatingInsertButton/getPopupOptions.ts +100 -115
- package/src/ui/FloatingInsertButton/index.tsx +248 -292
- package/src/ui/FloatingToolbarLabel/FloatingToolbarLabel.tsx +24 -29
- package/src/ui/TableFloatingColumnControls/ColumnControls/index.tsx +308 -329
- package/src/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.tsx +85 -94
- package/src/ui/TableFloatingColumnControls/ColumnDropTargets/index.tsx +46 -46
- package/src/ui/TableFloatingColumnControls/index.tsx +116 -136
- package/src/ui/TableFloatingControls/CornerControls/ClassicCornerControls.tsx +79 -91
- package/src/ui/TableFloatingControls/CornerControls/DragCornerControls.tsx +95 -102
- package/src/ui/TableFloatingControls/CornerControls/index.tsx +1 -4
- package/src/ui/TableFloatingControls/CornerControls/types.ts +8 -8
- package/src/ui/TableFloatingControls/FloatingControlsWithSelection.tsx +50 -50
- package/src/ui/TableFloatingControls/NumberColumn/index.tsx +111 -124
- package/src/ui/TableFloatingControls/RowControls/ClassicControls.tsx +86 -105
- package/src/ui/TableFloatingControls/RowControls/DragControls.tsx +305 -341
- package/src/ui/TableFloatingControls/RowDropTarget/index.tsx +72 -75
- package/src/ui/TableFloatingControls/index.tsx +191 -193
- package/src/ui/TableFullWidthLabel/index.tsx +20 -20
- package/src/ui/common-styles.ts +880 -912
- package/src/ui/consts.ts +29 -74
- package/src/ui/icons/AddColLeftIcon.tsx +33 -39
- package/src/ui/icons/AddColRightIcon.tsx +33 -39
- package/src/ui/icons/AddRowAboveIcon.tsx +16 -22
- package/src/ui/icons/AddRowBelowIcon.tsx +33 -39
- package/src/ui/icons/DisplayModeIcon.tsx +31 -31
- package/src/ui/icons/DragHandleDisabledIcon.tsx +19 -21
- package/src/ui/icons/DragHandleIcon.tsx +12 -12
- package/src/ui/icons/DragInMotionIcon.tsx +45 -52
- package/src/ui/icons/MergeCellsIcon.tsx +22 -28
- package/src/ui/icons/MinimisedHandle.tsx +9 -9
- package/src/ui/icons/SplitCellIcon.tsx +30 -36
- package/src/ui/ui-styles.ts +769 -798
- package/src/utils/alignment.ts +1 -1
- package/src/utils/analytics.ts +192 -208
- package/src/utils/collapse.ts +55 -64
- package/src/utils/column-controls.ts +237 -254
- package/src/utils/create.ts +30 -30
- package/src/utils/decoration.ts +482 -502
- package/src/utils/dom.ts +127 -134
- package/src/utils/drag-menu.ts +322 -373
- package/src/utils/get-allow-add-column-custom-step.ts +4 -5
- package/src/utils/guidelines.ts +16 -21
- package/src/utils/index.ts +68 -68
- package/src/utils/merged-cells.ts +245 -254
- package/src/utils/nodes.ts +91 -106
- package/src/utils/paste.ts +119 -135
- package/src/utils/row-controls.ts +199 -213
- package/src/utils/selection.ts +77 -87
- package/src/utils/snapping.ts +87 -100
- package/src/utils/table.ts +44 -44
- package/src/utils/transforms.ts +5 -5
- package/src/utils/update-plugin-state-decorations.ts +5 -9
|
@@ -5,20 +5,14 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
|
5
5
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
6
6
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
7
7
|
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
8
|
-
import {
|
|
9
|
-
getCellsInRow,
|
|
10
|
-
getSelectedCellInfo,
|
|
11
|
-
} from '@atlaskit/editor-tables/utils';
|
|
8
|
+
import { getCellsInRow, getSelectedCellInfo } from '@atlaskit/editor-tables/utils';
|
|
12
9
|
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
13
10
|
import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
|
|
14
11
|
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
|
15
12
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
16
13
|
|
|
17
14
|
import type { DraggableSourceData } from '../../types';
|
|
18
|
-
import {
|
|
19
|
-
findNearestCellIndexToPoint,
|
|
20
|
-
hasMergedCellsInBetween,
|
|
21
|
-
} from '../../utils';
|
|
15
|
+
import { findNearestCellIndexToPoint, hasMergedCellsInBetween } from '../../utils';
|
|
22
16
|
import { getPluginState as getTablePluginState } from '../plugin-factory';
|
|
23
17
|
import { pluginKey as tablePluginKey } from '../plugin-key';
|
|
24
18
|
import { insertColgroupFromNode } from '../table-resizing/utils';
|
|
@@ -26,9 +20,9 @@ import { insertColgroupFromNode } from '../table-resizing/utils';
|
|
|
26
20
|
import { DragAndDropActionType } from './actions';
|
|
27
21
|
import { clearDropTarget, setDropTarget, toggleDragMenu } from './commands';
|
|
28
22
|
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
clearDropTargetWithAnalytics,
|
|
24
|
+
cloneSourceWithAnalytics,
|
|
25
|
+
moveSourceWithAnalytics,
|
|
32
26
|
} from './commands-with-analytics';
|
|
33
27
|
import { DropTargetType } from './consts';
|
|
34
28
|
import { createPluginState, getPluginState } from './plugin-factory';
|
|
@@ -36,378 +30,330 @@ import { pluginKey } from './plugin-key';
|
|
|
36
30
|
import { getDraggableDataFromEvent } from './utils/monitor';
|
|
37
31
|
|
|
38
32
|
const destroyFn = (editorView: EditorView, editorAnalyticsAPI: any) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
let isTableScalingEnabledOnCurrentTable = isTableScalingEnabled;
|
|
241
|
-
if (
|
|
242
|
-
isTableScalingEnabled &&
|
|
243
|
-
getBooleanFF(
|
|
244
|
-
'platform.editor.table.preserve-widths-with-lock-button',
|
|
245
|
-
)
|
|
246
|
-
) {
|
|
247
|
-
isTableScalingEnabledOnCurrentTable =
|
|
248
|
-
tableNode.attrs.displayMode !== 'fixed';
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
insertColgroupFromNode(
|
|
252
|
-
tableRef,
|
|
253
|
-
tableNode,
|
|
254
|
-
isTableScalingEnabledOnCurrentTable,
|
|
255
|
-
);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
editorView.focus();
|
|
260
|
-
});
|
|
261
|
-
},
|
|
262
|
-
}),
|
|
263
|
-
);
|
|
33
|
+
const editorPageScrollContainer = document.querySelector('.fabric-editor-popup-scroll-parent');
|
|
34
|
+
|
|
35
|
+
const rowAutoScrollers = editorPageScrollContainer
|
|
36
|
+
? [
|
|
37
|
+
monitorForElements({
|
|
38
|
+
canMonitor({ source }) {
|
|
39
|
+
const { type } = source.data as Partial<DraggableSourceData>;
|
|
40
|
+
return type === 'table-row';
|
|
41
|
+
},
|
|
42
|
+
onDragStart() {
|
|
43
|
+
// auto scroller doesn't work when scroll-behavior: smooth is set, this monitor temporarily removes it via inline styles
|
|
44
|
+
(editorPageScrollContainer as HTMLElement).style.setProperty(
|
|
45
|
+
'scroll-behavior',
|
|
46
|
+
'unset',
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
onDrop() {
|
|
50
|
+
// 'null' will remove the inline style
|
|
51
|
+
(editorPageScrollContainer as HTMLElement).style.setProperty('scroll-behavior', null);
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
autoScrollForElements({
|
|
55
|
+
element: editorPageScrollContainer as HTMLElement,
|
|
56
|
+
canScroll: ({ source }) => {
|
|
57
|
+
const { type } = source.data as Partial<DraggableSourceData>;
|
|
58
|
+
return type === 'table-row';
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
61
|
+
]
|
|
62
|
+
: [];
|
|
63
|
+
|
|
64
|
+
return combine(
|
|
65
|
+
...rowAutoScrollers,
|
|
66
|
+
monitorForElements({
|
|
67
|
+
canMonitor({ source }) {
|
|
68
|
+
const { type, localId, indexes } = source.data as Partial<DraggableSourceData>;
|
|
69
|
+
|
|
70
|
+
// First; Perform any quick checks so we can abort early.
|
|
71
|
+
if (!indexes || !localId || !(type === 'table-row' || type === 'table-column')) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { tableNode } = getTablePluginState(editorView.state);
|
|
76
|
+
// If the draggable localId is the same as the current selected table localId then we will allow the monitor
|
|
77
|
+
// watch for changes
|
|
78
|
+
return localId === tableNode?.attrs.localId;
|
|
79
|
+
},
|
|
80
|
+
onDragStart: ({ location }) => {
|
|
81
|
+
toggleDragMenu(false)(editorView.state, editorView.dispatch);
|
|
82
|
+
},
|
|
83
|
+
onDrag(event) {
|
|
84
|
+
const data = getDraggableDataFromEvent(event);
|
|
85
|
+
// If no data can be found then it's most like we do not want to perform any drag actions
|
|
86
|
+
if (!data) {
|
|
87
|
+
clearDropTarget()(editorView.state, editorView.dispatch);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// TODO: as we drag an element around we are going to want to update the state to acurately reflect the current
|
|
92
|
+
// insert location as to where the draggable will most likely be go. For example;
|
|
93
|
+
const { sourceType, targetAdjustedIndex } = data;
|
|
94
|
+
const dropTargetType =
|
|
95
|
+
sourceType === 'table-row' ? DropTargetType.ROW : DropTargetType.COLUMN;
|
|
96
|
+
|
|
97
|
+
const hasMergedCells = hasMergedCellsInBetween(
|
|
98
|
+
[targetAdjustedIndex - 1, targetAdjustedIndex],
|
|
99
|
+
dropTargetType,
|
|
100
|
+
)(editorView.state.selection);
|
|
101
|
+
|
|
102
|
+
setDropTarget(
|
|
103
|
+
dropTargetType,
|
|
104
|
+
targetAdjustedIndex,
|
|
105
|
+
hasMergedCells,
|
|
106
|
+
)(editorView.state, editorView.dispatch);
|
|
107
|
+
},
|
|
108
|
+
onDrop(event) {
|
|
109
|
+
const data = getDraggableDataFromEvent(event);
|
|
110
|
+
|
|
111
|
+
// On Drop we need to update the table main plugin hoveredCell value with the current row/col that the mouse is
|
|
112
|
+
// over. This is so the drag handles update their positions to correctly align with the users mouse. Unfortunately
|
|
113
|
+
// at this point in time and during the drag opertation, the drop targets are eating all the mouse events so
|
|
114
|
+
// it's not possible to know what row/col the mouse is over (via mouse events). This attempts to locate the nearest cell and
|
|
115
|
+
// then tries to update the main table hoveredCell value by piggy-backing the transaction onto the command
|
|
116
|
+
// triggered by this on drop event.
|
|
117
|
+
const { hoveredCell } = getTablePluginState(editorView.state);
|
|
118
|
+
|
|
119
|
+
const cell = findNearestCellIndexToPoint(
|
|
120
|
+
event.location.current.input.clientX,
|
|
121
|
+
event.location.current.input.clientY,
|
|
122
|
+
);
|
|
123
|
+
const tr = editorView.state.tr;
|
|
124
|
+
const action = {
|
|
125
|
+
type: 'HOVER_CELL',
|
|
126
|
+
data: {
|
|
127
|
+
hoveredCell: {
|
|
128
|
+
rowIndex: cell?.row ?? hoveredCell.rowIndex,
|
|
129
|
+
colIndex: cell?.col ?? hoveredCell.colIndex,
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
tr.setMeta(tablePluginKey, action);
|
|
134
|
+
|
|
135
|
+
// If no data can be found then it's most like we do not want to perform any drop action
|
|
136
|
+
if (!data) {
|
|
137
|
+
// If we're able to determine the source type of the dropped element then we should report to analytics that
|
|
138
|
+
// the drop event was cancelled. Otherwise we will cancel silently.
|
|
139
|
+
if (
|
|
140
|
+
event?.source?.data?.type === 'table-row' ||
|
|
141
|
+
event?.source?.data?.type === 'table-column'
|
|
142
|
+
) {
|
|
143
|
+
return clearDropTargetWithAnalytics(editorAnalyticsAPI)(
|
|
144
|
+
INPUT_METHOD.DRAG_AND_DROP,
|
|
145
|
+
event.source.data.type,
|
|
146
|
+
event.source.data?.indexes as number[] | undefined,
|
|
147
|
+
TABLE_STATUS.CANCELLED,
|
|
148
|
+
tr,
|
|
149
|
+
)(editorView.state, editorView.dispatch);
|
|
150
|
+
}
|
|
151
|
+
return clearDropTarget(tr)(editorView.state, editorView.dispatch);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const {
|
|
155
|
+
sourceType,
|
|
156
|
+
sourceIndexes,
|
|
157
|
+
targetIndex,
|
|
158
|
+
targetAdjustedIndex,
|
|
159
|
+
targetDirection,
|
|
160
|
+
direction,
|
|
161
|
+
behaviour,
|
|
162
|
+
} = data;
|
|
163
|
+
|
|
164
|
+
// When we drop on a target we will know the targets row/col index for certain,
|
|
165
|
+
if (sourceType === 'table-row') {
|
|
166
|
+
action.data.hoveredCell.rowIndex = targetIndex;
|
|
167
|
+
} else {
|
|
168
|
+
action.data.hoveredCell.colIndex = targetIndex;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// If the drop target index contains merged cells then we should not allow the drop to occur.
|
|
172
|
+
if (
|
|
173
|
+
hasMergedCellsInBetween(
|
|
174
|
+
[targetAdjustedIndex - 1, targetAdjustedIndex],
|
|
175
|
+
sourceType === 'table-row' ? DropTargetType.ROW : DropTargetType.COLUMN,
|
|
176
|
+
)(editorView.state.selection)
|
|
177
|
+
) {
|
|
178
|
+
clearDropTargetWithAnalytics(editorAnalyticsAPI)(
|
|
179
|
+
INPUT_METHOD.DRAG_AND_DROP,
|
|
180
|
+
sourceType,
|
|
181
|
+
sourceIndexes,
|
|
182
|
+
// This event is mrked as invalid because the user is attempting to drop an element in an area which has merged cells.
|
|
183
|
+
TABLE_STATUS.INVALID,
|
|
184
|
+
tr,
|
|
185
|
+
)(editorView.state, editorView.dispatch);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
requestAnimationFrame(() => {
|
|
190
|
+
if (behaviour === 'clone') {
|
|
191
|
+
cloneSourceWithAnalytics(editorAnalyticsAPI)(
|
|
192
|
+
INPUT_METHOD.DRAG_AND_DROP,
|
|
193
|
+
sourceType,
|
|
194
|
+
sourceIndexes,
|
|
195
|
+
targetIndex,
|
|
196
|
+
targetDirection,
|
|
197
|
+
tr,
|
|
198
|
+
)(editorView.state, editorView.dispatch);
|
|
199
|
+
} else {
|
|
200
|
+
moveSourceWithAnalytics(editorAnalyticsAPI)(
|
|
201
|
+
INPUT_METHOD.DRAG_AND_DROP,
|
|
202
|
+
sourceType,
|
|
203
|
+
sourceIndexes,
|
|
204
|
+
targetAdjustedIndex + (direction === 1 ? -1 : 0),
|
|
205
|
+
tr,
|
|
206
|
+
)(editorView.state, editorView.dispatch);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// force a colgroup update here, otherwise dropped columns don't have
|
|
210
|
+
// the correct width immediately after the drop
|
|
211
|
+
if (sourceType === 'table-column') {
|
|
212
|
+
const { tableRef, tableNode } = getTablePluginState(editorView.state);
|
|
213
|
+
if (tableRef && tableNode) {
|
|
214
|
+
const { isTableScalingEnabled = false } = getTablePluginState(editorView.state);
|
|
215
|
+
|
|
216
|
+
let isTableScalingEnabledOnCurrentTable = isTableScalingEnabled;
|
|
217
|
+
if (
|
|
218
|
+
isTableScalingEnabled &&
|
|
219
|
+
getBooleanFF('platform.editor.table.preserve-widths-with-lock-button')
|
|
220
|
+
) {
|
|
221
|
+
isTableScalingEnabledOnCurrentTable = tableNode.attrs.displayMode !== 'fixed';
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
insertColgroupFromNode(tableRef, tableNode, isTableScalingEnabledOnCurrentTable);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
editorView.focus();
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
}),
|
|
232
|
+
);
|
|
264
233
|
};
|
|
265
234
|
|
|
266
|
-
export const createPlugin = (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
const keysToTrap = ['Enter', ' '];
|
|
391
|
-
|
|
392
|
-
const { isDragMenuOpen } = getPluginState(view.state);
|
|
393
|
-
|
|
394
|
-
// drag handle is focused, and user presses any key return them back to editing
|
|
395
|
-
if (
|
|
396
|
-
isDragHandleFocused &&
|
|
397
|
-
!isDragMenuOpen &&
|
|
398
|
-
!keysToTrap.includes(event.key)
|
|
399
|
-
) {
|
|
400
|
-
view.dom.focus();
|
|
401
|
-
return true;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
if (
|
|
405
|
-
(isDragHandleFocused && keysToTrap.includes(event.key)) ||
|
|
406
|
-
(isDragMenuOpen && keysToTrapWhen.includes(event.key))
|
|
407
|
-
) {
|
|
408
|
-
return true;
|
|
409
|
-
}
|
|
410
|
-
},
|
|
411
|
-
},
|
|
412
|
-
});
|
|
235
|
+
export const createPlugin = (dispatch: Dispatch, editorAnalyticsAPI?: EditorAnalyticsAPI) => {
|
|
236
|
+
return new SafePlugin({
|
|
237
|
+
state: createPluginState(dispatch, (state) => ({
|
|
238
|
+
decorationSet: DecorationSet.empty,
|
|
239
|
+
dropTargetType: DropTargetType.NONE,
|
|
240
|
+
dropTargetIndex: 0,
|
|
241
|
+
isDragMenuOpen: false,
|
|
242
|
+
dragMenuIndex: 0,
|
|
243
|
+
isDragging: false,
|
|
244
|
+
isKeyboardModeActive: false,
|
|
245
|
+
})),
|
|
246
|
+
key: pluginKey,
|
|
247
|
+
appendTransaction: (transactions, oldState, newState) => {
|
|
248
|
+
const { targetCellPosition: oldTargetCellPosition } = getTablePluginState(oldState);
|
|
249
|
+
const { targetCellPosition: newTargetCellPosition } = getTablePluginState(newState);
|
|
250
|
+
const { isDragMenuOpen, dragMenuIndex } = getPluginState(newState);
|
|
251
|
+
|
|
252
|
+
transactions.forEach((transaction) => {
|
|
253
|
+
if (transaction.getMeta('selectedRowViaKeyboard')) {
|
|
254
|
+
const button = document.querySelector('#drag-handle-button-row');
|
|
255
|
+
if (button) {
|
|
256
|
+
(button as HTMLButtonElement).focus();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (transaction.getMeta('selectedColumnViaKeyboard')) {
|
|
260
|
+
const button = document.querySelector('#drag-handle-button-column');
|
|
261
|
+
if (button) {
|
|
262
|
+
(button as HTMLButtonElement).focus();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// What's happening here? you asked... In a nutshell;
|
|
268
|
+
// If the target cell position changes while the drag menu is open then we want to close the drag menu if it has been opened.
|
|
269
|
+
// This will stop the drag menu from moving around the screen to different row/cols. Too achieve this we need
|
|
270
|
+
// to check if the new target cell position is pointed at a different cell than what the drag menu was opened on.
|
|
271
|
+
if (oldTargetCellPosition !== newTargetCellPosition) {
|
|
272
|
+
if (isDragMenuOpen) {
|
|
273
|
+
const tr = newState.tr;
|
|
274
|
+
const action = {
|
|
275
|
+
type: DragAndDropActionType.TOGGLE_DRAG_MENU,
|
|
276
|
+
data: {
|
|
277
|
+
isDragMenuOpen: false,
|
|
278
|
+
direction: undefined,
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
if (newTargetCellPosition !== undefined) {
|
|
283
|
+
const cells = getCellsInRow(dragMenuIndex)(tr.selection);
|
|
284
|
+
// ED-20673 check if it is a cell selection,
|
|
285
|
+
// when true, a drag handle is clicked and isDragMenuOpen is true here
|
|
286
|
+
// should not close the drag menu.
|
|
287
|
+
const isCellSelection = tr.selection instanceof CellSelection;
|
|
288
|
+
if (
|
|
289
|
+
cells &&
|
|
290
|
+
cells.length &&
|
|
291
|
+
cells[0].node !== tr.doc.nodeAt(newTargetCellPosition) &&
|
|
292
|
+
!isCellSelection
|
|
293
|
+
) {
|
|
294
|
+
return tr.setMeta(pluginKey, action);
|
|
295
|
+
} // else NOP
|
|
296
|
+
} else {
|
|
297
|
+
return tr.setMeta(pluginKey, action);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
view: (editorView: EditorView) => {
|
|
303
|
+
return {
|
|
304
|
+
destroy: destroyFn(editorView, editorAnalyticsAPI),
|
|
305
|
+
};
|
|
306
|
+
},
|
|
307
|
+
props: {
|
|
308
|
+
decorations: (state) => {
|
|
309
|
+
const { decorationSet } = getPluginState(state);
|
|
310
|
+
return decorationSet;
|
|
311
|
+
},
|
|
312
|
+
handleKeyDown: (view, event) => {
|
|
313
|
+
const {
|
|
314
|
+
state: { tr },
|
|
315
|
+
} = view;
|
|
316
|
+
|
|
317
|
+
const keysToTrapWhen = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
|
|
318
|
+
|
|
319
|
+
/** fix for NCS spam update where the user is holding down the move column / row keyboard shortcut
|
|
320
|
+
* if the user is holding down shortcut (ctrl + shift + alt + arrowKey), we want to move the selection only once
|
|
321
|
+
* See ticket ED-22154 https://product-fabric.atlassian.net/browse/ED-22154
|
|
322
|
+
*/
|
|
323
|
+
|
|
324
|
+
// Do early check for the keys we want to trap here so we can abort early
|
|
325
|
+
if (event.ctrlKey && event.shiftKey && event.altKey) {
|
|
326
|
+
const { verticalCells, horizontalCells, totalRowCount, totalColumnCount } =
|
|
327
|
+
getSelectedCellInfo(tr.selection);
|
|
328
|
+
|
|
329
|
+
const isRowOrColumnSelected =
|
|
330
|
+
horizontalCells === totalColumnCount || verticalCells === totalRowCount;
|
|
331
|
+
if (isRowOrColumnSelected && keysToTrapWhen.includes(event.key) && event.repeat) {
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const isDragHandleFocused = [
|
|
337
|
+
'drag-handle-button-row',
|
|
338
|
+
'drag-handle-button-column',
|
|
339
|
+
].includes(((event.target as HTMLElement) || null)?.id);
|
|
340
|
+
const keysToTrap = ['Enter', ' '];
|
|
341
|
+
|
|
342
|
+
const { isDragMenuOpen } = getPluginState(view.state);
|
|
343
|
+
|
|
344
|
+
// drag handle is focused, and user presses any key return them back to editing
|
|
345
|
+
if (isDragHandleFocused && !isDragMenuOpen && !keysToTrap.includes(event.key)) {
|
|
346
|
+
view.dom.focus();
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (
|
|
351
|
+
(isDragHandleFocused && keysToTrap.includes(event.key)) ||
|
|
352
|
+
(isDragMenuOpen && keysToTrapWhen.includes(event.key))
|
|
353
|
+
) {
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
});
|
|
413
359
|
};
|