@atlassian/atlassian-connect-js 5.3.190

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 (190) hide show
  1. package/.depcheckrc.json +16 -0
  2. package/.editorconfig +9 -0
  3. package/.envrc +5 -0
  4. package/.eslintignore +12 -0
  5. package/.eslintrc +31 -0
  6. package/.husky/pre-commit +11 -0
  7. package/.lintstagedrc.js +6 -0
  8. package/.netrc +1 -0
  9. package/.npmrc-public +4 -0
  10. package/.nvmrc +1 -0
  11. package/LICENSE +3 -0
  12. package/README.md +281 -0
  13. package/bitbucket-pipelines.yml +33 -0
  14. package/build/bin/bin-helper.js +29 -0
  15. package/build/bin/npm-postinstall.js +9 -0
  16. package/build/configs/append-sourcemapping.js +13 -0
  17. package/build/configs/availabletasks.js +15 -0
  18. package/build/configs/clean.js +12 -0
  19. package/build/configs/concat.js +44 -0
  20. package/build/configs/copy.js +32 -0
  21. package/build/configs/index.js +19 -0
  22. package/build/configs/jshint.js +9 -0
  23. package/build/configs/karma.js +11 -0
  24. package/build/configs/replace.js +10 -0
  25. package/build/configs/requirejs.js +187 -0
  26. package/build/configs/saucelabs-launchers.js +30 -0
  27. package/build/configs/shell.js +24 -0
  28. package/build/configs/uglify.js +15 -0
  29. package/build/configs/watch.js +45 -0
  30. package/build/end.frag +13 -0
  31. package/build/start.frag +18 -0
  32. package/bundlesize.config.json +14 -0
  33. package/dist/connect-host.css +225 -0
  34. package/dist/connect-host.js +13908 -0
  35. package/dist/connect-host.min.css +1 -0
  36. package/dist/iframe-fedramp.js +13663 -0
  37. package/dist/iframe.js +13663 -0
  38. package/dist/legacy-text-colors.css +245 -0
  39. package/dist/surfaces.css +11 -0
  40. package/dist/themes/atlaskit-tokens_dark-future.css +6 -0
  41. package/dist/themes/atlaskit-tokens_dark.css +394 -0
  42. package/dist/themes/atlaskit-tokens_legacy-dark.css +394 -0
  43. package/dist/themes/atlaskit-tokens_legacy-light.css +394 -0
  44. package/dist/themes/atlaskit-tokens_light-future.css +6 -0
  45. package/dist/themes/atlaskit-tokens_light.css +394 -0
  46. package/dist/themes/atlaskit-tokens_shape.css +14 -0
  47. package/dist/themes/atlaskit-tokens_spacing.css +26 -0
  48. package/dist/themes/atlaskit-tokens_typography-adg3.css +25 -0
  49. package/dist/themes/atlaskit-tokens_typography-modernized.css +25 -0
  50. package/dist/themes/atlaskit-tokens_typography-refreshed.css +25 -0
  51. package/gulpfile.js +204 -0
  52. package/memleak-check/app.html +10 -0
  53. package/memleak-check/index.html +31 -0
  54. package/memleak-check/index.js +33 -0
  55. package/package.json +102 -0
  56. package/renovate.json +11 -0
  57. package/security-assistant.yml +2 -0
  58. package/spec/.eslintrc +10 -0
  59. package/spec/config/karma.base.conf.js +200 -0
  60. package/spec/config/karma.conf.js +20 -0
  61. package/spec/fixtures/base_dialog_component_tests.js +180 -0
  62. package/spec/mocks/mock_feature_flag.js +23 -0
  63. package/spec/tests/amd_spec.js +122 -0
  64. package/spec/tests/analytics_dispatcher_spec.js +429 -0
  65. package/spec/tests/analytics_performance_spec.js +41 -0
  66. package/spec/tests/button_spec.js +143 -0
  67. package/spec/tests/dialog_extension_spec.js +59 -0
  68. package/spec/tests/dialog_module_provider_spec.js +499 -0
  69. package/spec/tests/dialog_module_spec.js +395 -0
  70. package/spec/tests/dialog_spec.js +296 -0
  71. package/spec/tests/dialog_webitem_spec.js +183 -0
  72. package/spec/tests/dropdown_module_spec.js +77 -0
  73. package/spec/tests/env_module_spec.js +153 -0
  74. package/spec/tests/events_spec.js +77 -0
  75. package/spec/tests/extension_configuration_options_store_spec.js +25 -0
  76. package/spec/tests/flag_module_provider_spec.js +79 -0
  77. package/spec/tests/flag_module_spec.js +118 -0
  78. package/spec/tests/flag_spec.js +243 -0
  79. package/spec/tests/host-api_spec.js +220 -0
  80. package/spec/tests/iframe-create_spec.js +43 -0
  81. package/spec/tests/iframe_container_spec.js +19 -0
  82. package/spec/tests/iframe_spec.js +265 -0
  83. package/spec/tests/inline_dialog_spec.js +41 -0
  84. package/spec/tests/inline_dialog_webitem_spec.js +331 -0
  85. package/spec/tests/loading_indicator_spec.js +48 -0
  86. package/spec/tests/messages_module_spec.js +108 -0
  87. package/spec/tests/meta_spec.js +71 -0
  88. package/spec/tests/module_args_spec.js +52 -0
  89. package/spec/tests/observe_spec.js +73 -0
  90. package/spec/tests/public_events.spec.js +102 -0
  91. package/spec/tests/scroll_position_spec.js +109 -0
  92. package/spec/tests/theming_spec.js +594 -0
  93. package/spec/tests/util_spec.js +55 -0
  94. package/spec/tests/utils/base64_spec.js +20 -0
  95. package/spec/tests/utils/button_spec.js +11 -0
  96. package/spec/tests/utils/cookie_spec.js +19 -0
  97. package/spec/tests/utils/deprecate_spec.js +22 -0
  98. package/spec/tests/utils/dialog_spec.js +297 -0
  99. package/spec/tests/utils/host_util_spec.js +45 -0
  100. package/spec/tests/utils/iframe_spec.js +41 -0
  101. package/spec/tests/utils/jwt_spec.js +135 -0
  102. package/spec/tests/utils/url_spec.js +37 -0
  103. package/spec/tests/utils/waitUntilReadyNextTick.js +5 -0
  104. package/spec/tests/utils/webitem.js +219 -0
  105. package/spec/tests/webitem_spec.js +131 -0
  106. package/src/css/host/dialog.css +144 -0
  107. package/src/css/host/flags.css +5 -0
  108. package/src/css/host/host.css +64 -0
  109. package/src/css/host/messages.css +12 -0
  110. package/src/css/plugin/legacy-text-colors.less +55 -0
  111. package/src/css/plugin/surfaces.css +11 -0
  112. package/src/host/ACJSFrameworkAdaptor.js +44 -0
  113. package/src/host/actions/analytics_action.js +35 -0
  114. package/src/host/actions/button_actions.js +21 -0
  115. package/src/host/actions/dialog_actions.js +27 -0
  116. package/src/host/actions/dialog_extension_actions.js +25 -0
  117. package/src/host/actions/dom_event_actions.js +32 -0
  118. package/src/host/actions/dropdown_actions.js +12 -0
  119. package/src/host/actions/env_actions.js +57 -0
  120. package/src/host/actions/event_actions.js +33 -0
  121. package/src/host/actions/flag_actions.js +22 -0
  122. package/src/host/actions/iframe_actions.js +27 -0
  123. package/src/host/actions/inline_dialog_actions.js +26 -0
  124. package/src/host/actions/inline_dialog_webitem_actions.js +10 -0
  125. package/src/host/actions/jwt_actions.js +51 -0
  126. package/src/host/actions/loading_indicator_actions.js +10 -0
  127. package/src/host/actions/module_actions.js +14 -0
  128. package/src/host/actions/webitem_actions.js +29 -0
  129. package/src/host/components/button.js +112 -0
  130. package/src/host/components/dialog.js +447 -0
  131. package/src/host/components/dialog_extension.js +106 -0
  132. package/src/host/components/dialog_webitem.js +69 -0
  133. package/src/host/components/flag.js +102 -0
  134. package/src/host/components/iframe.js +130 -0
  135. package/src/host/components/iframe_container.js +38 -0
  136. package/src/host/components/inline_dialog.js +108 -0
  137. package/src/host/components/inline_dialog_webitem.js +157 -0
  138. package/src/host/components/loading_indicator.js +110 -0
  139. package/src/host/components/webitem.js +227 -0
  140. package/src/host/deprecate.js +20 -0
  141. package/src/host/dispatchers/analytics_dispatcher.js +512 -0
  142. package/src/host/dispatchers/event_dispatcher.js +46 -0
  143. package/src/host/dollar.js +8 -0
  144. package/src/host/host-api.js +325 -0
  145. package/src/host/iframe-create.js +7 -0
  146. package/src/host/index.js +108 -0
  147. package/src/host/module-providers.js +13 -0
  148. package/src/host/modules/_featureFlag.js +42 -0
  149. package/src/host/modules/_performance.js +54 -0
  150. package/src/host/modules/analytics.js +17 -0
  151. package/src/host/modules/dialog.js +496 -0
  152. package/src/host/modules/dropdown.js +255 -0
  153. package/src/host/modules/env.js +156 -0
  154. package/src/host/modules/events.js +28 -0
  155. package/src/host/modules/flag.js +170 -0
  156. package/src/host/modules/host.js +19 -0
  157. package/src/host/modules/inline-dialog.js +33 -0
  158. package/src/host/modules/messages.js +309 -0
  159. package/src/host/modules/page.js +29 -0
  160. package/src/host/modules/scroll-position.js +102 -0
  161. package/src/host/modules/theming.js +114 -0
  162. package/src/host/stores/extension_configuration_options_store.js +24 -0
  163. package/src/host/util.js +98 -0
  164. package/src/host/utils/access-narrowing-context.js +18 -0
  165. package/src/host/utils/base64.js +22 -0
  166. package/src/host/utils/button.js +10 -0
  167. package/src/host/utils/cookie.js +14 -0
  168. package/src/host/utils/dialog.js +239 -0
  169. package/src/host/utils/feature-flag.js +27 -0
  170. package/src/host/utils/iframe.js +23 -0
  171. package/src/host/utils/jwt.js +60 -0
  172. package/src/host/utils/observe.js +34 -0
  173. package/src/host/utils/removal-observer.js +30 -0
  174. package/src/host/utils/simplexdm.js +58 -0
  175. package/src/host/utils/url.js +23 -0
  176. package/src/host/utils/webitem.js +214 -0
  177. package/src/plugin/amd.js +115 -0
  178. package/src/plugin/analytics.js +84 -0
  179. package/src/plugin/deprecate.js +16 -0
  180. package/src/plugin/dialog.js +197 -0
  181. package/src/plugin/dollar.js +77 -0
  182. package/src/plugin/events-instance.js +2 -0
  183. package/src/plugin/events.js +246 -0
  184. package/src/plugin/extension_configuration_options_store.js +27 -0
  185. package/src/plugin/featureFlag.js +8 -0
  186. package/src/plugin/index.js +118 -0
  187. package/src/plugin/meta.js +14 -0
  188. package/src/plugin/public-events.js +73 -0
  189. package/src/plugin/theming.js +211 -0
  190. package/src/plugin/util.js +104 -0
@@ -0,0 +1,309 @@
1
+ /**
2
+ * Messages are the primary method for providing system feedback in the product user interface.
3
+ * Messages include notifications of various kinds: alerts, confirmations, notices, warnings, info and errors.
4
+ * For visual examples of each kind please see the [Design guide](https://docs.atlassian.com/aui/latest/docs/messages.html).
5
+ * ### Example ###
6
+ * ```
7
+ * //create a message
8
+ * var message = AP.messages.info('plain text title', 'plain text body');
9
+ * ```
10
+ * @deprecated after August 2017 | Please use the Flag module instead.
11
+ * @name Messages
12
+ * @module
13
+ * @ignore
14
+ */
15
+
16
+ import $ from '../dollar';
17
+ import HostApi from '../host-api';
18
+ import util from '../util';
19
+ import AnalyticsAction from '../actions/analytics_action';
20
+
21
+ const MESSAGE_BAR_ID = 'ac-message-container';
22
+ const MESSAGE_TYPES = ['generic', 'error', 'warning', 'success', 'info', 'hint'];
23
+ const MSGID_PREFIX = 'ap-message-';
24
+ const MSGID_REGEXP = new RegExp(`^${MSGID_PREFIX}[0-9A-fa-f]+$`);
25
+ const _messages = {};
26
+
27
+ function validateMessageId(msgId) {
28
+ return MSGID_REGEXP.test(msgId);
29
+ }
30
+
31
+ function getMessageBar() {
32
+ let $msgBar = $('#' + MESSAGE_BAR_ID);
33
+
34
+ if ($msgBar.length < 1) {
35
+ $msgBar = $('<div id="' + MESSAGE_BAR_ID + '" />').appendTo('body');
36
+ }
37
+ return $msgBar;
38
+ }
39
+
40
+ function filterMessageOptions(options) {
41
+ const copy = {};
42
+ const allowed = ['closeable', 'fadeout', 'delay', 'duration', 'id'];
43
+ if (typeof options === 'object') {
44
+ allowed.forEach(key => {
45
+ if (key in options) {
46
+ copy[key] = options[key];
47
+ }
48
+ });
49
+ }
50
+ return copy;
51
+ }
52
+
53
+ var messageCloseListenerCreated = false;
54
+
55
+ function showMessage(name, title, body, options) {
56
+ if(!messageCloseListenerCreated) {
57
+ createMessageCloseListener();
58
+ messageCloseListenerCreated = true;
59
+ }
60
+
61
+ const $msgBar = getMessageBar();
62
+ options = filterMessageOptions(options);
63
+ $.extend(options, {
64
+ title: title,
65
+ body: AJS.escapeHtml(body)
66
+ });
67
+
68
+ if (MESSAGE_TYPES.indexOf(name) < 0) {
69
+ throw 'Invalid message type. Must be: ' + MESSAGE_TYPES.join(', ');
70
+ }
71
+ if (validateMessageId(options.id)) {
72
+ AJS.messages[name]($msgBar, options);
73
+ // Calculate the left offset based on the content width.
74
+ // This ensures the message always stays in the centre of the window.
75
+ $msgBar.css('margin-left', '-' + $msgBar.innerWidth() / 2 + 'px');
76
+ }
77
+ }
78
+
79
+ function deprecatedShowMessage(name, title, body, options, callback) {
80
+ const methodUsed = `AP.messages.${name}`;
81
+ console.warn(`DEPRECATED API - AP.messages.${name} has been deprecated since ACJS 5.0 and will be removed in a future release. Use AP.flag.create instead.`);
82
+ AnalyticsAction.trackDeprecatedMethodUsed(methodUsed, callback._context.extension);
83
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
84
+ const messageProvider = frameworkAdaptor.getProviderByModuleName('messages');
85
+ if (messageProvider) {
86
+ const messageType = name;
87
+ let createMessage = messageProvider[messageType];
88
+ if (!createMessage) {
89
+ messageProvider[messageType] = messageProvider.generic;
90
+ }
91
+ createMessage(title, body, options);
92
+ } else {
93
+ showMessage(name, title, body, options);
94
+ }
95
+ }
96
+
97
+ function createMessageCloseListener(){
98
+ $(document).on('aui-message-close', function(e, $msg) {
99
+ const _id = $msg.attr('id').replace(MSGID_PREFIX, '');
100
+ if (_messages[_id]) {
101
+ if ($.isFunction(_messages[_id].onCloseTrigger)) {
102
+ _messages[_id].onCloseTrigger();
103
+ }
104
+ _messages[_id]._destroy();
105
+ }
106
+ });
107
+ }
108
+
109
+
110
+
111
+ function messageModule(messageType) {
112
+ return {
113
+ constructor: function(title, body, options, callback) {
114
+ callback = util.last(arguments);
115
+ const _id = callback._id;
116
+ if (typeof title !== 'string') {
117
+ title = '';
118
+ }
119
+ if (typeof body !== 'string') {
120
+ body = '';
121
+ }
122
+ if (typeof options !== 'object') {
123
+ options = {};
124
+ }
125
+ options.id = MSGID_PREFIX + _id;
126
+ deprecatedShowMessage(messageType, title, body, options, callback);
127
+ _messages[_id] = this;
128
+ }
129
+ };
130
+ }
131
+
132
+ export default {
133
+ /**
134
+ * Close a message
135
+ * @deprecated after August 2017 | Please use the Flag module instead.
136
+ * @name clear
137
+ * @method
138
+ * @memberof module:Messages#
139
+ * @param {String} id The id that was returned when the message was created.
140
+ * @example
141
+ * //create a message
142
+ * var message = AP.messages.info('title', 'body');
143
+ * setTimeout(function(){
144
+ * AP.messages.clear(message);
145
+ * }, 2000);
146
+ */
147
+ clear: function(msg) {
148
+ const id = MSGID_PREFIX + msg._id;
149
+ if (validateMessageId(id)) {
150
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
151
+ const messageProvider = frameworkAdaptor.getProviderByModuleName('messages');
152
+ if (messageProvider) {
153
+ messageProvider.clear(id);
154
+ } else {
155
+ $('#' + id).closeMessage();
156
+ }
157
+ }
158
+ },
159
+
160
+ /**
161
+ * Trigger an event when a message is closed
162
+ * @deprecated after August 2017 | Please use the Flag module instead.
163
+ * @name onClose
164
+ * @method
165
+ * @memberof module:Messages#
166
+ * @param {String} id The id that was returned when the message was created.
167
+ * @param {Function} callback The function that is run when the event is triggered
168
+ * @example
169
+ * //create a message
170
+ * var message = AP.messages.info('title', 'body');
171
+ * AP.messages.onClose(message, function() {
172
+ * console.log(message, ' has been closed!');
173
+ * });
174
+ */
175
+ onClose: function(msg, callback) {
176
+ callback = util.last(arguments);
177
+ const id = msg._id;
178
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
179
+ const messageProvider = frameworkAdaptor.getProviderByModuleName('messages');
180
+ if (messageProvider) {
181
+ const fullId = MSGID_PREFIX + msg._id;
182
+ messageProvider.onClose(fullId, callback);
183
+ } else {
184
+ if (_messages[id]) {
185
+ _messages[id].onCloseTrigger = callback;
186
+ }
187
+ }
188
+ },
189
+
190
+ /**
191
+ * Show a generic message
192
+ * @deprecated after August 2017 | Please use the Flag module instead.
193
+ * @name generic
194
+ * @method
195
+ * @memberof module:Messages#
196
+ * @param {String} title Sets the title text of the message.
197
+ * @param {String} body The main content of the message.
198
+ * @param {Object} options Message Options
199
+ * @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
200
+ * @param {Boolean} options.fadeout Toggles the fade away on the message
201
+ * @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
202
+ * @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
203
+ * @returns {String} The id to be used when clearing the message
204
+ * @example
205
+ * //create a message
206
+ * var message = AP.messages.generic('title', 'generic message example');
207
+ */
208
+ generic: messageModule('generic'),
209
+
210
+ /**
211
+ * Show an error message
212
+ * @deprecated after August 2017 | Please use the Flag module instead.
213
+ * @name error
214
+ * @method
215
+ * @memberof module:Messages#
216
+ * @param {String} title Sets the title text of the message.
217
+ * @param {String} body The main content of the message.
218
+ * @param {Object} options Message Options
219
+ * @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
220
+ * @param {Boolean} options.fadeout Toggles the fade away on the message
221
+ * @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
222
+ * @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
223
+ * @returns {String} The id to be used when clearing the message
224
+ * @example
225
+ * //create a message
226
+ * var message = AP.messages.error('title', 'error message example');
227
+ */
228
+ error: messageModule('error'),
229
+
230
+ /**
231
+ * Show a warning message
232
+ * @deprecated after August 2017 | Please use the Flag module instead.
233
+ * @name warning
234
+ * @method
235
+ * @memberof module:Messages#
236
+ * @param {String} title Sets the title text of the message.
237
+ * @param {String} body The main content of the message.
238
+ * @param {Object} options Message Options
239
+ * @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
240
+ * @param {Boolean} options.fadeout Toggles the fade away on the message
241
+ * @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
242
+ * @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
243
+ * @returns {String} The id to be used when clearing the message
244
+ * @example
245
+ * //create a message
246
+ * var message = AP.messages.warning('title', 'warning message example');
247
+ */
248
+ warning: messageModule('warning'),
249
+
250
+ /**
251
+ * Show a success message
252
+ * @deprecated after August 2017 | Please use the Flag module instead.
253
+ * @name success
254
+ * @method
255
+ * @memberof module:Messages#
256
+ * @param {String} title Sets the title text of the message.
257
+ * @param {String} body The main content of the message.
258
+ * @param {Object} options Message Options
259
+ * @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
260
+ * @param {Boolean} options.fadeout Toggles the fade away on the message
261
+ * @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
262
+ * @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
263
+ * @returns {String} The id to be used when clearing the message
264
+ * @example
265
+ * //create a message
266
+ * var message = AP.messages.success('title', 'success message example');
267
+ */
268
+ success: messageModule('success'),
269
+
270
+ /**
271
+ * Show an info message
272
+ * @deprecated after August 2017 | Please use the Flag module instead.
273
+ * @name info
274
+ * @method
275
+ * @memberof module:Messages#
276
+ * @param {String} title Sets the title text of the message.
277
+ * @param {String} body The main content of the message.
278
+ * @param {Object} options Message Options
279
+ * @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
280
+ * @param {Boolean} options.fadeout Toggles the fade away on the message
281
+ * @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
282
+ * @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
283
+ * @returns {String} The id to be used when clearing the message
284
+ * @example
285
+ * //create a message
286
+ * var message = AP.messages.info('title', 'info message example');
287
+ */
288
+ info: messageModule('info'),
289
+
290
+ /**
291
+ * Show a hint message
292
+ * @deprecated after August 2017 | Please use the Flag module instead.
293
+ * @name hint
294
+ * @method
295
+ * @memberof module:Messages#
296
+ * @param {String} title Sets the title text of the message.
297
+ * @param {String} body The main content of the message.
298
+ * @param {Object} options Message Options
299
+ * @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
300
+ * @param {Boolean} options.fadeout Toggles the fade away on the message
301
+ * @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
302
+ * @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
303
+ * @returns {String} The id to be used when clearing the message
304
+ * @example
305
+ * //create a message
306
+ * var message = AP.messages.hint('title', 'hint message example');
307
+ */
308
+ hint: messageModule('hint')
309
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A JavaScript module which provides functions for general page modules.
3
+ * @module Page
4
+ */
5
+ import util from '../util';
6
+
7
+ export default {
8
+ /**
9
+ * Sets the title of the document when a full page iframe is loaded.
10
+ * @memberOf module:Page
11
+ * @method setTitle
12
+ * @param {String} title the title of the document to be set.
13
+ * @example
14
+ * AP.page.setTitle(title)
15
+ */
16
+ setTitle: function (title, callback) {
17
+ callback = util.last(arguments);
18
+
19
+ if (
20
+ callback._context.extension.options &&
21
+ callback._context.extension.options.isFullPage
22
+ ) {
23
+ const productSuffix =
24
+ ' - ' + util.guessProductFromModuleDefined(window.connectHost);
25
+
26
+ document.title = title + productSuffix;
27
+ }
28
+ },
29
+ };
@@ -0,0 +1,102 @@
1
+ import util from '../util';
2
+ import $ from '../dollar';
3
+ import EventDispatcher from '../dispatchers/event_dispatcher';
4
+ import EventActions from '../actions/event_actions';
5
+
6
+
7
+ const TRIGGER_PERCENTAGE = 10; //% before scroll events are fired
8
+ let activeGeneralPageAddon;
9
+ let lastScrollEventTriggered; //top or bottom
10
+
11
+ EventDispatcher.register('iframe-bridge-established', function(data) {
12
+ if(data.extension.options.isFullPage) {
13
+ window.addEventListener('scroll', scrollEventHandler);
14
+ activeGeneralPageAddon = data.extension.id;
15
+ }
16
+ });
17
+
18
+ EventDispatcher.register('iframe-destroyed', function(extension) {
19
+ removeScrollEvent();
20
+ });
21
+
22
+ EventDispatcher.register('iframe-unload', function(extension) {
23
+ removeScrollEvent();
24
+ });
25
+
26
+ function removeScrollEvent(){
27
+ window.removeEventListener('scroll', scrollEventHandler);
28
+ activeGeneralPageAddon = undefined;
29
+ lastScrollEventTriggered = undefined;
30
+ }
31
+
32
+ function scrollEventHandler(){
33
+ var documentHeight = document.documentElement.scrollHeight;
34
+ var windowHeight = window.innerHeight;
35
+
36
+ var boundary = documentHeight * (TRIGGER_PERCENTAGE/100);
37
+ if(window.pageYOffset <= boundary) {
38
+ triggerEvent('nearTop');
39
+ } else if((windowHeight + window.pageYOffset + boundary) >= documentHeight) {
40
+ triggerEvent('nearBottom');
41
+ } else {
42
+ lastScrollEventTriggered = undefined;
43
+ }
44
+ }
45
+
46
+ function triggerEvent(type) {
47
+ if(lastScrollEventTriggered === type) {
48
+ return; // only once per scroll.
49
+ }
50
+ EventActions.broadcast('scroll.' + type, {id: activeGeneralPageAddon}, {});
51
+ lastScrollEventTriggered = type;
52
+ }
53
+
54
+ /**
55
+ * Enables apps to get and set the scroll position.
56
+ * @exports Scroll-position
57
+ */
58
+ export default {
59
+ /**
60
+ * Gets the scroll position relative to the browser viewport
61
+ *
62
+ * @param callback {Function} callback to pass the scroll position
63
+ * @noDemo
64
+ * @example
65
+ * AP.scrollPosition.getPosition(function(obj) { console.log(obj); });
66
+ */
67
+ getPosition: function (callback) {
68
+ callback = util.last(arguments);
69
+ // scrollPosition.getPosition is only available for general-pages
70
+ if (callback._context.extension.options.isFullPage) {
71
+ var $el = util.getIframeByExtensionId(callback._context.extension_id);
72
+ var offset = $el.offset();
73
+ var $window = $(window);
74
+
75
+ callback({
76
+ scrollY: $window.scrollTop() - offset.top,
77
+ scrollX: $window.scrollLeft() - offset.left,
78
+ width: window.innerWidth,
79
+ height: window.innerHeight
80
+ });
81
+ }
82
+ },
83
+ /**
84
+ * Sets the vertical scroll position relative to the iframe
85
+ *
86
+ * @param y {Number} vertical offset position
87
+ * @param callback {Function} callback to pass the scroll position
88
+ * @noDemo
89
+ * @example
90
+ * AP.scrollPosition.setVerticalPosition(30, function(obj) { console.log(obj); });
91
+ */
92
+ setVerticalPosition: function(y, callback) {
93
+ callback = util.last(arguments);
94
+ if (callback._context.extension.options && callback._context.extension.options.isFullPage) {
95
+ var $el = util.getIframeByExtensionId(callback._context.extension_id);
96
+ var offset = $el.offset();
97
+ if(typeof y === 'number') {
98
+ document.documentElement.scrollTop = offset.top + y;
99
+ }
100
+ }
101
+ }
102
+ };
@@ -0,0 +1,114 @@
1
+ import simpleXDM from 'simple-xdm/host';
2
+ import { getGlobalTheme, ThemeMutationObserver, CURRENT_SURFACE_CSS_VAR } from '@atlaskit/tokens';
3
+
4
+ import util from '../util';
5
+
6
+
7
+ const getPluginFeatureFlags = () => ({
8
+ // Add feature flags sent to the plugin on theming bootstrap here
9
+ })
10
+
11
+ const getSurfaceValue = (extension_id) => {
12
+ const iframe = document.getElementById(extension_id);
13
+ if (!iframe) {
14
+ return;
15
+ }
16
+
17
+ const styles = getComputedStyle(iframe);
18
+ const currentSurface = styles.getPropertyValue(CURRENT_SURFACE_CSS_VAR);
19
+ const raised = styles.getPropertyValue('--ds-surface-raised');
20
+ const overlay = styles.getPropertyValue('--ds-surface-overlay');
21
+
22
+ if (currentSurface === raised) {
23
+ return 'raised';
24
+ }
25
+
26
+ if (currentSurface === overlay) {
27
+ return 'overlay';
28
+ }
29
+ };
30
+
31
+ /**
32
+ * Broadcasts the new theme to all plugins.
33
+ * @typedef {import("@atlaskit/tokens").ThemeState} ThemeState
34
+ * @param newTheme {ThemeState}
35
+ */
36
+ function broadcastThemeChange(newTheme) {
37
+ const featureFlags = getPluginFeatureFlags();
38
+ if (ThemingModuleState.extensionIds.length) {
39
+ ThemingModuleState.extensionIds.forEach((id) => {
40
+ const surface = getSurfaceValue(id);
41
+ simpleXDM.broadcast(
42
+ 'theme_changed',
43
+ { id },
44
+ { newTheme, featureFlags, surface }
45
+ );
46
+ });
47
+ }
48
+ }
49
+
50
+ // Exported only for testing
51
+ export const ThemingModuleState = {
52
+ /**
53
+ * An array containing extension ID's for each app that has enabled theming.
54
+ * Theme change events are only sent to apps listed in this array.
55
+ */
56
+ extensionIds: [],
57
+ /**
58
+ * Observer that will only trigger on changes to data-theme on the root html element.
59
+ * Dispatches the new theme to all plugins when the theme changes.
60
+ */
61
+ themeObserver: new ThemeMutationObserver((newTheme) => {
62
+ broadcastThemeChange(newTheme);
63
+ })
64
+ }
65
+
66
+ // Only functions that make up the public ACJS theming API should be exported on this object.
67
+ const ThemingModule = {
68
+ /**
69
+ * Starts observing theme changes and dispatches the `theme_initialized` event to the plugin.
70
+ * This event causes the plugin to react when the host's theme changes.
71
+ */
72
+ initializeTheming() {
73
+ const callback = util.last(arguments);
74
+ const forceNoCleanup = arguments.length === 1 ? false : arguments[0];
75
+
76
+ if (!callback || !callback._context || !callback._context.extension_id) {
77
+ return;
78
+ }
79
+
80
+ const { _context: { extension_id } } = callback;
81
+
82
+ if (!extension_id) {
83
+ return;
84
+ }
85
+
86
+ const initialTheme = getGlobalTheme();
87
+ const surface = getSurfaceValue(extension_id);
88
+ const featureFlags = getPluginFeatureFlags();
89
+
90
+ // The theme_initialized event should be broadcast even if it has previously been initialized by the plugin.
91
+ // This is to ensure that theming works in multi-page apps after navigating to a different page.
92
+ // The reason is that isThemingInitialized on the plugin side starts as `false` when all.js is loaded.
93
+ // The theme_initialized event is needed to change it to `true` for any new page.
94
+ simpleXDM.broadcast(
95
+ 'theme_initialized',
96
+ { id: extension_id },
97
+ { initialTheme, featureFlags, surface, forceNoCleanup }
98
+ );
99
+
100
+ if (!ThemingModuleState.extensionIds.includes(extension_id)) {
101
+ ThemingModuleState.extensionIds.push(extension_id);
102
+ ThemingModuleState.themeObserver.observe(document.documentElement);
103
+ }
104
+ },
105
+ /**
106
+ * This has to be part of the API so the plugin can notify us when theme loading is finished.
107
+ * The underscore indicates it should not be called by apps directly.
108
+ * @private
109
+ */
110
+ _finishedInitTheming() {
111
+ }
112
+ };
113
+
114
+ export default ThemingModule;
@@ -0,0 +1,24 @@
1
+ import util from '../util';
2
+
3
+ class ExtensionConfigurationOptionsStore {
4
+ constructor() {
5
+ this.store = {};
6
+ }
7
+ set(obj, val) {
8
+ if(val) {
9
+ var toSet = {};
10
+ toSet[obj] = val;
11
+ } else {
12
+ toSet = obj;
13
+ }
14
+ util.extend(this.store, toSet);
15
+ }
16
+ get(key) {
17
+ if(key) {
18
+ return this.store[key];
19
+ }
20
+ return util.extend({}, this.store); //clone
21
+ }
22
+ }
23
+
24
+ export default new ExtensionConfigurationOptionsStore();
@@ -0,0 +1,98 @@
1
+ import $ from './dollar';
2
+
3
+ function escapeSelector(s) {
4
+ if (!s) {
5
+ throw new Error('No selector to escape');
6
+ }
7
+ return s.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, '\\$&');
8
+ }
9
+
10
+ function stringToDimension(value) {
11
+ var percent = false;
12
+ var unit = 'px';
13
+
14
+ if(typeof value === 'string') {
15
+ percent = value.indexOf('%') === value.length - 1;
16
+ value = parseInt(value, 10);
17
+ if (percent) {
18
+ unit = '%';
19
+ }
20
+ }
21
+
22
+ if(!isNaN(value)) {
23
+ return value + unit;
24
+ }
25
+ }
26
+
27
+ function getIframeByExtensionId(id) {
28
+ return $('iframe#' + escapeSelector(id));
29
+ }
30
+
31
+ function first(arr, numb){
32
+ if(numb) {
33
+ return arr.slice(0, numb);
34
+ }
35
+ return arr[0];
36
+ }
37
+
38
+ function last(arr){
39
+ return arr[arr.length - 1];
40
+ }
41
+
42
+ function pick(obj, keys) {
43
+ if(typeof obj !== 'object') {
44
+ return {};
45
+ }
46
+ return Object.keys(obj)
47
+ .filter((key) => keys.indexOf(key) >= 0)
48
+ .reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {});
49
+ }
50
+
51
+ function debounce (fn, wait) {
52
+ var timeout;
53
+ return function () {
54
+ var ctx = this;
55
+ var args = [].slice.call(arguments);
56
+ function later() {
57
+ timeout = null;
58
+ fn.apply(ctx, args);
59
+ }
60
+ if (timeout) {
61
+ clearTimeout(timeout);
62
+ }
63
+ timeout = setTimeout(later, wait || 50);
64
+ };
65
+ }
66
+
67
+ function isSupported(domElem, attr, value, defaultValue) {
68
+ if (domElem && domElem[attr] && domElem[attr].supports) {
69
+ return domElem[attr].supports(value);
70
+ } else {
71
+ return defaultValue;
72
+ }
73
+ }
74
+
75
+ function guessProductFromModuleDefined(connectHost) {
76
+ if (connectHost.isModuleDefined('jira')) {
77
+ return 'Jira';
78
+ }
79
+
80
+ if (connectHost.isModuleDefined('confluence')) {
81
+ return 'Confluence';
82
+ }
83
+
84
+ return '';
85
+ }
86
+
87
+ export default {
88
+ escapeSelector,
89
+ stringToDimension,
90
+ getIframeByExtensionId,
91
+ first,
92
+ last,
93
+ pick,
94
+ debounce,
95
+ isSupported,
96
+ extend: Object.assign,
97
+ guessProductFromModuleDefined,
98
+ };
@@ -0,0 +1,18 @@
1
+ export function getAccessNarrowingSpaceContext(extension) {
2
+ if (extension?.options && AJS?.Meta?.get) {
3
+ const productContext = {
4
+ ...(extension.options.productContext || {})
5
+ };
6
+ if (AJS.Meta.get('space-key')) {
7
+ productContext['an.spaceKey'] = AJS.Meta.get('space-key');
8
+ }
9
+ return {
10
+ ...extension,
11
+ options: {
12
+ ...extension.options,
13
+ productContext,
14
+ }
15
+ };
16
+ }
17
+ return extension;
18
+ }