@atlaskit/editor-core 187.8.13 → 187.9.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 (89) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/plugins/emoji/commands/insert-emoji.js +31 -28
  3. package/dist/cjs/plugins/emoji/index.js +4 -3
  4. package/dist/cjs/plugins/emoji/pm-plugins/ascii-input-rules.js +23 -18
  5. package/dist/cjs/plugins/extension/pm-plugins/main.js +54 -9
  6. package/dist/cjs/plugins/floating-toolbar/index.js +1 -3
  7. package/dist/cjs/plugins/insert-block/ui/ToolbarInsertBlock/index.js +1 -1
  8. package/dist/cjs/plugins/media/nodeviews/mediaSingle.js +33 -23
  9. package/dist/cjs/plugins/media/toolbar/index.js +16 -2
  10. package/dist/cjs/plugins/media/toolbar/utils.js +7 -2
  11. package/dist/cjs/plugins/media/ui/ResizableMediaSingle/ResizableMediaSingleNext.js +574 -0
  12. package/dist/cjs/plugins/media/ui/ResizableMediaSingle/guidelines.js +117 -0
  13. package/dist/cjs/plugins/media/ui/ResizableMediaSingle/resizable-media-single-messages.js +15 -0
  14. package/dist/cjs/plugins/selection/pm-plugins/events/keydown.js +61 -25
  15. package/dist/cjs/ui/Resizer/ResizeLabel/index.js +20 -0
  16. package/dist/cjs/ui/Resizer/ResizeLabel/styles.js +17 -0
  17. package/dist/cjs/version-wrapper.js +1 -1
  18. package/dist/cjs/version.json +1 -1
  19. package/dist/es2019/plugins/emoji/commands/insert-emoji.js +5 -5
  20. package/dist/es2019/plugins/emoji/index.js +6 -3
  21. package/dist/es2019/plugins/emoji/pm-plugins/ascii-input-rules.js +14 -11
  22. package/dist/es2019/plugins/extension/pm-plugins/main.js +50 -0
  23. package/dist/es2019/plugins/floating-toolbar/index.js +1 -1
  24. package/dist/es2019/plugins/insert-block/ui/ToolbarInsertBlock/index.js +1 -1
  25. package/dist/es2019/plugins/media/nodeviews/mediaSingle.js +34 -23
  26. package/dist/es2019/plugins/media/toolbar/index.js +19 -3
  27. package/dist/es2019/plugins/media/toolbar/utils.js +7 -1
  28. package/dist/es2019/plugins/media/ui/ResizableMediaSingle/ResizableMediaSingleNext.js +493 -0
  29. package/dist/es2019/plugins/media/ui/ResizableMediaSingle/guidelines.js +108 -0
  30. package/dist/es2019/plugins/media/ui/ResizableMediaSingle/resizable-media-single-messages.js +8 -0
  31. package/dist/es2019/plugins/selection/pm-plugins/events/keydown.js +60 -24
  32. package/dist/es2019/ui/Resizer/ResizeLabel/index.js +12 -0
  33. package/dist/es2019/ui/Resizer/ResizeLabel/styles.js +25 -0
  34. package/dist/es2019/version-wrapper.js +1 -1
  35. package/dist/es2019/version.json +1 -1
  36. package/dist/esm/plugins/emoji/commands/insert-emoji.js +29 -27
  37. package/dist/esm/plugins/emoji/index.js +4 -3
  38. package/dist/esm/plugins/emoji/pm-plugins/ascii-input-rules.js +23 -18
  39. package/dist/esm/plugins/extension/pm-plugins/main.js +45 -0
  40. package/dist/esm/plugins/floating-toolbar/index.js +1 -3
  41. package/dist/esm/plugins/insert-block/ui/ToolbarInsertBlock/index.js +1 -1
  42. package/dist/esm/plugins/media/nodeviews/mediaSingle.js +33 -23
  43. package/dist/esm/plugins/media/toolbar/index.js +17 -3
  44. package/dist/esm/plugins/media/toolbar/utils.js +5 -1
  45. package/dist/esm/plugins/media/ui/ResizableMediaSingle/ResizableMediaSingleNext.js +564 -0
  46. package/dist/esm/plugins/media/ui/ResizableMediaSingle/guidelines.js +108 -0
  47. package/dist/esm/plugins/media/ui/ResizableMediaSingle/resizable-media-single-messages.js +8 -0
  48. package/dist/esm/plugins/selection/pm-plugins/events/keydown.js +62 -25
  49. package/dist/esm/ui/Resizer/ResizeLabel/index.js +12 -0
  50. package/dist/esm/ui/Resizer/ResizeLabel/styles.js +7 -0
  51. package/dist/esm/version-wrapper.js +1 -1
  52. package/dist/esm/version.json +1 -1
  53. package/dist/types/labs/next/presets/universal.d.ts +1 -2
  54. package/dist/types/plugins/emoji/commands/insert-emoji.d.ts +2 -2
  55. package/dist/types/plugins/emoji/pm-plugins/ascii-input-rules.d.ts +3 -2
  56. package/dist/types/plugins/extension/pm-plugins/main.d.ts +1 -1
  57. package/dist/types/plugins/floating-toolbar/index.d.ts +3 -1
  58. package/dist/types/plugins/insert-block/ui/ToolbarInsertBlock/index.d.ts +1 -0
  59. package/dist/types/plugins/media/index.d.ts +2 -0
  60. package/dist/types/plugins/media/nodeviews/styles.d.ts +1 -1
  61. package/dist/types/plugins/media/pm-plugins/main.d.ts +1 -1
  62. package/dist/types/plugins/media/toolbar/utils.d.ts +1 -0
  63. package/dist/types/plugins/media/types.d.ts +1 -0
  64. package/dist/types/plugins/media/ui/ResizableMediaSingle/ResizableMediaSingleNext.d.ts +61 -0
  65. package/dist/types/plugins/media/ui/ResizableMediaSingle/guidelines.d.ts +4 -0
  66. package/dist/types/plugins/media/ui/ResizableMediaSingle/resizable-media-single-messages.d.ts +7 -0
  67. package/dist/types/plugins/media/ui/ResizableMediaSingle/types.d.ts +1 -0
  68. package/dist/types/ui/Resizer/ResizeLabel/index.d.ts +8 -0
  69. package/dist/types/ui/Resizer/ResizeLabel/styles.d.ts +3 -0
  70. package/dist/types-ts4.5/labs/next/presets/universal.d.ts +1 -2
  71. package/dist/types-ts4.5/plugins/emoji/commands/insert-emoji.d.ts +2 -2
  72. package/dist/types-ts4.5/plugins/emoji/pm-plugins/ascii-input-rules.d.ts +3 -2
  73. package/dist/types-ts4.5/plugins/extension/pm-plugins/main.d.ts +1 -1
  74. package/dist/types-ts4.5/plugins/floating-toolbar/index.d.ts +3 -1
  75. package/dist/types-ts4.5/plugins/insert-block/ui/ToolbarInsertBlock/index.d.ts +1 -0
  76. package/dist/types-ts4.5/plugins/media/index.d.ts +2 -0
  77. package/dist/types-ts4.5/plugins/media/nodeviews/styles.d.ts +1 -1
  78. package/dist/types-ts4.5/plugins/media/pm-plugins/main.d.ts +1 -1
  79. package/dist/types-ts4.5/plugins/media/toolbar/utils.d.ts +1 -0
  80. package/dist/types-ts4.5/plugins/media/types.d.ts +1 -0
  81. package/dist/types-ts4.5/plugins/media/ui/ResizableMediaSingle/ResizableMediaSingleNext.d.ts +61 -0
  82. package/dist/types-ts4.5/plugins/media/ui/ResizableMediaSingle/guidelines.d.ts +4 -0
  83. package/dist/types-ts4.5/plugins/media/ui/ResizableMediaSingle/resizable-media-single-messages.d.ts +7 -0
  84. package/dist/types-ts4.5/plugins/media/ui/ResizableMediaSingle/types.d.ts +1 -0
  85. package/dist/types-ts4.5/ui/Resizer/ResizeLabel/index.d.ts +8 -0
  86. package/dist/types-ts4.5/ui/Resizer/ResizeLabel/styles.d.ts +3 -0
  87. package/package.json +2 -2
  88. package/report.api.md +7 -4
  89. package/tmp/api-report-tmp.d.ts +5 -1
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.messages = void 0;
7
+ var _reactIntlNext = require("react-intl-next");
8
+ var messages = (0, _reactIntlNext.defineMessages)({
9
+ fullWidthImage: {
10
+ id: 'fabric.editor.image.fullWidthImage',
11
+ defaultMessage: 'Full width image',
12
+ description: 'The image has reached its full width'
13
+ }
14
+ });
15
+ exports.messages = messages;
@@ -5,38 +5,69 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.onKeydown = void 0;
7
7
  var _state = require("@atlaskit/editor-prosemirror/state");
8
+ /*
9
+ * The way expand was built, no browser reconize selection on it.
10
+ * For instance, when a selection going to a "collapsed" expand
11
+ * the browser will try to send the cursor to inside the expand content (wrong),
12
+ * this behavior is caused because the expand content is never true hidden
13
+ * we just set the height to 1px.
14
+ *
15
+ * So, we need to capture a possible selection event
16
+ * when a collapsed exxpand is the next node in the common depth.
17
+ * If that is true, we create a new TextSelection and stop the event bubble
18
+ */
8
19
  var isCollpasedExpand = function isCollpasedExpand(node) {
9
20
  return Boolean(node && ['expand', 'nestedExpand'].includes(node.type.name) && !node.attrs.__expanded);
10
21
  };
11
- var findFixedProblematicNodePosition = function findFixedProblematicNodePosition($pos, direction) {
12
- if ($pos.pos === 0 || $pos.depth === 0) {
22
+
23
+ /**
24
+ * ED-18072 - Cannot shift + arrow past bodied extension if it is not empty
25
+ */
26
+ var isBodiedExtension = function isBodiedExtension(node) {
27
+ return Boolean(node && ['bodiedExtension'].includes(node.type.name));
28
+ };
29
+ var isProblematicNode = function isProblematicNode(node) {
30
+ return isCollpasedExpand(node) || isBodiedExtension(node);
31
+ };
32
+ var findFixedProblematicNodePosition = function findFixedProblematicNodePosition(doc, $head, direction) {
33
+ if ($head.pos === 0 || $head.depth === 0) {
13
34
  return null;
14
35
  }
15
- var pos = direction === 'up' ? $pos.before() : $pos.after();
16
- var $posResolved = $pos.doc.resolve(pos);
17
- var maybeExpandNode = direction === 'up' ? $posResolved.nodeBefore : $posResolved.nodeAfter;
18
- if (maybeExpandNode && isCollpasedExpand(maybeExpandNode)) {
19
- var nodeSize = maybeExpandNode.nodeSize;
20
- var expandPosition = direction === 'up' ? pos - nodeSize : pos + nodeSize;
21
- var startPosNode = Math.max(expandPosition, 0);
22
- var $startPosNode = $pos.doc.resolve(Math.min(startPosNode, $pos.doc.content.size));
23
- return $startPosNode;
36
+ if (direction === 'up') {
37
+ var pos = $head.before();
38
+ var $posResolved = $head.doc.resolve(pos);
39
+ var maybeProblematicNode = $posResolved.nodeBefore;
40
+ if (maybeProblematicNode && isProblematicNode(maybeProblematicNode)) {
41
+ var nodeSize = maybeProblematicNode.nodeSize;
42
+ var nodeStartPosition = pos - nodeSize;
43
+
44
+ // ($head.pos - 1) will correspond to (nodeStartPosition + nodeSize) when we are at the start of the text node
45
+ var isAtEndOfProblematicNode = $head.pos - 1 === nodeStartPosition + nodeSize;
46
+ if (isAtEndOfProblematicNode) {
47
+ var startPosNode = Math.max(nodeStartPosition, 0);
48
+ var $startPosNode = $head.doc.resolve(Math.min(startPosNode, $head.doc.content.size));
49
+ return $startPosNode;
50
+ }
51
+ }
52
+ }
53
+ if (direction === 'down') {
54
+ var _pos = $head.after();
55
+ var _maybeProblematicNode = doc.nodeAt(_pos);
56
+ if (_maybeProblematicNode && isProblematicNode(_maybeProblematicNode) && $head.pos + 1 === _pos) {
57
+ var _nodeSize = _maybeProblematicNode.nodeSize;
58
+ var nodePosition = _pos + _nodeSize;
59
+ var _startPosNode = Math.max(nodePosition, 0);
60
+ var _$startPosNode = $head.doc.resolve(Math.min(_startPosNode, $head.doc.content.size));
61
+ return _$startPosNode;
62
+ }
24
63
  }
25
64
  return null;
26
65
  };
27
66
  var onKeydown = function onKeydown(view, event) {
28
67
  /*
29
- * This workaround is needed for some specific situation with collapsed expand.
30
- *
31
- * The way expand was built, no browser reconize selection on it.
32
- * For instance, when a selection going to a "collapsed" expand
33
- * the browser will try to send the cursor to inside the expand content (wrong),
34
- * this behavior is caused because the expand content is never true hidden
35
- * we just set the height to 1px.
36
- *
37
- * So, we need to capture a possible selection event
38
- * when a collapsed exxpand is the next node in the common depth.
39
- * If that is true, we create a new TextSelection and stop the event bubble
68
+ * This workaround is needed for some specific situations.
69
+ * - expand collapse
70
+ * - bodied extension
40
71
  */
41
72
  if (!(event instanceof KeyboardEvent)) {
42
73
  return false;
@@ -47,16 +78,21 @@ var onKeydown = function onKeydown(view, event) {
47
78
  if (!['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft', 'Home', 'End'].includes(event.key)) {
48
79
  return false;
49
80
  }
50
- var _view$state$selection = view.state.selection,
81
+ var _view$state = view.state,
82
+ doc = _view$state.doc,
83
+ _view$state$selection = _view$state.selection,
51
84
  $head = _view$state$selection.$head,
52
85
  $anchor = _view$state$selection.$anchor;
53
86
  if (event.key === 'ArrowRight' && $head.nodeAfter || event.key === 'ArrowLeft' && $head.nodeBefore) {
54
87
  return false;
55
88
  }
56
89
  var direction = ['ArrowLeft', 'ArrowUp', 'Home'].includes(event.key) ? 'up' : 'down';
57
- var $fixedProblematicNodePosition = findFixedProblematicNodePosition($head, direction);
90
+ var $fixedProblematicNodePosition = findFixedProblematicNodePosition(doc, $head, direction);
58
91
  if ($fixedProblematicNodePosition) {
59
- var forcedTextSelection = _state.TextSelection.create(view.state.doc, $anchor.pos, $fixedProblematicNodePosition.pos);
92
+ // an offset is used here so that left arrow selects the first character before the node (consistent with arrow right)
93
+ var headOffset = event.key === 'ArrowLeft' ? -1 : 0;
94
+ var head = $fixedProblematicNodePosition.pos + headOffset;
95
+ var forcedTextSelection = _state.TextSelection.create(view.state.doc, $anchor.pos, head);
60
96
  var tr = view.state.tr;
61
97
  tr.setSelection(forcedTextSelection);
62
98
  view.dispatch(tr);
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = require("@emotion/react");
8
+ var _styles = require("./styles");
9
+ /** @jsx jsx */
10
+
11
+ var ResizeLabelBreakoutWidth = 110;
12
+ var ResizeLabel = function ResizeLabel(props) {
13
+ return (0, _react.jsx)("div", {
14
+ css: _styles.wrapper
15
+ }, (0, _react.jsx)("span", {
16
+ css: [_styles.text, props.containerWidth < ResizeLabelBreakoutWidth && _styles.smallText]
17
+ }, props.label));
18
+ };
19
+ var _default = ResizeLabel;
20
+ exports.default = _default;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.wrapper = exports.text = exports.smallText = void 0;
8
+ var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
9
+ var _react = require("@emotion/react");
10
+ var _colors = require("@atlaskit/theme/colors");
11
+ var _templateObject, _templateObject2, _templateObject3;
12
+ var wrapper = (0, _react.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n font-size: ", ";\n width: 100%;\n text-align: center;\n position: absolute;\n transform: translateY(-125%);\n top: 0;\n"])), "var(--ds-font-size-100, 14px)");
13
+ exports.wrapper = wrapper;
14
+ var text = (0, _react.css)(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2.default)(["\n display: inline-block;\n border-radius: 6px;\n min-width: 75px;\n background-color: ", ";\n color: ", ";\n padding: ", " ", ";\n letter-spacing: 0.5px;\n"])), "var(--ds-text-accent-blue, ".concat(_colors.B300, ")"), "var(--ds-text-inverse, white)", "var(--ds-space-050, 4px)", "var(--ds-space-200, 16px)");
15
+ exports.text = text;
16
+ var smallText = (0, _react.css)(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2.default)(["\n letter-spacing: -0.5px;\n font-size: ", ";\n min-width: 27px;\n padding: ", " ", ";\n"])), "var(--ds-font-size-050, 8px)", "var(--ds-space-0, 0px)", "var(--ds-space-025, 2px)");
17
+ exports.smallText = smallText;
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.version = exports.nextMajorVersion = exports.name = void 0;
7
7
  var name = "@atlaskit/editor-core";
8
8
  exports.name = name;
9
- var version = "187.8.13";
9
+ var version = "187.9.2";
10
10
  exports.version = version;
11
11
  var nextMajorVersion = function nextMajorVersion() {
12
12
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-core",
3
- "version": "187.8.13",
3
+ "version": "187.9.2",
4
4
  "sideEffects": false
5
5
  }
@@ -1,8 +1,8 @@
1
1
  import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
2
2
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
3
3
  import { Selection } from '@atlaskit/editor-prosemirror/state';
4
- import { addAnalytics, EVENT_TYPE, ACTION_SUBJECT_ID, ACTION_SUBJECT, ACTION } from '../../analytics';
5
- export function insertEmoji(emojiId, inputMethod) {
4
+ import { EVENT_TYPE, ACTION_SUBJECT_ID, ACTION_SUBJECT, ACTION } from '@atlaskit/editor-common/analytics';
5
+ export const insertEmoji = editorAnalyticsAPI => (emojiId, inputMethod) => {
6
6
  return (state, dispatch) => {
7
7
  const {
8
8
  emoji
@@ -17,7 +17,7 @@ export function insertEmoji(emojiId, inputMethod) {
17
17
  const fragment = Fragment.fromArray([node, textNode]);
18
18
  const tr = safeInsert(fragment)(state.tr);
19
19
  if (inputMethod) {
20
- addAnalytics(state, tr, {
20
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent({
21
21
  action: ACTION.INSERTED,
22
22
  actionSubject: ACTION_SUBJECT.DOCUMENT,
23
23
  actionSubjectId: ACTION_SUBJECT_ID.EMOJI,
@@ -25,7 +25,7 @@ export function insertEmoji(emojiId, inputMethod) {
25
25
  inputMethod
26
26
  },
27
27
  eventType: EVENT_TYPE.TRACK
28
- });
28
+ })(tr);
29
29
  }
30
30
  dispatch(tr.setSelection(Selection.near(tr.doc.resolve(state.selection.$from.pos + fragment.size))));
31
31
  }
@@ -33,4 +33,4 @@ export function insertEmoji(emojiId, inputMethod) {
33
33
  }
34
34
  return false;
35
35
  };
36
- }
36
+ };
@@ -169,7 +169,10 @@ const emojiPlugin = (options, api) => {
169
169
  schema,
170
170
  providerFactory,
171
171
  featureFlags
172
- }) => asciiInputRulePlugin(schema, providerFactory, featureFlags)
172
+ }) => {
173
+ var _api$dependencies$ana8;
174
+ return asciiInputRulePlugin(schema, providerFactory, featureFlags, api === null || api === void 0 ? void 0 : (_api$dependencies$ana8 = api.dependencies.analytics) === null || _api$dependencies$ana8 === void 0 ? void 0 : _api$dependencies$ana8.actions);
175
+ }
173
176
  }];
174
177
  },
175
178
  pluginsOptions: {
@@ -183,13 +186,13 @@ const emojiPlugin = (options, api) => {
183
186
  keyshortcut: ':',
184
187
  icon: () => /*#__PURE__*/React.createElement(IconEmoji, null),
185
188
  action(insert, state) {
186
- var _api$dependencies$ana8;
189
+ var _api$dependencies$ana9;
187
190
  const tr = insert(undefined);
188
191
  openTypeAheadAtCursor({
189
192
  triggerHandler: typeAhead,
190
193
  inputMethod: INPUT_METHOD.QUICK_INSERT
191
194
  })(tr);
192
- api === null || api === void 0 ? void 0 : (_api$dependencies$ana8 = api.dependencies.analytics) === null || _api$dependencies$ana8 === void 0 ? void 0 : _api$dependencies$ana8.actions.attachAnalyticsEvent({
195
+ api === null || api === void 0 ? void 0 : (_api$dependencies$ana9 = api.dependencies.analytics) === null || _api$dependencies$ana9 === void 0 ? void 0 : _api$dependencies$ana9.actions.attachAnalyticsEvent({
193
196
  action: ACTION.INVOKED,
194
197
  actionSubject: ACTION_SUBJECT.TYPEAHEAD,
195
198
  actionSubjectId: ACTION_SUBJECT_ID.TYPEAHEAD_EMOJI,
@@ -2,12 +2,12 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
3
  import { createRule, createPlugin } from '@atlaskit/prosemirror-input-rules';
4
4
  import { leafNodeReplacementCharacter } from '@atlaskit/prosemirror-input-rules';
5
- import { addAnalytics, ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, INPUT_METHOD, EVENT_TYPE } from '../../analytics';
5
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, INPUT_METHOD, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
6
6
  let matcher;
7
- export function inputRulePlugin(schema, providerFactory, featureFlags) {
7
+ export function inputRulePlugin(schema, providerFactory, featureFlags, editorAnalyticsAPI) {
8
8
  if (schema.nodes.emoji && providerFactory) {
9
9
  initMatcher(providerFactory);
10
- const asciiEmojiRule = createRule(AsciiEmojiMatcher.REGEX, inputRuleHandler);
10
+ const asciiEmojiRule = createRule(AsciiEmojiMatcher.REGEX, inputRuleHandler(editorAnalyticsAPI));
11
11
  return createPlugin('emoji', [asciiEmojiRule]);
12
12
  }
13
13
  return;
@@ -25,17 +25,17 @@ function initMatcher(providerFactory) {
25
25
  };
26
26
  providerFactory.subscribe('emojiProvider', handleProvider);
27
27
  }
28
- function inputRuleHandler(state, matchParts, start, end) {
28
+ const inputRuleHandler = editorAnalyticsAPI => (state, matchParts, start, end) => {
29
29
  if (!matcher) {
30
30
  return null;
31
31
  }
32
32
  const match = matcher.match(matchParts);
33
33
  if (match) {
34
- const transactionCreator = new AsciiEmojiTransactionCreator(state, match, start, end);
34
+ const transactionCreator = new AsciiEmojiTransactionCreator(state, match, start, end, editorAnalyticsAPI);
35
35
  return transactionCreator.create();
36
36
  }
37
37
  return null;
38
- }
38
+ };
39
39
  const REGEX_LEADING_CAPTURE_INDEX = 1;
40
40
  const REGEX_EMOJI_LEADING_PARENTHESES = 2;
41
41
  const REGEX_EMOJI_ASCII_CAPTURE_INDEX = 3;
@@ -107,15 +107,17 @@ class RecordingAsciiEmojiMatcher extends AsciiEmojiMatcher {
107
107
  }
108
108
  }
109
109
  class AsciiEmojiTransactionCreator {
110
- constructor(state, match, start, end) {
110
+ constructor(state, match, start, end, editorAnalyticsAPI) {
111
111
  this.state = state;
112
112
  this.match = match;
113
113
  this.start = start;
114
114
  this.end = end;
115
+ this.editorAnalyticsAPI = editorAnalyticsAPI;
115
116
  }
116
117
  create() {
118
+ var _this$editorAnalytics;
117
119
  const tr = this.state.tr.replaceWith(this.from, this.to, this.createNodes());
118
- return addAnalytics(this.state, tr, {
120
+ (_this$editorAnalytics = this.editorAnalyticsAPI) === null || _this$editorAnalytics === void 0 ? void 0 : _this$editorAnalytics.attachAnalyticsEvent({
119
121
  action: ACTION.INSERTED,
120
122
  actionSubject: ACTION_SUBJECT.DOCUMENT,
121
123
  actionSubjectId: ACTION_SUBJECT_ID.EMOJI,
@@ -123,7 +125,8 @@ class AsciiEmojiTransactionCreator {
123
125
  inputMethod: INPUT_METHOD.ASCII
124
126
  },
125
127
  eventType: EVENT_TYPE.TRACK
126
- });
128
+ })(tr);
129
+ return tr;
127
130
  }
128
131
  get from() {
129
132
  return this.start + this.match.leadingString.length;
@@ -160,7 +163,7 @@ class AsciiEmojiTransactionCreator {
160
163
  }
161
164
  }
162
165
  export const stateKey = new PluginKey('asciiEmojiPlugin');
163
- const plugins = (schema, providerFactory, featureFlags) => {
164
- return [inputRulePlugin(schema, providerFactory, featureFlags)].filter(plugin => !!plugin);
166
+ const plugins = (schema, providerFactory, featureFlags, editorAnalyticsAPI) => {
167
+ return [inputRulePlugin(schema, providerFactory, featureFlags, editorAnalyticsAPI)].filter(plugin => !!plugin);
165
168
  };
166
169
  export default plugins;
@@ -1,4 +1,7 @@
1
+ import { TextSelection, NodeSelection } from '@atlaskit/editor-prosemirror/state';
2
+ import { findParentNodeOfTypeClosestToPos, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
1
3
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
4
+ import { isSelectionAtStartOfNode, isSelectionAtEndOfNode } from '@atlaskit/editor-common/selection';
2
5
  import { createSelectionClickHandler } from '../../selection/utils';
3
6
  import ExtensionNodeView from '../nodeviews/extension';
4
7
  import { updateState, clearEditingContext } from '../commands';
@@ -163,6 +166,53 @@ const createPlugin = (dispatch, providerFactory, extensionHandlers, portalProvid
163
166
  },
164
167
  key: pluginKey,
165
168
  props: {
169
+ handleDOMEvents: {
170
+ /**
171
+ * ED-18072 - Cannot shift + arrow past bodied extension if it is not empty.
172
+ * This code is to handle the case where the selection starts inside or on the node and the user is trying to shift + arrow.
173
+ * For other part of the solution see code in: packages/editor/editor-core/src/plugins/selection/pm-plugins/events/keydown.ts
174
+ */
175
+ keydown: (view, event) => {
176
+ if (event instanceof KeyboardEvent && event.shiftKey && ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {
177
+ const {
178
+ schema,
179
+ selection,
180
+ selection: {
181
+ $head
182
+ },
183
+ doc,
184
+ tr
185
+ } = view.state;
186
+ const {
187
+ bodiedExtension
188
+ } = schema.nodes;
189
+ if (selection instanceof TextSelection || selection instanceof NodeSelection) {
190
+ const maybeBodiedExtension = selection instanceof TextSelection ? findParentNodeOfTypeClosestToPos($head, bodiedExtension) : findSelectedNodeOfType(bodiedExtension)(selection);
191
+ if (maybeBodiedExtension) {
192
+ const end = maybeBodiedExtension.pos + maybeBodiedExtension.node.nodeSize;
193
+ if (event.key === 'ArrowUp' || event.key === 'ArrowLeft' && isSelectionAtStartOfNode($head, maybeBodiedExtension)) {
194
+ const anchor = end + 1;
195
+
196
+ // an offset is used here so that left arrow selects the first character before the node (consistent with arrow right)
197
+ const headOffset = event.key === 'ArrowLeft' ? -1 : 0;
198
+ const head = maybeBodiedExtension.pos + headOffset;
199
+ const newSelection = TextSelection.create(doc, Math.max(anchor, selection.anchor), head);
200
+ view.dispatch(tr.setSelection(newSelection));
201
+ return true;
202
+ }
203
+ if (event.key === 'ArrowDown' || event.key === 'ArrowRight' && isSelectionAtEndOfNode($head, maybeBodiedExtension)) {
204
+ const anchor = maybeBodiedExtension.pos - 1;
205
+ const head = end + 1;
206
+ const newSelection = TextSelection.create(doc, Math.min(anchor, selection.anchor), head);
207
+ view.dispatch(tr.setSelection(newSelection));
208
+ return true;
209
+ }
210
+ }
211
+ }
212
+ }
213
+ return false;
214
+ }
215
+ },
166
216
  nodeViews: {
167
217
  // WARNING: referentiality-plugin also creates these nodeviews
168
218
  extension: ExtensionNodeView(portalProviderAPI, eventDispatcher, providerFactory, extensionHandlers, extensionNodeViewOptions, pluginInjectionApi),
@@ -315,7 +315,7 @@ function floatingToolbarPluginFactory(options) {
315
315
  };
316
316
  const apply = (tr, pluginState) => {
317
317
  const newPluginState = {
318
- getConfigWithNodeInfo
318
+ ...pluginState
319
319
  };
320
320
  dispatch(pluginKey, newPluginState);
321
321
  return newPluginState;
@@ -290,7 +290,7 @@ export class ToolbarInsertBlock extends React.PureComponent {
290
290
  });
291
291
  _defineProperty(this, "handleSelectedEmoji", emojiId => {
292
292
  this.props.editorView.focus();
293
- insertEmoji(emojiId, INPUT_METHOD.PICKER)(this.props.editorView.state, this.props.editorView.dispatch);
293
+ insertEmoji(this.editorAnalyticsAPI)(emojiId, INPUT_METHOD.PICKER)(this.props.editorView.state, this.props.editorView.dispatch);
294
294
  this.toggleEmojiPicker();
295
295
  return true;
296
296
  });
@@ -1,4 +1,3 @@
1
- import _extends from "@babel/runtime/helpers/extends";
2
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
2
  /** @jsx jsx */
4
3
  import { jsx } from '@emotion/react';
@@ -8,6 +7,7 @@ import { MediaSingle, DEFAULT_IMAGE_HEIGHT, DEFAULT_IMAGE_WIDTH } from '@atlaski
8
7
  import { browser, floatingLayouts, isRichMediaInsideOfBlockNode } from '@atlaskit/editor-common/utils';
9
8
  import { isNodeSelectedOrInRange } from '../../../utils/nodes';
10
9
  import { setNodeSelection, setTextSelection } from '../../../utils';
10
+ import ResizableMediaSingleNext from '../ui/ResizableMediaSingle/ResizableMediaSingleNext';
11
11
  import ResizableMediaSingle from '../ui/ResizableMediaSingle';
12
12
  import { MEDIA_CONTENT_WRAP_CLASS_NAME } from '../pm-plugins/main';
13
13
  import { MediaNodeUpdater } from './mediaNodeUpdater';
@@ -22,6 +22,8 @@ import CaptionPlaceholder from '../ui/CaptionPlaceholder';
22
22
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
23
23
  import { insertAndSelectCaptionFromMediaSinglePos } from '../commands/captions';
24
24
  import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
25
+ import { getMediaSinglePixelWidth } from '@atlaskit/editor-common/media-single';
26
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
25
27
  export default class MediaSingleNode extends Component {
26
28
  constructor(...args) {
27
29
  super(...args);
@@ -133,7 +135,8 @@ export default class MediaSingleNode extends Component {
133
135
  const tr = state.tr.setNodeMarkup(pos, undefined, {
134
136
  ...this.props.node.attrs,
135
137
  layout,
136
- width
138
+ width,
139
+ widthType: 'pixel'
137
140
  });
138
141
  tr.setMeta('scrollIntoView', false);
139
142
  /**
@@ -220,14 +223,21 @@ export default class MediaSingleNode extends Component {
220
223
  view: {
221
224
  state
222
225
  },
223
- view
226
+ view,
227
+ pluginInjectionApi,
228
+ width: containerWidth,
229
+ lineLength,
230
+ dispatchAnalyticsEvent
224
231
  } = this.props;
225
232
  const {
226
233
  layout,
227
- width: mediaSingleWidth
234
+ widthType,
235
+ width: mediaSingleWidthAttribute
228
236
  } = node.attrs;
229
237
  const childNode = node.firstChild;
230
238
  const attrs = childNode.attrs;
239
+
240
+ // original width and height of child media node (scaled)
231
241
  let {
232
242
  width,
233
243
  height
@@ -259,15 +269,29 @@ export default class MediaSingleNode extends Component {
259
269
  width = DEFAULT_IMAGE_WIDTH;
260
270
  height = DEFAULT_IMAGE_HEIGHT;
261
271
  }
272
+ const isSelected = selected();
262
273
  const mediaSingleProps = {
263
274
  layout,
264
275
  width,
265
276
  height,
266
- containerWidth: this.props.width,
267
- lineLength: this.props.lineLength,
268
- pctWidth: mediaSingleWidth,
277
+ containerWidth: containerWidth,
278
+ lineLength: this.getLineLength(view, getPos()) || lineLength,
279
+ pctWidth: mediaSingleWidthAttribute,
269
280
  fullWidthMode,
270
- hasFallbackContainer: false
281
+ hasFallbackContainer: false,
282
+ mediaSingleWidth: mediaSingleWidthAttribute && getMediaSinglePixelWidth(mediaSingleWidthAttribute, lineLength, widthType)
283
+ };
284
+ const ResizableMediaSingleProps = {
285
+ view: view,
286
+ getPos: getPos,
287
+ updateSize: this.updateSize,
288
+ gridSize: 12,
289
+ viewMediaClientConfig: this.state.viewMediaClientConfig,
290
+ allowBreakoutSnapPoints: mediaOptions && mediaOptions.allowBreakoutSnapPoints,
291
+ selected: isSelected,
292
+ dispatchAnalyticsEvent: dispatchAnalyticsEvent,
293
+ pluginInjectionApi: pluginInjectionApi,
294
+ ...mediaSingleProps
271
295
  };
272
296
  let canResize = !!this.props.mediaOptions.allowResizing;
273
297
  if (!this.props.mediaOptions.allowResizingInTables) {
@@ -282,12 +306,10 @@ export default class MediaSingleNode extends Component {
282
306
  canResize = canResize && !disabledNode;
283
307
  }
284
308
  }
285
- const lineLength = this.getLineLength(view, getPos()) || this.props.lineLength;
286
- const isSelected = selected();
287
309
  const shouldShowPlaceholder = getMediaFeatureFlag('captions', mediaOptions.featureFlags) && node.childCount !== 2 && isSelected && state.selection instanceof NodeSelection;
288
310
  const MediaChildren = jsx("figure", {
289
311
  ref: this.mediaSingleWrapperRef,
290
- css: figureWrapper,
312
+ css: [figureWrapper],
291
313
  className: MediaSingleNodeSelector,
292
314
  onClick: this.onMediaSingleClicked
293
315
  }, jsx("div", {
@@ -296,18 +318,7 @@ export default class MediaSingleNode extends Component {
296
318
  ref: this.captionPlaceHolderRef,
297
319
  onClick: this.clickPlaceholder
298
320
  }));
299
- return canResize ? jsx(ResizableMediaSingle, _extends({}, mediaSingleProps, {
300
- lineLength: lineLength,
301
- view: this.props.view,
302
- getPos: getPos,
303
- updateSize: this.updateSize,
304
- gridSize: 12,
305
- viewMediaClientConfig: this.state.viewMediaClientConfig,
306
- allowBreakoutSnapPoints: mediaOptions && mediaOptions.allowBreakoutSnapPoints,
307
- selected: isSelected,
308
- dispatchAnalyticsEvent: this.props.dispatchAnalyticsEvent,
309
- pluginInjectionApi: this.props.pluginInjectionApi
310
- }), MediaChildren) : jsx(MediaSingle, mediaSingleProps, MediaChildren);
321
+ return canResize ? getBooleanFF('platform.editor.media.extended-resize-experience') ? jsx(ResizableMediaSingleNext, ResizableMediaSingleProps, MediaChildren) : jsx(ResizableMediaSingle, ResizableMediaSingleProps, MediaChildren) : jsx(MediaSingle, mediaSingleProps, MediaChildren);
311
322
  }
312
323
  }
313
324
  _defineProperty(MediaSingleNode, "defaultProps", {
@@ -16,8 +16,9 @@ import { LinkToolbarAppearance } from './linking-toolbar-appearance';
16
16
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
17
17
  import { messages } from '@atlaskit/media-ui';
18
18
  import { cardMessages } from '@atlaskit/editor-common/messages';
19
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
19
20
  import { FilePreviewItem } from './filePreviewItem';
20
- import { downloadMedia, removeMediaGroupNode } from './utils';
21
+ import { downloadMedia, getSelectedMediaSingle, removeMediaGroupNode } from './utils';
21
22
  import { changeInlineToMediaCard, changeMediaCardToInline, removeInlineCard, setBorderMark, toggleBorderMark } from './commands';
22
23
  import { MediaInlineNodeSelector, MediaSingleNodeSelector } from '../nodeviews/styles';
23
24
  import ImageBorderItem from '../ui/ImageBorder';
@@ -231,7 +232,22 @@ const generateMediaSingleFloatingToolbar = (state, intl, options, pluginState, m
231
232
  }
232
233
  if (allowAdvancedToolBarOptions) {
233
234
  var _pluginInjectionApi$d;
234
- const layoutButtons = buildLayoutButtons(state, intl, state.schema.nodes.mediaSingle, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.dependencies.width, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d = pluginInjectionApi.dependencies.analytics) === null || _pluginInjectionApi$d === void 0 ? void 0 : _pluginInjectionApi$d.actions, allowResizing, allowResizingInTables);
235
+ const widthPlugin = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.dependencies.width;
236
+ let isChangingLayoutDisabled = false;
237
+ if (getBooleanFF('platform.editor.media.extended-resize-experience')) {
238
+ var _widthPlugin$sharedSt;
239
+ const contentWidth = widthPlugin === null || widthPlugin === void 0 ? void 0 : (_widthPlugin$sharedSt = widthPlugin.sharedState.currentState()) === null || _widthPlugin$sharedSt === void 0 ? void 0 : _widthPlugin$sharedSt.lineLength;
240
+ const selectedNode = getSelectedMediaSingle(state);
241
+ if (selectedNode && contentWidth) {
242
+ const {
243
+ width
244
+ } = selectedNode.node.attrs;
245
+ if (width >= contentWidth) {
246
+ isChangingLayoutDisabled = true;
247
+ }
248
+ }
249
+ }
250
+ const layoutButtons = buildLayoutButtons(state, intl, state.schema.nodes.mediaSingle, widthPlugin, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d = pluginInjectionApi.dependencies.analytics) === null || _pluginInjectionApi$d === void 0 ? void 0 : _pluginInjectionApi$d.actions, allowResizing, allowResizingInTables, true, true, isChangingLayoutDisabled);
235
251
  toolbarButtons = [...toolbarButtons, ...layoutButtons];
236
252
  if (layoutButtons.length) {
237
253
  toolbarButtons.push({
@@ -342,7 +358,7 @@ export const floatingToolbar = (state, intl, options = {}, pluginInjectionApi) =
342
358
  const {
343
359
  hoverDecoration
344
360
  } = (_pluginInjectionApi$d4 = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : pluginInjectionApi.dependencies.decorations.actions) !== null && _pluginInjectionApi$d4 !== void 0 ? _pluginInjectionApi$d4 : {};
345
- if (!mediaPluginState) {
361
+ if (!mediaPluginState || mediaPluginState.isResizing) {
346
362
  return;
347
363
  }
348
364
  const nodeType = allowMediaInline ? [mediaInline, mediaSingle, media] : [mediaSingle];
@@ -1,5 +1,5 @@
1
1
  import { getMediaClient } from '@atlaskit/media-client';
2
- import { findParentNodeOfType, removeParentNodeOfType, removeSelectedNode } from '@atlaskit/editor-prosemirror/utils';
2
+ import { findParentNodeOfType, removeParentNodeOfType, removeSelectedNode, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
3
3
  export const getSelectedMediaContainerNodeAttrs = mediaPluginState => {
4
4
  const selectedNode = mediaPluginState.selectedMediaContainerNode();
5
5
  if (selectedNode && selectedNode.attrs) {
@@ -40,4 +40,10 @@ export const removeMediaGroupNode = state => {
40
40
  tr = removeSelectedNode(tr);
41
41
  }
42
42
  return tr;
43
+ };
44
+ export const getSelectedMediaSingle = state => {
45
+ const {
46
+ mediaSingle
47
+ } = state.schema.nodes;
48
+ return findSelectedNodeOfType(mediaSingle)(state.selection) || findParentNodeOfType(mediaSingle)(state.selection);
43
49
  };