@atlaskit/editor-plugin-insert-block 0.2.18 → 0.2.20

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.
@@ -15,6 +15,7 @@ import * as colors from '@atlaskit/theme/colors';
15
15
  import { BlockInsertMenu } from './block-insert-menu';
16
16
  import { createItems } from './create-items';
17
17
  import { messages } from './messages';
18
+ import TableSelectorPopup from './table-selector-popup-with-listeners';
18
19
  /**
19
20
  * Checks if an element is detached (i.e. not in the current document)
20
21
  */
@@ -31,10 +32,13 @@ const getHoverStyles = selector => `&:hover ${selector} {
31
32
  background: ${`var(--ds-background-neutral-hovered, ${colors.N30A})`};
32
33
  }
33
34
  }`;
34
- export const tableButtonWrapper = css`
35
+ export const tableButtonWrapper = ({
36
+ isTableSelectorOpen,
37
+ isButtonDisabled
38
+ }) => css`
35
39
  display: flex;
36
- ${getHoverStyles('.table-selector-toolbar-btn')}
37
- ${getHoverStyles('.table-toolbar-btn')}
40
+ ${!isTableSelectorOpen && !isButtonDisabled && getHoverStyles('.table-selector-toolbar-btn')}
41
+ ${!isTableSelectorOpen && !isButtonDisabled && getHoverStyles('.table-toolbar-btn')}
38
42
 
39
43
  .table-toolbar-btn {
40
44
  border-top-right-radius: ${"var(--ds-border-radius-200, 0px)"};
@@ -42,6 +46,7 @@ export const tableButtonWrapper = css`
42
46
  margin-right: ${"var(--ds-space-025, 1px)"};
43
47
  padding: ${"var(--ds-space-0, 0px)"};
44
48
  & > span {
49
+ min-width: 16px;
45
50
  margin: ${"var(--ds-space-0, 0px)"};
46
51
  }
47
52
  }
@@ -63,6 +68,8 @@ export const tableButtonWrapper = css`
63
68
  export class ToolbarInsertBlock extends React.PureComponent {
64
69
  constructor(...args) {
65
70
  super(...args);
71
+ _defineProperty(this, "tableButtonRef", /*#__PURE__*/React.createRef());
72
+ _defineProperty(this, "tableSelectorButtonRef", /*#__PURE__*/React.createRef());
66
73
  _defineProperty(this, "state", {
67
74
  isPlusMenuOpen: false,
68
75
  emojiPickerOpen: false,
@@ -169,6 +176,26 @@ export class ToolbarInsertBlock extends React.PureComponent {
169
176
  this.dropdownButtonRef = ref;
170
177
  }
171
178
  });
179
+ _defineProperty(this, "toggleTableSelector", (inputMethod = INPUT_METHOD.TOOLBAR) => {
180
+ this.setState(prevState => ({
181
+ isTableSelectorOpen: !prevState.isTableSelectorOpen
182
+ }));
183
+ });
184
+ _defineProperty(this, "handleSelectedTableSize", (rowsCount, colsCount) => {
185
+ this.insertTableWithSize(INPUT_METHOD.TOOLBAR, rowsCount, colsCount)();
186
+ this.toggleTableSelector();
187
+ });
188
+ _defineProperty(this, "handleTableSelectorPressEscape", () => {
189
+ var _this$tableSelectorBu;
190
+ this.toggleTableSelector(INPUT_METHOD.KEYBOARD);
191
+ (_this$tableSelectorBu = this.tableSelectorButtonRef.current) === null || _this$tableSelectorBu === void 0 ? void 0 : _this$tableSelectorBu.focus();
192
+ });
193
+ _defineProperty(this, "handleTableSelectorClickOutside", e => {
194
+ // Ignore click events for detached elements.
195
+ if (e.target && !isDetachedElement(e.target)) {
196
+ this.toggleTableSelector(INPUT_METHOD.TOOLBAR);
197
+ }
198
+ });
172
199
  _defineProperty(this, "handleClick", () => {
173
200
  this.togglePlusMenuVisibility();
174
201
  });
@@ -183,11 +210,11 @@ export class ToolbarInsertBlock extends React.PureComponent {
183
210
  }
184
211
  });
185
212
  _defineProperty(this, "toggleLinkPanel", inputMethod => {
186
- var _pluginInjectionApi$c, _pluginInjectionApi$h;
213
+ var _pluginInjectionApi$c, _pluginInjectionApi$c2, _pluginInjectionApi$h;
187
214
  const {
188
215
  pluginInjectionApi
189
216
  } = this.props;
190
- return (_pluginInjectionApi$c = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.core.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$h = pluginInjectionApi.hyperlink) === null || _pluginInjectionApi$h === void 0 ? void 0 : _pluginInjectionApi$h.commands.showLinkToolbar(inputMethod))) !== null && _pluginInjectionApi$c !== void 0 ? _pluginInjectionApi$c : false;
217
+ return (_pluginInjectionApi$c = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c2 = pluginInjectionApi.core) === null || _pluginInjectionApi$c2 === void 0 ? void 0 : _pluginInjectionApi$c2.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$h = pluginInjectionApi.hyperlink) === null || _pluginInjectionApi$h === void 0 ? void 0 : _pluginInjectionApi$h.commands.showLinkToolbar(inputMethod))) !== null && _pluginInjectionApi$c !== void 0 ? _pluginInjectionApi$c : false;
191
218
  });
192
219
  _defineProperty(this, "insertMention", inputMethod => {
193
220
  var _pluginInjectionApi$m, _pluginInjectionApi$m2, _pluginInjectionApi$m3;
@@ -225,18 +252,18 @@ export class ToolbarInsertBlock extends React.PureComponent {
225
252
  })(state, dispatch)) !== null && _pluginInjectionApi$t !== void 0 ? _pluginInjectionApi$t : false;
226
253
  });
227
254
  _defineProperty(this, "insertTableWithSize", (inputMethod, rowsCount, colsCount) => () => {
228
- var _pluginInjectionApi$t5;
255
+ var _pluginInjectionApi$c3, _pluginInjectionApi$t5;
229
256
  const {
230
257
  pluginInjectionApi
231
258
  } = this.props;
232
- return pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.core.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$t5 = pluginInjectionApi.table) === null || _pluginInjectionApi$t5 === void 0 ? void 0 : _pluginInjectionApi$t5.commands.insertTableWithSize(rowsCount, colsCount, INPUT_METHOD.PICKER));
259
+ return pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c3 = pluginInjectionApi.core) === null || _pluginInjectionApi$c3 === void 0 ? void 0 : _pluginInjectionApi$c3.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$t5 = pluginInjectionApi.table) === null || _pluginInjectionApi$t5 === void 0 ? void 0 : _pluginInjectionApi$t5.commands.insertTableWithSize(rowsCount, colsCount, INPUT_METHOD.PICKER));
233
260
  });
234
261
  _defineProperty(this, "createDate", inputMethod => {
235
- var _pluginInjectionApi$d, _pluginInjectionApi$d2;
262
+ var _pluginInjectionApi$c4, _pluginInjectionApi$d, _pluginInjectionApi$d2;
236
263
  const {
237
264
  pluginInjectionApi
238
265
  } = this.props;
239
- pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.core.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d = pluginInjectionApi.date) === null || _pluginInjectionApi$d === void 0 ? void 0 : (_pluginInjectionApi$d2 = _pluginInjectionApi$d.commands) === null || _pluginInjectionApi$d2 === void 0 ? void 0 : _pluginInjectionApi$d2.insertDate({
266
+ 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$d = pluginInjectionApi.date) === null || _pluginInjectionApi$d === void 0 ? void 0 : (_pluginInjectionApi$d2 = _pluginInjectionApi$d.commands) === null || _pluginInjectionApi$d2 === void 0 ? void 0 : _pluginInjectionApi$d2.insertDate({
240
267
  inputMethod
241
268
  }));
242
269
  return true;
@@ -335,21 +362,21 @@ export class ToolbarInsertBlock extends React.PureComponent {
335
362
  return true;
336
363
  });
337
364
  _defineProperty(this, "handleSelectedEmoji", emojiId => {
338
- var _pluginInjectionApi$e3;
365
+ var _pluginInjectionApi$c5, _pluginInjectionApi$e3;
339
366
  const {
340
367
  pluginInjectionApi
341
368
  } = this.props;
342
369
  this.props.editorView.focus();
343
- pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.core.actions.execute((_pluginInjectionApi$e3 = pluginInjectionApi.emoji) === null || _pluginInjectionApi$e3 === void 0 ? void 0 : _pluginInjectionApi$e3.commands.insertEmoji(emojiId, INPUT_METHOD.PICKER));
370
+ pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c5 = pluginInjectionApi.core) === null || _pluginInjectionApi$c5 === void 0 ? void 0 : _pluginInjectionApi$c5.actions.execute((_pluginInjectionApi$e3 = pluginInjectionApi.emoji) === null || _pluginInjectionApi$e3 === void 0 ? void 0 : _pluginInjectionApi$e3.commands.insertEmoji(emojiId, INPUT_METHOD.PICKER));
344
371
  this.toggleEmojiPicker();
345
372
  return true;
346
373
  });
347
374
  _defineProperty(this, "openElementBrowser", () => {
348
- var _pluginInjectionApi$q;
375
+ var _pluginInjectionApi$c6, _pluginInjectionApi$q;
349
376
  const {
350
377
  pluginInjectionApi
351
378
  } = this.props;
352
- pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.core.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q === void 0 ? void 0 : _pluginInjectionApi$q.commands.openElementBrowserModal);
379
+ pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$c6 = pluginInjectionApi.core) === null || _pluginInjectionApi$c6 === void 0 ? void 0 : _pluginInjectionApi$c6.actions.execute(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$q = pluginInjectionApi.quickInsert) === null || _pluginInjectionApi$q === void 0 ? void 0 : _pluginInjectionApi$q.commands.openElementBrowserModal);
353
380
  });
354
381
  _defineProperty(this, "onItemActivated", ({
355
382
  item,
@@ -374,7 +401,7 @@ export class ToolbarInsertBlock extends React.PureComponent {
374
401
  this.insertTable(inputMethod);
375
402
  break;
376
403
  case 'table selector':
377
- this.insertTableWithSize(inputMethod, 4, 4)(); // adding command here to pass typecheck but will implement the actual feature in future ticket
404
+ this.toggleTableSelector(inputMethod);
378
405
  break;
379
406
  case 'image upload':
380
407
  if (handleImageUpload) {
@@ -490,10 +517,11 @@ export class ToolbarInsertBlock extends React.PureComponent {
490
517
  };
491
518
  }
492
519
  componentDidUpdate(prevProps) {
493
- // If number of visible buttons changed, close emoji picker
520
+ // If number of visible buttons changed, close emoji picker and table selector
494
521
  if (prevProps.buttons !== this.props.buttons) {
495
522
  this.setState({
496
- emojiPickerOpen: false
523
+ emojiPickerOpen: false,
524
+ isTableSelectorOpen: false
497
525
  });
498
526
  }
499
527
  if (this.state.isOpenedByKeyboard) {
@@ -547,12 +575,37 @@ export class ToolbarInsertBlock extends React.PureComponent {
547
575
  handleEscapeKeydown: this.handleEmojiPressEscape
548
576
  }));
549
577
  }
578
+ renderTableSelectorPopup() {
579
+ var _this$tableButtonRef$;
580
+ const {
581
+ isTableSelectorOpen
582
+ } = this.state;
583
+ const {
584
+ popupsMountPoint,
585
+ popupsBoundariesElement,
586
+ popupsScrollableElement
587
+ } = this.props;
588
+ const ref = (_this$tableButtonRef$ = this.tableButtonRef.current) !== null && _this$tableButtonRef$ !== void 0 ? _this$tableButtonRef$ : undefined;
589
+ if (!isTableSelectorOpen) {
590
+ return null;
591
+ }
592
+ return jsx(TableSelectorPopup, {
593
+ target: ref,
594
+ onSelection: this.handleSelectedTableSize,
595
+ popupsMountPoint: popupsMountPoint,
596
+ popupsBoundariesElement: popupsBoundariesElement,
597
+ popupsScrollableElement: popupsScrollableElement,
598
+ handleClickOutside: this.handleTableSelectorClickOutside,
599
+ handleEscapeKeydown: this.handleTableSelectorPressEscape
600
+ });
601
+ }
550
602
  render() {
551
- var _tableButton, _tableButton2, _tableButton3, _tableButton4, _tableButton5, _tableButton6, _tableSelectorButton, _tableSelectorButton2, _tableSelectorButton3, _tableSelectorButton4, _tableSelectorButton5, _tableSelectorButton6, _this$props$isDisable, _this$props$replacePl;
603
+ var _tableButton, _tableButton2, _tableButton3, _tableButton4, _tableButton5, _tableButton6, _tableButton7, _tableSelectorButton, _tableSelectorButton2, _tableSelectorButton3, _tableSelectorButton4, _tableSelectorButton5, _tableSelectorButton6, _this$props$isDisable, _this$props$replacePl;
552
604
  const {
553
605
  buttons,
554
606
  dropdownItems,
555
- emojiPickerOpen
607
+ emojiPickerOpen,
608
+ isTableSelectorOpen
556
609
  } = this.state;
557
610
  const {
558
611
  isDisabled,
@@ -595,20 +648,23 @@ export class ToolbarInsertBlock extends React.PureComponent {
595
648
  "aria-keyshortcuts": btn['aria-keyshortcuts'],
596
649
  onItemClick: this.insertToolbarMenuItem
597
650
  });
598
- }), this.props.tableSelectorSupported &&
599
- // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
600
- jsx("div", {
601
- css: tableButtonWrapper
651
+ }), this.props.tableSelectorSupported && jsx("div", {
652
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
653
+ css: tableButtonWrapper({
654
+ isTableSelectorOpen,
655
+ isButtonDisabled: (_tableButton = tableButton) === null || _tableButton === void 0 ? void 0 : _tableButton.isDisabled
656
+ })
602
657
  }, jsx(ToolbarButton, {
603
658
  className: "table-toolbar-btn",
604
659
  item: tableButton,
605
- testId: String((_tableButton = tableButton) === null || _tableButton === void 0 ? void 0 : _tableButton.content),
606
- key: (_tableButton2 = tableButton) === null || _tableButton2 === void 0 ? void 0 : _tableButton2.value.name,
660
+ ref: this.tableButtonRef,
661
+ testId: String((_tableButton2 = tableButton) === null || _tableButton2 === void 0 ? void 0 : _tableButton2.content),
662
+ key: (_tableButton3 = tableButton) === null || _tableButton3 === void 0 ? void 0 : _tableButton3.value.name,
607
663
  spacing: isReducedSpacing ? 'none' : 'default',
608
- disabled: isDisabled || ((_tableButton3 = tableButton) === null || _tableButton3 === void 0 ? void 0 : _tableButton3.isDisabled),
609
- iconBefore: (_tableButton4 = tableButton) === null || _tableButton4 === void 0 ? void 0 : _tableButton4.elemBefore,
610
- selected: (_tableButton5 = tableButton) === null || _tableButton5 === void 0 ? void 0 : _tableButton5.isActive,
611
- title: (_tableButton6 = tableButton) === null || _tableButton6 === void 0 ? void 0 : _tableButton6.title,
664
+ disabled: isDisabled || ((_tableButton4 = tableButton) === null || _tableButton4 === void 0 ? void 0 : _tableButton4.isDisabled),
665
+ iconBefore: (_tableButton5 = tableButton) === null || _tableButton5 === void 0 ? void 0 : _tableButton5.elemBefore,
666
+ selected: ((_tableButton6 = tableButton) === null || _tableButton6 === void 0 ? void 0 : _tableButton6.isActive) || isTableSelectorOpen,
667
+ title: (_tableButton7 = tableButton) === null || _tableButton7 === void 0 ? void 0 : _tableButton7.title,
612
668
  "aria-label": tableButton ? tableButton['aria-label'] : undefined,
613
669
  "aria-haspopup": tableButton ? tableButton['aria-haspopup'] : undefined,
614
670
  "aria-keyshortcuts": tableButton ? tableButton['aria-keyshortcuts'] : undefined,
@@ -618,10 +674,11 @@ export class ToolbarInsertBlock extends React.PureComponent {
618
674
  item: tableSelectorButton,
619
675
  testId: String((_tableSelectorButton = tableSelectorButton) === null || _tableSelectorButton === void 0 ? void 0 : _tableSelectorButton.content),
620
676
  key: (_tableSelectorButton2 = tableSelectorButton) === null || _tableSelectorButton2 === void 0 ? void 0 : _tableSelectorButton2.value.name,
677
+ ref: this.tableSelectorButtonRef,
621
678
  spacing: isReducedSpacing ? 'none' : 'default',
622
679
  disabled: isDisabled || ((_tableSelectorButton3 = tableSelectorButton) === null || _tableSelectorButton3 === void 0 ? void 0 : _tableSelectorButton3.isDisabled),
623
680
  iconBefore: (_tableSelectorButton4 = tableSelectorButton) === null || _tableSelectorButton4 === void 0 ? void 0 : _tableSelectorButton4.elemBefore,
624
- selected: (_tableSelectorButton5 = tableSelectorButton) === null || _tableSelectorButton5 === void 0 ? void 0 : _tableSelectorButton5.isActive,
681
+ selected: ((_tableSelectorButton5 = tableSelectorButton) === null || _tableSelectorButton5 === void 0 ? void 0 : _tableSelectorButton5.isActive) || isTableSelectorOpen,
625
682
  title: (_tableSelectorButton6 = tableSelectorButton) === null || _tableSelectorButton6 === void 0 ? void 0 : _tableSelectorButton6.title,
626
683
  "aria-label": tableSelectorButton ? tableSelectorButton['aria-label'] : undefined,
627
684
  "aria-haspopup": tableSelectorButton ? tableSelectorButton['aria-haspopup'] : undefined,
@@ -629,7 +686,7 @@ export class ToolbarInsertBlock extends React.PureComponent {
629
686
  onItemClick: this.insertToolbarMenuItem
630
687
  })), jsx("span", {
631
688
  css: wrapperStyle
632
- }, this.renderPopup(), jsx(BlockInsertMenu, {
689
+ }, this.renderPopup(), this.renderTableSelectorPopup(), jsx(BlockInsertMenu, {
633
690
  popupsMountPoint: this.props.popupsMountPoint,
634
691
  popupsBoundariesElement: this.props.popupsBoundariesElement,
635
692
  popupsScrollableElement: this.props.popupsScrollableElement,
@@ -0,0 +1,101 @@
1
+ /** @jsx jsx */
2
+
3
+ import { useCallback, useEffect, useRef, useState } from 'react';
4
+ import { css, jsx } from '@emotion/react';
5
+ import { bind } from 'bind-event-listener';
6
+ import { Popup } from '@atlaskit/editor-common/ui';
7
+ import { withReactEditorViewOuterListeners as withOuterListeners } from '@atlaskit/editor-common/ui-react';
8
+ import { akEditorMenuZIndex } from '@atlaskit/editor-shared-styles';
9
+ import { N0, N30A, N60A } from '@atlaskit/theme/colors';
10
+ import tableSelectorPopup, { TABLE_SELECTOR_BUTTON_GAP, TABLE_SELECTOR_BUTTON_SIZE } from './table-selector-popup';
11
+ const TABLE_SELECTOR_PADDING_TOP = 8;
12
+ const TABLE_SELECTOR_PADDING_SIDE = 10;
13
+ const DEFAULT_TABLE_SELECTOR_ROWS = 5;
14
+ const DEFAULT_TABLE_SELECTOR_COLS = 10;
15
+ const DEFAULT_TABLE_SELECTOR_SELECTION_SIZE = 1;
16
+ const TableSelectorWithListeners = withOuterListeners(tableSelectorPopup);
17
+ const tableSelectorPopupWrapperStyles = css({
18
+ borderRadius: "var(--ds-border-radius, 3px)",
19
+ backgroundColor: `var(--ds-surface-overlay, ${N0})`,
20
+ boxShadow: `var(--ds-shadow-overlay, ${`0 0 0 1px ${N30A}, 0 2px 1px ${N30A}, 0 0 20px -6px ${N60A}`})`,
21
+ padding: `${`var(--ds-space-100, ${`${TABLE_SELECTOR_PADDING_TOP}px`})`} ${TABLE_SELECTOR_PADDING_SIDE}px`
22
+ });
23
+ export const TableSelectorPopup = props => {
24
+ const [size, setSize] = useState({
25
+ col: DEFAULT_TABLE_SELECTOR_SELECTION_SIZE,
26
+ row: DEFAULT_TABLE_SELECTOR_SELECTION_SIZE,
27
+ maxCol: DEFAULT_TABLE_SELECTOR_COLS,
28
+ maxRow: DEFAULT_TABLE_SELECTOR_ROWS
29
+ });
30
+ const tablePopupRef = useRef(null);
31
+
32
+ // Mouse move is used to allow selection changes outside of the popup and is more reactive to changes.
33
+ const handleMouseMove = useCallback(e => {
34
+ if (!tablePopupRef.current) {
35
+ return;
36
+ }
37
+ const tablePopup = tablePopupRef.current;
38
+ const {
39
+ left,
40
+ top
41
+ } = tablePopup.getBoundingClientRect();
42
+
43
+ // Mouse position on popup
44
+ const selectedWidth = e.clientX - left;
45
+ const selectedHeight = e.clientY - top;
46
+
47
+ // Calculate number grid cells selected
48
+ let selectedGridCols = Math.ceil((selectedWidth - TABLE_SELECTOR_PADDING_SIDE + TABLE_SELECTOR_BUTTON_GAP) / (TABLE_SELECTOR_BUTTON_GAP + TABLE_SELECTOR_BUTTON_SIZE));
49
+ let selectedGridRows = Math.ceil((selectedHeight - TABLE_SELECTOR_PADDING_TOP + TABLE_SELECTOR_BUTTON_GAP) / (TABLE_SELECTOR_BUTTON_GAP + TABLE_SELECTOR_BUTTON_SIZE));
50
+
51
+ // Keep the selected rows and columns within the defined bounds
52
+ if (selectedGridCols < 1) {
53
+ selectedGridCols = 1;
54
+ }
55
+ if (selectedGridCols > size.maxCol) {
56
+ selectedGridCols = size.maxCol;
57
+ }
58
+ if (selectedGridRows < 1) {
59
+ selectedGridRows = 1;
60
+ }
61
+ if (selectedGridRows > size.maxRow) {
62
+ selectedGridRows = size.maxRow;
63
+ }
64
+ if (selectedGridCols !== size.col || selectedGridRows !== size.row) {
65
+ setSize({
66
+ col: selectedGridCols,
67
+ row: selectedGridRows,
68
+ maxCol: DEFAULT_TABLE_SELECTOR_COLS,
69
+ maxRow: DEFAULT_TABLE_SELECTOR_ROWS
70
+ });
71
+ }
72
+ }, [size, setSize]);
73
+ useEffect(() => {
74
+ const unbind = bind(window, {
75
+ type: 'mousemove',
76
+ listener: handleMouseMove
77
+ });
78
+ return unbind;
79
+ }, [handleMouseMove]);
80
+ return jsx(Popup, {
81
+ target: props.target,
82
+ offset: [0, 3],
83
+ mountTo: props.popupsMountPoint,
84
+ boundariesElement: props.popupsBoundariesElement,
85
+ scrollableElement: props.popupsScrollableElement,
86
+ focusTrap: true,
87
+ zIndex: akEditorMenuZIndex
88
+ }, jsx("div", {
89
+ css: tableSelectorPopupWrapperStyles,
90
+ ref: tablePopupRef
91
+ }, jsx(TableSelectorWithListeners, {
92
+ handleClickOutside: props.handleClickOutside,
93
+ handleEscapeKeydown: props.handleEscapeKeydown,
94
+ maxCols: size.maxCol,
95
+ maxRows: size.maxRow,
96
+ onSelection: props.onSelection,
97
+ selectedCol: size.col,
98
+ selectedRow: size.row
99
+ })));
100
+ };
101
+ export default TableSelectorPopup;
@@ -0,0 +1,102 @@
1
+ /** @jsx jsx */
2
+ import { useMemo } from 'react';
3
+ import { css, jsx } from '@emotion/react';
4
+ import { injectIntl } from 'react-intl-next';
5
+ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
6
+ import { Stack } from '@atlaskit/primitives';
7
+ export const TABLE_SELECTOR_BUTTON_GAP = 2;
8
+ export const TABLE_SELECTOR_BUTTON_SIZE = 17;
9
+ const selectedButtonStyles = css({
10
+ backgroundColor: "var(--ds-background-accent-blue-subtlest, #579DFF)",
11
+ border: `1px solid ${"var(--ds-background-accent-blue-subtle, #579DFF)"}`
12
+ });
13
+ const buttonStyles = css({
14
+ height: `${TABLE_SELECTOR_BUTTON_SIZE}px`,
15
+ width: `${TABLE_SELECTOR_BUTTON_SIZE}px`,
16
+ border: `1px solid ${"var(--ds-border, #091e4224)"}`,
17
+ backgroundColor: "var(--ds-background-input, #ffffff)",
18
+ borderRadius: '3px',
19
+ cursor: 'pointer',
20
+ display: 'block',
21
+ '&:hover': {
22
+ backgroundColor: "var(--ds-background-accent-blue-subtlest, #579DFF)",
23
+ border: `1px solid ${"var(--ds-background-accent-blue-subtle, #579DFF)"}`
24
+ }
25
+ });
26
+ const selectionSizeTextStyles = css({
27
+ lineHeight: '14px',
28
+ display: 'flex',
29
+ justifyContent: 'center',
30
+ marginTop: "var(--ds-space-075, 5px)",
31
+ padding: "var(--ds-space-075, 10px)"
32
+ });
33
+ const TableSelectorButton = ({
34
+ row,
35
+ col,
36
+ isActive,
37
+ onClick,
38
+ label
39
+ }) => {
40
+ return jsx("button", {
41
+ css: [buttonStyles, isActive ? selectedButtonStyles : undefined],
42
+ onClick: () => onClick(row, col),
43
+ "aria-label": label
44
+ });
45
+ };
46
+ const createArray = (maxCols, maxRows) => {
47
+ const arr = [];
48
+ for (let i = 1; i < maxRows + 1; i++) {
49
+ for (let j = 1; j < maxCols + 1; j++) {
50
+ arr.push({
51
+ col: j,
52
+ row: i
53
+ });
54
+ }
55
+ }
56
+ return arr;
57
+ };
58
+ const gridWrapperStyles = ({
59
+ maxCols,
60
+ maxRows
61
+ }) => css({
62
+ display: 'grid',
63
+ gridTemplateColumns: `repeat(${maxCols}, 1fr)`,
64
+ gridTemplateRows: `repeat(${maxRows}, 1fr)`,
65
+ gap: `${`var(--ds-space-025, ${`${TABLE_SELECTOR_BUTTON_GAP}px`})`}`
66
+ });
67
+ const TableSelectorPopup = ({
68
+ maxCols,
69
+ maxRows,
70
+ onSelection,
71
+ selectedCol,
72
+ selectedRow,
73
+ intl
74
+ }) => {
75
+ const buttons = useMemo(() => {
76
+ return createArray(maxCols, maxRows);
77
+ }, [maxCols, maxRows]);
78
+ return jsx(Stack, null, jsx("div", {
79
+ css:
80
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
81
+ gridWrapperStyles({
82
+ maxCols: maxCols,
83
+ maxRows: maxRows
84
+ })
85
+ }, buttons.map(({
86
+ col,
87
+ row
88
+ }, index) => {
89
+ const isActive = selectedCol >= col && selectedRow >= row ? true : false;
90
+ return jsx(TableSelectorButton, {
91
+ key: index,
92
+ isActive: isActive,
93
+ col: col,
94
+ row: row,
95
+ onClick: onSelection,
96
+ label: `${intl.formatMessage(messages.tableSizeSelectorButton)} ${row} x ${col}`
97
+ });
98
+ })), jsx("span", {
99
+ css: selectionSizeTextStyles
100
+ }, `${selectedRow} x ${selectedCol}`));
101
+ };
102
+ export default injectIntl(TableSelectorPopup);