@atlaskit/editor-plugin-table 12.1.15 → 12.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/afm-cc/tsconfig.json +3 -0
  3. package/afm-dev-agents/tsconfig.json +3 -0
  4. package/afm-jira/tsconfig.json +3 -0
  5. package/afm-passionfruit/tsconfig.json +3 -0
  6. package/afm-post-office/tsconfig.json +3 -0
  7. package/afm-rovo-extension/tsconfig.json +3 -0
  8. package/afm-townsquare/tsconfig.json +3 -0
  9. package/dist/cjs/nodeviews/TableComponent.js +73 -22
  10. package/dist/cjs/nodeviews/TableContainer.js +270 -10
  11. package/dist/cjs/nodeviews/TableResizer.js +9 -2
  12. package/dist/cjs/nodeviews/table.js +12 -2
  13. package/dist/cjs/nodeviews/toDOM.js +23 -7
  14. package/dist/cjs/pm-plugins/main.js +57 -23
  15. package/dist/cjs/pm-plugins/table-resizing/utils/colgroup.js +72 -1
  16. package/dist/cjs/pm-plugins/table-resizing/utils/misc.js +70 -1
  17. package/dist/cjs/tablePlugin.js +17 -3
  18. package/dist/es2019/nodeviews/TableComponent.js +76 -22
  19. package/dist/es2019/nodeviews/TableContainer.js +256 -2
  20. package/dist/es2019/nodeviews/TableResizer.js +9 -2
  21. package/dist/es2019/nodeviews/table.js +12 -2
  22. package/dist/es2019/nodeviews/toDOM.js +24 -8
  23. package/dist/es2019/pm-plugins/main.js +57 -23
  24. package/dist/es2019/pm-plugins/table-resizing/utils/colgroup.js +72 -3
  25. package/dist/es2019/pm-plugins/table-resizing/utils/misc.js +70 -1
  26. package/dist/es2019/tablePlugin.js +17 -3
  27. package/dist/esm/nodeviews/TableComponent.js +73 -22
  28. package/dist/esm/nodeviews/TableContainer.js +270 -10
  29. package/dist/esm/nodeviews/TableResizer.js +9 -2
  30. package/dist/esm/nodeviews/table.js +12 -2
  31. package/dist/esm/nodeviews/toDOM.js +24 -8
  32. package/dist/esm/pm-plugins/main.js +57 -23
  33. package/dist/esm/pm-plugins/table-resizing/utils/colgroup.js +74 -3
  34. package/dist/esm/pm-plugins/table-resizing/utils/misc.js +70 -1
  35. package/dist/esm/tablePlugin.js +17 -3
  36. package/dist/types/nodeviews/TableContainer.d.ts +7 -2
  37. package/dist/types/nodeviews/TableResizer.d.ts +1 -1
  38. package/dist/types/nodeviews/toDOM.d.ts +5 -0
  39. package/dist/types/nodeviews/types.d.ts +1 -0
  40. package/dist/types/pm-plugins/table-resizing/utils/colgroup.d.ts +1 -0
  41. package/dist/types/pm-plugins/table-resizing/utils/misc.d.ts +41 -0
  42. package/dist/types-ts4.5/nodeviews/TableContainer.d.ts +7 -2
  43. package/dist/types-ts4.5/nodeviews/TableResizer.d.ts +1 -1
  44. package/dist/types-ts4.5/nodeviews/toDOM.d.ts +5 -0
  45. package/dist/types-ts4.5/nodeviews/types.d.ts +1 -0
  46. package/dist/types-ts4.5/pm-plugins/table-resizing/utils/colgroup.d.ts +1 -0
  47. package/dist/types-ts4.5/pm-plugins/table-resizing/utils/misc.d.ts +41 -0
  48. package/package.json +8 -7
  49. package/src/nodeviews/TableComponent.tsx +105 -19
  50. package/src/nodeviews/TableContainer.tsx +331 -2
  51. package/src/nodeviews/TableResizer.tsx +10 -5
  52. package/src/nodeviews/table.tsx +14 -0
  53. package/src/nodeviews/toDOM.ts +75 -9
  54. package/src/nodeviews/types.ts +1 -0
  55. package/src/pm-plugins/main.ts +41 -18
  56. package/src/pm-plugins/table-resizing/utils/colgroup.ts +139 -6
  57. package/src/pm-plugins/table-resizing/utils/misc.ts +87 -0
  58. package/src/tablePlugin.tsx +21 -0
  59. package/tsconfig.app.json +3 -0
  60. package/types/package.json +1 -1
  61. package/ui/common-styles/package.json +1 -1
@@ -2,14 +2,17 @@ import _extends from "@babel/runtime/helpers/extends";
2
2
  import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import classNames from 'classnames';
4
4
  import { CHANGE_ALIGNMENT_REASON, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
5
+ import { isSSR } from '@atlaskit/editor-common/core-utils';
5
6
  import { sharedPluginStateHookMigratorFactory, useSharedPluginState, useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
6
7
  import { getTableContainerWidth } from '@atlaskit/editor-common/node-width';
7
8
  import { akEditorDefaultLayoutWidth, akEditorGutterPaddingDynamic, akEditorGutterPaddingReduced, akEditorFullPageNarrowBreakout, akEditorMobileBreakoutPoint } from '@atlaskit/editor-shared-styles';
8
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
+ import { componentWithCondition } from '@atlaskit/platform-feature-flags-react';
9
11
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
10
12
  import { setTableAlignmentWithTableContentWithPosWithAnalytics } from '../pm-plugins/commands/commands-with-analytics';
11
13
  import { getPluginState } from '../pm-plugins/plugin-factory';
12
14
  import { TABLE_MAX_WIDTH, TABLE_OFFSET_IN_COMMENT_EDITOR } from '../pm-plugins/table-resizing/utils/consts';
15
+ import { getTableResizerContainerMaxWidthInCSS, getTableResizerContainerForFullPageWidthInCSS } from '../pm-plugins/table-resizing/utils/misc';
13
16
  import { ALIGN_CENTER, ALIGN_START } from '../pm-plugins/utils/alignment';
14
17
  import { TableCssClassName as ClassName } from '../types';
15
18
  import { getAlignmentStyle } from './table-container-styles';
@@ -159,7 +162,7 @@ const useSharedState = sharedPluginStateHookMigratorFactory(api => {
159
162
  const getPadding = containerWidth => {
160
163
  return containerWidth <= akEditorFullPageNarrowBreakout && expValEquals('platform_editor_preview_panel_responsiveness', 'isEnabled', true) ? akEditorGutterPaddingReduced : akEditorGutterPaddingDynamic();
161
164
  };
162
- export const ResizableTableContainer = /*#__PURE__*/React.memo(({
165
+ const ResizableTableContainerLegacy = /*#__PURE__*/React.memo(({
163
166
  children,
164
167
  className,
165
168
  node,
@@ -352,6 +355,254 @@ export const ResizableTableContainer = /*#__PURE__*/React.memo(({
352
355
  node: node
353
356
  }, children)) : null));
354
357
  });
358
+ const ResizableTableContainerNext = /*#__PURE__*/React.memo(({
359
+ children,
360
+ className,
361
+ node,
362
+ containerWidth,
363
+ lineLength,
364
+ editorView,
365
+ getPos,
366
+ tableRef,
367
+ isResizing,
368
+ isWindowResized,
369
+ pluginInjectionApi,
370
+ tableWrapperHeight,
371
+ isWholeTableInDanger,
372
+ isTableScalingEnabled,
373
+ isTableWithFixedColumnWidthsOptionEnabled,
374
+ isTableAlignmentEnabled,
375
+ shouldUseIncreasedScalingPercent,
376
+ isCommentEditor,
377
+ isChromelessEditor
378
+ }) => {
379
+ const tableWidth = getTableContainerWidth(node);
380
+ const containerRef = useRef(null);
381
+ const tableWidthRef = useRef(akEditorDefaultLayoutWidth);
382
+ const [resizing, setIsResizing] = useState(false);
383
+ const [tableMaxWidthForFullPageOnLoad, setTableMaxWidthForFullPageOnLoad] = useState(tableWidth);
384
+ const {
385
+ tableState,
386
+ editorViewModeState
387
+ } = useSharedState(pluginInjectionApi);
388
+ const isFullWidthModeEnabled = tableState === null || tableState === void 0 ? void 0 : tableState.isFullWidthModeEnabled;
389
+ const mode = editorViewModeState === null || editorViewModeState === void 0 ? void 0 : editorViewModeState.mode;
390
+ const updateContainerHeight = useCallback(height => {
391
+ var _containerRef$current3;
392
+ // current StickyHeader State is not stable to be fetch.
393
+ // we need to update stickyHeader plugin to make sure state can be
394
+ // consistently fetch and refactor below
395
+ const stickyHeaders = (_containerRef$current3 = containerRef.current) === null || _containerRef$current3 === void 0 ? void 0 : _containerRef$current3.getElementsByClassName('pm-table-sticky');
396
+ if (!stickyHeaders || stickyHeaders.length < 1) {
397
+ // when starting to drag, we need to keep the original space,
398
+ // -- When sticky header not appear, margin top(24px) and margin bottom(16px), should be 40px,
399
+ // 1px is border width but collapse make it 0.5.
400
+ // -- When sticky header appear, we should add first row height but reduce
401
+ // collapsed border
402
+ return typeof height === 'number' ? `${height + 40.5}px` : 'auto';
403
+ } else {
404
+ var _containerRef$current4;
405
+ const stickyHeaderHeight = ((_containerRef$current4 = containerRef.current) === null || _containerRef$current4 === void 0 ? void 0 : _containerRef$current4.getElementsByTagName('th')[0].getBoundingClientRect().height) || 0;
406
+ return typeof height === 'number' ? `${height + stickyHeaderHeight + 39.5}px` : 'auto';
407
+ }
408
+ }, []);
409
+ const onResizeStart = useCallback(() => {
410
+ setIsResizing(true);
411
+ }, []);
412
+ const onResizeStop = useCallback(() => {
413
+ setIsResizing(false);
414
+ }, []);
415
+ const updateWidth = useCallback(width => {
416
+ if (!containerRef.current) {
417
+ return;
418
+ }
419
+
420
+ // make sure during resizing
421
+ // the pm-table-resizer-container width is the same as its child div resizer-item
422
+ // otherwise when resize table from wider to narrower , pm-table-resizer-container stays wider
423
+ // and cause the fabric-editor-popup-scroll-parent to overflow
424
+ if (containerRef.current.style.width !== `${width}px`) {
425
+ containerRef.current.style.width = `${width}px`;
426
+ }
427
+ }, []);
428
+ const displayGuideline = useCallback(guidelines => {
429
+ var _pluginInjectionApi$g4, _pluginInjectionApi$g5, _pluginInjectionApi$g6;
430
+ return (_pluginInjectionApi$g4 = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$g5 = pluginInjectionApi.guideline) === null || _pluginInjectionApi$g5 === void 0 ? void 0 : (_pluginInjectionApi$g6 = _pluginInjectionApi$g5.actions) === null || _pluginInjectionApi$g6 === void 0 ? void 0 : _pluginInjectionApi$g6.displayGuideline(editorView)({
431
+ guidelines
432
+ })) !== null && _pluginInjectionApi$g4 !== void 0 ? _pluginInjectionApi$g4 : false;
433
+ }, [pluginInjectionApi, editorView]);
434
+ const attachAnalyticsEvent = useCallback(payload => {
435
+ var _pluginInjectionApi$a3;
436
+ return pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a3 = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a3 === void 0 ? void 0 : _pluginInjectionApi$a3.actions.attachAnalyticsEvent(payload);
437
+ }, [pluginInjectionApi]);
438
+ const displayGapCursor = useCallback(toggle => {
439
+ var _pluginInjectionApi$c3, _pluginInjectionApi$c4, _pluginInjectionApi$s2;
440
+ return (_pluginInjectionApi$c3 = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c4 = pluginInjectionApi.core) === null || _pluginInjectionApi$c4 === void 0 ? void 0 : _pluginInjectionApi$c4.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$s2 = pluginInjectionApi.selection) === null || _pluginInjectionApi$s2 === void 0 ? void 0 : _pluginInjectionApi$s2.commands.displayGapCursor(toggle))) !== null && _pluginInjectionApi$c3 !== void 0 ? _pluginInjectionApi$c3 : false;
441
+ }, [pluginInjectionApi]);
442
+ const isFullPageAppearance = !isCommentEditor && !isChromelessEditor;
443
+ let responsiveContainerWidth = 0;
444
+ const resizeHandleSpacing = 12;
445
+ const padding = getPadding(containerWidth);
446
+ // When Full width editor enabled, a Mac OS user can change "ak-editor-content-area" width by
447
+ // updating Settings -> Appearance -> Show scroll bars from "When scrolling" to "Always". It causes
448
+ // issues when viwport width is less than full width Editor's width. To detect avoid them
449
+ // we need to use lineLength to defined responsiveWidth instead of containerWidth
450
+ // (which does not get updated when Mac setting changes) in Full-width editor.
451
+ if (isFullWidthModeEnabled) {
452
+ // When: Show scroll bars -> containerWidth = akEditorGutterPadding * 2 + lineLength;
453
+ // When: Always -> containerWidth = akEditorGutterPadding * 2 + lineLength + scrollbarWidth;
454
+ // scrollbarWidth can vary. Values can be 14, 15, 16 and up to 20px;
455
+ responsiveContainerWidth = isTableScalingEnabled ? lineLength : containerWidth - padding * 2 - resizeHandleSpacing;
456
+
457
+ // platform_editor_table_fw_numcol_overflow_fix:
458
+ // lineLength is undefined on first paint → width: NaN → wrapper expands to page
459
+ // width. rAF col-sizing then runs before the number-column padding and
460
+ // the final shrink, so column widths are locked in wrong.
461
+ // With the flag ON, if the value isn’t finite we fall back to gutterWidth
462
+ // for that first frame—no flash, no premature rAF.
463
+ //
464
+ // Type clean-up comes later:
465
+ // 1) ship this runtime guard (quick fix, no breakage);
466
+ // 2) TODO: widen lineLength to `number|undefined` and remove this block.
467
+ if (fg('platform_editor_table_fw_numcol_overflow_fix')) {
468
+ if (isTableScalingEnabled && !Number.isFinite(responsiveContainerWidth)) {
469
+ responsiveContainerWidth = containerWidth - padding * 2 - resizeHandleSpacing;
470
+ }
471
+ }
472
+ } else if (isCommentEditor) {
473
+ responsiveContainerWidth = containerWidth - TABLE_OFFSET_IN_COMMENT_EDITOR;
474
+ } else {
475
+ // 76 is currently an accepted padding value considering the spacing for resizer handle
476
+ // containerWidth = width of a DIV with test id="ak-editor-fp-content-area". It is a parent of
477
+ // a DIV with className="ak-editor-content-area". This DIV has padding left and padding right.
478
+ // padding left = padding right = akEditorGutterPadding = 32
479
+ responsiveContainerWidth = isTableScalingEnabled ? containerWidth - padding * 2 : containerWidth - padding * 2 - resizeHandleSpacing;
480
+ }
481
+ const width = !node.attrs.width && isCommentEditor ? responsiveContainerWidth : Math.min(tableWidth, responsiveContainerWidth);
482
+ if (!isResizing) {
483
+ tableWidthRef.current = width;
484
+ }
485
+ const maxResizerWidth = isCommentEditor ? responsiveContainerWidth : Math.min(responsiveContainerWidth, TABLE_MAX_WIDTH);
486
+
487
+ // CSS solution for table resizer item width
488
+ // The `width` is used for .resizer-item in <TableResizer>, and it has to be a number
489
+ // So we can't use min(var(--ak-editor-table-width), ${tableWidth}px) here
490
+ // We get the correct width from CSS value on page load
491
+ // After window resize, we use the width from plugin state
492
+ // After table resize, the table width attribute is used
493
+ const tableResizerItemWidth = useMemo(() => {
494
+ // if not on full page editor, we just rely on the width calculated from plugin state
495
+ // if on full page editor and after window resize, we use the width from plugin state
496
+ if (!isFullPageAppearance || isFullPageAppearance && isWindowResized) {
497
+ return width;
498
+ }
499
+ if (isResizing) {
500
+ return tableWidth;
501
+ }
502
+ // if on full page editor and on page load, we use the computed value from CSS
503
+ return Math.min(tableWidth, tableMaxWidthForFullPageOnLoad);
504
+ }, [isWindowResized, isResizing, isFullPageAppearance, tableMaxWidthForFullPageOnLoad, tableWidth, width]);
505
+
506
+ // CSS Solution for table resizer container width
507
+ const tableResizerContainerWidth = useMemo(() => {
508
+ return getTableResizerContainerForFullPageWidthInCSS(node, isTableScalingEnabled);
509
+ }, [node, isTableScalingEnabled]);
510
+
511
+ // CSS Solution for table resizer max width
512
+ const tableResizerMaxWidth = React.useMemo(() => {
513
+ const isFullPageAppearance = !isCommentEditor && !isChromelessEditor;
514
+ const nonResizingMaxWidth = isFullPageAppearance ? getTableResizerContainerMaxWidthInCSS(isCommentEditor, isChromelessEditor, isTableScalingEnabled) : maxResizerWidth;
515
+ // isResizing is needed, otherwise we can't resize table.
516
+ // when not resizing, maxWidth is calculated based on the container width via CSS
517
+ return !isResizing ? nonResizingMaxWidth : maxResizerWidth;
518
+ }, [isCommentEditor, isChromelessEditor, isTableScalingEnabled, isResizing, maxResizerWidth]);
519
+
520
+ // on SSR, the width would be the default state, which is tableWidth
521
+ // but because we have maxWidth set to the editor container width via CSS
522
+ // So it would work just fine
523
+ useEffect(() => {
524
+ var _containerRef$current5;
525
+ if (!isSSR() && isFullPageAppearance && (_containerRef$current5 = containerRef.current) !== null && _containerRef$current5 !== void 0 && _containerRef$current5.firstElementChild) {
526
+ // get the computed value of max-width from '.resizer-item', because it uses `cqw` unit in CSS
527
+ const computedStyle = window.getComputedStyle(containerRef.current.firstElementChild);
528
+ const containerWidth = computedStyle.maxWidth ? parseFloat(computedStyle.maxWidth) : tableWidth;
529
+ setTableMaxWidthForFullPageOnLoad(Math.min(containerWidth, tableWidth));
530
+ }
531
+ }, [tableWidthRef, tableWidth, isFullPageAppearance]);
532
+ const tableResizerProps = {
533
+ width: tableResizerItemWidth,
534
+ maxWidth: tableResizerMaxWidth,
535
+ containerWidth,
536
+ lineLength,
537
+ updateWidth,
538
+ editorView,
539
+ getPos,
540
+ node,
541
+ tableRef,
542
+ displayGuideline,
543
+ attachAnalyticsEvent,
544
+ displayGapCursor,
545
+ isTableAlignmentEnabled,
546
+ isFullWidthModeEnabled,
547
+ isTableScalingEnabled,
548
+ isTableWithFixedColumnWidthsOptionEnabled,
549
+ isWholeTableInDanger,
550
+ shouldUseIncreasedScalingPercent,
551
+ pluginInjectionApi,
552
+ onResizeStart,
553
+ onResizeStop,
554
+ isCommentEditor
555
+ };
556
+ const isLivePageViewMode = mode === 'view';
557
+ return /*#__PURE__*/React.createElement(AlignmentTableContainerWrapper, {
558
+ isTableAlignmentEnabled: isTableAlignmentEnabled,
559
+ node: node,
560
+ pluginInjectionApi: pluginInjectionApi,
561
+ getPos: getPos,
562
+ editorView: editorView
563
+ }, /*#__PURE__*/React.createElement("div", {
564
+ style: {
565
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
566
+ '--ak-editor-table-gutter-padding': 'calc(var(--ak-editor--large-gutter-padding) * 2)',
567
+ '--ak-editor-table-width': isFullPageAppearance ? tableResizerContainerWidth : `${tableWidthRef.current}px`,
568
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
569
+ width: 'var(--ak-editor-table-width)',
570
+ height: resizing ? updateContainerHeight(tableWrapperHeight !== null && tableWrapperHeight !== void 0 ? tableWrapperHeight : 'auto') : 'auto',
571
+ position: isLivePageViewMode ? 'relative' : 'unset'
572
+ }
573
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
574
+ ,
575
+ className: ClassName.TABLE_RESIZER_CONTAINER,
576
+ ref: containerRef
577
+ }, fg('platform_editor_live_page_prevent_table_recreation') ? null : isLivePageViewMode ? /*#__PURE__*/React.createElement(InnerContainer
578
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
579
+ , {
580
+ className: className,
581
+ node: node
582
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
583
+ ,
584
+ style: {
585
+ width: 'inherit'
586
+ }
587
+ }, children) :
588
+ /*#__PURE__*/
589
+ // Ignored via go/ees005
590
+ // eslint-disable-next-line react/jsx-props-no-spreading
591
+ React.createElement(TableResizer, tableResizerProps, /*#__PURE__*/React.createElement(InnerContainer, {
592
+ className: className,
593
+ node: node
594
+ }, children)), fg('platform_editor_live_page_prevent_table_recreation') ?
595
+ /*#__PURE__*/
596
+ // Ignored via go/ees005
597
+ // eslint-disable-next-line react/jsx-props-no-spreading
598
+ React.createElement(TableResizer, _extends({}, tableResizerProps, {
599
+ disabled: isLivePageViewMode
600
+ }), /*#__PURE__*/React.createElement(InnerContainer, {
601
+ className: className,
602
+ node: node
603
+ }, children)) : null));
604
+ });
605
+ export const ResizableTableContainer = componentWithCondition(() => expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true), ResizableTableContainerNext, ResizableTableContainerLegacy);
355
606
  export const TableContainer = ({
356
607
  children,
357
608
  node,
@@ -366,6 +617,7 @@ export const TableContainer = ({
366
617
  isNested,
367
618
  tableWrapperHeight,
368
619
  isResizing,
620
+ isWindowResized,
369
621
  pluginInjectionApi,
370
622
  isWholeTableInDanger,
371
623
  isTableResizingEnabled,
@@ -395,13 +647,15 @@ export const TableContainer = ({
395
647
  tableRef: tableRef,
396
648
  tableWrapperHeight: tableWrapperHeight,
397
649
  isResizing: isResizing,
650
+ isWindowResized: isWindowResized,
398
651
  pluginInjectionApi: pluginInjectionApi,
399
652
  isTableScalingEnabled: isTableScalingEnabled,
400
653
  isTableWithFixedColumnWidthsOptionEnabled: isTableWithFixedColumnWidthsOptionEnabled,
401
654
  isWholeTableInDanger: isWholeTableInDanger,
402
655
  isTableAlignmentEnabled: isTableAlignmentEnabled,
403
656
  shouldUseIncreasedScalingPercent: shouldUseIncreasedScalingPercent,
404
- isCommentEditor: isCommentEditor
657
+ isCommentEditor: isCommentEditor,
658
+ isChromelessEditor: isChromelessEditor
405
659
  }, children);
406
660
  }
407
661
  const {
@@ -404,8 +404,15 @@ export const TableResizer = ({
404
404
  }, [editorView, getPos, node, isCommentEditor, widthToWidest, endMeasure, displayGapCursor, displayGuideline, updateWidth, scheduleResize, onResizeStop, attachAnalyticsEvent, tableRef, pluginInjectionApi, isTableScalingEnabled, shouldUseIncreasedScalingPercent, formatMessage]);
405
405
  const handleTableSizeChangeOnKeypress = useCallback(step => {
406
406
  const newWidth = width + step;
407
- if (newWidth > maxWidth || newWidth < resizerMinWidth) {
408
- return;
407
+ if (expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true)) {
408
+ if (newWidth < resizerMinWidth) {
409
+ return;
410
+ }
411
+ } else {
412
+ // maxWidth when platform_editor_tables_scaling_css off is always a number
413
+ if (newWidth > maxWidth || newWidth < resizerMinWidth) {
414
+ return;
415
+ }
409
416
  }
410
417
  handleResizeStop({
411
418
  width: width,
@@ -64,10 +64,17 @@ export default class TableView extends ReactNodeView {
64
64
  this.handleRef = node => this._handleTableRef(node);
65
65
  }
66
66
  getContentDOM() {
67
+ var _this$reactComponentP, _this$reactComponentP2, _this$reactComponentP3, _this$reactComponentP4;
68
+ const isNested = isTableNested(this.view.state, this.getPos());
67
69
  const tableDOMStructure = tableNodeSpecWithFixedToDOM({
68
70
  allowColumnResizing: !!this.reactComponentProps.allowColumnResizing,
69
71
  tableResizingEnabled: !!this.reactComponentProps.allowTableResizing,
70
- getEditorContainerWidth: this.reactComponentProps.getEditorContainerWidth
72
+ getEditorContainerWidth: this.reactComponentProps.getEditorContainerWidth,
73
+ isTableScalingEnabled: (_this$reactComponentP = this.reactComponentProps.options) === null || _this$reactComponentP === void 0 ? void 0 : _this$reactComponentP.isTableScalingEnabled,
74
+ shouldUseIncreasedScalingPercent: (_this$reactComponentP2 = this.reactComponentProps.options) === null || _this$reactComponentP2 === void 0 ? void 0 : _this$reactComponentP2.shouldUseIncreasedScalingPercent,
75
+ isCommentEditor: (_this$reactComponentP3 = this.reactComponentProps.options) === null || _this$reactComponentP3 === void 0 ? void 0 : _this$reactComponentP3.isCommentEditor,
76
+ isChromelessEditor: (_this$reactComponentP4 = this.reactComponentProps.options) === null || _this$reactComponentP4 === void 0 ? void 0 : _this$reactComponentP4.isChromelessEditor,
77
+ isNested
71
78
  }).toDOM(this.node);
72
79
  const rendered = DOMSerializer.renderSpec(document, tableDOMStructure);
73
80
  if (rendered.dom) {
@@ -374,6 +381,8 @@ export const createTableView = (node, view, getPos, portalProviderAPI, eventDisp
374
381
  allowTableResizing,
375
382
  allowTableAlignment
376
383
  } = getPluginConfig(pluginConfig);
384
+ const isTableFixedColumnWidthsOptionEnabled = (getEditorFeatureFlags === null || getEditorFeatureFlags === void 0 ? void 0 : getEditorFeatureFlags().tableWithFixedColumnWidthsOption) || false;
385
+ const shouldUseIncreasedScalingPercent = isTableScalingEnabled && (isTableFixedColumnWidthsOptionEnabled || isCommentEditor);
377
386
  return new TableView({
378
387
  node,
379
388
  view,
@@ -391,7 +400,8 @@ export const createTableView = (node, view, getPos, portalProviderAPI, eventDisp
391
400
  isTableScalingEnabled,
392
401
  // same as options.isTableScalingEnabled
393
402
  isCommentEditor,
394
- isChromelessEditor
403
+ isChromelessEditor,
404
+ shouldUseIncreasedScalingPercent
395
405
  },
396
406
  getEditorContainerWidth,
397
407
  getEditorFeatureFlags,
@@ -3,14 +3,16 @@ import { table, tableWithNestedTable } from '@atlaskit/adf-schema';
3
3
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
4
4
  import { akEditorGutterPaddingDynamic } from '@atlaskit/editor-shared-styles';
5
5
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
6
- import { generateColgroup, getResizerMinWidth } from '../pm-plugins/table-resizing/utils/colgroup';
6
+ import { generateColgroup, generateColgroupFromNode, getResizerMinWidth } from '../pm-plugins/table-resizing/utils/colgroup';
7
7
  import { TABLE_MAX_WIDTH } from '../pm-plugins/table-resizing/utils/consts';
8
+ import { getTableResizerContainerMaxWidthInCSS, getTableResizerContainerForFullPageWidthInCSS, getTableResizerItemWidthInCSS } from '../pm-plugins/table-resizing/utils/misc';
8
9
  import { getAlignmentStyle } from './table-container-styles';
9
10
  export const tableNodeSpecWithFixedToDOM = config => {
10
11
  const tableNode = config.isNestingSupported ? tableWithNestedTable : table;
11
12
  return {
12
13
  ...tableNode,
13
14
  toDOM: node => {
15
+ var _node$attrs$width;
14
16
  const gutterPadding = () => {
15
17
  if (expValEquals('platform_editor_preview_panel_responsiveness', 'isEnabled', true)) {
16
18
  return 'calc(var(--ak-editor--large-gutter-padding) * 2)';
@@ -20,6 +22,8 @@ export const tableNodeSpecWithFixedToDOM = config => {
20
22
  };
21
23
  const alignmentStyle = Object.entries(getAlignmentStyle(node.attrs.layout)).map(([k, v]) => `${kebabCase(k)}: ${kebabCase(v)}`).join(';');
22
24
  const tableMinWidth = getResizerMinWidth(node);
25
+ const tableWidthAttribute = node.attrs.width ? `${node.attrs.width}px` : `100%`;
26
+ const isFullPageEditor = !config.isChromelessEditor && !config.isCommentEditor;
23
27
  const attrs = {
24
28
  'data-number-column': node.attrs.isNumberColumnEnabled,
25
29
  'data-layout': node.attrs.layout,
@@ -27,10 +31,20 @@ export const tableNodeSpecWithFixedToDOM = config => {
27
31
  'data-table-local-id': node.attrs.localId,
28
32
  'data-table-width': node.attrs.width
29
33
  };
34
+
35
+ // This would be used for table scaling in colgroup CSS
36
+ // cqw, or px is well supported
37
+ const resizableTableWidth = expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true) ? isFullPageEditor ? getTableResizerContainerForFullPageWidthInCSS(node, config.isTableScalingEnabled) : `calc(100cqw - calc(var(--ak-editor--large-gutter-padding) * 2))` : `min(calc(100cqw - calc(var(--ak-editor--large-gutter-padding) * 2)), ${(_node$attrs$width = node.attrs.width) !== null && _node$attrs$width !== void 0 ? _node$attrs$width : '100%'})`;
30
38
  let colgroup = '';
31
39
  if (config.allowColumnResizing) {
32
- colgroup = ['colgroup', {}, ...generateColgroup(node)];
40
+ if (expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true)) {
41
+ colgroup = ['colgroup', {}, ...generateColgroupFromNode(node, config.isCommentEditor, config.isChromelessEditor, config.isNested, config.isTableScalingEnabled, config.shouldUseIncreasedScalingPercent)];
42
+ } else {
43
+ colgroup = ['colgroup', {}, ...generateColgroup(node)];
44
+ }
33
45
  }
46
+
47
+ // For Chromeless editor, and nested tables in full page editor
34
48
  const tableContainerDiv = ['div', {
35
49
  class: 'pm-table-container',
36
50
  'data-number-column': node.attrs.isNumberColumnEnabled,
@@ -57,31 +71,33 @@ export const tableNodeSpecWithFixedToDOM = config => {
57
71
  class: 'pm-table-sticky-sentinel-bottom',
58
72
  'data-testid': 'sticky-sentinel-bottom'
59
73
  }]];
60
- if (!config.tableResizingEnabled) {
74
+ if (!config.tableResizingEnabled || expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true) && config.isNested) {
61
75
  return ['div', {
62
76
  class: 'tableView-content-wrap',
63
77
  'data-prosemirror-initial-toDOM-render': 'true'
64
78
  }, tableContainerDiv];
65
79
  }
66
- const tableWidthAttribute = node.attrs.width ? `${node.attrs.width}px` : `100%`;
67
80
  const tableResizingDiv = ['div', {
68
81
  'data-testid': 'table-alignment-container',
69
82
  style: alignmentStyle
70
83
  }, ['div', {
71
84
  class: 'pm-table-resizer-container',
72
- style: `width: min(calc(100cqw - ${gutterPadding()}), ${tableWidthAttribute});`
85
+ style: convertToInlineCss({
86
+ '--ak-editor-table-gutter-padding': config.isTableScalingEnabled ? 'calc(var(--ak-editor--large-gutter-padding) * 2)' : 'calc(var(--ak-editor--large-gutter-padding) * 2 - var(--ak-editor-resizer-handle-spacing))',
87
+ '--ak-editor-table-width': resizableTableWidth,
88
+ width: expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true) ? `var(--ak-editor-table-width)` : `min(calc(100cqw - ${gutterPadding()}), ${tableWidthAttribute})`
89
+ })
73
90
  }, ['div', {
74
91
  class: 'resizer-item display-handle',
75
92
  style: convertToInlineCss({
76
93
  position: 'relative',
77
94
  userSelect: 'auto',
78
95
  boxSizing: 'border-box',
79
- '--ak-editor-table-gutter-padding': `${gutterPadding()}`,
80
96
  '--ak-editor-table-max-width': `${TABLE_MAX_WIDTH}px`,
81
97
  '--ak-editor-table-min-width': `${tableMinWidth}px`,
82
98
  minWidth: 'var(--ak-editor-table-min-width)',
83
- maxWidth: `min(calc(100cqw - var(--ak-editor-table-gutter-padding)), var(--ak-editor-table-max-width))`,
84
- width: `min(calc(100cqw - var(--ak-editor-table-gutter-padding)), ${tableWidthAttribute})`
99
+ maxWidth: expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true) ? getTableResizerContainerMaxWidthInCSS(config.isCommentEditor, config.isChromelessEditor, config.isTableScalingEnabled) : `min(calc(100cqw - var(--ak-editor-table-gutter-padding)), var(--ak-editor-table-max-width))`,
100
+ width: expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true) ? getTableResizerItemWidthInCSS(node, config.isCommentEditor, config.isChromelessEditor) : `min(calc(100cqw - var(--ak-editor-table-gutter-padding)), ${tableWidthAttribute})`
85
101
  })
86
102
  }, ['span', {
87
103
  class: 'resizer-hover-zone'
@@ -7,6 +7,7 @@ import { findParentDomRefOfType, findParentNodeOfType } from '@atlaskit/editor-p
7
7
  import { TableMap } from '@atlaskit/editor-tables';
8
8
  import { findTable } from '@atlaskit/editor-tables/utils';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
10
11
  import { tableCellView, tableHeaderView, tableRowView, tableView } from '../nodeviews/table-node-views';
11
12
  import { pluginKey as decorationsPluginKey } from '../pm-plugins/decorations/plugin';
12
13
  import { TableCssClassName as ClassName } from '../types';
@@ -50,30 +51,63 @@ export const createPlugin = (dispatchAnalyticsEvent, dispatch, portalProviderAPI
50
51
  }
51
52
  return editorView.state;
52
53
  };
53
- const nodeViews = isSSR() && fg('platform_editor_table_fallback_to_dom_on_ssr') ? undefined : {
54
- table: tableView({
55
- portalProviderAPI,
56
- eventDispatcher,
57
- getEditorContainerWidth,
58
- getEditorFeatureFlags,
59
- dispatchAnalyticsEvent,
60
- pluginInjectionApi,
61
- isCommentEditor,
62
- isChromelessEditor
63
- }),
64
- tableRow: tableRowView({
65
- eventDispatcher,
66
- pluginInjectionApi
67
- }),
68
- tableCell: tableCellView({
69
- eventDispatcher,
70
- pluginInjectionApi
71
- }),
72
- tableHeader: tableHeaderView({
73
- eventDispatcher,
74
- pluginInjectionApi
75
- })
54
+ const getNodeView = () => {
55
+ // Because the layout shift issues has been fixed under experiment platform_editor_tables_scaling_css, so still want to load nodeview on SSR if experiment is enabled
56
+ if (expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true)) {
57
+ return {
58
+ table: tableView({
59
+ portalProviderAPI,
60
+ eventDispatcher,
61
+ getEditorContainerWidth,
62
+ getEditorFeatureFlags,
63
+ dispatchAnalyticsEvent,
64
+ pluginInjectionApi,
65
+ isCommentEditor,
66
+ isChromelessEditor
67
+ }),
68
+ tableRow: tableRowView({
69
+ eventDispatcher,
70
+ pluginInjectionApi
71
+ }),
72
+ tableCell: tableCellView({
73
+ eventDispatcher,
74
+ pluginInjectionApi
75
+ }),
76
+ tableHeader: tableHeaderView({
77
+ eventDispatcher,
78
+ pluginInjectionApi
79
+ })
80
+ };
81
+ }
82
+ if (isSSR() && fg('platform_editor_table_fallback_to_dom_on_ssr')) {
83
+ return undefined;
84
+ }
85
+ return {
86
+ table: tableView({
87
+ portalProviderAPI,
88
+ eventDispatcher,
89
+ getEditorContainerWidth,
90
+ getEditorFeatureFlags,
91
+ dispatchAnalyticsEvent,
92
+ pluginInjectionApi,
93
+ isCommentEditor,
94
+ isChromelessEditor
95
+ }),
96
+ tableRow: tableRowView({
97
+ eventDispatcher,
98
+ pluginInjectionApi
99
+ }),
100
+ tableCell: tableCellView({
101
+ eventDispatcher,
102
+ pluginInjectionApi
103
+ }),
104
+ tableHeader: tableHeaderView({
105
+ eventDispatcher,
106
+ pluginInjectionApi
107
+ })
108
+ };
76
109
  };
110
+ const nodeViews = getNodeView();
77
111
  return new SafePlugin({
78
112
  state: state,
79
113
  key: pluginKey,
@@ -1,9 +1,10 @@
1
1
  import { tableCellMinWidth } from '@atlaskit/editor-common/styles';
2
- import { getFragmentBackingArray } from '@atlaskit/editor-common/utils';
2
+ import { calcTableColumnWidths, getFragmentBackingArray } from '@atlaskit/editor-common/utils';
3
3
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
4
+ import { akEditorTableNumberColumnWidth } from '@atlaskit/editor-shared-styles';
4
5
  import { TableMap } from '@atlaskit/editor-tables/table-map';
5
- import { COLUMN_MIN_WIDTH } from './consts';
6
- import { getScalingPercentForTableWithoutWidth, getTableScalingPercent } from './misc';
6
+ import { COLUMN_MIN_WIDTH, MAX_SCALING_PERCENT, MAX_SCALING_PERCENT_TABLES_WITH_FIXED_COLUMN_WIDTHS_OPTION } from './consts';
7
+ import { getScalingPercentForTableWithoutWidth, getTableContainerElementWidth, getTableScalingPercent } from './misc';
7
8
  /**
8
9
  * This ensures the combined width of the columns (and tbody) of table is always smaller or equal
9
10
  * than the table and table wrapper elements. This is necessary as there is no longer
@@ -11,6 +12,73 @@ import { getScalingPercentForTableWithoutWidth, getTableScalingPercent } from '.
11
12
  * overflow.
12
13
  */
13
14
  export const getColWidthFix = (colwidth, tableColumnCount) => colwidth - 1 / tableColumnCount;
15
+ const generateColStyle = (fixedColWidth, tableWidth, isCommentEditor, isChromelessEditor, isNested, shouldUseIncreasedScalingPercent, isNumberColumnEnabled, isTableHasWidth, hasTableBeenResized) => {
16
+ const maxScalingPercent = shouldUseIncreasedScalingPercent ? MAX_SCALING_PERCENT_TABLES_WITH_FIXED_COLUMN_WIDTHS_OPTION : MAX_SCALING_PERCENT;
17
+ const maxScaledRatio = 1 - maxScalingPercent;
18
+ const isFullPageEditor = !isChromelessEditor && !isCommentEditor;
19
+
20
+ // for nested tables, or chromeless editor, which used non resizable table container
21
+ if (isNested || isChromelessEditor) {
22
+ if (hasTableBeenResized) {
23
+ return `width: max(${fixedColWidth}px, ${tableCellMinWidth}px)`;
24
+ }
25
+ return `width: ${tableCellMinWidth}px)`;
26
+ }
27
+ if (isFullPageEditor || !isFullPageEditor && isTableHasWidth) {
28
+ const scaledPercent = isNumberColumnEnabled ? `calc(calc(var(--ak-editor-table-width) - ${akEditorTableNumberColumnWidth}px - 1px)/${tableWidth})` : `calc(calc(var(--ak-editor-table-width) - 1px)/${tableWidth})`;
29
+ return `width: max(calc(${fixedColWidth}px * ${maxScaledRatio}), calc(${fixedColWidth} * ${scaledPercent}), ${tableCellMinWidth}px)`;
30
+ }
31
+ // table resized to full-width in comment editor
32
+ // it doesn't have a width attribute, and cols has been resized
33
+ if (hasTableBeenResized) {
34
+ const scaledPercent = isNumberColumnEnabled ? `calc(calc(var(--ak-editor-table-width) - ${akEditorTableNumberColumnWidth}px - 1px)/${tableWidth})` : `calc(calc(var(--ak-editor-table-width) - 1px)/${tableWidth})`;
35
+ return `width: max(calc(${fixedColWidth} * ${scaledPercent}), ${tableCellMinWidth}px)`;
36
+ }
37
+ return `width: ${tableCellMinWidth}px`;
38
+ };
39
+ export const generateColgroupFromNode = (table, isCommentEditor, isChromelessEditor, isNested, isTableScalingEnabled, shouldUseIncreasedScalingPercent) => {
40
+ const cols = [];
41
+ const map = TableMap.get(table);
42
+ const isTableHasWidth = !!table.attrs.width;
43
+ const isNumberColumnEnabled = table.attrs.isNumberColumnEnabled || false;
44
+ const isFullPageEditor = !isChromelessEditor && !isCommentEditor;
45
+
46
+ // Ignored via go/ees005
47
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
48
+ table.content.firstChild.content.forEach(cell => {
49
+ const colspan = cell.attrs.colspan || 1;
50
+ // if the table has been resized
51
+ if (Array.isArray(cell.attrs.colwidth)) {
52
+ cell.attrs.colwidth.slice(0, colspan).forEach(width => {
53
+ // existing logic for calculating the width of the column
54
+ const fixedColWidth = getColWidthFix(width, map.width);
55
+ const tableWidth = isFullPageEditor || !isFullPageEditor && isTableHasWidth ? getTableContainerElementWidth(table) : calcTableColumnWidths(table).reduce((sum, width) => sum + width, 0);
56
+ if (isTableScalingEnabled) {
57
+ cols.push(['col', {
58
+ style: generateColStyle(fixedColWidth, tableWidth, isCommentEditor, isChromelessEditor, isNested, shouldUseIncreasedScalingPercent, isNumberColumnEnabled, isTableHasWidth, true)
59
+ }]);
60
+ } else {
61
+ cols.push(['col', {
62
+ style: `width: max(${fixedColWidth}px, ${tableCellMinWidth}px)`
63
+ }]);
64
+ }
65
+ });
66
+ } else {
67
+ // columns has not been resized, so distribute the width evenly
68
+ cols.push(...Array.from({
69
+ length: colspan
70
+ }, _ => {
71
+ const tableWidth = getTableContainerElementWidth(table);
72
+ const columnWidth = tableWidth / map.width || 0;
73
+ const fixedColWidth = getColWidthFix(columnWidth, map.width || 0);
74
+ return ['col', {
75
+ style: generateColStyle(fixedColWidth, tableWidth, isCommentEditor, isChromelessEditor, isNested, shouldUseIncreasedScalingPercent, isNumberColumnEnabled, isTableHasWidth)
76
+ }];
77
+ }));
78
+ }
79
+ });
80
+ return cols;
81
+ };
14
82
  export const generateColgroup = (table, tableRef, shouldUseIncreasedScalingPercent, isCommentEditor) => {
15
83
  const cols = [];
16
84
  const map = TableMap.get(table);
@@ -32,6 +100,7 @@ export const generateColgroup = (table, tableRef, shouldUseIncreasedScalingPerce
32
100
  scalePercent = getTableScalingPercent(table, tableRef, shouldUseIncreasedScalingPercent);
33
101
  }
34
102
  cell.attrs.colwidth.slice(0, colspan).forEach(width => {
103
+ // existing logic for calculating the width of the column
35
104
  const fixedColWidth = getColWidthFix(width, map.width);
36
105
  const scaledWidth = fixedColWidth * scalePercent;
37
106
  const finalWidth = Math.max(scaledWidth, tableCellMinWidth);