@atlaskit/editor-plugin-table 1.2.0 → 1.2.2

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 (107) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/cjs/i18n/en.js +43 -0
  3. package/dist/cjs/i18n/en_GB.js +43 -0
  4. package/dist/cjs/plugins/table/index.js +2 -1
  5. package/dist/cjs/plugins/table/nodeviews/OverflowShadowsObserver.js +13 -26
  6. package/dist/cjs/plugins/table/nodeviews/TableComponent.js +18 -3
  7. package/dist/cjs/plugins/table/nodeviews/table.js +7 -0
  8. package/dist/cjs/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +32 -17
  9. package/dist/cjs/plugins/table/pm-plugins/table-resizing/event-handlers.js +1 -5
  10. package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/misc.js +3 -38
  11. package/dist/cjs/plugins/table/transforms/delete-rows.js +1 -1
  12. package/dist/cjs/plugins/table/transforms/index.js +3 -3
  13. package/dist/cjs/plugins/table/transforms/merge.js +39 -54
  14. package/dist/cjs/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +16 -3
  15. package/dist/cjs/plugins/table/ui/FloatingContextualMenu/index.js +6 -3
  16. package/dist/cjs/plugins/table/ui/common-styles.js +2 -2
  17. package/dist/cjs/plugins/table/utils/row-controls.js +3 -2
  18. package/dist/cjs/types/i18n.js +5 -0
  19. package/dist/cjs/version.json +1 -1
  20. package/dist/es2019/i18n/en.js +36 -0
  21. package/dist/es2019/i18n/en_GB.js +36 -0
  22. package/dist/es2019/plugins/table/index.js +2 -1
  23. package/dist/es2019/plugins/table/nodeviews/OverflowShadowsObserver.js +13 -26
  24. package/dist/es2019/plugins/table/nodeviews/TableComponent.js +22 -3
  25. package/dist/es2019/plugins/table/nodeviews/table.js +7 -0
  26. package/dist/es2019/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +32 -17
  27. package/dist/es2019/plugins/table/pm-plugins/table-resizing/event-handlers.js +1 -5
  28. package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/misc.js +1 -37
  29. package/dist/es2019/plugins/table/transforms/delete-rows.js +2 -2
  30. package/dist/es2019/plugins/table/transforms/index.js +1 -1
  31. package/dist/es2019/plugins/table/transforms/merge.js +39 -43
  32. package/dist/es2019/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +18 -4
  33. package/dist/es2019/plugins/table/ui/FloatingContextualMenu/index.js +6 -3
  34. package/dist/es2019/plugins/table/ui/common-styles.js +21 -1
  35. package/dist/es2019/plugins/table/utils/row-controls.js +3 -2
  36. package/dist/es2019/types/i18n.js +1 -0
  37. package/dist/es2019/version.json +1 -1
  38. package/dist/esm/i18n/en.js +36 -0
  39. package/dist/esm/i18n/en_GB.js +36 -0
  40. package/dist/esm/plugins/table/index.js +2 -1
  41. package/dist/esm/plugins/table/nodeviews/OverflowShadowsObserver.js +13 -26
  42. package/dist/esm/plugins/table/nodeviews/TableComponent.js +18 -3
  43. package/dist/esm/plugins/table/nodeviews/table.js +7 -0
  44. package/dist/esm/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +32 -17
  45. package/dist/esm/plugins/table/pm-plugins/table-resizing/event-handlers.js +1 -5
  46. package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/misc.js +1 -35
  47. package/dist/esm/plugins/table/transforms/delete-rows.js +2 -2
  48. package/dist/esm/plugins/table/transforms/index.js +1 -1
  49. package/dist/esm/plugins/table/transforms/merge.js +38 -53
  50. package/dist/esm/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +17 -4
  51. package/dist/esm/plugins/table/ui/FloatingContextualMenu/index.js +6 -3
  52. package/dist/esm/plugins/table/ui/common-styles.js +2 -2
  53. package/dist/esm/plugins/table/utils/row-controls.js +3 -2
  54. package/dist/esm/types/i18n.js +1 -0
  55. package/dist/esm/version.json +1 -1
  56. package/dist/types/i18n/en.d.ts +35 -0
  57. package/dist/types/i18n/en_GB.d.ts +35 -0
  58. package/dist/types/plugins/table/nodeviews/OverflowShadowsObserver.d.ts +4 -5
  59. package/dist/types/plugins/table/nodeviews/TableComponent.d.ts +1 -0
  60. package/dist/types/plugins/table/nodeviews/__mocks__/OverflowShadowsObserver.d.ts +3 -3
  61. package/dist/types/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +2 -2
  62. package/dist/types/plugins/table/pm-plugins/table-resizing/utils/misc.d.ts +1 -2
  63. package/dist/types/plugins/table/transforms/index.d.ts +1 -1
  64. package/dist/types/plugins/table/transforms/merge.d.ts +1 -1
  65. package/dist/types/plugins/table/types.d.ts +2 -0
  66. package/dist/types/plugins/table/ui/FloatingContextualMenu/ContextualMenu.d.ts +2 -1
  67. package/dist/types/plugins/table/ui/FloatingContextualMenu/index.d.ts +3 -2
  68. package/dist/types/types/i18n.d.ts +5 -0
  69. package/package.json +10 -9
  70. package/src/__tests__/integration/__fixtures__/table-and-paragraph-adf.ts +130 -0
  71. package/src/__tests__/integration/horizontal-scroll-shadows.ts +199 -0
  72. package/src/__tests__/integration/horizontal-scroll.ts +4 -9
  73. package/src/__tests__/integration/meta-arrowup-cursor-in-first-row.ts +4 -2
  74. package/src/__tests__/integration/sticky-header.ts +61 -1
  75. package/src/__tests__/unit/commands/insert.ts +8 -8
  76. package/src/__tests__/unit/commands/sort.ts +4 -0
  77. package/src/__tests__/unit/commands.ts +2 -0
  78. package/src/__tests__/unit/index.ts +2 -0
  79. package/src/__tests__/unit/keymap.ts +4 -2
  80. package/src/__tests__/unit/layout.ts +2 -0
  81. package/src/__tests__/unit/nodeviews/OverflowShadowsObserver.ts +20 -11
  82. package/src/__tests__/unit/nodeviews/cell.ts +14 -0
  83. package/src/__tests__/unit/pm-plugins/main-with-allow-collapse.ts +2 -0
  84. package/src/__tests__/unit/pm-plugins/sticky-headers/tableRow.tsx +2 -2
  85. package/src/__tests__/unit/transforms/delete-rows.ts +45 -0
  86. package/src/__tests__/unit/ui/ContextualMenu.tsx +2 -0
  87. package/src/__tests__/unit/ui/FloatingContextualMenu.tsx +1 -0
  88. package/src/__tests__/unit/utils/collapse.ts +4 -1
  89. package/src/i18n/en.ts +36 -0
  90. package/src/i18n/en_GB.ts +36 -0
  91. package/src/plugins/table/index.tsx +4 -0
  92. package/src/plugins/table/nodeviews/OverflowShadowsObserver.ts +24 -40
  93. package/src/plugins/table/nodeviews/TableComponent.tsx +20 -4
  94. package/src/plugins/table/nodeviews/__mocks__/OverflowShadowsObserver.ts +3 -3
  95. package/src/plugins/table/nodeviews/table.tsx +12 -0
  96. package/src/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.ts +40 -23
  97. package/src/plugins/table/pm-plugins/table-resizing/event-handlers.ts +1 -9
  98. package/src/plugins/table/pm-plugins/table-resizing/utils/misc.ts +1 -57
  99. package/src/plugins/table/transforms/delete-rows.ts +2 -2
  100. package/src/plugins/table/transforms/index.ts +1 -1
  101. package/src/plugins/table/transforms/merge.ts +41 -43
  102. package/src/plugins/table/ui/FloatingContextualMenu/ContextualMenu.tsx +21 -2
  103. package/src/plugins/table/ui/FloatingContextualMenu/index.tsx +8 -1
  104. package/src/plugins/table/ui/common-styles.ts +21 -0
  105. package/src/plugins/table/utils/row-controls.ts +3 -2
  106. package/src/types/i18n.ts +5 -0
  107. package/src/__tests__/integration/__fixtures__/table-and-paragraph-adf.json +0 -130
@@ -8,7 +8,7 @@ import {
8
8
  goToEditorTestingWDExample,
9
9
  mountEditor,
10
10
  } from '@atlaskit/editor-test-helpers/testing-example-page';
11
- import tableAdf from './__fixtures__/table-and-paragraph-adf.json';
11
+ import tableAdf from './__fixtures__/table-and-paragraph-adf';
12
12
 
13
13
  BrowserTestCase(
14
14
  'meta-arrowup-cursor-in-first-row.ts: pressing command/ctrl + arrow up should move cursor into first row',
@@ -20,7 +20,9 @@ BrowserTestCase(
20
20
  );
21
21
  await mountEditor(page, {
22
22
  appearance: fullpage.appearance,
23
- allowTables: {},
23
+ allowTables: {
24
+ advanced: true,
25
+ },
24
26
  defaultValue: tableAdf,
25
27
  });
26
28
 
@@ -3,6 +3,7 @@ import { BrowserTestCase } from '@atlaskit/webdriver-runner/runner';
3
3
  import {
4
4
  fullpage,
5
5
  tableSelectors,
6
+ toggleBreakout,
6
7
  } from '@atlaskit/editor-test-helpers/integration/helpers';
7
8
  import {
8
9
  goToEditorTestingWDExample,
@@ -22,6 +23,15 @@ const scrollTo = async (page: WebdriverPage, height: number) => {
22
23
  );
23
24
  };
24
25
 
26
+ // const resizeScrollParent = async (page: WebdriverPage) => {
27
+ // const editorScrollParentSelector = '.ak-editor-fp-content-area';
28
+ // await page.execute((editorScrollParentSelector: string) => {
29
+ // const editor = document.querySelector(editorScrollParentSelector);
30
+ // console.log('editort', editor);
31
+ // editor && editor.setAttribute('width', '1000px');
32
+ // }, editorScrollParentSelector);
33
+ // };
34
+
25
35
  const insertColumn = async (page: any, cell: 'first' | 'last') => {
26
36
  const columnControl = tableSelectors.nthColumnControl(1);
27
37
  const insertButton = tableSelectors.insertButton;
@@ -41,9 +51,12 @@ const insertColumn = async (page: any, cell: 'first' | 'last') => {
41
51
  await page.click(insertButton);
42
52
  };
43
53
 
54
+ // FIXME: This test was automatically skipped due to failure on 01/04/2023: https://product-fabric.atlassian.net/browse/ED-17364
44
55
  BrowserTestCase(
45
56
  'Sticky header should correctly toggle on and off',
46
- { skip: [] },
57
+ {
58
+ skip: ['*'],
59
+ },
47
60
  async (client: any, testName: string) => {
48
61
  const page = await goToEditorTestingWDExample(
49
62
  client,
@@ -158,3 +171,50 @@ BrowserTestCase(
158
171
  expect(!numberedColStyle.includes('top')).toBeTruthy();
159
172
  },
160
173
  );
174
+
175
+ BrowserTestCase(
176
+ 'Sticky header should resize when the width of parent scroll container changes',
177
+ {},
178
+ async (client: any, testName: string) => {
179
+ const page = await goToEditorTestingWDExample(
180
+ client,
181
+ 'editor-plugin-table',
182
+ );
183
+
184
+ await mountEditor(page, {
185
+ appearance: fullpage.appearance,
186
+ defaultValue: JSON.stringify(stickyTable),
187
+ allowTables: {
188
+ advanced: true,
189
+ stickyHeaders: true,
190
+ },
191
+ featureFlags: {
192
+ stickyHeadersOptimization: true,
193
+ },
194
+ });
195
+
196
+ await page.waitForSelector('table');
197
+
198
+ await toggleBreakout(page, 2);
199
+
200
+ await scrollTo(page, window.innerHeight * 100);
201
+
202
+ await page.execute(() => {
203
+ const editorScrollParentSelector = '.fabric-editor-popup-scroll-parent';
204
+ const editor = document.querySelector(
205
+ editorScrollParentSelector,
206
+ ) as HTMLElement;
207
+ if (editor) {
208
+ editor.style.flexGrow = '0';
209
+ editor.style.width = '750px';
210
+ }
211
+ });
212
+
213
+ const table = await page.$(tableSelectors.stickyTable);
214
+ const tableWidth = await table.getSize();
215
+ const stickyHeader = await page.$(tableSelectors.stickyTr);
216
+ const stickyHeaderWidth = await stickyHeader.getSize();
217
+
218
+ expect(tableWidth.width).toEqual(stickyHeaderWidth.width);
219
+ },
220
+ );
@@ -37,14 +37,14 @@ describe('table plugin: insert', () => {
37
37
 
38
38
  const createEditor = createProsemirrorEditorFactory();
39
39
 
40
- const preset = new Preset<LightEditorPlugin>();
41
- preset.add([
42
- tablePlugin,
43
- {
44
- tableOptions: {},
45
- },
46
- ]);
47
- preset.add(widthPlugin);
40
+ const preset = new Preset<LightEditorPlugin>()
41
+ .add([
42
+ tablePlugin,
43
+ {
44
+ tableOptions: {},
45
+ },
46
+ ])
47
+ .add(widthPlugin);
48
48
 
49
49
  const editor = (doc: DocBuilder) =>
50
50
  createEditor<TablePluginState, PluginKey>({
@@ -22,8 +22,10 @@ import { TableSortOrder as SortOrder } from '@atlaskit/adf-schema/steps';
22
22
  import tablePlugin from '../../../plugins/table-plugin';
23
23
  import statusPlugin from '@atlaskit/editor-core/src/plugins/status';
24
24
  import mentionsPlugin from '@atlaskit/editor-core/src/plugins/mentions';
25
+ import editorDisabledPlugin from '@atlaskit/editor-core/src/plugins/editor-disabled';
25
26
  import hyperlinkPlugin from '@atlaskit/editor-core/src/plugins/hyperlink';
26
27
  import datePlugin from '@atlaskit/editor-core/src/plugins/date';
28
+ import featureFlagsPlugin from '@atlaskit/editor-plugin-feature-flags';
27
29
 
28
30
  const TABLE_LOCAL_ID = 'test-table-local-id';
29
31
 
@@ -118,6 +120,8 @@ describe('Sort Table', () => {
118
120
  beforeEach(() => {
119
121
  ({ editorView } = createEditor({
120
122
  preset: new Preset<LightEditorPlugin>()
123
+ .add([featureFlagsPlugin, {}])
124
+ .add(editorDisabledPlugin)
121
125
  .add([tablePlugin, { tableOptions: { allowHeaderRow: true } }])
122
126
  .add([statusPlugin, { menuDisabled: false }])
123
127
  .add(mentionsPlugin)
@@ -60,6 +60,7 @@ import expandPlugin from '@atlaskit/editor-core/src/plugins/expand';
60
60
  import extensionPlugin from '@atlaskit/editor-core/src/plugins/extension';
61
61
  import mediaPlugin from '@atlaskit/editor-core/src/plugins/media';
62
62
  import textFormattingPlugin from '@atlaskit/editor-core/src/plugins/text-formatting';
63
+ import featureFlagsPlugin from '@atlaskit/editor-plugin-feature-flags';
63
64
 
64
65
  const TABLE_LOCAL_ID = 'test-table-local-id';
65
66
 
@@ -78,6 +79,7 @@ describe('table plugin: actions', () => {
78
79
  doc,
79
80
  attachTo: document.body,
80
81
  preset: new Preset<LightEditorPlugin>()
82
+ .add([featureFlagsPlugin, {}])
81
83
  .add(tablePlugin)
82
84
  .add(panelPlugin)
83
85
  .add(textFormattingPlugin)
@@ -62,6 +62,7 @@ import { getPluginState } from '../../plugins/table/pm-plugins/plugin-factory';
62
62
  import { pluginKey } from '../../plugins/table/pm-plugins/plugin-key';
63
63
  import type { GetEditorContainerWidth } from '@atlaskit/editor-common/types';
64
64
  import tablePlugin from '../../plugins/table-plugin';
65
+ import featureFlagsPlugin from '@atlaskit/editor-plugin-feature-flags';
65
66
 
66
67
  const TABLE_LOCAL_ID = 'test-table-local-id';
67
68
 
@@ -91,6 +92,7 @@ describe('table plugin', () => {
91
92
  } as PluginConfig;
92
93
 
93
94
  const preset = new Preset<LightEditorPlugin>()
95
+ .add([featureFlagsPlugin, {}])
94
96
  .add([tablePlugin, { tableOptions }])
95
97
  .add([mediaPlugin, { allowMediaSingle: true }])
96
98
  .add([analyticsPlugin, {}])
@@ -56,8 +56,9 @@ import statusPlugin from '@atlaskit/editor-core/src/plugins/status';
56
56
  import tablePlugin from '../../plugins/table';
57
57
  import { TablePluginState } from '../../plugins/table/types';
58
58
  import { pluginKey } from '../../plugins/table/pm-plugins/plugin-key';
59
- import featureFlagsPlugin from '@atlaskit/editor-core/src/plugins/feature-flags-context';
60
59
  import widthPlugin from '@atlaskit/editor-core/src/plugins/width';
60
+ import editorDisabledPlugin from '@atlaskit/editor-core/src/plugins/editor-disabled';
61
+ import featureFlagsPlugin from '@atlaskit/editor-plugin-feature-flags';
61
62
 
62
63
  const TABLE_LOCAL_ID = 'test-table-local-id';
63
64
 
@@ -81,6 +82,7 @@ describe('table keymap', () => {
81
82
 
82
83
  const createEditor = createProsemirrorEditorFactory();
83
84
  const preset = new Preset<LightEditorPlugin>()
85
+ .add([featureFlagsPlugin, {}])
84
86
  .add(selectionPlugin)
85
87
  .add([
86
88
  tablePlugin,
@@ -97,12 +99,12 @@ describe('table keymap', () => {
97
99
  .add(emojiPlugin)
98
100
  .add(jiraIssuePlugin)
99
101
  .add(extensionPlugin)
102
+ .add(editorDisabledPlugin)
100
103
  .add(datePlugin)
101
104
  .add(layoutPlugin)
102
105
  .add([statusPlugin, { menuDisabled: false }])
103
106
  .add([mediaPlugin, { allowMediaSingle: true }])
104
107
  .add([analyticsPlugin, { createAnalyticsEvent }])
105
- .add([featureFlagsPlugin, {}])
106
108
  .add(widthPlugin);
107
109
 
108
110
  const editor = (doc: DocBuilder) =>
@@ -35,6 +35,7 @@ import expandPlugin from '@atlaskit/editor-core/src/plugins/expand';
35
35
  import extensionPlugin from '@atlaskit/editor-core/src/plugins/extension';
36
36
  import layoutPlugin from '@atlaskit/editor-core/src/plugins/layout';
37
37
  import { PluginKey } from 'prosemirror-state';
38
+ import featureFlagsPlugin from '@atlaskit/editor-plugin-feature-flags';
38
39
 
39
40
  describe('table toolbar', () => {
40
41
  const tableOptions = {
@@ -46,6 +47,7 @@ describe('table toolbar', () => {
46
47
 
47
48
  const createEditor = createProsemirrorEditorFactory();
48
49
  const preset = new Preset<LightEditorPlugin>()
50
+ .add([featureFlagsPlugin, {}])
49
51
  .add([tablePlugin, { tableOptions }])
50
52
  .add(expandPlugin)
51
53
  .add(extensionPlugin)
@@ -1,12 +1,15 @@
1
1
  import { MockIntersectionObserver } from '@atlaskit/editor-test-helpers/mock-intersection-observer';
2
2
 
3
3
  import { OverflowShadowsObserver } from '../../../plugins/table/nodeviews/OverflowShadowsObserver';
4
+ import { TableCssClassName as className } from '../../../plugins/table/types';
4
5
  import { ShadowEvent } from '../../../plugins/table/types';
5
6
 
6
7
  describe('OverflowShadowsObserver', () => {
7
8
  let table: HTMLTableElement;
8
9
  let td1: HTMLTableDataCellElement;
9
10
  let td2: HTMLTableDataCellElement;
11
+ let shadowSentinelLeft: HTMLDivElement;
12
+ let shadowSentinelRight: HTMLDivElement;
10
13
  let wrapper: HTMLDivElement;
11
14
  const updateSpy = jest.fn();
12
15
  const observeSpy = jest.fn();
@@ -37,15 +40,15 @@ describe('OverflowShadowsObserver', () => {
37
40
  });
38
41
 
39
42
  it('observes on first and last table cells', () => {
40
- overflowShadowsObserver.observeCells();
41
- expect(observeSpy).toHaveBeenCalledWith(td1);
42
- expect(observeSpy).toHaveBeenCalledWith(td2);
43
+ overflowShadowsObserver.observeShadowSentinels();
44
+ expect(observeSpy).toHaveBeenCalledWith(shadowSentinelLeft);
45
+ expect(observeSpy).toHaveBeenCalledWith(shadowSentinelRight);
43
46
  });
44
47
 
45
- it('does not re-observe if cells did not change', () => {
46
- overflowShadowsObserver.observeCells();
48
+ it('does not re-observe if shadow sentinels are already observed', () => {
49
+ overflowShadowsObserver.observeShadowSentinels();
47
50
  observeSpy.mockClear();
48
- overflowShadowsObserver.observeCells();
51
+ overflowShadowsObserver.observeShadowSentinels();
49
52
  expect(observeSpy).not.toHaveBeenCalled();
50
53
  });
51
54
 
@@ -61,14 +64,14 @@ describe('OverflowShadowsObserver', () => {
61
64
 
62
65
  describe('calls the provided update function when intersecting', () => {
63
66
  beforeEach(() => {
64
- overflowShadowsObserver.observeCells();
67
+ overflowShadowsObserver.observeShadowSentinels();
65
68
  });
66
69
 
67
70
  it.each([
68
71
  [
69
72
  'hides first shadow when first cell fully intersects',
70
73
  {
71
- getTarget: () => td1,
74
+ getTarget: () => shadowSentinelLeft,
72
75
  intersectionRatio: 1,
73
76
  isIntersecting: true,
74
77
  expectedShadow: ShadowEvent.SHOW_BEFORE_SHADOW,
@@ -78,7 +81,7 @@ describe('OverflowShadowsObserver', () => {
78
81
  [
79
82
  'hides last shadow when last cell fully intersects',
80
83
  {
81
- getTarget: () => td2,
84
+ getTarget: () => shadowSentinelRight,
82
85
  intersectionRatio: 1,
83
86
  isIntersecting: true,
84
87
  expectedShadow: ShadowEvent.SHOW_AFTER_SHADOW,
@@ -88,7 +91,7 @@ describe('OverflowShadowsObserver', () => {
88
91
  [
89
92
  'shows first shadow when first cell partially intersects',
90
93
  {
91
- getTarget: () => td1,
94
+ getTarget: () => shadowSentinelLeft,
92
95
  intersectionRatio: 0,
93
96
  isIntersecting: true,
94
97
  expectedShadow: ShadowEvent.SHOW_BEFORE_SHADOW,
@@ -98,7 +101,7 @@ describe('OverflowShadowsObserver', () => {
98
101
  [
99
102
  'shows last shadow when last cell partially intersects',
100
103
  {
101
- getTarget: () => td2,
104
+ getTarget: () => shadowSentinelRight,
102
105
  intersectionRatio: 0,
103
106
  isIntersecting: true,
104
107
  expectedShadow: ShadowEvent.SHOW_AFTER_SHADOW,
@@ -140,6 +143,12 @@ describe('OverflowShadowsObserver', () => {
140
143
  function buildTable() {
141
144
  wrapper = document.createElement('div');
142
145
  table = document.createElement('table');
146
+ shadowSentinelLeft = document.createElement('div');
147
+ shadowSentinelLeft.className = className.TABLE_SHADOW_SENTINEL_LEFT;
148
+ shadowSentinelRight = document.createElement('div');
149
+ shadowSentinelRight.className = className.TABLE_SHADOW_SENTINEL_RIGHT;
150
+ table.prepend(shadowSentinelLeft);
151
+ table.prepend(shadowSentinelRight);
143
152
  wrapper.appendChild(table);
144
153
  const tbody = document.createElement('tbody');
145
154
  table.appendChild(tbody);
@@ -39,6 +39,20 @@ jest.mock('@atlaskit/editor-common/utils', () => ({
39
39
  },
40
40
  }));
41
41
 
42
+ jest.mock('@atlaskit/editor-palette', () => ({
43
+ ...jest.requireActual<Object>('@atlaskit/editor-palette'),
44
+ hexToEditorBackgroundPaletteColorTokenName: jest.fn((hexColor: string) => {
45
+ return hexColor;
46
+ }),
47
+ }));
48
+
49
+ jest.mock('@atlaskit/tokens', () => ({
50
+ ...jest.requireActual<Object>('@atlaskit/tokens'),
51
+ getTokenValue: jest.fn((tokenId: string, fallback: string = '') => {
52
+ return tokenId || fallback;
53
+ }),
54
+ }));
55
+
42
56
  describe('table -> nodeviews -> tableCell.tsx', () => {
43
57
  const TABLE_LOCAL_ID = 'test-table-local-id';
44
58
  const createEditor = createProsemirrorEditorFactory();
@@ -21,6 +21,7 @@ import { TablePluginState } from '../../../plugins/table/types';
21
21
  import { handleDocOrSelectionChanged } from '../../../plugins/table/handlers';
22
22
  import expandPlugin from '@atlaskit/editor-core/src/plugins/expand';
23
23
  import extensionPlugin from '@atlaskit/editor-core/src/plugins/extension';
24
+ import featureFlagsPlugin from '@atlaskit/editor-plugin-feature-flags';
24
25
 
25
26
  describe('tables: main plugin with allowCollapse: true', () => {
26
27
  const createEditor = createProsemirrorEditorFactory();
@@ -28,6 +29,7 @@ describe('tables: main plugin with allowCollapse: true', () => {
28
29
  createEditor({
29
30
  doc,
30
31
  preset: new Preset<LightEditorPlugin>()
32
+ .add([featureFlagsPlugin, {}])
31
33
  .add(tablePlugin)
32
34
  .add(expandPlugin)
33
35
  .add(extensionPlugin),
@@ -472,7 +472,7 @@ describe('TableRowNodeView', () => {
472
472
  triggerElementIntersect({
473
473
  target: sentinelTop,
474
474
  isIntersecting: false,
475
- rootBounds: { bottom: 0, top: 0 },
475
+ rootBounds: { bottom: 0, top: 56 },
476
476
  boundingClientRect: { bottom: 0, top: 0 },
477
477
  });
478
478
 
@@ -507,7 +507,7 @@ describe('TableRowNodeView', () => {
507
507
  triggerElementIntersect({
508
508
  target: sentinelBottom,
509
509
  isIntersecting: true,
510
- rootBounds: { bottom: 0, top: 0 },
510
+ rootBounds: { bottom: 0, top: 56 },
511
511
  boundingClientRect: { bottom: 0, top: -100 },
512
512
  });
513
513
 
@@ -241,6 +241,51 @@ describe('table plugin -> transforms -> delete rows', () => {
241
241
  });
242
242
  });
243
243
 
244
+ describe('when delete the row in between rows that have merged cells with an extra row underneath', () => {
245
+ it('should decrement colspan of these cells', () => {
246
+ const { editorView } = editor(
247
+ doc(
248
+ p('text'),
249
+ table()(
250
+ tr(td({ colspan: 5 })(p('a1')), td({})(p('a6'))),
251
+ tr(
252
+ td({})(p('b1{<cell}')),
253
+ td({})(p('b2')),
254
+ td({})(p('b3')),
255
+ td({})(p('b4')),
256
+ td({})(p('b5')),
257
+ td({})(p('b6{cell>}')),
258
+ ),
259
+ tr(td({})(p('c1')), td({ colspan: 5 })(p('c6'))),
260
+ tr(
261
+ td({ colspan: 3 })(p('d1')),
262
+ td({})(p('d4')),
263
+ td({})(p('d5')),
264
+ td({})(p('d6')),
265
+ ),
266
+ ),
267
+ ),
268
+ );
269
+ const { state, dispatch } = editorView;
270
+ dispatch(deleteRows(getSelectionRect(state.selection)!)(state.tr));
271
+ expect(editorView.state.doc).toEqualDocument(
272
+ doc(
273
+ p('text'),
274
+ table({ localId: TABLE_LOCAL_ID })(
275
+ tr(td({ colspan: 4 })(p('a1')), td({})(p('a6'))),
276
+ tr(td({})(p('c1')), td({ colspan: 4 })(p('c6'))),
277
+ tr(
278
+ td({ colspan: 2 })(p('d1')),
279
+ td({})(p('d4')),
280
+ td({})(p('d5')),
281
+ td({})(p('d6')),
282
+ ),
283
+ ),
284
+ ),
285
+ );
286
+ });
287
+ });
288
+
244
289
  describe('when after deleting the first row table has columns where all cells have colspan > 1', () => {
245
290
  it('should decrement colspan of these cells', () => {
246
291
  const { editorView } = editor(
@@ -22,6 +22,7 @@ import { ContextualMenu } from '../../../plugins/table/ui/FloatingContextualMenu
22
22
 
23
23
  describe('ContextualMenu', () => {
24
24
  const getEditorContainerWidth = () => ({ width: 500 });
25
+ const getEditorFeatureFlags = () => ({});
25
26
  const createEditor = createProsemirrorEditorFactory();
26
27
  describe('with right table cell position in plugin state', () => {
27
28
  let editorView: EditorView;
@@ -44,6 +45,7 @@ describe('ContextualMenu', () => {
44
45
  isOpen
45
46
  selectionRect={{ bottom: 0, left: 0, right: 0, top: 0 }}
46
47
  getEditorContainerWidth={getEditorContainerWidth}
48
+ getEditorFeatureFlags={getEditorFeatureFlags}
47
49
  />,
48
50
  );
49
51
 
@@ -40,6 +40,7 @@ describe('FloatingContextualMenu', () => {
40
40
  isOpen
41
41
  pluginConfig={getPluginState(editorView.state).pluginConfig}
42
42
  getEditorContainerWidth={jest.fn()}
43
+ getEditorFeatureFlags={() => ({})}
43
44
  />
44
45
  </IntlProvider>,
45
46
  );
@@ -18,12 +18,15 @@ import {
18
18
  isTableCollapsible,
19
19
  collapseSelectedTable,
20
20
  } from '../../../plugins/table/utils/collapse';
21
+ import featureFlagsPlugin from '@atlaskit/editor-plugin-feature-flags';
21
22
 
22
23
  describe('collapse', () => {
23
24
  const createEditor = createProsemirrorEditorFactory();
24
25
 
25
26
  const editor = (doc: DocBuilder, expandInPlugins?: boolean) => {
26
- const preset = new Preset<LightEditorPlugin>().add(tablePlugin);
27
+ const preset = new Preset<LightEditorPlugin>()
28
+ .add([featureFlagsPlugin, {}])
29
+ .add(tablePlugin);
27
30
 
28
31
  const finalPreset = expandInPlugins ? preset.add(expandPlugin) : preset;
29
32
 
package/src/i18n/en.ts ADDED
@@ -0,0 +1,36 @@
1
+ /* prettier-ignore */
2
+ /**
3
+ * NOTE:
4
+ *
5
+ * This file is automatically generated by Traduki 2.0.
6
+ * DO NOT CHANGE IT BY HAND or your changes will be lost.
7
+ */
8
+ //
9
+ export default {
10
+ 'fabric.editor.canNotSortTable': "⚠️ You can't sort a table with merged cells",
11
+ 'fabric.editor.cellBackground': 'Cell background',
12
+ 'fabric.editor.cellOptions': 'Cell options',
13
+ 'fabric.editor.clearCells': 'Clear {0, plural, one {cell} other {cells}}',
14
+ 'fabric.editor.collapseTable': 'Collapse table',
15
+ 'fabric.editor.cornerControl': 'Highlight table',
16
+ 'fabric.editor.distributeColumns': 'Distribute columns',
17
+ 'fabric.editor.extension.confirmDeleteLinkedModalMessagePrefix': 'Deleting',
18
+ 'fabric.editor.extension.deleteElementTitle': 'Delete element',
19
+ 'fabric.editor.extension.sourceNoTitledName': 'this element',
20
+ 'fabric.editor.floatingToolbar.confirmModalCheckboxLabel': 'Also delete connected elements',
21
+ 'fabric.editor.headerColumn': 'Header column',
22
+ 'fabric.editor.headerRow': 'Header row',
23
+ 'fabric.editor.insertColumn': 'Insert column right',
24
+ 'fabric.editor.insertRow': 'Insert row below',
25
+ 'fabric.editor.mergeCells': 'Merge cells',
26
+ 'fabric.editor.numberedColumn': 'Numbered column',
27
+ 'fabric.editor.removeColumns': 'Delete {0, plural, one {column} other {columns}}',
28
+ 'fabric.editor.removeRows': 'Delete {0, plural, one {row} other {rows}}',
29
+ 'fabric.editor.rowControl': 'Highlight row',
30
+ 'fabric.editor.sortColumnASC': 'Sort column A → Z',
31
+ 'fabric.editor.sortColumnDESC': 'Sort column Z → A',
32
+ 'fabric.editor.splitCell': 'Split cell',
33
+ 'fabric.editor.tableOptions': 'Table options',
34
+ 'fabric.editor.tables.confirmDeleteLinkedModalMessage': 'Deleting {nodeName} will break anything connected to it.',
35
+ 'fabric.editor.tables.confirmDeleteLinkedModalOKButton': 'Delete',
36
+ };
@@ -0,0 +1,36 @@
1
+ /* prettier-ignore */
2
+ /**
3
+ * NOTE:
4
+ *
5
+ * This file is automatically generated by Traduki 2.0.
6
+ * DO NOT CHANGE IT BY HAND or your changes will be lost.
7
+ */
8
+ //English (United Kingdom)
9
+ export default {
10
+ 'fabric.editor.canNotSortTable': "⚠️ You can't sort a table with merged cells",
11
+ 'fabric.editor.cellBackground': 'Cell background',
12
+ 'fabric.editor.cellOptions': 'Cell options',
13
+ 'fabric.editor.clearCells': 'Clear {0, plural, one {cell} other {cells}}',
14
+ 'fabric.editor.collapseTable': 'Collapse table',
15
+ 'fabric.editor.cornerControl': 'Highlight table',
16
+ 'fabric.editor.distributeColumns': 'Distribute columns',
17
+ 'fabric.editor.extension.confirmDeleteLinkedModalMessagePrefix': 'Deleting',
18
+ 'fabric.editor.extension.deleteElementTitle': 'Delete element',
19
+ 'fabric.editor.extension.sourceNoTitledName': 'this element',
20
+ 'fabric.editor.floatingToolbar.confirmModalCheckboxLabel': 'Also delete connected elements',
21
+ 'fabric.editor.headerColumn': 'Header column',
22
+ 'fabric.editor.headerRow': 'Header row',
23
+ 'fabric.editor.insertColumn': 'Insert column right',
24
+ 'fabric.editor.insertRow': 'Insert row below',
25
+ 'fabric.editor.mergeCells': 'Merge cells',
26
+ 'fabric.editor.numberedColumn': 'Numbered column',
27
+ 'fabric.editor.removeColumns': 'Delete {0, plural, one {column} other {columns}}',
28
+ 'fabric.editor.removeRows': 'Delete {0, plural, one {row} other {rows}}',
29
+ 'fabric.editor.rowControl': 'Highlight row',
30
+ 'fabric.editor.sortColumnASC': 'Sort column A → Z',
31
+ 'fabric.editor.sortColumnDESC': 'Sort column Z → A',
32
+ 'fabric.editor.splitCell': 'Split cell',
33
+ 'fabric.editor.tableOptions': 'Table options',
34
+ 'fabric.editor.tables.confirmDeleteLinkedModalMessage': 'Deleting {nodeName} will break anything connected to it.',
35
+ 'fabric.editor.tables.confirmDeleteLinkedModalOKButton': 'Delete',
36
+ };
@@ -371,6 +371,10 @@ const tablesPlugin: NextEditorPlugin<
371
371
  pluginConfig={pluginConfig}
372
372
  editorAnalyticsAPI={options?.editorAnalyticsAPI}
373
373
  getEditorContainerWidth={defaultGetEditorContainerWidth}
374
+ getEditorFeatureFlags={
375
+ options?.getEditorFeatureFlags ||
376
+ defaultGetEditorFeatureFlags
377
+ }
374
378
  />
375
379
  {allowControls && (
376
380
  <FloatingDeleteButton
@@ -8,25 +8,9 @@ export class OverflowShadowsObserver {
8
8
  private table: HTMLElement;
9
9
  private wrapper: HTMLDivElement;
10
10
 
11
- private firstCell: HTMLElement | null = null;
12
- private lastCell: HTMLElement | null = null;
13
-
14
- private getFirstCell: (
15
- isSticky?: boolean,
16
- hasHeaderRow?: boolean,
17
- ) => HTMLElement | null = (isSticky, hasHeaderRow) =>
18
- this.table?.querySelector(
19
- isSticky || !hasHeaderRow ? 'table tbody tr td' : 'table tbody tr th',
20
- );
21
- private getLastCell: (
22
- isSticky?: boolean,
23
- hasHeaderRow?: boolean,
24
- ) => HTMLElement | null = (isSticky, hasHeaderRow) =>
25
- this.table?.querySelector(
26
- isSticky || !hasHeaderRow
27
- ? 'table tbody tr td:last-child'
28
- : 'table tbody tr th:last-child',
29
- );
11
+ private leftShadowSentinel: HTMLElement | null = null;
12
+ private rightShadowSentinel: HTMLElement | null = null;
13
+ private shadowsObserved: boolean = false;
30
14
 
31
15
  private isSticky = false;
32
16
  private stickyRowHeight = 0;
@@ -58,13 +42,16 @@ export class OverflowShadowsObserver {
58
42
  if (!entry.rootBounds?.height && !entry.rootBounds?.width) {
59
43
  return;
60
44
  }
61
- if (entry.target !== this.firstCell && entry.target !== this.lastCell) {
45
+ if (
46
+ entry.target !== this.leftShadowSentinel &&
47
+ entry.target !== this.rightShadowSentinel
48
+ ) {
62
49
  return;
63
50
  }
64
51
  this.updateStickyShadowsHeightIfChanged();
65
52
  this.checkIntersectionEvent(
66
53
  entry,
67
- this.firstCell === entry.target
54
+ this.leftShadowSentinel === entry.target
68
55
  ? ShadowEvent.SHOW_BEFORE_SHADOW
69
56
  : ShadowEvent.SHOW_AFTER_SHADOW,
70
57
  );
@@ -123,32 +110,29 @@ export class OverflowShadowsObserver {
123
110
  return stickyCell;
124
111
  }
125
112
 
126
- observeCells = (isSticky?: boolean, hasHeaderRow?: boolean) => {
127
- const stickyChanged = !!isSticky !== this.isSticky;
113
+ observeShadowSentinels = (isSticky?: boolean) => {
128
114
  this.isSticky = !!isSticky;
129
115
 
130
116
  // update sticky shadows
131
117
  this.updateStickyShadowsHeightIfChanged();
132
118
 
133
- if (!stickyChanged) {
134
- const firstCell = this.getFirstCell(isSticky, hasHeaderRow);
135
- const lastCell = this.getLastCell(isSticky, hasHeaderRow);
136
- if (
137
- !firstCell ||
138
- !lastCell ||
139
- (firstCell === this.firstCell && lastCell === this.lastCell)
140
- ) {
141
- return;
142
- }
143
- }
144
-
145
- this.firstCell = this.getFirstCell(isSticky, hasHeaderRow);
146
- this.lastCell = this.getLastCell(isSticky, hasHeaderRow);
119
+ this.leftShadowSentinel = this.table?.querySelector(
120
+ `.${ClassName.TABLE_SHADOW_SENTINEL_LEFT}`,
121
+ );
122
+ this.rightShadowSentinel = this.table?.querySelector(
123
+ `.${ClassName.TABLE_SHADOW_SENTINEL_RIGHT}`,
124
+ );
147
125
 
148
- if (this.tableIntersectionObserver && this.firstCell && this.lastCell) {
126
+ if (
127
+ this.tableIntersectionObserver &&
128
+ this.leftShadowSentinel &&
129
+ this.rightShadowSentinel &&
130
+ !this.shadowsObserved
131
+ ) {
149
132
  this.tableIntersectionObserver.disconnect();
150
- this.tableIntersectionObserver.observe(this.firstCell);
151
- this.tableIntersectionObserver.observe(this.lastCell);
133
+ this.tableIntersectionObserver.observe(this.leftShadowSentinel);
134
+ this.tableIntersectionObserver.observe(this.rightShadowSentinel);
135
+ this.shadowsObserved = true;
152
136
  }
153
137
  };
154
138