@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,255 @@
1
+ /**
2
+ * DO NOT INCLUDE ME IN THE PUBLIC DOCUMENTATION
3
+ * there is no AUI implementation of this
4
+ */
5
+
6
+ import HostApi from '../host-api';
7
+ import util from '../util';
8
+ import EventDispatcher from '../dispatchers/event_dispatcher';
9
+ import EventActions from '../actions/event_actions';
10
+ import DropdownActions from '../actions/dropdown_actions';
11
+
12
+ var dropdownProvider;
13
+
14
+ function buildListItem(listItem) {
15
+ let finishedListItem = {};
16
+ if (typeof listItem === 'string') {
17
+ finishedListItem.content = listItem;
18
+ } else if (listItem.text && typeof listItem.text === 'string') {
19
+ finishedListItem.content = listItem.text;
20
+ if(typeof listItem.disabled === 'boolean') {
21
+ finishedListItem.disabled = listItem.disabled;
22
+ }
23
+ if(typeof listItem.itemId !== 'undefined') {
24
+ finishedListItem.itemId = listItem.itemId;
25
+ }
26
+ } else {
27
+ throw new Error('Unknown dropdown list item format.');
28
+ }
29
+ return finishedListItem;
30
+ }
31
+
32
+ function moduleListToApiList(list) {
33
+ return list.map((item) => {
34
+ if (item.list && Array.isArray(item.list)) {
35
+ let returnval = {
36
+ heading: item.heading
37
+ }
38
+ returnval.items = item.list.map((listitem) => {
39
+ return buildListItem(listitem);
40
+ });
41
+ return returnval;
42
+ }
43
+ });
44
+ }
45
+
46
+ /**
47
+ * @class DropdownItem
48
+ * A single item in a dropdown menu can be a string or an object
49
+ * @param {String} itemId The id of a single dropdown item
50
+ * @param {String} text The text to display in the dropdown item
51
+ */
52
+
53
+ /**
54
+ * @module Dropdown
55
+ * @description Dropdown menu that can go outside the iframe bounds.
56
+ * @example
57
+ * // create a dropdown menu with 1 section and 2 items
58
+ * var mydropdown = {
59
+ * dropdownId: 'my-dropdown',
60
+ * list: [{
61
+ * heading: 'section heading',
62
+ * list: [
63
+ * {text: 'one'},
64
+ * {text: 'two'}
65
+ * ]
66
+ * }]
67
+ * };
68
+ *
69
+ * AP.events.on('dropdown-item-selected', (data) =>{
70
+ * console.log('dropdown item selected', data.dropdownId, data.item);
71
+ * });
72
+ *
73
+ * AP.dropdown.create(mydropdown);
74
+ * // button is an element in our document that triggered the dropdown
75
+ * let rect = document.querySelector('button').getBoundingClientRect();
76
+ * AP.dropdown.showAt('my-dropdown', rect.left, rect.top, rect.width);
77
+ *
78
+ */
79
+
80
+ export default {
81
+ /**
82
+ * @name create
83
+ * @method
84
+ * @description Creates a new dropdown.
85
+ * @param {Object} options Options of the dropdown.
86
+ * @param {String} options.dropdownId A unique identifier for the dropdown that will be referenced in events.
87
+ * @param {String} options.list An array containing dropdown items {Dropdown~DropdownItem}
88
+ * @example
89
+ * // create a dropdown menu with 1 section and 2 items
90
+ * var mydropdown = {
91
+ * dropdownId: 'my-dropdown',
92
+ * list: [{
93
+ * heading: 'section heading',
94
+ * list: [
95
+ * {text: 'one'},
96
+ * {text: 'two'}
97
+ * ]
98
+ * }]
99
+ * };
100
+ *
101
+ * AP.dropdown.create(mydropdown);
102
+ */
103
+ create(options, callback) {
104
+ callback = util.last(arguments);
105
+ if (typeof options !== 'object') {
106
+ return;
107
+ }
108
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
109
+ const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
110
+ if (dropdownProvider) {
111
+ const dropdownGroups = moduleListToApiList(options.list);
112
+ const dropdownProviderOptions = {
113
+ dropdownId: options.dropdownId,
114
+ dropdownGroups: dropdownGroups,
115
+ dropdownItemNotifier: (data) => {
116
+ DropdownActions.itemSelected(data.dropdownId, data.item, callback._context.extension);
117
+ }
118
+ };
119
+ dropdownProvider.create(dropdownProviderOptions, callback._context);
120
+ return dropdownProviderOptions;
121
+ }
122
+ },
123
+
124
+ /**
125
+ * @name showAt
126
+ * @method
127
+ * @description Displays a created dropdown menu.
128
+ * @param {String} dropdownId Id used when creating the dropdown
129
+ * @param {String} x x position from the edge of your iframe to display
130
+ * @param {String} y y position from the edge of your iframe to display
131
+ * @param {String} width Optionally enforce a width for the dropdown menu
132
+ * @example
133
+ * // create a dropdown menu with 1 section and 2 items
134
+ * var mydropdown = {
135
+ * dropdownId: 'my-dropdown',
136
+ * list: [{
137
+ * list:['one', 'two']
138
+ * }]
139
+ * };
140
+ *
141
+ * AP.dropdown.create(mydropdown);
142
+ * // Get the button that activated the dropdown
143
+ * let rect = document.querySelector('button').getBoundingClientRect();
144
+ * AP.dropdown.showAt('my-dropdown', rect.left, rect.top, rect.width);
145
+ */
146
+ showAt(dropdownId, x, y, width) {
147
+ let callback = util.last(arguments);
148
+ let rect = {left: 0, top: 0};
149
+ let iframe = document.getElementById(callback._context.extension_id);
150
+ if(iframe) {
151
+ rect = iframe.getBoundingClientRect();
152
+ } else {
153
+ console.error('ACJS: no iframe found for dropdown');
154
+ }
155
+
156
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
157
+ const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
158
+ if (dropdownProvider) {
159
+ const dropdownProviderArgs = {
160
+ dropdownId: dropdownId,
161
+ x: x,
162
+ y: y,
163
+ width: width
164
+ };
165
+ dropdownProvider.showAt(dropdownProviderArgs, {
166
+ iframeDimensions: rect,
167
+ onItemSelection: (dropdownId, item) => {
168
+ DropdownActions.itemSelected(dropdownId, item, callback._context.extension);
169
+ }
170
+ });
171
+ }
172
+ },
173
+ /**
174
+ * @name hide
175
+ * @method
176
+ * @description Hide a dropdown menu
177
+ * @param {String} dropdownId The id of the dropdown to hide
178
+ * @example
179
+ * AP.dropdown.create('my-dropdown');
180
+ * AP.dropdown.hide('my-dropdown');
181
+ */
182
+ hide(id) {
183
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
184
+ const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
185
+ if (dropdownProvider) {
186
+ dropdownProvider.hide(id);
187
+ }
188
+ },
189
+
190
+ /**
191
+ * @name itemDisable
192
+ * @method
193
+ * @description Disable an item in the dropdown menu
194
+ * @param {String} dropdownId The id of the dropdown
195
+ * @param {String} itemId The dropdown item to disable
196
+ * @example
197
+ * AP.dropdown.create('my-dropdown');
198
+ * AP.dropdown.itemDisable('my-dropdown', 'item-id');
199
+ */
200
+ itemDisable(dropdownId, itemId) {
201
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
202
+ const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
203
+ if (dropdownProvider) {
204
+ dropdownProvider.itemDisable(dropdownId, itemId);
205
+ }
206
+ },
207
+
208
+ /**
209
+ * @name itemEnable
210
+ * @method
211
+ * @description Hide a dropdown menu
212
+ * @param {String} dropdownId The id of the dropdown
213
+ * @param {String} itemId The id of the dropdown item to enable
214
+ * @example
215
+ * AP.dropdown.create('my-dropdown');
216
+ * AP.dropdown.itemEnable('my-dropdown', 'item-id');
217
+ */
218
+ itemEnable(dropdownId, itemId) {
219
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
220
+ const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
221
+ if (dropdownProvider) {
222
+ dropdownProvider.itemEnable(dropdownId, itemId);
223
+ }
224
+ }
225
+
226
+ }
227
+
228
+
229
+ EventDispatcher.register('dropdown-item-selected', (data) => {
230
+ EventActions.broadcast('dropdown-item-selected', {
231
+ addon_key: data.extension.addon_key,
232
+ key: data.extension.key
233
+ }, {
234
+ dropdownId: data.id,
235
+ item: data.item
236
+ });
237
+ });
238
+
239
+ // friendly unload with connectHost.destroy
240
+ EventDispatcher.register('iframe-destroyed', (data) => {
241
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
242
+ const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
243
+ if (dropdownProvider) {
244
+ dropdownProvider.destroyByExtension(data.extension.extension_id);
245
+ }
246
+ });
247
+
248
+ // unfriendly unload by removing the iframe from the DOM
249
+ EventDispatcher.register('after:iframe-unload', (data) => {
250
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
251
+ const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
252
+ if (dropdownProvider) {
253
+ dropdownProvider.destroyByExtension(data.extension.extension_id);
254
+ }
255
+ });
@@ -0,0 +1,156 @@
1
+ import EnvActions from '../actions/env_actions';
2
+ import EventDispatcher from '../dispatchers/event_dispatcher';
3
+ import util from '../util';
4
+ import ModuleProviders from '../module-providers';
5
+ import {Flags} from '../utils/feature-flag';
6
+
7
+ var debounce = util.debounce;
8
+ var resizeFuncHolder = {};
9
+ // ignore resize events for iframes that use sizeToParent
10
+ var ignoreResizeForExtension = [];
11
+ var sizeToParentExtension = {};
12
+
13
+ /**
14
+ * Enables apps to resize their iframes.
15
+ * @exports iframe
16
+ */
17
+ export default {
18
+ /**
19
+ * Get the location of the current page of the host product.
20
+ *
21
+ * @param {Function} callback function (location) {...} The callback to pass the location to.
22
+ * @example
23
+ * AP.getLocation(function(location){
24
+ * alert(location);
25
+ * });
26
+ */
27
+ getLocation: function(callback) {
28
+ callback = util.last(arguments);
29
+ let pageLocationProvider = ModuleProviders.getProvider('get-location');
30
+ if (typeof pageLocationProvider === 'function') {
31
+ callback(pageLocationProvider());
32
+ } else {
33
+ callback(window.location.href);
34
+ }
35
+ },
36
+ /**
37
+ * Resize the iframe to a width and height.
38
+ *
39
+ * Only content within an element with the class `ac-content` is resized automatically.
40
+ * Content without this identifier is sized according to the `body` element, and
41
+ * is *not* dynamically resized. The recommended DOM layout for your app is:
42
+ *
43
+ * ``` html
44
+ * <div class="ac-content">
45
+ * <p>Hello World</p>
46
+ * <div id="your-id-here">
47
+ * <p>App content goes here</p>
48
+ * </div>
49
+ *
50
+ * ...this area reserved for the resize sensor divs
51
+ * </div>
52
+ * ```
53
+ *
54
+ * The resize sensor div is added on the iframe's [load event](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event).
55
+ * Removing the `ac-content` element after this, prevents resizing from working correctly.
56
+ *
57
+ * This method cannot be used in dialogs.
58
+ *
59
+ * @method
60
+ * @param {String} width The desired width in pixels or percentage.
61
+ * @param {String} height The desired height in pixels or percentage.
62
+ * @example
63
+ * AP.resize('400','400');
64
+ */
65
+ resize: function(width, height, callback) {
66
+ callback = util.last(arguments);
67
+ let addon = ModuleProviders.getProvider('addon');
68
+ if (addon) {
69
+ addon.resize(width, height, callback._context);
70
+ } else {
71
+ var iframeId = callback._context.extension.id;
72
+ var options = callback._context.extension.options;
73
+ if (ignoreResizeForExtension.indexOf(iframeId) !== -1 || (options && options.isDialog)) {
74
+ return false;
75
+ }
76
+
77
+ if (!resizeFuncHolder[iframeId]) {
78
+ resizeFuncHolder[iframeId] = debounce(function(dwidth, dheight, dcallback) {
79
+ EnvActions.iframeResize(dwidth, dheight, dcallback._context);
80
+ }, 50);
81
+ }
82
+
83
+ resizeFuncHolder[iframeId](width, height, callback);
84
+ }
85
+ return true;
86
+ },
87
+ /**
88
+ * Resize the iframe so that it takes up the entire page.
89
+ *
90
+ * This method is only available for general page modules.
91
+ *
92
+ * @method
93
+ * @example
94
+ * AP.sizeToParent();
95
+ */
96
+ sizeToParent: debounce(function(hideFooter, callback) {
97
+ callback = util.last(arguments);
98
+ let addon = ModuleProviders.getProvider('addon');
99
+ if (addon) {
100
+ addon.sizeToParent(hideFooter, callback._context);
101
+ } else {
102
+ // sizeToParent is only available for general-pages
103
+ if (callback._context.extension.options.isFullPage) {
104
+ // This adds border between the iframe and the page footer as the connect addon has scrolling content and can't do this
105
+ util.getIframeByExtensionId(callback._context.extension_id).addClass('full-size-general-page');
106
+ util.getIframeByExtensionId(callback._context.extension_id).addClass('sized-to-parent');
107
+ EnvActions.sizeToParent(callback._context.extension_id, hideFooter);
108
+ sizeToParentExtension[callback._context.extension_id] = { hideFooter: hideFooter };
109
+ } else {
110
+ // This is only here to support integration testing
111
+ // see com.atlassian.plugin.connect.test.pageobjects.RemotePage#isNotFullSize()
112
+ util.getIframeByExtensionId(callback._context.extension_id).addClass('full-size-general-page-fail');
113
+ }
114
+ }
115
+ }),
116
+ /**
117
+ * Hide the footer.
118
+ *
119
+ * @method
120
+ * @param {boolean} hideFooter Whether the footer should be hidden.
121
+ * @ignore
122
+ */
123
+ hideFooter: function(hideFooter) {
124
+ if (hideFooter) {
125
+ EnvActions.hideFooter(hideFooter);
126
+ }
127
+ }
128
+ };
129
+
130
+ const _removeIframeReferenceAfterUnloadAndDestroyed = (extensionId) => {
131
+ delete resizeFuncHolder[extensionId];
132
+ delete sizeToParentExtension[extensionId];
133
+ if (ignoreResizeForExtension.indexOf(extensionId) !== -1) {
134
+ ignoreResizeForExtension.splice(ignoreResizeForExtension.indexOf(extensionId), 1);
135
+ }
136
+ }
137
+
138
+ EventDispatcher.register('host-window-resize', data => {
139
+ Object.getOwnPropertyNames(sizeToParentExtension).forEach(extensionId => {
140
+ EnvActions.sizeToParent(extensionId, sizeToParentExtension[extensionId].hideFooter);
141
+ });
142
+ });
143
+
144
+ EventDispatcher.register('after:iframe-unload', function(data) {
145
+ _removeIframeReferenceAfterUnloadAndDestroyed(data.extension.id);
146
+ });
147
+
148
+ EventDispatcher.register('after:iframe-destroyed', function(data) {
149
+ _removeIframeReferenceAfterUnloadAndDestroyed(data.extension.extension.id);
150
+ });
151
+
152
+ EventDispatcher.register('before:iframe-size-to-parent', function(data) {
153
+ if (ignoreResizeForExtension.indexOf(data.extensionId) === -1) {
154
+ ignoreResizeForExtension.push(data.extensionId);
155
+ }
156
+ });
@@ -0,0 +1,28 @@
1
+ import EventActions from '../actions/event_actions';
2
+ import Util from '../util';
3
+
4
+ export default {
5
+ emit: function(name, ...args) {
6
+ var callback = Util.last(args);
7
+ args = Util.first(args, -1);
8
+ EventActions.broadcast(name, {
9
+ addon_key: callback._context.extension.addon_key
10
+ }, args);
11
+ },
12
+
13
+ emitPublic: function(name, ...args) {
14
+ var callback = Util.last(args);
15
+ var extension = callback._context.extension;
16
+ args = Util.first(args, -1);
17
+ EventActions.broadcastPublic(name, args, extension);
18
+ },
19
+
20
+ emitToDataProvider: function(...args) {
21
+ var callback = Util.last(args);
22
+ var extension = callback._context.extension;
23
+ args = Util.first(args, -1);
24
+ EventActions.broadcast('dataProviderEvent', {
25
+ addon_key: callback._context.extension.addon_key
26
+ }, args);
27
+ },
28
+ };
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Flags are the primary method for providing system feedback in the product user interface. Messages include notifications of various kinds: alerts, confirmations, notices, warnings, info and errors.
3
+ * @module Flag
4
+ */
5
+
6
+ import HostApi from '../host-api';
7
+ import EventDispatcher from '../dispatchers/event_dispatcher';
8
+ import FlagActions from '../actions/flag_actions';
9
+ import FlagComponent from '../components/flag';
10
+ import util from '../util';
11
+ import EventActions from '../actions/event_actions';
12
+ import ModuleProviders from '../module-providers';
13
+ import getBooleanFeatureFlag from '../utils/feature-flag';
14
+
15
+ const _flags = {};
16
+
17
+ /**
18
+ * @class Flag~Flag
19
+ * @description A flag object created by the [AP.flag]{@link module:Flag} module.
20
+ * @example
21
+ * // complete flag API example:
22
+ * var outFlagId;
23
+ * var flag = AP.flag.create({
24
+ * title: 'Successfully created a flag.',
25
+ * body: 'This is a flag.',
26
+ * type: 'info',
27
+ * actions: {
28
+ * 'actionOne': 'action name'
29
+ * }
30
+ * }, function(identifier) {
31
+ * // Each flag will have a unique id. Save it for later.
32
+ * ourFlagId = identifier;
33
+ * });
34
+ *
35
+ * // listen to flag events
36
+ * AP.events.on('flag.close', function(data) {
37
+ * // a flag was closed. data.flagIdentifier should match ourFlagId
38
+ * console.log('flag id: ', data.flagIdentifier);
39
+ * });
40
+ * AP.events.on('flag.action', function(data) {
41
+ * // a flag action was clicked. data.actionIdentifier will be 'actionOne'
42
+ * // data.flagIdentifier will equal ourFlagId
43
+ * console.log('flag id: ', data.flagIdentifier, 'flag action id', data.actionIdentifier);
44
+ * });
45
+ */
46
+ class Flag {
47
+ constructor(options, callback) {
48
+ callback = util.last(arguments);
49
+ if(typeof options !== 'object') {
50
+ return;
51
+ }
52
+ const flagId = callback._id;
53
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
54
+ const flagProvider = frameworkAdaptor.getProviderByModuleName('flag');
55
+ if (flagProvider) {
56
+ let actions = [];
57
+ if (typeof options.actions === 'object') {
58
+ actions = Object.getOwnPropertyNames(options.actions).map(key => {
59
+ return {
60
+ actionKey: key,
61
+ actionText: options.actions[key],
62
+ executeAction: FlagActions.actionInvoked.bind(null, key, flagId)
63
+ };
64
+ });
65
+ }
66
+ let type = options.type || 'info';
67
+ let flagOptions = {
68
+ id: flagId,
69
+ title: options.title,
70
+ body: options.body,
71
+ actions: actions,
72
+ onClose: FlagActions.closed,
73
+ close: options.close,
74
+ type: type.toLowerCase()
75
+ };
76
+ this.flag = flagProvider.create(flagOptions);
77
+ let addonProvider = ModuleProviders.getProvider('addon');
78
+ if (addonProvider && addonProvider.registerUnmountCallback) {
79
+ addonProvider.registerUnmountCallback(this.close.bind(this), callback._context);
80
+ }
81
+ } else {
82
+ this.flag = FlagComponent.render({
83
+ type: options.type,
84
+ title: options.title,
85
+ body: AJS.escapeHtml(options.body),
86
+ actions: options.actions,
87
+ close: options.close,
88
+ id: flagId
89
+ });
90
+
91
+ FlagActions.open(this.flag.attr('id'));
92
+ }
93
+
94
+ this.onTriggers= {};
95
+ this.extension = callback._context.extension;
96
+ _flags[callback._id] = this;
97
+ callback.call(null, callback._id);
98
+ }
99
+
100
+ /**
101
+ * @name close
102
+ * @memberof Flag~Flag
103
+ * @method
104
+ * @description Closes the Flag.
105
+ * @example
106
+ * // Display a nice green flag using the Flags JavaScript API.
107
+ * var flag = AP.flag.create({
108
+ * title: 'Successfully created a flag.',
109
+ * body: 'This is a flag.',
110
+ * type: 'info'
111
+ * });
112
+ *
113
+ * // Close the flag.
114
+ * flag.close()
115
+ *
116
+ */
117
+ close() {
118
+ this.flag.close();
119
+ }
120
+ }
121
+
122
+ function invokeTrigger(id, eventName, data) {
123
+ if (_flags[id]) {
124
+ let extension = _flags[id].extension;
125
+ data = data || {};
126
+ data.flagIdentifier = id;
127
+ const targetSpec = { id: extension.id };
128
+ EventActions.broadcast(eventName, targetSpec, data);
129
+ }
130
+ }
131
+
132
+ EventDispatcher.register('flag-closed', (data) => {
133
+ invokeTrigger(data.id, 'flag.close');
134
+ if (_flags[data.id]) {
135
+ delete _flags[data.id];
136
+ }
137
+ });
138
+
139
+ EventDispatcher.register('flag-action-invoked', (data) => {
140
+ invokeTrigger(data.id, 'flag.action', {actionIdentifier: data.actionId});
141
+ });
142
+
143
+ export default {
144
+ /**
145
+ * @name create
146
+ * @method
147
+ * @description Creates a new flag.
148
+ * @param {Object} options Options of the flag.
149
+ * @param {String} options.title The title text of the flag.
150
+ * @param {String} options.body The body text of the flag.
151
+ * @param {String} options.type=info Sets the type of the message. Valid options are "info", "success", "warning" and "error".
152
+ * @param {String} options.close The closing behaviour that this flag has. Valid options are "manual", and "auto".
153
+ * @param {Object} options.actions Map of {actionIdentifier: 'Action link text'} to add to the flag. The actionIdentifier will be passed to a 'flag.action' event if the link is clicked.
154
+ * @returns {Flag~Flag}
155
+ * @example
156
+ * // Display a nice green flag using the Flags JavaScript API.
157
+ * var flag = AP.flag.create({
158
+ * title: 'Successfully created a flag.',
159
+ * body: 'This is a flag.',
160
+ * type: 'success',
161
+ * actions: {
162
+ * 'actionkey': 'Click me'
163
+ * }
164
+ * });
165
+ */
166
+ create: {
167
+ constructor: Flag,
168
+ close: Flag.prototype.close
169
+ }
170
+ }
@@ -0,0 +1,19 @@
1
+ import deprecateHost from '../deprecate';
2
+
3
+ export default {
4
+
5
+ /*
6
+ This function could be used in Connect app for moving focus to Host app.
7
+ As Connect App - iframe app, it can get control. When it's happen - host app events such short-cuts
8
+ stop working. This function could help in this case.
9
+ */
10
+ focus: () => {
11
+ window.document.querySelector('a').focus({preventScroll:true});
12
+ window.document.querySelector('a').blur();
13
+ },
14
+
15
+ getSelectedText: deprecateHost(function(callback) {
16
+ callback('');
17
+ return;
18
+ }, 'AP.host.getSelectedText()')
19
+ };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The inline dialog is a wrapper for secondary content/controls to be displayed on user request. Consider this component as displayed in context to the triggering control with the dialog overlaying the page content.
3
+ * An inline dialog should be preferred over a modal dialog when a connection between the action has a clear benefit versus having a lower user focus.
4
+ *
5
+ * Inline dialogs can be shown via a [web item target](../../modules/web-item/#target).
6
+ *
7
+ * For more information, read about the Atlassian User Interface [inline dialog component](https://docs.atlassian.com/aui/latest/docs/inline-dialog.html).
8
+ * @module Inline-dialog
9
+ */
10
+ import HostApi from '../host-api';
11
+ import InlineDialogActions from '../actions/inline_dialog_actions';
12
+ import util from '../util';
13
+
14
+ export default {
15
+ /**
16
+ * Hide the inline dialog that contains the iframe where this method is called from.
17
+ * @memberOf module:Inline-dialog
18
+ * @method hide
19
+ * @noDemo
20
+ * @example
21
+ * AP.inlineDialog.hide();
22
+ */
23
+ hide: function(callback) {
24
+ callback = util.last(arguments);
25
+ const frameworkAdaptor = HostApi.getFrameworkAdaptor();
26
+ const inlineDialogProvider = frameworkAdaptor.getProviderByModuleName('inlineDialog');
27
+ if (inlineDialogProvider) {
28
+ inlineDialogProvider.hide(callback._context);
29
+ } else {
30
+ InlineDialogActions.close();
31
+ }
32
+ }
33
+ };