@atlaskit/link-create 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/controllers/exit-warning-modal-context/index.js +42 -0
  3. package/dist/cjs/controllers/form-context/main.js +2 -15
  4. package/dist/cjs/ui/create-form/main.js +4 -2
  5. package/dist/cjs/ui/link-create/confirm-dismiss-dialog/main.js +11 -2
  6. package/dist/cjs/ui/link-create/main.js +63 -49
  7. package/dist/cjs/ui/main.js +1 -1
  8. package/dist/es2019/controllers/exit-warning-modal-context/index.js +28 -0
  9. package/dist/es2019/controllers/form-context/main.js +3 -14
  10. package/dist/es2019/ui/create-form/main.js +5 -2
  11. package/dist/es2019/ui/link-create/confirm-dismiss-dialog/main.js +10 -2
  12. package/dist/es2019/ui/link-create/main.js +54 -45
  13. package/dist/es2019/ui/main.js +1 -1
  14. package/dist/esm/controllers/exit-warning-modal-context/index.js +33 -0
  15. package/dist/esm/controllers/form-context/main.js +3 -16
  16. package/dist/esm/ui/create-form/main.js +4 -2
  17. package/dist/esm/ui/link-create/confirm-dismiss-dialog/main.js +11 -2
  18. package/dist/esm/ui/link-create/main.js +64 -50
  19. package/dist/esm/ui/main.js +1 -1
  20. package/dist/types/controllers/exit-warning-modal-context/index.d.ts +10 -0
  21. package/dist/types/controllers/form-context/main.d.ts +0 -3
  22. package/dist/types/ui/link-create/confirm-dismiss-dialog/main.d.ts +2 -3
  23. package/dist/types-ts4.5/controllers/exit-warning-modal-context/index.d.ts +10 -0
  24. package/dist/types-ts4.5/controllers/form-context/main.d.ts +0 -3
  25. package/dist/types-ts4.5/ui/link-create/confirm-dismiss-dialog/main.d.ts +2 -3
  26. package/example-helpers/mock-plugin-form.tsx +7 -8
  27. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @atlaskit/link-create
2
2
 
3
+ ## 1.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#43068](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43068) [`76817bfbd5d`](https://bitbucket.org/atlassian/atlassian-frontend/commits/76817bfbd5d) - EDM-8402: under a FF platform.linking-platform.link-create.enable-edit internally refactor onCloseComplete hook to be conditionally called when active prop is false
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+
13
+ ## 1.8.1
14
+
15
+ ### Patch Changes
16
+
17
+ - [#43001](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43001) [`7eed2972d58`](https://bitbucket.org/atlassian/atlassian-frontend/commits/7eed2972d58) - Internal refactor moving show exit warning modal conditions to React context
18
+
3
19
  ## 1.8.0
4
20
 
5
21
  ### Minor Changes
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ var _typeof = require("@babel/runtime/helpers/typeof");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useExitWarningModal = exports.ExitWarningModalProvider = void 0;
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
10
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
11
+ var ExitWarningModalContext = /*#__PURE__*/(0, _react.createContext)({
12
+ getShouldShowWarning: function getShouldShowWarning() {
13
+ return false;
14
+ },
15
+ setShouldShowWarning: function setShouldShowWarning() {}
16
+ });
17
+ var ExitWarningModalProvider = exports.ExitWarningModalProvider = function ExitWarningModalProvider(_ref) {
18
+ var children = _ref.children;
19
+ var shouldShowWarning = (0, _react.useRef)(false);
20
+ var getShouldShowWarning = (0, _react.useCallback)(function () {
21
+ return shouldShowWarning.current;
22
+ }, []);
23
+ var setShouldShowWarning = (0, _react.useCallback)(function (show) {
24
+ shouldShowWarning.current = show;
25
+ }, []);
26
+ var value = (0, _react.useMemo)(function () {
27
+ return {
28
+ getShouldShowWarning: getShouldShowWarning,
29
+ setShouldShowWarning: setShouldShowWarning
30
+ };
31
+ }, [getShouldShowWarning, setShouldShowWarning]);
32
+ return /*#__PURE__*/_react.default.createElement(ExitWarningModalContext.Provider, {
33
+ value: value
34
+ }, children);
35
+ };
36
+ var useExitWarningModal = exports.useExitWarningModal = function useExitWarningModal() {
37
+ var value = (0, _react.useContext)(ExitWarningModalContext);
38
+ if (!value) {
39
+ throw new Error('useExitWarningModal used outside of ExitWarningModalProvider');
40
+ }
41
+ return value;
42
+ };
@@ -19,11 +19,7 @@ var FormContext = exports.FormContext = /*#__PURE__*/(0, _react.createContext)({
19
19
  return {};
20
20
  },
21
21
  setFormErrorMessage: function setFormErrorMessage() {},
22
- enableEditView: undefined,
23
- setFormDirty: function setFormDirty() {},
24
- isFormDirty: function isFormDirty() {
25
- return false;
26
- }
22
+ enableEditView: undefined
27
23
  });
28
24
  var FormContextProvider = exports.FormContextProvider = function FormContextProvider(_ref) {
29
25
  var enableEditView = _ref.enableEditView,
@@ -36,13 +32,6 @@ var FormContextProvider = exports.FormContextProvider = function FormContextProv
36
32
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
37
33
  validators = _useState4[0],
38
34
  setValidators = _useState4[1];
39
- var dirty = (0, _react.useRef)(false);
40
- var isFormDirty = (0, _react.useCallback)(function () {
41
- return dirty.current;
42
- }, [dirty]);
43
- var setFormDirty = (0, _react.useCallback)(function (isDirty) {
44
- dirty.current = !!isDirty;
45
- }, [dirty]);
46
35
 
47
36
  // Add validators to the form
48
37
  var assignValidator = (0, _react.useCallback)(function (name, fieldValidators) {
@@ -66,9 +55,7 @@ var FormContextProvider = exports.FormContextProvider = function FormContextProv
66
55
  getValidators: getValidators,
67
56
  setFormErrorMessage: setFormErrorMessage,
68
57
  formErrorMessage: error,
69
- enableEditView: enableEditView,
70
- setFormDirty: setFormDirty,
71
- isFormDirty: isFormDirty
58
+ enableEditView: enableEditView
72
59
  }
73
60
  }, children);
74
61
  };
@@ -17,6 +17,7 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
17
17
  var _primitives = require("@atlaskit/primitives");
18
18
  var _constants = require("../../common/constants");
19
19
  var _analytics = _interopRequireDefault(require("../../common/utils/analytics/analytics.codegen"));
20
+ var _exitWarningModalContext = require("../../controllers/exit-warning-modal-context");
20
21
  var _formContext = require("../../controllers/form-context");
21
22
  var _formFooter = require("./form-footer");
22
23
  var _formLoader = require("./form-loader");
@@ -45,8 +46,9 @@ var CreateForm = exports.CreateForm = function CreateForm(_ref) {
45
46
  var _useFormContext = (0, _formContext.useFormContext)(),
46
47
  getValidators = _useFormContext.getValidators,
47
48
  formErrorMessage = _useFormContext.formErrorMessage,
48
- setFormDirty = _useFormContext.setFormDirty,
49
49
  enableEditView = _useFormContext.enableEditView;
50
+ var _useExitWarningModal = (0, _exitWarningModalContext.useExitWarningModal)(),
51
+ setShouldShowWarning = _useExitWarningModal.setShouldShowWarning;
50
52
  var handleSubmit = (0, _react.useCallback)( /*#__PURE__*/function () {
51
53
  var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(data) {
52
54
  var validators, errors, shouldEnableEditView, formData;
@@ -119,7 +121,7 @@ var CreateForm = exports.CreateForm = function CreateForm(_ref) {
119
121
  dirty: true
120
122
  },
121
123
  onChange: function onChange(state) {
122
- return setFormDirty(state.dirty);
124
+ return setShouldShowWarning(state.dirty);
123
125
  }
124
126
  }), (0, _react2.jsx)(_primitives.Box, null, children), !hideFooter && (0, _react2.jsx)(_formFooter.CreateFormFooter, {
125
127
  formErrorMessage: formErrorMessage,
@@ -12,6 +12,7 @@ var _analyticsNext = require("@atlaskit/analytics-next");
12
12
  var _modalDialog = _interopRequireWildcard(require("@atlaskit/modal-dialog"));
13
13
  var _Button = require("../../../common/ui/Button");
14
14
  var _components = require("../../../common/utils/analytics/components");
15
+ var _callbackContext = require("../../../controllers/callback-context");
15
16
  var _messages = _interopRequireDefault(require("./messages"));
16
17
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
18
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -22,9 +23,17 @@ var context = {
22
23
  };
23
24
  var ConfirmDismissDialog = exports.ConfirmDismissDialog = function ConfirmDismissDialog(_ref) {
24
25
  var active = _ref.active,
25
- onCancelDismiss = _ref.onCancelDismiss,
26
- onConfirmDismiss = _ref.onConfirmDismiss;
26
+ onClose = _ref.onClose;
27
27
  var intl = (0, _reactIntlNext.useIntl)();
28
+ var _useLinkCreateCallbac = (0, _callbackContext.useLinkCreateCallback)(),
29
+ onCancel = _useLinkCreateCallbac.onCancel;
30
+ var onCancelDismiss = function onCancelDismiss() {
31
+ return onClose();
32
+ };
33
+ var onConfirmDismiss = function onConfirmDismiss() {
34
+ onClose();
35
+ onCancel === null || onCancel === void 0 || onCancel();
36
+ };
28
37
  return /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTransition, null, active && /*#__PURE__*/_react.default.createElement(_analyticsNext.AnalyticsContext, {
29
38
  data: context
30
39
  }, /*#__PURE__*/_react.default.createElement(_modalDialog.default, {
@@ -20,6 +20,7 @@ var _primitives = require("@atlaskit/primitives");
20
20
  var _constants = require("../../common/constants");
21
21
  var _callbackContext = require("../../controllers/callback-context");
22
22
  var _editPostCreateContext = require("../../controllers/edit-post-create-context");
23
+ var _exitWarningModalContext = require("../../controllers/exit-warning-modal-context");
23
24
  var _formContext = require("../../controllers/form-context");
24
25
  var _pluginContext = require("../../controllers/plugin-context");
25
26
  var _confirmDismissDialog = require("./confirm-dismiss-dialog");
@@ -27,8 +28,8 @@ var _editModal = require("./edit-modal");
27
28
  var _errorBoundary = require("./error-boundary");
28
29
  var _messages = require("./messages");
29
30
  var _trackMount = _interopRequireDefault(require("./track-mount"));
30
- var _excluded = ["testId", "onCreate", "onFailure", "onCancel", "triggeredFrom"],
31
- _excluded2 = ["active", "modalTitle", "onCancel", "onOpenComplete", "onCloseComplete"];
31
+ var _excluded = ["testId", "triggeredFrom"],
32
+ _excluded2 = ["active", "modalTitle", "onCreate", "onFailure", "onCancel", "onOpenComplete", "onCloseComplete"];
32
33
  /** @jsx jsx */
33
34
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
34
35
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -47,15 +48,26 @@ var LinkCreateContent = function LinkCreateContent(_ref) {
47
48
  var LinkCreate = function LinkCreate(_ref2) {
48
49
  var _ref2$testId = _ref2.testId,
49
50
  testId = _ref2$testId === void 0 ? TEST_ID : _ref2$testId,
50
- onCreate = _ref2.onCreate,
51
- onFailure = _ref2.onFailure,
52
- onCancel = _ref2.onCancel,
53
51
  triggeredFrom = _ref2.triggeredFrom,
54
52
  restProps = (0, _objectWithoutProperties2.default)(_ref2, _excluded);
53
+ return (0, _react2.jsx)(_primitives.Box, {
54
+ testId: testId
55
+ }, (0, _react2.jsx)(_errorBoundary.ErrorBoundary, null, (0, _react2.jsx)(_trackMount.default, null), (0, _react2.jsx)(LinkCreateContent, restProps)));
56
+ };
57
+ var LinkCreateWithModal = function LinkCreateWithModal(_ref3) {
58
+ var active = _ref3.active,
59
+ modalTitle = _ref3.modalTitle,
60
+ onCreate = _ref3.onCreate,
61
+ onFailure = _ref3.onFailure,
62
+ onCancel = _ref3.onCancel,
63
+ onOpenComplete = _ref3.onOpenComplete,
64
+ onCloseComplete = _ref3.onCloseComplete,
65
+ createProps = (0, _objectWithoutProperties2.default)(_ref3, _excluded2);
66
+ var intl = (0, _reactIntlNext.useIntl)();
55
67
  var _useFormContext = (0, _formContext.useFormContext)(),
56
68
  setFormErrorMessage = _useFormContext.setFormErrorMessage;
57
69
  var handleCreate = (0, _react.useCallback)( /*#__PURE__*/function () {
58
- var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(result) {
70
+ var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(result) {
59
71
  return _regenerator.default.wrap(function _callee$(_context) {
60
72
  while (1) switch (_context.prev = _context.next) {
61
73
  case 0:
@@ -74,7 +86,7 @@ var LinkCreate = function LinkCreate(_ref2) {
74
86
  }, _callee);
75
87
  }));
76
88
  return function (_x) {
77
- return _ref3.apply(this, arguments);
89
+ return _ref4.apply(this, arguments);
78
90
  };
79
91
  }(), [onCreate, setFormErrorMessage]);
80
92
  var handleFailure = (0, _react.useCallback)(function (error) {
@@ -82,63 +94,56 @@ var LinkCreate = function LinkCreate(_ref2) {
82
94
  setFormErrorMessage(error.message);
83
95
  onFailure && onFailure(error);
84
96
  }, [onFailure, setFormErrorMessage]);
85
- return (0, _react2.jsx)(_primitives.Box, {
86
- testId: testId
87
- }, (0, _react2.jsx)(_errorBoundary.ErrorBoundary, null, (0, _react2.jsx)(_callbackContext.LinkCreateCallbackProvider, {
88
- onCancel: onCancel,
89
- onCreate: handleCreate,
90
- onFailure: handleFailure
91
- }, (0, _react2.jsx)(_trackMount.default, null), (0, _react2.jsx)(LinkCreateContent, restProps))));
92
- };
93
- var LinkCreateWithModal = function LinkCreateWithModal(_ref4) {
94
- var active = _ref4.active,
95
- modalTitle = _ref4.modalTitle,
96
- onCancel = _ref4.onCancel,
97
- onOpenComplete = _ref4.onOpenComplete,
98
- onCloseComplete = _ref4.onCloseComplete,
99
- createProps = (0, _objectWithoutProperties2.default)(_ref4, _excluded2);
97
+ var _useExitWarningModal = (0, _exitWarningModalContext.useExitWarningModal)(),
98
+ getShouldShowWarning = _useExitWarningModal.getShouldShowWarning;
100
99
  var _useState = (0, _react.useState)(false),
101
100
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
102
- dismissDialog = _useState2[0],
103
- setDismissDialog = _useState2[1];
104
- var _useFormContext2 = (0, _formContext.useFormContext)(),
105
- isFormDirty = _useFormContext2.isFormDirty;
106
- var intl = (0, _reactIntlNext.useIntl)();
101
+ showExitWarning = _useState2[0],
102
+ setShowExitWarning = _useState2[1];
107
103
  var handleCancel = (0, _react.useCallback)(function () {
108
104
  if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.confirm-dismiss-dialog')) {
109
- if (isFormDirty()) {
110
- return setDismissDialog(true);
105
+ if (getShouldShowWarning() && !showExitWarning) {
106
+ setShowExitWarning(true);
107
+ return;
111
108
  }
112
109
  }
113
- onCancel && onCancel();
114
- }, [onCancel, isFormDirty]);
115
- var handleCancelDismiss = (0, _react.useCallback)(function () {
116
- setDismissDialog(false);
110
+ onCancel === null || onCancel === void 0 || onCancel();
111
+ }, [onCancel, getShouldShowWarning, showExitWarning]);
112
+ var handleCloseExitWarning = (0, _react.useCallback)(function () {
113
+ return setShowExitWarning(false);
117
114
  }, []);
118
- var handleConfirmDismiss = (0, _react.useCallback)(function () {
119
- setDismissDialog(false);
120
- onCancel && onCancel();
121
- }, [onCancel]);
122
- return (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(_modalDialog.ModalTransition, null, !!active && (0, _react2.jsx)(_modalDialog.default, {
115
+ return (0, _react2.jsx)(_callbackContext.LinkCreateCallbackProvider, {
116
+ onCreate: handleCreate,
117
+ onFailure: handleFailure,
118
+ onCancel: handleCancel
119
+ }, (0, _react2.jsx)(_modalDialog.ModalTransition, null, active && (0, _react2.jsx)(_modalDialog.default, {
123
120
  testId: "link-create-modal",
124
121
  onClose: handleCancel,
125
122
  shouldScrollInViewport: true,
126
123
  onOpenComplete: onOpenComplete,
127
124
  onCloseComplete: onCloseComplete,
128
125
  width: "".concat(_constants.CREATE_FORM_MAX_WIDTH_IN_PX, "px")
129
- }, (0, _react2.jsx)(_modalDialog.ModalHeader, null, (0, _react2.jsx)(_modalDialog.ModalTitle, null, modalTitle || intl.formatMessage(_messages.messages.heading))), (0, _react2.jsx)(_modalDialog.ModalBody, null, (0, _react2.jsx)(LinkCreate, (0, _extends2.default)({}, createProps, {
130
- onCancel: handleCancel
131
- }))))), (0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.enable-edit') && createProps.onComplete && (0, _react2.jsx)(_editModal.EditModal, {
126
+ }, (0, _react2.jsx)(_modalDialog.ModalHeader, null, (0, _react2.jsx)(_modalDialog.ModalTitle, null, modalTitle || intl.formatMessage(_messages.messages.heading))), (0, _react2.jsx)(_modalDialog.ModalBody, null, (0, _react2.jsx)(LinkCreate, createProps)))), (0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.enable-edit') && createProps.onComplete && (0, _react2.jsx)(_editModal.EditModal, {
132
127
  onCloseComplete: onCloseComplete,
133
128
  onClose: createProps.onComplete
134
129
  }), (0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.confirm-dismiss-dialog') && (0, _react2.jsx)(_confirmDismissDialog.ConfirmDismissDialog, {
135
- active: dismissDialog,
136
- onCancelDismiss: handleCancelDismiss,
137
- onConfirmDismiss: handleConfirmDismiss
130
+ active: showExitWarning,
131
+ onClose: handleCloseExitWarning
138
132
  }));
139
133
  };
140
134
  var LinkCreateModal = function LinkCreateModal(props) {
141
135
  if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.enable-edit')) {
136
+ // eslint-disable-next-line react-hooks/rules-of-hooks
137
+ var shouldCallCloseComplete = (0, _react.useRef)(!props.active);
138
+
139
+ // modal calls onCloseComplete in a useEffect(), so we can track whether
140
+ // or not we should execute it based on the active prop in a
141
+ // useLayoutEffect() which will be run before child useEffect()s
142
+ // eslint-disable-next-line react-hooks/rules-of-hooks
143
+ (0, _react.useLayoutEffect)(function () {
144
+ // onCloseComplete should only be called when it is not active
145
+ shouldCallCloseComplete.current = !props.active;
146
+ }, [props.active]);
142
147
  return (0, _react2.jsx)(_pluginContext.LinkCreatePluginsProvider, {
143
148
  plugins: props.plugins,
144
149
  entityKey: props.entityKey
@@ -153,7 +158,7 @@ var LinkCreateModal = function LinkCreateModal(props) {
153
158
  enableEditView = _ref5.enableEditView;
154
159
  return (0, _react2.jsx)(_formContext.FormContextProvider, {
155
160
  enableEditView: pluginsProvider !== null && pluginsProvider !== void 0 && (_pluginsProvider$acti = pluginsProvider.activePlugin) !== null && _pluginsProvider$acti !== void 0 && _pluginsProvider$acti.editView && props !== null && props !== void 0 && props.onComplete ? enableEditView : undefined
156
- }, (0, _react2.jsx)(LinkCreateWithModal, (0, _extends2.default)({}, props, {
161
+ }, (0, _react2.jsx)(_exitWarningModalContext.ExitWarningModalProvider, null, (0, _react2.jsx)(LinkCreateWithModal, (0, _extends2.default)({}, props, {
157
162
  active: props.active && !editViewPayload,
158
163
  onCreate: /*#__PURE__*/function () {
159
164
  var _ref6 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(payload) {
@@ -183,12 +188,21 @@ var LinkCreateModal = function LinkCreateModal(props) {
183
188
  return function (_x2) {
184
189
  return _ref6.apply(this, arguments);
185
190
  };
186
- }()
187
- })));
191
+ }(),
192
+ onCloseComplete: function onCloseComplete() {
193
+ if (shouldCallCloseComplete.current) {
194
+ var _props$onCloseComplet;
195
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
196
+ args[_key] = arguments[_key];
197
+ }
198
+ (_props$onCloseComplet = props.onCloseComplete) === null || _props$onCloseComplet === void 0 || _props$onCloseComplet.call.apply(_props$onCloseComplet, [props].concat(args));
199
+ }
200
+ }
201
+ }))));
188
202
  });
189
203
  });
190
204
  }
191
- return (0, _react2.jsx)(_formContext.FormContextProvider, null, (0, _react2.jsx)(LinkCreateWithModal, (0, _extends2.default)({}, props, {
205
+ return (0, _react2.jsx)(_formContext.FormContextProvider, null, (0, _react2.jsx)(_exitWarningModalContext.ExitWarningModalProvider, null, (0, _react2.jsx)(LinkCreateWithModal, (0, _extends2.default)({}, props, {
192
206
  onCreate: /*#__PURE__*/function () {
193
207
  var _ref7 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(payload) {
194
208
  var _props$onCreate2, _props$onComplete;
@@ -209,6 +223,6 @@ var LinkCreateModal = function LinkCreateModal(props) {
209
223
  return _ref7.apply(this, arguments);
210
224
  };
211
225
  }()
212
- })));
226
+ }))));
213
227
  };
214
228
  var _default = exports.default = LinkCreateModal;
@@ -35,7 +35,7 @@ var LinkCreateWithAnalyticsContext = (0, _analytics.withLinkCreateAnalyticsConte
35
35
  }));
36
36
  var PACKAGE_DATA = exports.PACKAGE_DATA = {
37
37
  packageName: "@atlaskit/link-create" || '',
38
- packageVersion: "1.8.0" || '',
38
+ packageVersion: "1.9.0" || '',
39
39
  componentName: _constants.COMPONENT_NAME,
40
40
  source: _constants.COMPONENT_NAME
41
41
  };
@@ -0,0 +1,28 @@
1
+ import React, { createContext, useCallback, useContext, useMemo, useRef } from 'react';
2
+ const ExitWarningModalContext = /*#__PURE__*/createContext({
3
+ getShouldShowWarning: () => false,
4
+ setShouldShowWarning: () => {}
5
+ });
6
+ export const ExitWarningModalProvider = ({
7
+ children
8
+ }) => {
9
+ const shouldShowWarning = useRef(false);
10
+ const getShouldShowWarning = useCallback(() => shouldShowWarning.current, []);
11
+ const setShouldShowWarning = useCallback(show => {
12
+ shouldShowWarning.current = show;
13
+ }, []);
14
+ const value = useMemo(() => ({
15
+ getShouldShowWarning,
16
+ setShouldShowWarning
17
+ }), [getShouldShowWarning, setShouldShowWarning]);
18
+ return /*#__PURE__*/React.createElement(ExitWarningModalContext.Provider, {
19
+ value: value
20
+ }, children);
21
+ };
22
+ export const useExitWarningModal = () => {
23
+ const value = useContext(ExitWarningModalContext);
24
+ if (!value) {
25
+ throw new Error('useExitWarningModal used outside of ExitWarningModalProvider');
26
+ }
27
+ return value;
28
+ };
@@ -1,11 +1,9 @@
1
- import React, { createContext, useCallback, useContext, useRef, useState } from 'react';
1
+ import React, { createContext, useCallback, useContext, useState } from 'react';
2
2
  export const FormContext = /*#__PURE__*/createContext({
3
3
  assignValidator: () => {},
4
4
  getValidators: () => ({}),
5
5
  setFormErrorMessage: () => {},
6
- enableEditView: undefined,
7
- setFormDirty: () => {},
8
- isFormDirty: () => false
6
+ enableEditView: undefined
9
7
  });
10
8
  const FormContextProvider = ({
11
9
  enableEditView,
@@ -13,13 +11,6 @@ const FormContextProvider = ({
13
11
  }) => {
14
12
  const [error, setError] = useState();
15
13
  const [validators, setValidators] = useState({});
16
- const dirty = useRef(false);
17
- const isFormDirty = useCallback(() => {
18
- return dirty.current;
19
- }, [dirty]);
20
- const setFormDirty = useCallback(isDirty => {
21
- dirty.current = !!isDirty;
22
- }, [dirty]);
23
14
 
24
15
  // Add validators to the form
25
16
  const assignValidator = useCallback((name, fieldValidators) => {
@@ -44,9 +35,7 @@ const FormContextProvider = ({
44
35
  getValidators,
45
36
  setFormErrorMessage,
46
37
  formErrorMessage: error,
47
- enableEditView,
48
- setFormDirty,
49
- isFormDirty
38
+ enableEditView
50
39
  }
51
40
  }, children);
52
41
  };
@@ -7,6 +7,7 @@ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
7
7
  import { Box } from '@atlaskit/primitives';
8
8
  import { ANALYTICS_CHANNEL, CREATE_FORM_MAX_WIDTH_IN_PX, LINK_CREATE_FORM_POST_CREATE_FIELD } from '../../common/constants';
9
9
  import createEventPayload from '../../common/utils/analytics/analytics.codegen';
10
+ import { useExitWarningModal } from '../../controllers/exit-warning-modal-context';
10
11
  import { useFormContext } from '../../controllers/form-context';
11
12
  import { CreateFormFooter } from './form-footer';
12
13
  import { CreateFormLoader } from './form-loader';
@@ -33,9 +34,11 @@ export const CreateForm = ({
33
34
  const {
34
35
  getValidators,
35
36
  formErrorMessage,
36
- setFormDirty,
37
37
  enableEditView
38
38
  } = useFormContext();
39
+ const {
40
+ setShouldShowWarning
41
+ } = useExitWarningModal();
39
42
  const handleSubmit = useCallback(async data => {
40
43
  createAnalyticsEvent(createEventPayload('ui.button.clicked.create', {})).fire(ANALYTICS_CHANNEL);
41
44
  const validators = getValidators();
@@ -90,7 +93,7 @@ export const CreateForm = ({
90
93
  subscription: {
91
94
  dirty: true
92
95
  },
93
- onChange: state => setFormDirty(state.dirty)
96
+ onChange: state => setShouldShowWarning(state.dirty)
94
97
  }), jsx(Box, null, children), !hideFooter && jsx(CreateFormFooter, {
95
98
  formErrorMessage: formErrorMessage,
96
99
  handleCancel: handleCancel,
@@ -4,6 +4,7 @@ import { AnalyticsContext } from '@atlaskit/analytics-next';
4
4
  import Modal, { ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
5
5
  import { Button } from '../../../common/ui/Button';
6
6
  import { ScreenViewedEvent } from '../../../common/utils/analytics/components';
7
+ import { useLinkCreateCallback } from '../../../controllers/callback-context';
7
8
  import messages from './messages';
8
9
  const screen = 'linkCreateExitWarningScreen';
9
10
  const context = {
@@ -12,10 +13,17 @@ const context = {
12
13
  };
13
14
  export const ConfirmDismissDialog = ({
14
15
  active,
15
- onCancelDismiss,
16
- onConfirmDismiss
16
+ onClose
17
17
  }) => {
18
18
  const intl = useIntl();
19
+ const {
20
+ onCancel
21
+ } = useLinkCreateCallback();
22
+ const onCancelDismiss = () => onClose();
23
+ const onConfirmDismiss = () => {
24
+ onClose();
25
+ onCancel === null || onCancel === void 0 ? void 0 : onCancel();
26
+ };
19
27
  return /*#__PURE__*/React.createElement(ModalTransition, null, active && /*#__PURE__*/React.createElement(AnalyticsContext, {
20
28
  data: context
21
29
  }, /*#__PURE__*/React.createElement(Modal, {
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  /** @jsx jsx */
3
- import { Fragment, useCallback, useState } from 'react';
3
+ import { Fragment, useCallback, useLayoutEffect, useRef, useState } from 'react';
4
4
  import { jsx } from '@emotion/react';
5
5
  import { useIntl } from 'react-intl-next';
6
6
  import Modal, { ModalBody, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
@@ -9,6 +9,7 @@ import { Box } from '@atlaskit/primitives';
9
9
  import { CREATE_FORM_MAX_WIDTH_IN_PX } from '../../common/constants';
10
10
  import { LinkCreateCallbackProvider } from '../../controllers/callback-context';
11
11
  import { EditPostCreateModalProvider } from '../../controllers/edit-post-create-context';
12
+ import { ExitWarningModalProvider, useExitWarningModal } from '../../controllers/exit-warning-modal-context';
12
13
  import { FormContextProvider, useFormContext } from '../../controllers/form-context';
13
14
  import { LinkCreatePluginsProvider } from '../../controllers/plugin-context';
14
15
  import { ConfirmDismissDialog } from './confirm-dismiss-dialog';
@@ -29,12 +30,24 @@ const LinkCreateContent = ({
29
30
  };
30
31
  const LinkCreate = ({
31
32
  testId = TEST_ID,
33
+ triggeredFrom,
34
+ ...restProps
35
+ }) => {
36
+ return jsx(Box, {
37
+ testId: testId
38
+ }, jsx(ErrorBoundary, null, jsx(TrackMount, null), jsx(LinkCreateContent, restProps)));
39
+ };
40
+ const LinkCreateWithModal = ({
41
+ active,
42
+ modalTitle,
32
43
  onCreate,
33
44
  onFailure,
34
45
  onCancel,
35
- triggeredFrom,
36
- ...restProps
46
+ onOpenComplete,
47
+ onCloseComplete,
48
+ ...createProps
37
49
  }) => {
50
+ const intl = useIntl();
38
51
  const {
39
52
  setFormErrorMessage
40
53
  } = useFormContext();
@@ -50,62 +63,52 @@ const LinkCreate = ({
50
63
  setFormErrorMessage(error.message);
51
64
  onFailure && onFailure(error);
52
65
  }, [onFailure, setFormErrorMessage]);
53
- return jsx(Box, {
54
- testId: testId
55
- }, jsx(ErrorBoundary, null, jsx(LinkCreateCallbackProvider, {
56
- onCancel: onCancel,
57
- onCreate: handleCreate,
58
- onFailure: handleFailure
59
- }, jsx(TrackMount, null), jsx(LinkCreateContent, restProps))));
60
- };
61
- const LinkCreateWithModal = ({
62
- active,
63
- modalTitle,
64
- onCancel,
65
- onOpenComplete,
66
- onCloseComplete,
67
- ...createProps
68
- }) => {
69
- const [dismissDialog, setDismissDialog] = useState(false);
70
66
  const {
71
- isFormDirty
72
- } = useFormContext();
73
- const intl = useIntl();
67
+ getShouldShowWarning
68
+ } = useExitWarningModal();
69
+ const [showExitWarning, setShowExitWarning] = useState(false);
74
70
  const handleCancel = useCallback(() => {
75
71
  if (getBooleanFF('platform.linking-platform.link-create.confirm-dismiss-dialog')) {
76
- if (isFormDirty()) {
77
- return setDismissDialog(true);
72
+ if (getShouldShowWarning() && !showExitWarning) {
73
+ setShowExitWarning(true);
74
+ return;
78
75
  }
79
76
  }
80
- onCancel && onCancel();
81
- }, [onCancel, isFormDirty]);
82
- const handleCancelDismiss = useCallback(() => {
83
- setDismissDialog(false);
84
- }, []);
85
- const handleConfirmDismiss = useCallback(() => {
86
- setDismissDialog(false);
87
- onCancel && onCancel();
88
- }, [onCancel]);
89
- return jsx(Fragment, null, jsx(ModalTransition, null, !!active && jsx(Modal, {
77
+ onCancel === null || onCancel === void 0 ? void 0 : onCancel();
78
+ }, [onCancel, getShouldShowWarning, showExitWarning]);
79
+ const handleCloseExitWarning = useCallback(() => setShowExitWarning(false), []);
80
+ return jsx(LinkCreateCallbackProvider, {
81
+ onCreate: handleCreate,
82
+ onFailure: handleFailure,
83
+ onCancel: handleCancel
84
+ }, jsx(ModalTransition, null, active && jsx(Modal, {
90
85
  testId: "link-create-modal",
91
86
  onClose: handleCancel,
92
87
  shouldScrollInViewport: true,
93
88
  onOpenComplete: onOpenComplete,
94
89
  onCloseComplete: onCloseComplete,
95
90
  width: `${CREATE_FORM_MAX_WIDTH_IN_PX}px`
96
- }, jsx(ModalHeader, null, jsx(ModalTitle, null, modalTitle || intl.formatMessage(messages.heading))), jsx(ModalBody, null, jsx(LinkCreate, _extends({}, createProps, {
97
- onCancel: handleCancel
98
- }))))), getBooleanFF('platform.linking-platform.link-create.enable-edit') && createProps.onComplete && jsx(EditModal, {
91
+ }, jsx(ModalHeader, null, jsx(ModalTitle, null, modalTitle || intl.formatMessage(messages.heading))), jsx(ModalBody, null, jsx(LinkCreate, createProps)))), getBooleanFF('platform.linking-platform.link-create.enable-edit') && createProps.onComplete && jsx(EditModal, {
99
92
  onCloseComplete: onCloseComplete,
100
93
  onClose: createProps.onComplete
101
94
  }), getBooleanFF('platform.linking-platform.link-create.confirm-dismiss-dialog') && jsx(ConfirmDismissDialog, {
102
- active: dismissDialog,
103
- onCancelDismiss: handleCancelDismiss,
104
- onConfirmDismiss: handleConfirmDismiss
95
+ active: showExitWarning,
96
+ onClose: handleCloseExitWarning
105
97
  }));
106
98
  };
107
99
  const LinkCreateModal = props => {
108
100
  if (getBooleanFF('platform.linking-platform.link-create.enable-edit')) {
101
+ // eslint-disable-next-line react-hooks/rules-of-hooks
102
+ const shouldCallCloseComplete = useRef(!props.active);
103
+
104
+ // modal calls onCloseComplete in a useEffect(), so we can track whether
105
+ // or not we should execute it based on the active prop in a
106
+ // useLayoutEffect() which will be run before child useEffect()s
107
+ // eslint-disable-next-line react-hooks/rules-of-hooks
108
+ useLayoutEffect(() => {
109
+ // onCloseComplete should only be called when it is not active
110
+ shouldCallCloseComplete.current = !props.active;
111
+ }, [props.active]);
109
112
  return jsx(LinkCreatePluginsProvider, {
110
113
  plugins: props.plugins,
111
114
  entityKey: props.entityKey
@@ -120,7 +123,7 @@ const LinkCreateModal = props => {
120
123
  var _pluginsProvider$acti;
121
124
  return jsx(FormContextProvider, {
122
125
  enableEditView: pluginsProvider !== null && pluginsProvider !== void 0 && (_pluginsProvider$acti = pluginsProvider.activePlugin) !== null && _pluginsProvider$acti !== void 0 && _pluginsProvider$acti.editView && props !== null && props !== void 0 && props.onComplete ? enableEditView : undefined
123
- }, jsx(LinkCreateWithModal, _extends({}, props, {
126
+ }, jsx(ExitWarningModalProvider, null, jsx(LinkCreateWithModal, _extends({}, props, {
124
127
  active: props.active && !editViewPayload,
125
128
  onCreate: async payload => {
126
129
  var _props$onCreate;
@@ -136,16 +139,22 @@ const LinkCreateModal = props => {
136
139
  props.onComplete();
137
140
  }
138
141
  }
142
+ },
143
+ onCloseComplete: (...args) => {
144
+ if (shouldCallCloseComplete.current) {
145
+ var _props$onCloseComplet;
146
+ (_props$onCloseComplet = props.onCloseComplete) === null || _props$onCloseComplet === void 0 ? void 0 : _props$onCloseComplet.call(props, ...args);
147
+ }
139
148
  }
140
- })));
149
+ }))));
141
150
  }));
142
151
  }
143
- return jsx(FormContextProvider, null, jsx(LinkCreateWithModal, _extends({}, props, {
152
+ return jsx(FormContextProvider, null, jsx(ExitWarningModalProvider, null, jsx(LinkCreateWithModal, _extends({}, props, {
144
153
  onCreate: async payload => {
145
154
  var _props$onCreate2, _props$onComplete;
146
155
  await ((_props$onCreate2 = props.onCreate) === null || _props$onCreate2 === void 0 ? void 0 : _props$onCreate2.call(props, payload));
147
156
  (_props$onComplete = props.onComplete) === null || _props$onComplete === void 0 ? void 0 : _props$onComplete.call(props);
148
157
  }
149
- })));
158
+ }))));
150
159
  };
151
160
  export default LinkCreateModal;
@@ -26,7 +26,7 @@ const LinkCreateWithAnalyticsContext = withLinkCreateAnalyticsContext( /*#__PURE
26
26
  }));
27
27
  export const PACKAGE_DATA = {
28
28
  packageName: "@atlaskit/link-create" || '',
29
- packageVersion: "1.8.0" || '',
29
+ packageVersion: "1.9.0" || '',
30
30
  componentName: COMPONENT_NAME,
31
31
  source: COMPONENT_NAME
32
32
  };
@@ -0,0 +1,33 @@
1
+ import React, { createContext, useCallback, useContext, useMemo, useRef } from 'react';
2
+ var ExitWarningModalContext = /*#__PURE__*/createContext({
3
+ getShouldShowWarning: function getShouldShowWarning() {
4
+ return false;
5
+ },
6
+ setShouldShowWarning: function setShouldShowWarning() {}
7
+ });
8
+ export var ExitWarningModalProvider = function ExitWarningModalProvider(_ref) {
9
+ var children = _ref.children;
10
+ var shouldShowWarning = useRef(false);
11
+ var getShouldShowWarning = useCallback(function () {
12
+ return shouldShowWarning.current;
13
+ }, []);
14
+ var setShouldShowWarning = useCallback(function (show) {
15
+ shouldShowWarning.current = show;
16
+ }, []);
17
+ var value = useMemo(function () {
18
+ return {
19
+ getShouldShowWarning: getShouldShowWarning,
20
+ setShouldShowWarning: setShouldShowWarning
21
+ };
22
+ }, [getShouldShowWarning, setShouldShowWarning]);
23
+ return /*#__PURE__*/React.createElement(ExitWarningModalContext.Provider, {
24
+ value: value
25
+ }, children);
26
+ };
27
+ export var useExitWarningModal = function useExitWarningModal() {
28
+ var value = useContext(ExitWarningModalContext);
29
+ if (!value) {
30
+ throw new Error('useExitWarningModal used outside of ExitWarningModalProvider');
31
+ }
32
+ return value;
33
+ };
@@ -2,18 +2,14 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  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; }
4
4
  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; }
5
- import React, { createContext, useCallback, useContext, useRef, useState } from 'react';
5
+ import React, { createContext, useCallback, useContext, useState } from 'react';
6
6
  export var FormContext = /*#__PURE__*/createContext({
7
7
  assignValidator: function assignValidator() {},
8
8
  getValidators: function getValidators() {
9
9
  return {};
10
10
  },
11
11
  setFormErrorMessage: function setFormErrorMessage() {},
12
- enableEditView: undefined,
13
- setFormDirty: function setFormDirty() {},
14
- isFormDirty: function isFormDirty() {
15
- return false;
16
- }
12
+ enableEditView: undefined
17
13
  });
18
14
  var FormContextProvider = function FormContextProvider(_ref) {
19
15
  var enableEditView = _ref.enableEditView,
@@ -26,13 +22,6 @@ var FormContextProvider = function FormContextProvider(_ref) {
26
22
  _useState4 = _slicedToArray(_useState3, 2),
27
23
  validators = _useState4[0],
28
24
  setValidators = _useState4[1];
29
- var dirty = useRef(false);
30
- var isFormDirty = useCallback(function () {
31
- return dirty.current;
32
- }, [dirty]);
33
- var setFormDirty = useCallback(function (isDirty) {
34
- dirty.current = !!isDirty;
35
- }, [dirty]);
36
25
 
37
26
  // Add validators to the form
38
27
  var assignValidator = useCallback(function (name, fieldValidators) {
@@ -56,9 +45,7 @@ var FormContextProvider = function FormContextProvider(_ref) {
56
45
  getValidators: getValidators,
57
46
  setFormErrorMessage: setFormErrorMessage,
58
47
  formErrorMessage: error,
59
- enableEditView: enableEditView,
60
- setFormDirty: setFormDirty,
61
- isFormDirty: isFormDirty
48
+ enableEditView: enableEditView
62
49
  }
63
50
  }, children);
64
51
  };
@@ -14,6 +14,7 @@ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
14
14
  import { Box } from '@atlaskit/primitives';
15
15
  import { ANALYTICS_CHANNEL, CREATE_FORM_MAX_WIDTH_IN_PX, LINK_CREATE_FORM_POST_CREATE_FIELD } from '../../common/constants';
16
16
  import createEventPayload from '../../common/utils/analytics/analytics.codegen';
17
+ import { useExitWarningModal } from '../../controllers/exit-warning-modal-context';
17
18
  import { useFormContext } from '../../controllers/form-context';
18
19
  import { CreateFormFooter } from './form-footer';
19
20
  import { CreateFormLoader } from './form-loader';
@@ -39,8 +40,9 @@ export var CreateForm = function CreateForm(_ref) {
39
40
  var _useFormContext = useFormContext(),
40
41
  getValidators = _useFormContext.getValidators,
41
42
  formErrorMessage = _useFormContext.formErrorMessage,
42
- setFormDirty = _useFormContext.setFormDirty,
43
43
  enableEditView = _useFormContext.enableEditView;
44
+ var _useExitWarningModal = useExitWarningModal(),
45
+ setShouldShowWarning = _useExitWarningModal.setShouldShowWarning;
44
46
  var handleSubmit = useCallback( /*#__PURE__*/function () {
45
47
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(data) {
46
48
  var validators, errors, shouldEnableEditView, formData;
@@ -113,7 +115,7 @@ export var CreateForm = function CreateForm(_ref) {
113
115
  dirty: true
114
116
  },
115
117
  onChange: function onChange(state) {
116
- return setFormDirty(state.dirty);
118
+ return setShouldShowWarning(state.dirty);
117
119
  }
118
120
  }), jsx(Box, null, children), !hideFooter && jsx(CreateFormFooter, {
119
121
  formErrorMessage: formErrorMessage,
@@ -4,6 +4,7 @@ import { AnalyticsContext } from '@atlaskit/analytics-next';
4
4
  import Modal, { ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
5
5
  import { Button } from '../../../common/ui/Button';
6
6
  import { ScreenViewedEvent } from '../../../common/utils/analytics/components';
7
+ import { useLinkCreateCallback } from '../../../controllers/callback-context';
7
8
  import messages from './messages';
8
9
  var screen = 'linkCreateExitWarningScreen';
9
10
  var context = {
@@ -12,9 +13,17 @@ var context = {
12
13
  };
13
14
  export var ConfirmDismissDialog = function ConfirmDismissDialog(_ref) {
14
15
  var active = _ref.active,
15
- onCancelDismiss = _ref.onCancelDismiss,
16
- onConfirmDismiss = _ref.onConfirmDismiss;
16
+ onClose = _ref.onClose;
17
17
  var intl = useIntl();
18
+ var _useLinkCreateCallbac = useLinkCreateCallback(),
19
+ onCancel = _useLinkCreateCallbac.onCancel;
20
+ var onCancelDismiss = function onCancelDismiss() {
21
+ return onClose();
22
+ };
23
+ var onConfirmDismiss = function onConfirmDismiss() {
24
+ onClose();
25
+ onCancel === null || onCancel === void 0 || onCancel();
26
+ };
18
27
  return /*#__PURE__*/React.createElement(ModalTransition, null, active && /*#__PURE__*/React.createElement(AnalyticsContext, {
19
28
  data: context
20
29
  }, /*#__PURE__*/React.createElement(Modal, {
@@ -2,11 +2,11 @@ import _extends from "@babel/runtime/helpers/extends";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
4
4
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
5
- var _excluded = ["testId", "onCreate", "onFailure", "onCancel", "triggeredFrom"],
6
- _excluded2 = ["active", "modalTitle", "onCancel", "onOpenComplete", "onCloseComplete"];
5
+ var _excluded = ["testId", "triggeredFrom"],
6
+ _excluded2 = ["active", "modalTitle", "onCreate", "onFailure", "onCancel", "onOpenComplete", "onCloseComplete"];
7
7
  import _regeneratorRuntime from "@babel/runtime/regenerator";
8
8
  /** @jsx jsx */
9
- import { Fragment, useCallback, useState } from 'react';
9
+ import { Fragment, useCallback, useLayoutEffect, useRef, useState } from 'react';
10
10
  import { jsx } from '@emotion/react';
11
11
  import { useIntl } from 'react-intl-next';
12
12
  import Modal, { ModalBody, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
@@ -15,6 +15,7 @@ import { Box } from '@atlaskit/primitives';
15
15
  import { CREATE_FORM_MAX_WIDTH_IN_PX } from '../../common/constants';
16
16
  import { LinkCreateCallbackProvider } from '../../controllers/callback-context';
17
17
  import { EditPostCreateModalProvider } from '../../controllers/edit-post-create-context';
18
+ import { ExitWarningModalProvider, useExitWarningModal } from '../../controllers/exit-warning-modal-context';
18
19
  import { FormContextProvider, useFormContext } from '../../controllers/form-context';
19
20
  import { LinkCreatePluginsProvider } from '../../controllers/plugin-context';
20
21
  import { ConfirmDismissDialog } from './confirm-dismiss-dialog';
@@ -37,15 +38,26 @@ var LinkCreateContent = function LinkCreateContent(_ref) {
37
38
  var LinkCreate = function LinkCreate(_ref2) {
38
39
  var _ref2$testId = _ref2.testId,
39
40
  testId = _ref2$testId === void 0 ? TEST_ID : _ref2$testId,
40
- onCreate = _ref2.onCreate,
41
- onFailure = _ref2.onFailure,
42
- onCancel = _ref2.onCancel,
43
41
  triggeredFrom = _ref2.triggeredFrom,
44
42
  restProps = _objectWithoutProperties(_ref2, _excluded);
43
+ return jsx(Box, {
44
+ testId: testId
45
+ }, jsx(ErrorBoundary, null, jsx(TrackMount, null), jsx(LinkCreateContent, restProps)));
46
+ };
47
+ var LinkCreateWithModal = function LinkCreateWithModal(_ref3) {
48
+ var active = _ref3.active,
49
+ modalTitle = _ref3.modalTitle,
50
+ onCreate = _ref3.onCreate,
51
+ onFailure = _ref3.onFailure,
52
+ onCancel = _ref3.onCancel,
53
+ onOpenComplete = _ref3.onOpenComplete,
54
+ onCloseComplete = _ref3.onCloseComplete,
55
+ createProps = _objectWithoutProperties(_ref3, _excluded2);
56
+ var intl = useIntl();
45
57
  var _useFormContext = useFormContext(),
46
58
  setFormErrorMessage = _useFormContext.setFormErrorMessage;
47
59
  var handleCreate = useCallback( /*#__PURE__*/function () {
48
- var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(result) {
60
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(result) {
49
61
  return _regeneratorRuntime.wrap(function _callee$(_context) {
50
62
  while (1) switch (_context.prev = _context.next) {
51
63
  case 0:
@@ -64,7 +76,7 @@ var LinkCreate = function LinkCreate(_ref2) {
64
76
  }, _callee);
65
77
  }));
66
78
  return function (_x) {
67
- return _ref3.apply(this, arguments);
79
+ return _ref4.apply(this, arguments);
68
80
  };
69
81
  }(), [onCreate, setFormErrorMessage]);
70
82
  var handleFailure = useCallback(function (error) {
@@ -72,63 +84,56 @@ var LinkCreate = function LinkCreate(_ref2) {
72
84
  setFormErrorMessage(error.message);
73
85
  onFailure && onFailure(error);
74
86
  }, [onFailure, setFormErrorMessage]);
75
- return jsx(Box, {
76
- testId: testId
77
- }, jsx(ErrorBoundary, null, jsx(LinkCreateCallbackProvider, {
78
- onCancel: onCancel,
79
- onCreate: handleCreate,
80
- onFailure: handleFailure
81
- }, jsx(TrackMount, null), jsx(LinkCreateContent, restProps))));
82
- };
83
- var LinkCreateWithModal = function LinkCreateWithModal(_ref4) {
84
- var active = _ref4.active,
85
- modalTitle = _ref4.modalTitle,
86
- onCancel = _ref4.onCancel,
87
- onOpenComplete = _ref4.onOpenComplete,
88
- onCloseComplete = _ref4.onCloseComplete,
89
- createProps = _objectWithoutProperties(_ref4, _excluded2);
87
+ var _useExitWarningModal = useExitWarningModal(),
88
+ getShouldShowWarning = _useExitWarningModal.getShouldShowWarning;
90
89
  var _useState = useState(false),
91
90
  _useState2 = _slicedToArray(_useState, 2),
92
- dismissDialog = _useState2[0],
93
- setDismissDialog = _useState2[1];
94
- var _useFormContext2 = useFormContext(),
95
- isFormDirty = _useFormContext2.isFormDirty;
96
- var intl = useIntl();
91
+ showExitWarning = _useState2[0],
92
+ setShowExitWarning = _useState2[1];
97
93
  var handleCancel = useCallback(function () {
98
94
  if (getBooleanFF('platform.linking-platform.link-create.confirm-dismiss-dialog')) {
99
- if (isFormDirty()) {
100
- return setDismissDialog(true);
95
+ if (getShouldShowWarning() && !showExitWarning) {
96
+ setShowExitWarning(true);
97
+ return;
101
98
  }
102
99
  }
103
- onCancel && onCancel();
104
- }, [onCancel, isFormDirty]);
105
- var handleCancelDismiss = useCallback(function () {
106
- setDismissDialog(false);
100
+ onCancel === null || onCancel === void 0 || onCancel();
101
+ }, [onCancel, getShouldShowWarning, showExitWarning]);
102
+ var handleCloseExitWarning = useCallback(function () {
103
+ return setShowExitWarning(false);
107
104
  }, []);
108
- var handleConfirmDismiss = useCallback(function () {
109
- setDismissDialog(false);
110
- onCancel && onCancel();
111
- }, [onCancel]);
112
- return jsx(Fragment, null, jsx(ModalTransition, null, !!active && jsx(Modal, {
105
+ return jsx(LinkCreateCallbackProvider, {
106
+ onCreate: handleCreate,
107
+ onFailure: handleFailure,
108
+ onCancel: handleCancel
109
+ }, jsx(ModalTransition, null, active && jsx(Modal, {
113
110
  testId: "link-create-modal",
114
111
  onClose: handleCancel,
115
112
  shouldScrollInViewport: true,
116
113
  onOpenComplete: onOpenComplete,
117
114
  onCloseComplete: onCloseComplete,
118
115
  width: "".concat(CREATE_FORM_MAX_WIDTH_IN_PX, "px")
119
- }, jsx(ModalHeader, null, jsx(ModalTitle, null, modalTitle || intl.formatMessage(messages.heading))), jsx(ModalBody, null, jsx(LinkCreate, _extends({}, createProps, {
120
- onCancel: handleCancel
121
- }))))), getBooleanFF('platform.linking-platform.link-create.enable-edit') && createProps.onComplete && jsx(EditModal, {
116
+ }, jsx(ModalHeader, null, jsx(ModalTitle, null, modalTitle || intl.formatMessage(messages.heading))), jsx(ModalBody, null, jsx(LinkCreate, createProps)))), getBooleanFF('platform.linking-platform.link-create.enable-edit') && createProps.onComplete && jsx(EditModal, {
122
117
  onCloseComplete: onCloseComplete,
123
118
  onClose: createProps.onComplete
124
119
  }), getBooleanFF('platform.linking-platform.link-create.confirm-dismiss-dialog') && jsx(ConfirmDismissDialog, {
125
- active: dismissDialog,
126
- onCancelDismiss: handleCancelDismiss,
127
- onConfirmDismiss: handleConfirmDismiss
120
+ active: showExitWarning,
121
+ onClose: handleCloseExitWarning
128
122
  }));
129
123
  };
130
124
  var LinkCreateModal = function LinkCreateModal(props) {
131
125
  if (getBooleanFF('platform.linking-platform.link-create.enable-edit')) {
126
+ // eslint-disable-next-line react-hooks/rules-of-hooks
127
+ var shouldCallCloseComplete = useRef(!props.active);
128
+
129
+ // modal calls onCloseComplete in a useEffect(), so we can track whether
130
+ // or not we should execute it based on the active prop in a
131
+ // useLayoutEffect() which will be run before child useEffect()s
132
+ // eslint-disable-next-line react-hooks/rules-of-hooks
133
+ useLayoutEffect(function () {
134
+ // onCloseComplete should only be called when it is not active
135
+ shouldCallCloseComplete.current = !props.active;
136
+ }, [props.active]);
132
137
  return jsx(LinkCreatePluginsProvider, {
133
138
  plugins: props.plugins,
134
139
  entityKey: props.entityKey
@@ -143,7 +148,7 @@ var LinkCreateModal = function LinkCreateModal(props) {
143
148
  enableEditView = _ref5.enableEditView;
144
149
  return jsx(FormContextProvider, {
145
150
  enableEditView: pluginsProvider !== null && pluginsProvider !== void 0 && (_pluginsProvider$acti = pluginsProvider.activePlugin) !== null && _pluginsProvider$acti !== void 0 && _pluginsProvider$acti.editView && props !== null && props !== void 0 && props.onComplete ? enableEditView : undefined
146
- }, jsx(LinkCreateWithModal, _extends({}, props, {
151
+ }, jsx(ExitWarningModalProvider, null, jsx(LinkCreateWithModal, _extends({}, props, {
147
152
  active: props.active && !editViewPayload,
148
153
  onCreate: /*#__PURE__*/function () {
149
154
  var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(payload) {
@@ -173,12 +178,21 @@ var LinkCreateModal = function LinkCreateModal(props) {
173
178
  return function (_x2) {
174
179
  return _ref6.apply(this, arguments);
175
180
  };
176
- }()
177
- })));
181
+ }(),
182
+ onCloseComplete: function onCloseComplete() {
183
+ if (shouldCallCloseComplete.current) {
184
+ var _props$onCloseComplet;
185
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
186
+ args[_key] = arguments[_key];
187
+ }
188
+ (_props$onCloseComplet = props.onCloseComplete) === null || _props$onCloseComplet === void 0 || _props$onCloseComplet.call.apply(_props$onCloseComplet, [props].concat(args));
189
+ }
190
+ }
191
+ }))));
178
192
  });
179
193
  });
180
194
  }
181
- return jsx(FormContextProvider, null, jsx(LinkCreateWithModal, _extends({}, props, {
195
+ return jsx(FormContextProvider, null, jsx(ExitWarningModalProvider, null, jsx(LinkCreateWithModal, _extends({}, props, {
182
196
  onCreate: /*#__PURE__*/function () {
183
197
  var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(payload) {
184
198
  var _props$onCreate2, _props$onComplete;
@@ -199,6 +213,6 @@ var LinkCreateModal = function LinkCreateModal(props) {
199
213
  return _ref7.apply(this, arguments);
200
214
  };
201
215
  }()
202
- })));
216
+ }))));
203
217
  };
204
218
  export default LinkCreateModal;
@@ -27,7 +27,7 @@ var LinkCreateWithAnalyticsContext = withLinkCreateAnalyticsContext( /*#__PURE__
27
27
  }));
28
28
  export var PACKAGE_DATA = {
29
29
  packageName: "@atlaskit/link-create" || '',
30
- packageVersion: "1.8.0" || '',
30
+ packageVersion: "1.9.0" || '',
31
31
  componentName: COMPONENT_NAME,
32
32
  source: COMPONENT_NAME
33
33
  };
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ type ExitWarningModalContextValue = {
3
+ getShouldShowWarning: () => boolean;
4
+ setShouldShowWarning: (show: boolean) => void;
5
+ };
6
+ export declare const ExitWarningModalProvider: ({ children, }: {
7
+ children: React.ReactNode;
8
+ }) => JSX.Element;
9
+ export declare const useExitWarningModal: () => ExitWarningModalContextValue;
10
+ export {};
@@ -4,8 +4,6 @@ interface FormContextType {
4
4
  getValidators: () => ValidatorMap;
5
5
  assignValidator: (name: string, validators: Validator[]) => void;
6
6
  setFormErrorMessage: (errorMessage?: string) => void;
7
- setFormDirty: (dirty?: boolean) => void;
8
- isFormDirty: () => boolean;
9
7
  formErrorMessage?: string;
10
8
  /**
11
9
  * Callback that updates link create to tell it that it should/should not open the current plugins
@@ -13,7 +11,6 @@ interface FormContextType {
13
11
  * is not defined as a prop at the `LinkCreate` props level
14
12
  */
15
13
  enableEditView?: ((editButtonClicked: boolean) => void) | undefined;
16
- formDirty?: boolean;
17
14
  }
18
15
  export declare const FormContext: React.Context<FormContextType>;
19
16
  declare const FormContextProvider: React.FC<{
@@ -1,7 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  export type ConfirmDismissDialogProps = {
3
3
  active: boolean;
4
- onCancelDismiss?: () => void;
5
- onConfirmDismiss?: () => void;
4
+ onClose: () => void;
6
5
  };
7
- export declare const ConfirmDismissDialog: ({ active, onCancelDismiss, onConfirmDismiss, }: ConfirmDismissDialogProps) => JSX.Element;
6
+ export declare const ConfirmDismissDialog: ({ active, onClose, }: ConfirmDismissDialogProps) => JSX.Element;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ type ExitWarningModalContextValue = {
3
+ getShouldShowWarning: () => boolean;
4
+ setShouldShowWarning: (show: boolean) => void;
5
+ };
6
+ export declare const ExitWarningModalProvider: ({ children, }: {
7
+ children: React.ReactNode;
8
+ }) => JSX.Element;
9
+ export declare const useExitWarningModal: () => ExitWarningModalContextValue;
10
+ export {};
@@ -4,8 +4,6 @@ interface FormContextType {
4
4
  getValidators: () => ValidatorMap;
5
5
  assignValidator: (name: string, validators: Validator[]) => void;
6
6
  setFormErrorMessage: (errorMessage?: string) => void;
7
- setFormDirty: (dirty?: boolean) => void;
8
- isFormDirty: () => boolean;
9
7
  formErrorMessage?: string;
10
8
  /**
11
9
  * Callback that updates link create to tell it that it should/should not open the current plugins
@@ -13,7 +11,6 @@ interface FormContextType {
13
11
  * is not defined as a prop at the `LinkCreate` props level
14
12
  */
15
13
  enableEditView?: ((editButtonClicked: boolean) => void) | undefined;
16
- formDirty?: boolean;
17
14
  }
18
15
  export declare const FormContext: React.Context<FormContextType>;
19
16
  declare const FormContextProvider: React.FC<{
@@ -1,7 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  export type ConfirmDismissDialogProps = {
3
3
  active: boolean;
4
- onCancelDismiss?: () => void;
5
- onConfirmDismiss?: () => void;
4
+ onClose: () => void;
6
5
  };
7
- export declare const ConfirmDismissDialog: ({ active, onCancelDismiss, onConfirmDismiss, }: ConfirmDismissDialogProps) => JSX.Element;
6
+ export declare const ConfirmDismissDialog: ({ active, onClose, }: ConfirmDismissDialogProps) => JSX.Element;
@@ -1,4 +1,4 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useCallback, useMemo } from 'react';
2
2
 
3
3
  import {
4
4
  AsyncSelect,
@@ -41,12 +41,12 @@ export function MockPluginForm({ shouldThrowError }: pluginProps) {
41
41
  [],
42
42
  );
43
43
 
44
- const exampleOptions = [
45
- { label: 'Option 1', value: 'option-1' },
46
- { label: 'Option 2', value: 'option-2' },
47
- ];
44
+ const mockLoadOptions = useCallback(async () => {
45
+ const exampleOptions = [
46
+ { label: 'Option 1', value: 'option-1' },
47
+ { label: 'Option 2', value: 'option-2' },
48
+ ];
48
49
 
49
- const mockLoadOptions = async () => {
50
50
  try {
51
51
  if (shouldThrowError) {
52
52
  throw new Error('This is an error message.');
@@ -58,7 +58,7 @@ export function MockPluginForm({ shouldThrowError }: pluginProps) {
58
58
  }
59
59
  return [];
60
60
  }
61
- };
61
+ }, [onFailure, shouldThrowError]);
62
62
 
63
63
  return (
64
64
  <div>
@@ -82,7 +82,6 @@ export function MockPluginForm({ shouldThrowError }: pluginProps) {
82
82
  label={'Select an Option'}
83
83
  validators={[mockValidator]}
84
84
  defaultOptions={true}
85
- defaultOption={mockLoadOptions}
86
85
  loadOptions={mockLoadOptions}
87
86
  ></AsyncSelect>
88
87
  </CreateForm>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/link-create",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "The driver component of meta creation flow",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -35,12 +35,12 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@atlaskit/analytics-next": "^9.1.0",
38
- "@atlaskit/button": "^16.14.0",
38
+ "@atlaskit/button": "^16.15.0",
39
39
  "@atlaskit/empty-state": "^7.6.0",
40
40
  "@atlaskit/form": "^9.0.0",
41
41
  "@atlaskit/icon": "^21.12.0",
42
42
  "@atlaskit/intl-messages-provider": "^1.0.0",
43
- "@atlaskit/linking-common": "^4.17.0",
43
+ "@atlaskit/linking-common": "^4.18.0",
44
44
  "@atlaskit/modal-dialog": "^12.8.0",
45
45
  "@atlaskit/platform-feature-flags": "^0.2.1",
46
46
  "@atlaskit/primitives": "^1.10.0",