@atlaskit/editor-plugin-tasks-and-decisions 0.1.0 → 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.
Files changed (105) hide show
  1. package/.eslintrc.js +26 -0
  2. package/CHANGELOG.md +16 -0
  3. package/dist/cjs/commands.js +288 -0
  4. package/dist/cjs/index.js +8 -1
  5. package/dist/cjs/nodeviews/decisionItem.js +117 -0
  6. package/dist/cjs/nodeviews/hooks/use-show-placeholder.js +40 -0
  7. package/dist/cjs/nodeviews/taskItem.js +211 -0
  8. package/dist/cjs/plugin.js +166 -0
  9. package/dist/cjs/pm-plugins/commands.js +96 -0
  10. package/dist/cjs/pm-plugins/helpers.js +299 -0
  11. package/dist/cjs/pm-plugins/input-rules.js +94 -0
  12. package/dist/cjs/pm-plugins/keymaps.js +376 -0
  13. package/dist/cjs/pm-plugins/main.js +263 -0
  14. package/dist/cjs/pm-plugins/plugin-key.js +8 -0
  15. package/dist/cjs/pm-plugins/types.js +11 -0
  16. package/dist/cjs/types.js +5 -0
  17. package/dist/cjs/ui/Decision/index.js +30 -0
  18. package/dist/cjs/ui/Task/index.js +81 -0
  19. package/dist/cjs/ui/Task/task-item-with-providers.js +138 -0
  20. package/dist/cjs/ui/ToolbarDecision/index.js +41 -0
  21. package/dist/cjs/ui/ToolbarTask/index.js +40 -0
  22. package/dist/cjs/utils.js +41 -0
  23. package/dist/es2019/commands.js +279 -0
  24. package/dist/es2019/index.js +1 -1
  25. package/dist/es2019/nodeviews/decisionItem.js +76 -0
  26. package/dist/es2019/nodeviews/hooks/use-show-placeholder.js +36 -0
  27. package/dist/es2019/nodeviews/taskItem.js +173 -0
  28. package/dist/es2019/plugin.js +154 -0
  29. package/dist/es2019/pm-plugins/commands.js +94 -0
  30. package/dist/es2019/pm-plugins/helpers.js +316 -0
  31. package/dist/es2019/pm-plugins/input-rules.js +91 -0
  32. package/dist/es2019/pm-plugins/keymaps.js +370 -0
  33. package/dist/es2019/pm-plugins/main.js +262 -0
  34. package/dist/es2019/pm-plugins/plugin-key.js +2 -0
  35. package/dist/es2019/pm-plugins/types.js +5 -0
  36. package/dist/es2019/types.js +1 -0
  37. package/dist/es2019/ui/Decision/index.js +26 -0
  38. package/dist/es2019/ui/Task/index.js +55 -0
  39. package/dist/es2019/ui/Task/task-item-with-providers.js +72 -0
  40. package/dist/es2019/ui/ToolbarDecision/index.js +37 -0
  41. package/dist/es2019/ui/ToolbarTask/index.js +36 -0
  42. package/dist/es2019/utils.js +32 -0
  43. package/dist/esm/commands.js +281 -0
  44. package/dist/esm/index.js +1 -1
  45. package/dist/esm/nodeviews/decisionItem.js +110 -0
  46. package/dist/esm/nodeviews/hooks/use-show-placeholder.js +34 -0
  47. package/dist/esm/nodeviews/taskItem.js +204 -0
  48. package/dist/esm/plugin.js +155 -0
  49. package/dist/esm/pm-plugins/commands.js +90 -0
  50. package/dist/esm/pm-plugins/helpers.js +285 -0
  51. package/dist/esm/pm-plugins/input-rules.js +87 -0
  52. package/dist/esm/pm-plugins/keymaps.js +368 -0
  53. package/dist/esm/pm-plugins/main.js +256 -0
  54. package/dist/esm/pm-plugins/plugin-key.js +2 -0
  55. package/dist/esm/pm-plugins/types.js +5 -0
  56. package/dist/esm/types.js +1 -0
  57. package/dist/esm/ui/Decision/index.js +23 -0
  58. package/dist/esm/ui/Task/index.js +71 -0
  59. package/dist/esm/ui/Task/task-item-with-providers.js +129 -0
  60. package/dist/esm/ui/ToolbarDecision/index.js +34 -0
  61. package/dist/esm/ui/ToolbarTask/index.js +33 -0
  62. package/dist/esm/utils.js +30 -0
  63. package/dist/types/commands.d.ts +16 -0
  64. package/dist/types/index.d.ts +2 -1
  65. package/dist/types/nodeviews/decisionItem.d.ts +10 -0
  66. package/dist/types/nodeviews/hooks/use-show-placeholder.d.ts +11 -0
  67. package/dist/types/nodeviews/taskItem.d.ts +14 -0
  68. package/dist/types/plugin.d.ts +2 -0
  69. package/dist/types/pm-plugins/commands.d.ts +15 -0
  70. package/dist/types/pm-plugins/helpers.d.ts +76 -0
  71. package/dist/types/pm-plugins/input-rules.d.ts +6 -0
  72. package/dist/types/pm-plugins/keymaps.d.ts +11 -0
  73. package/dist/types/pm-plugins/main.d.ts +7 -0
  74. package/dist/types/pm-plugins/plugin-key.d.ts +2 -0
  75. package/dist/types/pm-plugins/types.d.ts +8 -0
  76. package/dist/types/types.d.ts +49 -0
  77. package/dist/types/ui/Decision/index.d.ts +15 -0
  78. package/dist/types/ui/Task/index.d.ts +28 -0
  79. package/dist/types/ui/Task/task-item-with-providers.d.ts +29 -0
  80. package/dist/types/ui/ToolbarDecision/index.d.ts +18 -0
  81. package/dist/types/ui/ToolbarTask/index.d.ts +18 -0
  82. package/dist/types/utils.d.ts +4 -0
  83. package/dist/types-ts4.5/commands.d.ts +16 -0
  84. package/dist/types-ts4.5/index.d.ts +2 -1
  85. package/dist/types-ts4.5/nodeviews/decisionItem.d.ts +10 -0
  86. package/dist/types-ts4.5/nodeviews/hooks/use-show-placeholder.d.ts +11 -0
  87. package/dist/types-ts4.5/nodeviews/taskItem.d.ts +14 -0
  88. package/dist/types-ts4.5/plugin.d.ts +2 -0
  89. package/dist/types-ts4.5/pm-plugins/commands.d.ts +15 -0
  90. package/dist/types-ts4.5/pm-plugins/helpers.d.ts +76 -0
  91. package/dist/types-ts4.5/pm-plugins/input-rules.d.ts +6 -0
  92. package/dist/types-ts4.5/pm-plugins/keymaps.d.ts +11 -0
  93. package/dist/types-ts4.5/pm-plugins/main.d.ts +7 -0
  94. package/dist/types-ts4.5/pm-plugins/plugin-key.d.ts +2 -0
  95. package/dist/types-ts4.5/pm-plugins/types.d.ts +8 -0
  96. package/dist/types-ts4.5/types.d.ts +49 -0
  97. package/dist/types-ts4.5/ui/Decision/index.d.ts +15 -0
  98. package/dist/types-ts4.5/ui/Task/index.d.ts +28 -0
  99. package/dist/types-ts4.5/ui/Task/task-item-with-providers.d.ts +29 -0
  100. package/dist/types-ts4.5/ui/ToolbarDecision/index.d.ts +18 -0
  101. package/dist/types-ts4.5/ui/ToolbarTask/index.d.ts +18 -0
  102. package/dist/types-ts4.5/utils.d.ts +4 -0
  103. package/package.json +16 -6
  104. package/report.api.md +100 -1
  105. package/tmp/api-report-tmp.d.ts +78 -0
@@ -0,0 +1,55 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import React, { PureComponent } from 'react';
4
+ import { defineMessages, injectIntl } from 'react-intl-next';
5
+ import { ProviderFactory, WithProviders } from '@atlaskit/editor-common/provider-factory';
6
+ import TaskItemWithProviders from './task-item-with-providers';
7
+ const messages = defineMessages({
8
+ placeholder: {
9
+ id: 'fabric.editor.taskPlaceholder',
10
+ defaultMessage: "Type your action, use '@' to assign to someone.",
11
+ description: 'Placeholder description for an empty action/task in the editor'
12
+ }
13
+ });
14
+ // eslint-disable-next-line @repo/internal/react/no-class-components
15
+ export class TaskItem extends PureComponent {
16
+ constructor(props) {
17
+ super(props);
18
+ _defineProperty(this, "renderWithProvider", providers => {
19
+ const {
20
+ providers: _providerFactory,
21
+ intl: {
22
+ formatMessage
23
+ },
24
+ ...otherProps
25
+ } = this.props;
26
+ const {
27
+ taskDecisionProvider,
28
+ contextIdentifierProvider
29
+ } = providers;
30
+ const placeholder = formatMessage(messages.placeholder);
31
+ return /*#__PURE__*/React.createElement(TaskItemWithProviders, _extends({}, otherProps, {
32
+ placeholder: placeholder,
33
+ taskDecisionProvider: taskDecisionProvider,
34
+ contextIdentifierProvider: contextIdentifierProvider
35
+ }));
36
+ });
37
+ this.providerFactory = props.providers || new ProviderFactory();
38
+ }
39
+ componentWillUnmount() {
40
+ if (!this.props.providers) {
41
+ // new ProviderFactory is created if no `providers` has been set
42
+ // in this case when component is unmounted it's safe to destroy this providerFactory
43
+ this.providerFactory.destroy();
44
+ }
45
+ }
46
+ render() {
47
+ return /*#__PURE__*/React.createElement(WithProviders, {
48
+ providers: ['taskDecisionProvider', 'contextIdentifierProvider'],
49
+ providerFactory: this.providerFactory,
50
+ renderNode: this.renderWithProvider
51
+ });
52
+ }
53
+ }
54
+ _defineProperty(TaskItem, "displayName", 'TaskItem');
55
+ export default injectIntl(TaskItem);
@@ -0,0 +1,72 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import React, { Component } from 'react';
4
+ import { FabricElementsAnalyticsContext } from '@atlaskit/analytics-namespaced-context';
5
+ import { ResourcedTaskItem } from '@atlaskit/task-decision';
6
+ // eslint-disable-next-line @repo/internal/react/no-class-components
7
+ export default class TaskItemWithProviders extends Component {
8
+ constructor(...args) {
9
+ super(...args);
10
+ _defineProperty(this, "state", {
11
+ resolvedContextProvider: undefined
12
+ });
13
+ // Storing the mounted state is an anti-pattern, however the asynchronous state
14
+ // updates via `updateContextIdentifierProvider` means we may be dismounted before
15
+ // it receives a response.
16
+ // Since we can't cancel the Promise we store the mounted state to avoid state
17
+ // updates when no longer suitable.
18
+ _defineProperty(this, "mounted", false);
19
+ }
20
+ UNSAFE_componentWillMount() {
21
+ this.mounted = true;
22
+ this.updateContextIdentifierProvider(this.props);
23
+ }
24
+ componentWillUnmount() {
25
+ this.mounted = false;
26
+ }
27
+ UNSAFE_componentWillReceiveProps(nextProps) {
28
+ if (nextProps.contextIdentifierProvider !== this.props.contextIdentifierProvider) {
29
+ this.updateContextIdentifierProvider(nextProps);
30
+ }
31
+ }
32
+ async updateContextIdentifierProvider(props) {
33
+ if (props.contextIdentifierProvider) {
34
+ try {
35
+ const resolvedContextProvider = await props.contextIdentifierProvider;
36
+ if (this.mounted) {
37
+ this.setState({
38
+ resolvedContextProvider
39
+ });
40
+ }
41
+ } catch (err) {
42
+ if (this.mounted) {
43
+ this.setState({
44
+ resolvedContextProvider: undefined
45
+ });
46
+ }
47
+ }
48
+ } else {
49
+ this.setState({
50
+ resolvedContextProvider: undefined
51
+ });
52
+ }
53
+ }
54
+ render() {
55
+ const {
56
+ contextIdentifierProvider,
57
+ ...otherProps
58
+ } = this.props;
59
+ const {
60
+ objectId
61
+ } = this.state.resolvedContextProvider || {};
62
+ const userContext = objectId ? 'edit' : 'new';
63
+ return /*#__PURE__*/React.createElement(FabricElementsAnalyticsContext, {
64
+ data: {
65
+ userContext
66
+ }
67
+ }, /*#__PURE__*/React.createElement(ResourcedTaskItem, _extends({}, otherProps, {
68
+ objectAri: objectId
69
+ })));
70
+ }
71
+ }
72
+ _defineProperty(TaskItemWithProviders, "displayName", 'TaskItemWithProviders');
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import { injectIntl } from 'react-intl-next';
3
+ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
4
+ import { TOOLBAR_BUTTON, ToolbarButton } from '@atlaskit/editor-common/ui-menu';
5
+ import DecisionIcon from '@atlaskit/icon/glyph/editor/decision';
6
+ import { insertTaskDecisionCommand } from '../../commands';
7
+ const ToolbarDecision = ({
8
+ isDisabled,
9
+ isReducedSpacing,
10
+ intl: {
11
+ formatMessage
12
+ },
13
+ editorView,
14
+ editorAPI
15
+ }) => {
16
+ const label = formatMessage(messages.decision);
17
+ const handleInsertDecision = () => {
18
+ var _editorAPI$analytics;
19
+ if (!editorView) {
20
+ return false;
21
+ }
22
+ insertTaskDecisionCommand(editorAPI === null || editorAPI === void 0 ? void 0 : (_editorAPI$analytics = editorAPI.analytics) === null || _editorAPI$analytics === void 0 ? void 0 : _editorAPI$analytics.actions)('decisionList')(editorView.state, editorView.dispatch);
23
+ return true;
24
+ };
25
+ return /*#__PURE__*/React.createElement(ToolbarButton, {
26
+ buttonId: TOOLBAR_BUTTON.DECISION_LIST,
27
+ onClick: handleInsertDecision,
28
+ disabled: isDisabled,
29
+ spacing: isReducedSpacing ? 'none' : 'default',
30
+ title: `${label} <>`,
31
+ "aria-keyshortcuts": "Shift+, Shift+. space",
32
+ iconBefore: /*#__PURE__*/React.createElement(DecisionIcon, {
33
+ label: label
34
+ })
35
+ });
36
+ };
37
+ export default injectIntl(ToolbarDecision);
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import { injectIntl } from 'react-intl-next';
3
+ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
4
+ import { TOOLBAR_BUTTON, ToolbarButton } from '@atlaskit/editor-common/ui-menu';
5
+ import TaskIcon from '@atlaskit/icon/glyph/editor/task';
6
+ import { insertTaskDecisionCommand } from '../../commands';
7
+ const ToolbarTask = ({
8
+ isDisabled,
9
+ isReducedSpacing,
10
+ intl: {
11
+ formatMessage
12
+ },
13
+ editorAPI,
14
+ editorView
15
+ }) => {
16
+ const label = formatMessage(messages.action);
17
+ const handleInsertTask = () => {
18
+ var _editorAPI$analytics;
19
+ if (!editorView) {
20
+ return false;
21
+ }
22
+ insertTaskDecisionCommand(editorAPI === null || editorAPI === void 0 ? void 0 : (_editorAPI$analytics = editorAPI.analytics) === null || _editorAPI$analytics === void 0 ? void 0 : _editorAPI$analytics.actions)('taskList')(editorView.state, editorView.dispatch);
23
+ return true;
24
+ };
25
+ return /*#__PURE__*/React.createElement(ToolbarButton, {
26
+ buttonId: TOOLBAR_BUTTON.TASK_LIST,
27
+ onClick: handleInsertTask,
28
+ disabled: isDisabled,
29
+ spacing: isReducedSpacing ? 'none' : 'default',
30
+ title: `${label} []`,
31
+ iconBefore: /*#__PURE__*/React.createElement(TaskIcon, {
32
+ label: label
33
+ })
34
+ });
35
+ };
36
+ export default injectIntl(ToolbarTask);
@@ -0,0 +1,32 @@
1
+ import { transformSliceToDecisionList } from '@atlaskit/editor-common/transforms';
2
+ import { NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
3
+ export { transformSliceToDecisionList };
4
+ function isTaskListNode(node) {
5
+ return Boolean(node && node.type && 'taskList' === node.type.name);
6
+ }
7
+ const resolvePositionToStartOfTaskItem = $pos => {
8
+ const fromRange = $pos.blockRange($pos, isTaskListNode);
9
+ const fromPosition = fromRange && $pos.textOffset === 0 && fromRange.end - 1 === $pos.pos ? Selection.near($pos.doc.resolve(fromRange.end + 1), 1).$from : $pos;
10
+ return fromPosition;
11
+ };
12
+ const resolvePositionToEndOfTaskItem = $pos => {
13
+ const toRange = $pos.blockRange($pos, isTaskListNode);
14
+ const toPosition = toRange && $pos.textOffset === 0 && toRange.start + 1 === $pos.pos ? Selection.near($pos.doc.resolve(toRange.start - 1), -1).$to : $pos;
15
+ return toPosition;
16
+ };
17
+ export const normalizeTaskItemsSelection = selection => {
18
+ if (selection.empty) {
19
+ return selection;
20
+ }
21
+ const {
22
+ $from,
23
+ $to
24
+ } = selection;
25
+ if (selection instanceof NodeSelection) {
26
+ const head = resolvePositionToStartOfTaskItem($from);
27
+ return new TextSelection(head, head);
28
+ }
29
+ const head = resolvePositionToStartOfTaskItem($from);
30
+ const anchor = resolvePositionToEndOfTaskItem($to);
31
+ return new TextSelection(anchor, head);
32
+ };
@@ -0,0 +1,281 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ import { uuid } from '@atlaskit/adf-schema';
5
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD, USER_CONTEXT } from '@atlaskit/editor-common/analytics';
6
+ import { GapCursorSelection } from '@atlaskit/editor-common/selection';
7
+ import { autoJoinTr } from '@atlaskit/editor-common/utils';
8
+ import { NodeRange } from '@atlaskit/editor-prosemirror/model';
9
+ import { TextSelection } from '@atlaskit/editor-prosemirror/state';
10
+ import { liftTarget } from '@atlaskit/editor-prosemirror/transform';
11
+ import { findParentNodeOfType, hasParentNodeOfType, replaceParentNodeOfType, safeInsert, setTextSelection } from '@atlaskit/editor-prosemirror/utils';
12
+ import { stateKey as taskDecisionStateKey } from './pm-plugins/plugin-key';
13
+ var getContextData = function getContextData() {
14
+ var contextProvider = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
15
+ var objectId = contextProvider.objectId,
16
+ containerId = contextProvider.containerId;
17
+ var userContext = objectId ? USER_CONTEXT.EDIT : USER_CONTEXT.NEW;
18
+ return {
19
+ objectId: objectId,
20
+ containerId: containerId,
21
+ userContext: userContext
22
+ };
23
+ };
24
+ var generateAnalyticsPayload = function generateAnalyticsPayload(listType, contextData, inputMethod, itemLocalId, listLocalId, itemIdx, listSize) {
25
+ var containerId;
26
+ var objectId;
27
+ var userContext;
28
+ if (contextData) {
29
+ containerId = contextData.containerId;
30
+ objectId = contextData.objectId;
31
+ userContext = contextData.userContext;
32
+ }
33
+ return {
34
+ action: ACTION.INSERTED,
35
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
36
+ actionSubjectId: listType === 'taskList' ? ACTION_SUBJECT_ID.ACTION : ACTION_SUBJECT_ID.DECISION,
37
+ eventType: EVENT_TYPE.TRACK,
38
+ attributes: {
39
+ inputMethod: inputMethod,
40
+ containerAri: containerId,
41
+ objectAri: objectId,
42
+ userContext: userContext,
43
+ localId: itemLocalId,
44
+ listLocalId: listLocalId,
45
+ position: itemIdx,
46
+ listSize: listSize
47
+ }
48
+ };
49
+ };
50
+ export var getListTypes = function getListTypes(listType, schema) {
51
+ var _schema$nodes = schema.nodes,
52
+ decisionList = _schema$nodes.decisionList,
53
+ decisionItem = _schema$nodes.decisionItem,
54
+ taskList = _schema$nodes.taskList,
55
+ taskItem = _schema$nodes.taskItem;
56
+ if (listType === 'taskList') {
57
+ return {
58
+ list: taskList,
59
+ item: taskItem
60
+ };
61
+ }
62
+ return {
63
+ list: decisionList,
64
+ item: decisionItem
65
+ };
66
+ };
67
+ export var insertTaskDecisionAction = function insertTaskDecisionAction(editorAnalyticsAPI) {
68
+ return function (state, listType) {
69
+ var inputMethod = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : INPUT_METHOD.TOOLBAR;
70
+ var addItem = arguments.length > 3 ? arguments[3] : undefined;
71
+ var listLocalId = arguments.length > 4 ? arguments[4] : undefined;
72
+ var itemLocalId = arguments.length > 5 ? arguments[5] : undefined;
73
+ var itemAttrs = arguments.length > 6 ? arguments[6] : undefined;
74
+ var schema = state.schema;
75
+ var addAndCreateList = function addAndCreateList(_ref) {
76
+ var tr = _ref.tr,
77
+ list = _ref.list,
78
+ item = _ref.item,
79
+ listLocalId = _ref.listLocalId,
80
+ itemLocalId = _ref.itemLocalId;
81
+ return createListAtSelection(tr, list, item, schema, state, listLocalId, itemLocalId, itemAttrs);
82
+ };
83
+ var addToList = function addToList(_ref2) {
84
+ var state = _ref2.state,
85
+ tr = _ref2.tr,
86
+ item = _ref2.item,
87
+ itemLocalId = _ref2.itemLocalId;
88
+ var $to = state.selection.$to;
89
+ var endPos = $to.end($to.depth);
90
+ var newItemParagraphPos = endPos + 2;
91
+ return tr.split(endPos, 1, [{
92
+ type: item,
93
+ attrs: {
94
+ localId: itemLocalId
95
+ }
96
+ }]).setSelection(new TextSelection(tr.doc.resolve(newItemParagraphPos)));
97
+ };
98
+ var addAndCreateListFn = addItem !== null && addItem !== void 0 ? addItem : addAndCreateList;
99
+ var tr = insertTaskDecisionWithAnalytics(editorAnalyticsAPI)(state, listType, inputMethod, addAndCreateListFn, addToList, listLocalId, itemLocalId, itemAttrs);
100
+ if (!tr) {
101
+ return state.tr;
102
+ }
103
+ autoJoinTr(tr, ['taskList', 'decisionList']);
104
+ return tr;
105
+ };
106
+ };
107
+ export var insertTaskDecisionCommand = function insertTaskDecisionCommand(editorAnalyticsAPI) {
108
+ return function (listType) {
109
+ var inputMethod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : INPUT_METHOD.TOOLBAR;
110
+ var addItem = arguments.length > 2 ? arguments[2] : undefined;
111
+ var listLocalId = arguments.length > 3 ? arguments[3] : undefined;
112
+ var itemLocalId = arguments.length > 4 ? arguments[4] : undefined;
113
+ return function (state, dispatch) {
114
+ var tr = insertTaskDecisionAction(editorAnalyticsAPI)(state, listType, inputMethod, addItem, listLocalId, itemLocalId);
115
+ if (dispatch) {
116
+ dispatch(tr);
117
+ }
118
+ return true;
119
+ };
120
+ };
121
+ };
122
+ export var insertTaskDecisionWithAnalytics = function insertTaskDecisionWithAnalytics(editorAnalyticsAPI) {
123
+ return function (state, listType, inputMethod, addAndCreateList, addToList, listLocalId, itemLocalId, itemAttrs) {
124
+ var schema = state.schema;
125
+ var _getListTypes = getListTypes(listType, schema),
126
+ list = _getListTypes.list,
127
+ item = _getListTypes.item;
128
+ var tr = state.tr;
129
+ var $to = state.selection.$to;
130
+ var listNode = findParentNodeOfType(list)(state.selection);
131
+ var contextIdentifierProvider = taskDecisionStateKey.getState(state).contextIdentifierProvider;
132
+ var contextData = getContextData(contextIdentifierProvider);
133
+ var insertTrCreator;
134
+ var itemIdx;
135
+ var listSize;
136
+ if (!listNode) {
137
+ // Not a list - convert to one.
138
+ itemIdx = 0;
139
+ listSize = 1;
140
+ insertTrCreator = addAndCreateList;
141
+ } else if ($to.node().textContent.length >= 0) {
142
+ listSize = listNode.node.childCount + 1;
143
+ listLocalId = listLocalId || listNode.node.attrs.localId;
144
+ var listItemNode = findParentNodeOfType(item)(state.selection); // finds current item in list
145
+ itemIdx = listItemNode ? state.doc.resolve(listItemNode.pos).index() + 1 : 0;
146
+ insertTrCreator = addToList ? addToList : addAndCreateList;
147
+ }
148
+ listLocalId = listLocalId || uuid.generate();
149
+ itemLocalId = itemLocalId || uuid.generate();
150
+ if (insertTrCreator) {
151
+ var insertTr = insertTrCreator({
152
+ state: state,
153
+ tr: tr,
154
+ list: list,
155
+ item: item,
156
+ listLocalId: listLocalId,
157
+ itemLocalId: itemLocalId,
158
+ itemAttrs: itemAttrs
159
+ });
160
+ if (insertTr) {
161
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent(generateAnalyticsPayload(listType, contextData, inputMethod, itemLocalId, listLocalId, itemIdx || 0, listSize || 0))(insertTr);
162
+ }
163
+ return insertTr;
164
+ }
165
+ return null;
166
+ };
167
+ };
168
+ export var isSupportedSourceNode = function isSupportedSourceNode(schema, selection) {
169
+ var _schema$nodes2 = schema.nodes,
170
+ paragraph = _schema$nodes2.paragraph,
171
+ blockquote = _schema$nodes2.blockquote,
172
+ decisionList = _schema$nodes2.decisionList,
173
+ taskList = _schema$nodes2.taskList;
174
+ return hasParentNodeOfType([blockquote, paragraph, decisionList, taskList])(selection);
175
+ };
176
+ export var changeInDepth = function changeInDepth(before, after) {
177
+ return after.depth - before.depth;
178
+ };
179
+ export var createListAtSelection = function createListAtSelection(tr, list, item, schema, state) {
180
+ var listLocalId = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : uuid.generate();
181
+ var itemLocalId = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : uuid.generate();
182
+ var itemAttrs = arguments.length > 7 ? arguments[7] : undefined;
183
+ var selection = state.selection;
184
+ var $from = selection.$from,
185
+ $to = selection.$to;
186
+ if ($from.parent !== $to.parent) {
187
+ // ignore selections across multiple nodes
188
+ return null;
189
+ }
190
+ var _schema$nodes3 = schema.nodes,
191
+ paragraph = _schema$nodes3.paragraph,
192
+ blockquote = _schema$nodes3.blockquote,
193
+ decisionList = _schema$nodes3.decisionList,
194
+ taskList = _schema$nodes3.taskList,
195
+ decisionItem = _schema$nodes3.decisionItem,
196
+ taskItem = _schema$nodes3.taskItem,
197
+ mediaGroup = _schema$nodes3.mediaGroup;
198
+ if ($from.parent.type === mediaGroup) {
199
+ return null;
200
+ }
201
+ var emptyList = list.create({
202
+ localId: listLocalId
203
+ }, [item.create(_objectSpread({
204
+ localId: itemLocalId
205
+ }, itemAttrs))]);
206
+
207
+ // we don't take the content of a block node next to the gap cursor and always create an empty task
208
+ if (selection instanceof GapCursorSelection) {
209
+ return safeInsert(emptyList)(tr);
210
+ }
211
+
212
+ // try to replace when selection is in nodes which support it
213
+ if (isSupportedSourceNode(schema, selection)) {
214
+ var _selection$$from$node = selection.$from.node(),
215
+ nodeType = _selection$$from$node.type,
216
+ childCount = _selection$$from$node.childCount;
217
+ var newListNode = list.create({
218
+ localId: uuid.generate()
219
+ }, [item.create({
220
+ localId: uuid.generate()
221
+ }, $from.node($from.depth).content)]);
222
+ var hasBlockquoteParent = findParentNodeOfType(blockquote)(selection);
223
+ if (hasBlockquoteParent) {
224
+ var liftedDepth = $from.depth - 1;
225
+ var range = new NodeRange($from, $to, liftedDepth);
226
+ tr.lift(range, liftTarget(range));
227
+ }
228
+ var listParent = findParentNodeOfType(taskList)(selection) || findParentNodeOfType(decisionList)(selection);
229
+ var listItem = findParentNodeOfType(taskItem)(selection) || findParentNodeOfType(decisionItem)(selection);
230
+
231
+ // For a selection inside a task/decision list, we can't just simply replace the
232
+ // node type as it will mess up lists with > 1 item
233
+ if (listParent && listItem) {
234
+ var start;
235
+ var end;
236
+ var selectionPos = selection.from;
237
+
238
+ // if selection is in first item in list, we need to delete extra so that
239
+ // this list isn't split
240
+ if (listParent.node.firstChild === listItem.node) {
241
+ start = listParent.start - 1;
242
+ end = listItem.start + listItem.node.nodeSize;
243
+ if (listParent.node.childCount === 1) {
244
+ end = listParent.start + listParent.node.nodeSize - 1;
245
+ }
246
+ } else {
247
+ start = listItem.start - 1;
248
+ end = listItem.start + listItem.node.nodeSize;
249
+ selectionPos += 2; // as we have added the new list node
250
+ }
251
+
252
+ tr.replaceWith(start, end, newListNode);
253
+ tr = setTextSelection(selectionPos)(tr);
254
+ return tr;
255
+ }
256
+
257
+ // For a selection inside one of these node types we can just convert the node type
258
+ var nodeTypesToReplace = [blockquote];
259
+ if (nodeType === paragraph && childCount > 0 || hasBlockquoteParent) {
260
+ // Only convert paragraphs containing content.
261
+ // Empty paragraphs use the default flow.
262
+ // This distinction ensures the text selection remains in the correct location.
263
+
264
+ // We also want to replace the paragraph type when we are inside a blockQuote
265
+ // to avoid inserting an extra taskList whilst keeping the paragraph
266
+ nodeTypesToReplace.push(paragraph);
267
+ }
268
+ var newTr = tr;
269
+ newTr = replaceParentNodeOfType(nodeTypesToReplace, newListNode)(tr);
270
+
271
+ // Adjust depth for new selection, if it has changed (e.g. paragraph to list (ol > li))
272
+ var depthAdjustment = changeInDepth($to, newTr.selection.$to);
273
+ tr = tr.setSelection(new TextSelection(tr.doc.resolve($to.pos + depthAdjustment)));
274
+
275
+ // replacing successful
276
+ if (newTr !== tr) {
277
+ return tr;
278
+ }
279
+ }
280
+ return safeInsert(emptyList)(tr);
281
+ };
package/dist/esm/index.js CHANGED
@@ -1 +1 @@
1
- export {};
1
+ export { tasksAndDecisionsPlugin } from './plugin';
@@ -0,0 +1,110 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _get from "@babel/runtime/helpers/get";
4
+ import _inherits from "@babel/runtime/helpers/inherits";
5
+ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
6
+ import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
7
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
8
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
9
+ import React from 'react';
10
+ import ReactNodeView from '@atlaskit/editor-common/react-node-view';
11
+ import DecisionItem from '../ui/Decision';
12
+ import { useShowPlaceholder } from './hooks/use-show-placeholder';
13
+ var DecisionItemWrapper = function DecisionItemWrapper(_ref) {
14
+ var api = _ref.api,
15
+ editorView = _ref.editorView,
16
+ forwardRef = _ref.forwardRef,
17
+ isContentNodeEmpty = _ref.isContentNodeEmpty,
18
+ getPos = _ref.getPos;
19
+ var showPlaceholder = useShowPlaceholder({
20
+ editorView: editorView,
21
+ isContentNodeEmpty: isContentNodeEmpty,
22
+ getPos: getPos,
23
+ api: api
24
+ });
25
+ return /*#__PURE__*/React.createElement(DecisionItem, {
26
+ contentRef: forwardRef,
27
+ showPlaceholder: showPlaceholder
28
+ });
29
+ };
30
+ var Decision = /*#__PURE__*/function (_ReactNodeView) {
31
+ _inherits(Decision, _ReactNodeView);
32
+ var _super = _createSuper(Decision);
33
+ function Decision() {
34
+ _classCallCheck(this, Decision);
35
+ return _super.apply(this, arguments);
36
+ }
37
+ _createClass(Decision, [{
38
+ key: "isContentEmpty",
39
+ value: function isContentEmpty(node) {
40
+ return node.content.childCount === 0;
41
+ }
42
+ }, {
43
+ key: "initWithAPI",
44
+ value: function initWithAPI(api) {
45
+ this.api = api;
46
+ this.init();
47
+ return this;
48
+ }
49
+ }, {
50
+ key: "createDomRef",
51
+ value: function createDomRef() {
52
+ var domRef = document.createElement('li');
53
+ domRef.style.listStyleType = 'none';
54
+ return domRef;
55
+ }
56
+ }, {
57
+ key: "getContentDOM",
58
+ value: function getContentDOM() {
59
+ var dom = document.createElement('div');
60
+ // setting a className prevents PM/Chrome mutation observer from
61
+ // incorrectly deleting nodes
62
+ dom.className = 'decision-item';
63
+ return {
64
+ dom: dom
65
+ };
66
+ }
67
+ }, {
68
+ key: "render",
69
+ value: function render(_props, forwardRef) {
70
+ var isContentNodeEmpty = this.isContentEmpty(this.node);
71
+ return /*#__PURE__*/React.createElement(DecisionItemWrapper, {
72
+ forwardRef: forwardRef,
73
+ isContentNodeEmpty: isContentNodeEmpty,
74
+ api: this.api
75
+ // The getPosHandler type is wrong, there is no `boolean` in the real implementation
76
+ // @ts-expect-error 2322: Type 'getPosHandler' is not assignable to type '() => number | undefined'.
77
+ ,
78
+ getPos: this.getPos,
79
+ editorView: this.view
80
+ });
81
+ }
82
+ }, {
83
+ key: "viewShouldUpdate",
84
+ value: function viewShouldUpdate(nextNode) {
85
+ /**
86
+ * To ensure the placeholder is correctly toggled we need to allow react to re-render
87
+ * on first character insertion.
88
+ * Note: last character deletion is handled externally and automatically re-renders.
89
+ */
90
+ return this.isContentEmpty(this.node) && !!nextNode.content.childCount;
91
+ }
92
+ }, {
93
+ key: "update",
94
+ value: function update(node, decorations) {
95
+ var _this = this;
96
+ return _get(_getPrototypeOf(Decision.prototype), "update", this).call(this, node, decorations, undefined,
97
+ // Toggle the placeholder based on whether user input exists.
98
+ function (_currentNode, _newNode) {
99
+ return !_this.isContentEmpty(_newNode);
100
+ });
101
+ }
102
+ }]);
103
+ return Decision;
104
+ }(ReactNodeView);
105
+ export var decisionItemNodeView = function decisionItemNodeView(portalProviderAPI, eventDispatcher, api) {
106
+ return function (node, view, getPos) {
107
+ var hasIntlContext = true;
108
+ return new Decision(node, view, getPos, portalProviderAPI, eventDispatcher, {}, undefined, undefined, undefined, hasIntlContext).initWithAPI(api);
109
+ };
110
+ };
@@ -0,0 +1,34 @@
1
+ import { useMemo } from 'react';
2
+ import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
3
+ import { TextSelection } from '@atlaskit/editor-prosemirror/state';
4
+ export var useShowPlaceholder = function useShowPlaceholder(_ref) {
5
+ var editorView = _ref.editorView,
6
+ api = _ref.api,
7
+ isContentNodeEmpty = _ref.isContentNodeEmpty,
8
+ getPos = _ref.getPos;
9
+ var _useSharedPluginState = useSharedPluginState(api, ['typeAhead']),
10
+ typeAheadState = _useSharedPluginState.typeAheadState;
11
+ var isTypeAheadOpen = Boolean(typeAheadState === null || typeAheadState === void 0 ? void 0 : typeAheadState.isOpen);
12
+ var isTypeAheadOpenedInsideItem = useMemo(function () {
13
+ var _selection$$cursor;
14
+ if (!isTypeAheadOpen) {
15
+ return false;
16
+ }
17
+ var itemPosition = getPos();
18
+ if (typeof itemPosition !== 'number') {
19
+ return false;
20
+ }
21
+ var selection = editorView.state.selection;
22
+ if (!(selection instanceof TextSelection)) {
23
+ return false;
24
+ }
25
+ var maybeItemNode = editorView.state.doc.nodeAt(itemPosition);
26
+ var maybeParentItemNode = (_selection$$cursor = selection.$cursor) === null || _selection$$cursor === void 0 ? void 0 : _selection$$cursor.node();
27
+ if (maybeItemNode && maybeParentItemNode && maybeItemNode.eq(maybeParentItemNode)) {
28
+ return true;
29
+ }
30
+ return false;
31
+ }, [isTypeAheadOpen, getPos, editorView]);
32
+ var showPlaceholder = Boolean(!isTypeAheadOpenedInsideItem && isContentNodeEmpty);
33
+ return showPlaceholder;
34
+ };