@atlaskit/editor-plugin-status 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/editor-plugin-status
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#42564](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/42564) [`7139d6b0a64`](https://bitbucket.org/atlassian/atlassian-frontend/commits/7139d6b0a64) - ED-20512 Fixed issue with adding status node inside a codeblock
8
+
9
+ ## 0.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#42325](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/42325) [`58f1fd91d09`](https://bitbucket.org/atlassian/atlassian-frontend/commits/58f1fd91d09) - ED-20512 Set Focus on status input field when tab is pressed
14
+
3
15
  ## 0.1.2
4
16
 
5
17
  ### Patch Changes
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.updateStatusWithAnalytics = exports.updateStatus = exports.setStatusPickerAt = exports.removeStatus = exports.createStatus = exports.commitStatusPicker = exports.DEFAULT_STATUS = void 0;
7
+ exports.verifyAndInsertStatus = exports.updateStatusWithAnalytics = exports.updateStatus = exports.setStatusPickerAt = exports.setFocusOnStatusInput = exports.removeStatus = exports.createStatus = exports.commitStatusPicker = exports.DEFAULT_STATUS = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _adfSchema = require("@atlaskit/adf-schema");
10
10
  var _analytics = require("@atlaskit/editor-common/analytics");
@@ -19,22 +19,26 @@ var DEFAULT_STATUS = exports.DEFAULT_STATUS = {
19
19
  text: '',
20
20
  color: 'neutral'
21
21
  };
22
- var createStatus = exports.createStatus = function createStatus() {
23
- var showStatusPickerAtOffset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
24
- return function (insert, state) {
25
- var statusNode = state.schema.nodes.status.createChecked(_objectSpread(_objectSpread({}, DEFAULT_STATUS), {}, {
26
- localId: _adfSchema.uuid.generate()
27
- }));
28
- var space = state.schema.text(' ');
29
- var tr = insert(_model.Fragment.from([statusNode, space]), {
30
- selectInlineNode: true
31
- });
32
- var showStatusPickerAt = tr.selection.from + showStatusPickerAtOffset;
33
- return tr.setSelection(_state.NodeSelection.create(tr.doc, showStatusPickerAt)).setMeta(_pluginKey.pluginKey, {
34
- showStatusPickerAt: showStatusPickerAt,
35
- isNew: true
36
- });
37
- };
22
+ var verifyAndInsertStatus = exports.verifyAndInsertStatus = function verifyAndInsertStatus(statusNode, state) {
23
+ var fragment = _model.Fragment.fromArray([statusNode, state.schema.text(' ')]);
24
+ var tr = state.tr;
25
+ var insertable = (0, _utils.canInsert)(tr.selection.$from, fragment);
26
+ if (!insertable) {
27
+ var parentSelection = _state.NodeSelection.create(tr.doc, tr.selection.from - tr.selection.$anchor.parentOffset - 1);
28
+ tr.insert(parentSelection.to, fragment).setSelection(_state.NodeSelection.create(tr.doc, parentSelection.to + 1));
29
+ } else {
30
+ tr.insert(tr.selection.from, fragment).setSelection(_state.NodeSelection.create(tr.doc, tr.selection.from - fragment.size));
31
+ }
32
+ return tr.setMeta(_pluginKey.pluginKey, {
33
+ showStatusPickerAt: tr.selection.from,
34
+ isNew: true
35
+ }).scrollIntoView();
36
+ };
37
+ var createStatus = exports.createStatus = function createStatus(state) {
38
+ var statusNode = state.schema.nodes.status.createChecked(_objectSpread(_objectSpread({}, DEFAULT_STATUS), {}, {
39
+ localId: _adfSchema.uuid.generate()
40
+ }));
41
+ return verifyAndInsertStatus(statusNode, state);
38
42
  };
39
43
  var updateStatus = exports.updateStatus = function updateStatus(status) {
40
44
  return function (state, dispatch) {
@@ -50,18 +54,7 @@ var updateStatus = exports.updateStatus = function updateStatus(status) {
50
54
  if (!showStatusPickerAt) {
51
55
  // Same behaviour as quick insert (used in createStatus)
52
56
  var statusNode = schema.nodes.status.createChecked(statusProps);
53
- var fragment = _model.Fragment.fromArray([statusNode, state.schema.text(' ')]);
54
- var insertable = (0, _utils.canInsert)(tr.selection.$from, fragment);
55
- if (!insertable) {
56
- var parentSelection = _state.NodeSelection.create(tr.doc, tr.selection.from - tr.selection.$anchor.parentOffset - 1);
57
- tr.insert(parentSelection.to, fragment).setSelection(_state.NodeSelection.create(tr.doc, parentSelection.to + 1));
58
- } else {
59
- tr.insert(tr.selection.from, fragment).setSelection(_state.NodeSelection.create(tr.doc, tr.selection.from - fragment.size));
60
- }
61
- tr.setMeta(_pluginKey.pluginKey, {
62
- showStatusPickerAt: tr.selection.from,
63
- isNew: true
64
- }).scrollIntoView();
57
+ tr = verifyAndInsertStatus(statusNode, state);
65
58
  if (dispatch) {
66
59
  dispatch(tr);
67
60
  }
@@ -108,6 +101,18 @@ var removeStatus = exports.removeStatus = function removeStatus(showStatusPicker
108
101
  return tr;
109
102
  };
110
103
  };
104
+ var setFocusOnStatusInput = exports.setFocusOnStatusInput = function setFocusOnStatusInput() {
105
+ return function (state, dispatch) {
106
+ if (!dispatch) {
107
+ return false;
108
+ }
109
+ var tr = state.tr.setMeta(_pluginKey.pluginKey, {
110
+ focusStatusInput: true
111
+ });
112
+ dispatch(tr);
113
+ return true;
114
+ };
115
+ };
111
116
  var handleClosingByArrows = function handleClosingByArrows(closingMethod, state, showStatusPickerAt, tr) {
112
117
  if (closingMethod === 'arrowLeft') {
113
118
  // put cursor right before status Lozenge
@@ -135,6 +140,7 @@ var commitStatusPicker = exports.commitStatusPicker = function commitStatusPicke
135
140
  var tr = state.tr;
136
141
  tr = tr.setMeta(_pluginKey.pluginKey, {
137
142
  showStatusPickerAt: null,
143
+ focusStatusInput: false,
138
144
  isNew: false
139
145
  });
140
146
  if (closingMethod) {
@@ -75,6 +75,7 @@ var baseStatusPlugin = function baseStatusPlugin(_ref) {
75
75
  localId = _statusNode$attrs.localId;
76
76
  return /*#__PURE__*/_react.default.createElement(_statusPicker.default, {
77
77
  isNew: statusState.isNew,
78
+ focusStatusInput: statusState.focusStatusInput,
78
79
  target: target,
79
80
  defaultText: text,
80
81
  defaultColor: color,
@@ -118,7 +119,7 @@ var decorateWithPluginOptions = function decorateWithPluginOptions(plugin, optio
118
119
  },
119
120
  action: function action(insert, state) {
120
121
  var _api$analytics2;
121
- var tr = (0, _actions.createStatus)()(insert, state);
122
+ var tr = (0, _actions.createStatus)(state);
122
123
  api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.attachAnalyticsEvent({
123
124
  action: _analytics.ACTION.INSERTED,
124
125
  actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
@@ -7,11 +7,25 @@ exports.default = void 0;
7
7
  exports.keymapPlugin = keymapPlugin;
8
8
  var _keymaps = require("@atlaskit/editor-common/keymaps");
9
9
  var _keymap = require("@atlaskit/editor-prosemirror/keymap");
10
+ var _state = require("@atlaskit/editor-prosemirror/state");
11
+ var _actions = require("../actions");
10
12
  var _utils = require("../utils");
13
+ var _pluginKey = require("./plugin-key");
11
14
  function keymapPlugin() {
12
15
  var list = {};
13
16
  (0, _keymaps.bindKeymapWithCommand)(_keymaps.enter.common, consumeKeyEvent, list);
14
- (0, _keymaps.bindKeymapWithCommand)(_keymaps.tab.common, consumeKeyEvent, list);
17
+ (0, _keymaps.bindKeymapWithCommand)(_keymaps.tab.common, function (state, dispatch) {
18
+ var statusPluginState = _pluginKey.pluginKey.getState(state);
19
+ var isStatusNode = state.selection instanceof _state.NodeSelection ? state.selection.node.type === state.schema.nodes.status : false;
20
+ if (!isStatusNode) {
21
+ return false;
22
+ }
23
+ if (statusPluginState !== null && statusPluginState !== void 0 && statusPluginState.showStatusPickerAt) {
24
+ (0, _actions.setFocusOnStatusInput)()(state, dispatch);
25
+ return true;
26
+ }
27
+ return false;
28
+ }, list);
15
29
  return (0, _keymap.keymap)(list);
16
30
  }
17
31
 
@@ -33,7 +33,8 @@ var createPlugin = function createPlugin(pmPluginFactoryParams, options) {
33
33
  init: function init() {
34
34
  return {
35
35
  isNew: false,
36
- showStatusPickerAt: null
36
+ showStatusPickerAt: null,
37
+ focusStatusInput: false
37
38
  };
38
39
  },
39
40
  apply: function apply(tr, state, oldEditorState) {
@@ -67,7 +68,8 @@ var createPlugin = function createPlugin(pmPluginFactoryParams, options) {
67
68
  if (_showStatusPickerAt !== state.showStatusPickerAt) {
68
69
  var _newState2 = _objectSpread(_objectSpread({}, state), {}, {
69
70
  isNew: false,
70
- showStatusPickerAt: _showStatusPickerAt
71
+ showStatusPickerAt: _showStatusPickerAt,
72
+ focusStatusInput: false
71
73
  });
72
74
  pmPluginFactoryParams.dispatch(_pluginKey.pluginKey, _newState2);
73
75
  return _newState2;
@@ -235,17 +235,8 @@ var StatusPickerWithoutAnalytcs = exports.StatusPickerWithoutAnalytcs = /*#__PUR
235
235
  }, {
236
236
  key: "componentDidMount",
237
237
  value: function componentDidMount() {
238
- var _this2 = this;
239
238
  this.reset();
240
239
  this.fireStatusPopupOpenedAnalytics(this.state);
241
- if (typeof this.props.isNew === 'boolean' && this.props.isNew === false) {
242
- // Wrapper should be focused only if status already exists otherwise input field will receive focus
243
- this.focusTimeout = requestAnimationFrame(function () {
244
- var _this2$popupBodyWrapp;
245
- // Defer to prevent editor scrolling to top. See https://product-fabric.atlassian.net/browse/DTR-1952
246
- (_this2$popupBodyWrapp = _this2.popupBodyWrapper) === null || _this2$popupBodyWrapp === void 0 || (_this2$popupBodyWrapp = _this2$popupBodyWrapp.current) === null || _this2$popupBodyWrapp === void 0 || _this2$popupBodyWrapp.focus();
247
- });
248
- }
249
240
  }
250
241
  }, {
251
242
  key: "componentWillUnmount",
@@ -288,7 +279,8 @@ var StatusPickerWithoutAnalytcs = exports.StatusPickerWithoutAnalytcs = /*#__PUR
288
279
  target = _this$props.target,
289
280
  mountTo = _this$props.mountTo,
290
281
  boundariesElement = _this$props.boundariesElement,
291
- scrollableElement = _this$props.scrollableElement;
282
+ scrollableElement = _this$props.scrollableElement,
283
+ focusStatusInput = _this$props.focusStatusInput;
292
284
  var _this$state3 = this.state,
293
285
  color = _this$state3.color,
294
286
  text = _this$state3.text;
@@ -310,7 +302,7 @@ var StatusPickerWithoutAnalytcs = exports.StatusPickerWithoutAnalytcs = /*#__PUR
310
302
  onClick: this.handlePopupClick,
311
303
  onKeyDown: this.onKeyDown
312
304
  }, (0, _react2.jsx)(_picker.StatusPicker, {
313
- autoFocus: isNew,
305
+ autoFocus: isNew || focusStatusInput,
314
306
  selectedColor: color,
315
307
  text: text,
316
308
  onColorClick: this.onColorClick,
@@ -9,20 +9,27 @@ export const DEFAULT_STATUS = {
9
9
  text: '',
10
10
  color: 'neutral'
11
11
  };
12
- export const createStatus = (showStatusPickerAtOffset = 0) => (insert, state) => {
12
+ export const verifyAndInsertStatus = (statusNode, state) => {
13
+ const fragment = Fragment.fromArray([statusNode, state.schema.text(' ')]);
14
+ const tr = state.tr;
15
+ const insertable = canInsert(tr.selection.$from, fragment);
16
+ if (!insertable) {
17
+ const parentSelection = NodeSelection.create(tr.doc, tr.selection.from - tr.selection.$anchor.parentOffset - 1);
18
+ tr.insert(parentSelection.to, fragment).setSelection(NodeSelection.create(tr.doc, parentSelection.to + 1));
19
+ } else {
20
+ tr.insert(tr.selection.from, fragment).setSelection(NodeSelection.create(tr.doc, tr.selection.from - fragment.size));
21
+ }
22
+ return tr.setMeta(pluginKey, {
23
+ showStatusPickerAt: tr.selection.from,
24
+ isNew: true
25
+ }).scrollIntoView();
26
+ };
27
+ export const createStatus = state => {
13
28
  const statusNode = state.schema.nodes.status.createChecked({
14
29
  ...DEFAULT_STATUS,
15
30
  localId: uuid.generate()
16
31
  });
17
- const space = state.schema.text(' ');
18
- const tr = insert(Fragment.from([statusNode, space]), {
19
- selectInlineNode: true
20
- });
21
- const showStatusPickerAt = tr.selection.from + showStatusPickerAtOffset;
22
- return tr.setSelection(NodeSelection.create(tr.doc, showStatusPickerAt)).setMeta(pluginKey, {
23
- showStatusPickerAt,
24
- isNew: true
25
- });
32
+ return verifyAndInsertStatus(statusNode, state);
26
33
  };
27
34
  export const updateStatus = status => (state, dispatch) => {
28
35
  const {
@@ -43,18 +50,7 @@ export const updateStatus = status => (state, dispatch) => {
43
50
  if (!showStatusPickerAt) {
44
51
  // Same behaviour as quick insert (used in createStatus)
45
52
  const statusNode = schema.nodes.status.createChecked(statusProps);
46
- const fragment = Fragment.fromArray([statusNode, state.schema.text(' ')]);
47
- const insertable = canInsert(tr.selection.$from, fragment);
48
- if (!insertable) {
49
- const parentSelection = NodeSelection.create(tr.doc, tr.selection.from - tr.selection.$anchor.parentOffset - 1);
50
- tr.insert(parentSelection.to, fragment).setSelection(NodeSelection.create(tr.doc, parentSelection.to + 1));
51
- } else {
52
- tr.insert(tr.selection.from, fragment).setSelection(NodeSelection.create(tr.doc, tr.selection.from - fragment.size));
53
- }
54
- tr.setMeta(pluginKey, {
55
- showStatusPickerAt: tr.selection.from,
56
- isNew: true
57
- }).scrollIntoView();
53
+ tr = verifyAndInsertStatus(statusNode, state);
58
54
  if (dispatch) {
59
55
  dispatch(tr);
60
56
  }
@@ -93,6 +89,16 @@ export const removeStatus = showStatusPickerAt => ({
93
89
  tr.replace(showStatusPickerAt, showStatusPickerAt + 1);
94
90
  return tr;
95
91
  };
92
+ export const setFocusOnStatusInput = () => (state, dispatch) => {
93
+ if (!dispatch) {
94
+ return false;
95
+ }
96
+ const tr = state.tr.setMeta(pluginKey, {
97
+ focusStatusInput: true
98
+ });
99
+ dispatch(tr);
100
+ return true;
101
+ };
96
102
  const handleClosingByArrows = (closingMethod, state, showStatusPickerAt, tr) => {
97
103
  if (closingMethod === 'arrowLeft') {
98
104
  // put cursor right before status Lozenge
@@ -123,6 +129,7 @@ export const commitStatusPicker = closingPayload => editorView => {
123
129
  let tr = state.tr;
124
130
  tr = tr.setMeta(pluginKey, {
125
131
  showStatusPickerAt: null,
132
+ focusStatusInput: false,
126
133
  isNew: false
127
134
  });
128
135
  if (closingMethod) {
@@ -71,6 +71,7 @@ const baseStatusPlugin = ({
71
71
  } = statusNode.attrs;
72
72
  return /*#__PURE__*/React.createElement(StatusPicker, {
73
73
  isNew: statusState.isNew,
74
+ focusStatusInput: statusState.focusStatusInput,
74
75
  target: target,
75
76
  defaultText: text,
76
77
  defaultColor: color,
@@ -112,7 +113,7 @@ const decorateWithPluginOptions = (plugin, options, api) => {
112
113
  icon: () => /*#__PURE__*/React.createElement(IconStatus, null),
113
114
  action(insert, state) {
114
115
  var _api$analytics2;
115
- const tr = createStatus()(insert, state);
116
+ const tr = createStatus(state);
116
117
  api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.attachAnalyticsEvent({
117
118
  action: ACTION.INSERTED,
118
119
  actionSubject: ACTION_SUBJECT.DOCUMENT,
@@ -1,10 +1,24 @@
1
1
  import { bindKeymapWithCommand, enter, tab } from '@atlaskit/editor-common/keymaps';
2
2
  import { keymap } from '@atlaskit/editor-prosemirror/keymap';
3
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
4
+ import { setFocusOnStatusInput } from '../actions';
3
5
  import { mayGetStatusAtSelection } from '../utils';
6
+ import { pluginKey } from './plugin-key';
4
7
  export function keymapPlugin() {
5
8
  const list = {};
6
9
  bindKeymapWithCommand(enter.common, consumeKeyEvent, list);
7
- bindKeymapWithCommand(tab.common, consumeKeyEvent, list);
10
+ bindKeymapWithCommand(tab.common, (state, dispatch) => {
11
+ const statusPluginState = pluginKey.getState(state);
12
+ const isStatusNode = state.selection instanceof NodeSelection ? state.selection.node.type === state.schema.nodes.status : false;
13
+ if (!isStatusNode) {
14
+ return false;
15
+ }
16
+ if (statusPluginState !== null && statusPluginState !== void 0 && statusPluginState.showStatusPickerAt) {
17
+ setFocusOnStatusInput()(state, dispatch);
18
+ return true;
19
+ }
20
+ return false;
21
+ }, list);
8
22
  return keymap(list);
9
23
  }
10
24
 
@@ -10,7 +10,8 @@ const createPlugin = (pmPluginFactoryParams, options) => new SafePlugin({
10
10
  state: {
11
11
  init: () => ({
12
12
  isNew: false,
13
- showStatusPickerAt: null
13
+ showStatusPickerAt: null,
14
+ focusStatusInput: false
14
15
  }),
15
16
  apply(tr, state, oldEditorState) {
16
17
  const meta = tr.getMeta(pluginKey);
@@ -49,7 +50,8 @@ const createPlugin = (pmPluginFactoryParams, options) => new SafePlugin({
49
50
  const newState = {
50
51
  ...state,
51
52
  isNew: false,
52
- showStatusPickerAt
53
+ showStatusPickerAt,
54
+ focusStatusInput: false
53
55
  };
54
56
  pmPluginFactoryParams.dispatch(pluginKey, newState);
55
57
  return newState;
@@ -215,14 +215,6 @@ export class StatusPickerWithoutAnalytcs extends React.Component {
215
215
  componentDidMount() {
216
216
  this.reset();
217
217
  this.fireStatusPopupOpenedAnalytics(this.state);
218
- if (typeof this.props.isNew === 'boolean' && this.props.isNew === false) {
219
- // Wrapper should be focused only if status already exists otherwise input field will receive focus
220
- this.focusTimeout = requestAnimationFrame(() => {
221
- var _this$popupBodyWrappe3, _this$popupBodyWrappe4;
222
- // Defer to prevent editor scrolling to top. See https://product-fabric.atlassian.net/browse/DTR-1952
223
- (_this$popupBodyWrappe3 = this.popupBodyWrapper) === null || _this$popupBodyWrappe3 === void 0 ? void 0 : (_this$popupBodyWrappe4 = _this$popupBodyWrappe3.current) === null || _this$popupBodyWrappe4 === void 0 ? void 0 : _this$popupBodyWrappe4.focus();
224
- });
225
- }
226
218
  }
227
219
  componentWillUnmount() {
228
220
  this.focusTimeout && cancelAnimationFrame(this.focusTimeout);
@@ -259,7 +251,8 @@ export class StatusPickerWithoutAnalytcs extends React.Component {
259
251
  target,
260
252
  mountTo,
261
253
  boundariesElement,
262
- scrollableElement
254
+ scrollableElement,
255
+ focusStatusInput
263
256
  } = this.props;
264
257
  const {
265
258
  color,
@@ -283,7 +276,7 @@ export class StatusPickerWithoutAnalytcs extends React.Component {
283
276
  onClick: this.handlePopupClick,
284
277
  onKeyDown: this.onKeyDown
285
278
  }, jsx(AkStatusPicker, {
286
- autoFocus: isNew,
279
+ autoFocus: isNew || focusStatusInput,
287
280
  selectedColor: color,
288
281
  text: text,
289
282
  onColorClick: this.onColorClick,
@@ -12,22 +12,26 @@ export var DEFAULT_STATUS = {
12
12
  text: '',
13
13
  color: 'neutral'
14
14
  };
15
- export var createStatus = function createStatus() {
16
- var showStatusPickerAtOffset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
17
- return function (insert, state) {
18
- var statusNode = state.schema.nodes.status.createChecked(_objectSpread(_objectSpread({}, DEFAULT_STATUS), {}, {
19
- localId: uuid.generate()
20
- }));
21
- var space = state.schema.text(' ');
22
- var tr = insert(Fragment.from([statusNode, space]), {
23
- selectInlineNode: true
24
- });
25
- var showStatusPickerAt = tr.selection.from + showStatusPickerAtOffset;
26
- return tr.setSelection(NodeSelection.create(tr.doc, showStatusPickerAt)).setMeta(pluginKey, {
27
- showStatusPickerAt: showStatusPickerAt,
28
- isNew: true
29
- });
30
- };
15
+ export var verifyAndInsertStatus = function verifyAndInsertStatus(statusNode, state) {
16
+ var fragment = Fragment.fromArray([statusNode, state.schema.text(' ')]);
17
+ var tr = state.tr;
18
+ var insertable = canInsert(tr.selection.$from, fragment);
19
+ if (!insertable) {
20
+ var parentSelection = NodeSelection.create(tr.doc, tr.selection.from - tr.selection.$anchor.parentOffset - 1);
21
+ tr.insert(parentSelection.to, fragment).setSelection(NodeSelection.create(tr.doc, parentSelection.to + 1));
22
+ } else {
23
+ tr.insert(tr.selection.from, fragment).setSelection(NodeSelection.create(tr.doc, tr.selection.from - fragment.size));
24
+ }
25
+ return tr.setMeta(pluginKey, {
26
+ showStatusPickerAt: tr.selection.from,
27
+ isNew: true
28
+ }).scrollIntoView();
29
+ };
30
+ export var createStatus = function createStatus(state) {
31
+ var statusNode = state.schema.nodes.status.createChecked(_objectSpread(_objectSpread({}, DEFAULT_STATUS), {}, {
32
+ localId: uuid.generate()
33
+ }));
34
+ return verifyAndInsertStatus(statusNode, state);
31
35
  };
32
36
  export var updateStatus = function updateStatus(status) {
33
37
  return function (state, dispatch) {
@@ -43,18 +47,7 @@ export var updateStatus = function updateStatus(status) {
43
47
  if (!showStatusPickerAt) {
44
48
  // Same behaviour as quick insert (used in createStatus)
45
49
  var statusNode = schema.nodes.status.createChecked(statusProps);
46
- var fragment = Fragment.fromArray([statusNode, state.schema.text(' ')]);
47
- var insertable = canInsert(tr.selection.$from, fragment);
48
- if (!insertable) {
49
- var parentSelection = NodeSelection.create(tr.doc, tr.selection.from - tr.selection.$anchor.parentOffset - 1);
50
- tr.insert(parentSelection.to, fragment).setSelection(NodeSelection.create(tr.doc, parentSelection.to + 1));
51
- } else {
52
- tr.insert(tr.selection.from, fragment).setSelection(NodeSelection.create(tr.doc, tr.selection.from - fragment.size));
53
- }
54
- tr.setMeta(pluginKey, {
55
- showStatusPickerAt: tr.selection.from,
56
- isNew: true
57
- }).scrollIntoView();
50
+ tr = verifyAndInsertStatus(statusNode, state);
58
51
  if (dispatch) {
59
52
  dispatch(tr);
60
53
  }
@@ -101,6 +94,18 @@ export var removeStatus = function removeStatus(showStatusPickerAt) {
101
94
  return tr;
102
95
  };
103
96
  };
97
+ export var setFocusOnStatusInput = function setFocusOnStatusInput() {
98
+ return function (state, dispatch) {
99
+ if (!dispatch) {
100
+ return false;
101
+ }
102
+ var tr = state.tr.setMeta(pluginKey, {
103
+ focusStatusInput: true
104
+ });
105
+ dispatch(tr);
106
+ return true;
107
+ };
108
+ };
104
109
  var handleClosingByArrows = function handleClosingByArrows(closingMethod, state, showStatusPickerAt, tr) {
105
110
  if (closingMethod === 'arrowLeft') {
106
111
  // put cursor right before status Lozenge
@@ -128,6 +133,7 @@ export var commitStatusPicker = function commitStatusPicker(closingPayload) {
128
133
  var tr = state.tr;
129
134
  tr = tr.setMeta(pluginKey, {
130
135
  showStatusPickerAt: null,
136
+ focusStatusInput: false,
131
137
  isNew: false
132
138
  });
133
139
  if (closingMethod) {
@@ -68,6 +68,7 @@ var baseStatusPlugin = function baseStatusPlugin(_ref) {
68
68
  localId = _statusNode$attrs.localId;
69
69
  return /*#__PURE__*/React.createElement(StatusPicker, {
70
70
  isNew: statusState.isNew,
71
+ focusStatusInput: statusState.focusStatusInput,
71
72
  target: target,
72
73
  defaultText: text,
73
74
  defaultColor: color,
@@ -111,7 +112,7 @@ var decorateWithPluginOptions = function decorateWithPluginOptions(plugin, optio
111
112
  },
112
113
  action: function action(insert, state) {
113
114
  var _api$analytics2;
114
- var tr = createStatus()(insert, state);
115
+ var tr = createStatus(state);
115
116
  api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.attachAnalyticsEvent({
116
117
  action: ACTION.INSERTED,
117
118
  actionSubject: ACTION_SUBJECT.DOCUMENT,
@@ -1,10 +1,24 @@
1
1
  import { bindKeymapWithCommand, enter, tab } from '@atlaskit/editor-common/keymaps';
2
2
  import { keymap } from '@atlaskit/editor-prosemirror/keymap';
3
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
4
+ import { setFocusOnStatusInput } from '../actions';
3
5
  import { mayGetStatusAtSelection } from '../utils';
6
+ import { pluginKey } from './plugin-key';
4
7
  export function keymapPlugin() {
5
8
  var list = {};
6
9
  bindKeymapWithCommand(enter.common, consumeKeyEvent, list);
7
- bindKeymapWithCommand(tab.common, consumeKeyEvent, list);
10
+ bindKeymapWithCommand(tab.common, function (state, dispatch) {
11
+ var statusPluginState = pluginKey.getState(state);
12
+ var isStatusNode = state.selection instanceof NodeSelection ? state.selection.node.type === state.schema.nodes.status : false;
13
+ if (!isStatusNode) {
14
+ return false;
15
+ }
16
+ if (statusPluginState !== null && statusPluginState !== void 0 && statusPluginState.showStatusPickerAt) {
17
+ setFocusOnStatusInput()(state, dispatch);
18
+ return true;
19
+ }
20
+ return false;
21
+ }, list);
8
22
  return keymap(list);
9
23
  }
10
24
 
@@ -15,7 +15,8 @@ var createPlugin = function createPlugin(pmPluginFactoryParams, options) {
15
15
  init: function init() {
16
16
  return {
17
17
  isNew: false,
18
- showStatusPickerAt: null
18
+ showStatusPickerAt: null,
19
+ focusStatusInput: false
19
20
  };
20
21
  },
21
22
  apply: function apply(tr, state, oldEditorState) {
@@ -49,7 +50,8 @@ var createPlugin = function createPlugin(pmPluginFactoryParams, options) {
49
50
  if (_showStatusPickerAt !== state.showStatusPickerAt) {
50
51
  var _newState2 = _objectSpread(_objectSpread({}, state), {}, {
51
52
  isNew: false,
52
- showStatusPickerAt: _showStatusPickerAt
53
+ showStatusPickerAt: _showStatusPickerAt,
54
+ focusStatusInput: false
53
55
  });
54
56
  pmPluginFactoryParams.dispatch(pluginKey, _newState2);
55
57
  return _newState2;
@@ -230,17 +230,8 @@ export var StatusPickerWithoutAnalytcs = /*#__PURE__*/function (_React$Component
230
230
  }, {
231
231
  key: "componentDidMount",
232
232
  value: function componentDidMount() {
233
- var _this2 = this;
234
233
  this.reset();
235
234
  this.fireStatusPopupOpenedAnalytics(this.state);
236
- if (typeof this.props.isNew === 'boolean' && this.props.isNew === false) {
237
- // Wrapper should be focused only if status already exists otherwise input field will receive focus
238
- this.focusTimeout = requestAnimationFrame(function () {
239
- var _this2$popupBodyWrapp;
240
- // Defer to prevent editor scrolling to top. See https://product-fabric.atlassian.net/browse/DTR-1952
241
- (_this2$popupBodyWrapp = _this2.popupBodyWrapper) === null || _this2$popupBodyWrapp === void 0 || (_this2$popupBodyWrapp = _this2$popupBodyWrapp.current) === null || _this2$popupBodyWrapp === void 0 || _this2$popupBodyWrapp.focus();
242
- });
243
- }
244
235
  }
245
236
  }, {
246
237
  key: "componentWillUnmount",
@@ -283,7 +274,8 @@ export var StatusPickerWithoutAnalytcs = /*#__PURE__*/function (_React$Component
283
274
  target = _this$props.target,
284
275
  mountTo = _this$props.mountTo,
285
276
  boundariesElement = _this$props.boundariesElement,
286
- scrollableElement = _this$props.scrollableElement;
277
+ scrollableElement = _this$props.scrollableElement,
278
+ focusStatusInput = _this$props.focusStatusInput;
287
279
  var _this$state3 = this.state,
288
280
  color = _this$state3.color,
289
281
  text = _this$state3.text;
@@ -305,7 +297,7 @@ export var StatusPickerWithoutAnalytcs = /*#__PURE__*/function (_React$Component
305
297
  onClick: this.handlePopupClick,
306
298
  onKeyDown: this.onKeyDown
307
299
  }, jsx(AkStatusPicker, {
308
- autoFocus: isNew,
300
+ autoFocus: isNew || focusStatusInput,
309
301
  selectedColor: color,
310
302
  text: text,
311
303
  onColorClick: this.onColorClick,
@@ -1,15 +1,16 @@
1
1
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
2
- import type { Command, EditorCommand, TOOLBAR_MENU_TYPE } from '@atlaskit/editor-common/types';
2
+ import type { Command, CommandDispatch, EditorCommand, TOOLBAR_MENU_TYPE } from '@atlaskit/editor-common/types';
3
+ import type { Node } from '@atlaskit/editor-prosemirror/model';
3
4
  import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
4
5
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
6
  import type { ClosingPayload, StatusType } from './types';
6
7
  export declare const DEFAULT_STATUS: StatusType;
7
- export declare const createStatus: (showStatusPickerAtOffset?: number) => (insert: (node: Node | Object | string, opts: {
8
- selectInlineNode: boolean;
9
- }) => Transaction, state: EditorState) => Transaction;
8
+ export declare const verifyAndInsertStatus: (statusNode: Node, state: EditorState) => Transaction;
9
+ export declare const createStatus: (state: EditorState) => Transaction;
10
10
  export declare const updateStatus: (status?: StatusType) => Command;
11
11
  export type UpdateStatus = (inputMethod: TOOLBAR_MENU_TYPE, status?: StatusType) => Command;
12
12
  export declare const updateStatusWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (inputMethod: TOOLBAR_MENU_TYPE, status?: StatusType) => Command;
13
13
  export declare const setStatusPickerAt: (showStatusPickerAt: number | null) => (state: EditorState, dispatch: (tr: Transaction) => void) => boolean;
14
14
  export declare const removeStatus: (showStatusPickerAt: number) => EditorCommand;
15
+ export declare const setFocusOnStatusInput: () => (state: EditorState, dispatch: CommandDispatch | undefined) => boolean;
15
16
  export declare const commitStatusPicker: (closingPayload?: ClosingPayload) => (editorView: EditorView) => void;
@@ -8,6 +8,7 @@ export type StatusType = {
8
8
  export type StatusState = {
9
9
  isNew: boolean;
10
10
  showStatusPickerAt: number | null;
11
+ focusStatusInput?: boolean;
11
12
  };
12
13
  export interface StatusPluginOptions {
13
14
  menuDisabled: boolean;
@@ -19,6 +19,7 @@ export interface Props {
19
19
  onTextChanged: (status: StatusType, isNew: boolean) => void;
20
20
  onEnter: (status: StatusType) => void;
21
21
  isNew?: boolean;
22
+ focusStatusInput?: boolean;
22
23
  defaultText?: string;
23
24
  defaultColor?: Color;
24
25
  defaultLocalId?: string;
@@ -1,15 +1,16 @@
1
1
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
2
- import type { Command, EditorCommand, TOOLBAR_MENU_TYPE } from '@atlaskit/editor-common/types';
2
+ import type { Command, CommandDispatch, EditorCommand, TOOLBAR_MENU_TYPE } from '@atlaskit/editor-common/types';
3
+ import type { Node } from '@atlaskit/editor-prosemirror/model';
3
4
  import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
4
5
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
5
6
  import type { ClosingPayload, StatusType } from './types';
6
7
  export declare const DEFAULT_STATUS: StatusType;
7
- export declare const createStatus: (showStatusPickerAtOffset?: number) => (insert: (node: Node | Object | string, opts: {
8
- selectInlineNode: boolean;
9
- }) => Transaction, state: EditorState) => Transaction;
8
+ export declare const verifyAndInsertStatus: (statusNode: Node, state: EditorState) => Transaction;
9
+ export declare const createStatus: (state: EditorState) => Transaction;
10
10
  export declare const updateStatus: (status?: StatusType) => Command;
11
11
  export type UpdateStatus = (inputMethod: TOOLBAR_MENU_TYPE, status?: StatusType) => Command;
12
12
  export declare const updateStatusWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (inputMethod: TOOLBAR_MENU_TYPE, status?: StatusType) => Command;
13
13
  export declare const setStatusPickerAt: (showStatusPickerAt: number | null) => (state: EditorState, dispatch: (tr: Transaction) => void) => boolean;
14
14
  export declare const removeStatus: (showStatusPickerAt: number) => EditorCommand;
15
+ export declare const setFocusOnStatusInput: () => (state: EditorState, dispatch: CommandDispatch | undefined) => boolean;
15
16
  export declare const commitStatusPicker: (closingPayload?: ClosingPayload) => (editorView: EditorView) => void;
@@ -8,6 +8,7 @@ export type StatusType = {
8
8
  export type StatusState = {
9
9
  isNew: boolean;
10
10
  showStatusPickerAt: number | null;
11
+ focusStatusInput?: boolean;
11
12
  };
12
13
  export interface StatusPluginOptions {
13
14
  menuDisabled: boolean;
@@ -19,6 +19,7 @@ export interface Props {
19
19
  onTextChanged: (status: StatusType, isNew: boolean) => void;
20
20
  onEnter: (status: StatusType) => void;
21
21
  isNew?: boolean;
22
+ focusStatusInput?: boolean;
22
23
  defaultText?: string;
23
24
  defaultColor?: Color;
24
25
  defaultLocalId?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-status",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "Status plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "@atlaskit/adf-schema": "^32.0.0",
35
35
  "@atlaskit/analytics-next": "^9.1.0",
36
- "@atlaskit/editor-common": "^76.17.0",
36
+ "@atlaskit/editor-common": "^76.18.0",
37
37
  "@atlaskit/editor-plugin-analytics": "^0.3.0",
38
38
  "@atlaskit/editor-prosemirror": "1.1.0",
39
39
  "@atlaskit/editor-shared-styles": "^2.8.0",
package/report.api.md CHANGED
@@ -76,6 +76,7 @@ interface StatusPluginOptions {
76
76
  export type StatusState = {
77
77
  isNew: boolean;
78
78
  showStatusPickerAt: null | number;
79
+ focusStatusInput?: boolean;
79
80
  };
80
81
 
81
82
  // @public (undocumented)
@@ -60,6 +60,7 @@ interface StatusPluginOptions {
60
60
  export type StatusState = {
61
61
  isNew: boolean;
62
62
  showStatusPickerAt: null | number;
63
+ focusStatusInput?: boolean;
63
64
  };
64
65
 
65
66
  // @public (undocumented)