@atlassian/aui 9.11.4 → 9.11.6

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 (31) hide show
  1. package/dist/aui/aui-prototyping-browserfocus.css +2 -651
  2. package/dist/aui/aui-prototyping-browserfocus.css.map +1 -0
  3. package/dist/aui/aui-prototyping-darkmode.css +2 -285
  4. package/dist/aui/aui-prototyping-darkmode.css.map +1 -0
  5. package/dist/aui/aui-prototyping-design-tokens-api-full.js +2 -2
  6. package/dist/aui/aui-prototyping-design-tokens-api-full.js.map +1 -1
  7. package/dist/aui/aui-prototyping-design-tokens-api.js +2 -2
  8. package/dist/aui/aui-prototyping-design-tokens-api.js.map +1 -1
  9. package/dist/aui/aui-prototyping-design-tokens-base-themes-css.css +1 -1
  10. package/dist/aui/aui-prototyping-design-tokens-base-themes-css.js +1 -1
  11. package/dist/aui/aui-prototyping-design-tokens-base-themes.js +1 -1
  12. package/dist/aui/aui-prototyping-design-tokens-compatibility.css +2 -115
  13. package/dist/aui/aui-prototyping-design-tokens-compatibility.css.map +1 -0
  14. package/dist/aui/aui-prototyping.css +5 -5
  15. package/dist/aui/aui-prototyping.css.map +1 -1
  16. package/dist/aui/aui-prototyping.js +2 -2
  17. package/dist/aui/aui-prototyping.js.map +1 -1
  18. package/dist/aui/aui-prototyping.nodeps.css +5 -5
  19. package/dist/aui/aui-prototyping.nodeps.css.map +1 -1
  20. package/dist/aui/aui-prototyping.nodeps.js +6 -6
  21. package/dist/aui/aui-prototyping.nodeps.js.map +1 -1
  22. package/package.json +4 -8
  23. package/src/js/aui/avatar-group.js +4 -4
  24. package/src/js/aui/banner.js +2 -2
  25. package/src/js/aui/date-picker.js +10 -8
  26. package/src/js/aui/design-tokens/design-tokens-init.js +2 -2
  27. package/src/js/aui/design-tokens/design-tokens-testing-theme.js +6 -6
  28. package/src/js/aui/flag.js +31 -3
  29. package/src/js/aui/focus-manager.js +51 -1
  30. package/src/js/aui/internal/i18n/aui.js +5 -1
  31. package/src/less/imports/aui-theme/components/form-notification.less +1 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atlassian/aui",
3
3
  "description": "Atlassian User Interface library",
4
- "version": "9.11.4",
4
+ "version": "9.11.6",
5
5
  "author": "Atlassian Pty Ltd.",
6
6
  "homepage": "https://aui.atlassian.com",
7
7
  "license": "Apache-2.0",
@@ -33,6 +33,7 @@
33
33
  "jquery": "^2 || ^3"
34
34
  },
35
35
  "dependencies": {
36
+ "@atlassian/adg-server-iconfont": "3.1.0",
36
37
  "@atlaskit/tokens": "1.43.0",
37
38
  "@atlassian/tipsy": "1.3.3",
38
39
  "@popperjs/core": "2.11.8",
@@ -52,11 +53,9 @@
52
53
  "jquery.hotkeys": "file:src/js-vendor/jquery.hotkeys"
53
54
  },
54
55
  "devDependencies": {
55
- "@atlassian/adg-server-iconfont": "3.1.0",
56
56
  "@atlassian/aui-webpack-config": "3.0.1",
57
57
  "@babel/core": "7.18.13",
58
58
  "@babel/preset-env": "7.18.10",
59
- "bundlesize": "1.0.0-beta.2",
60
59
  "cross-env": "7.0.3",
61
60
  "eslint": "7.32.0",
62
61
  "glob": "7.2.3",
@@ -64,7 +63,7 @@
64
63
  "jquery": "3.5.1",
65
64
  "jquery-migrate": "3.4.1",
66
65
  "less": "3.13.1",
67
- "react": "^18.2.0"
66
+ "react": "18.3.1"
68
67
  },
69
68
  "scripts": {
70
69
  "prepublishOnly": "yarn clean && cross-env NODE_ENV=production yarn build && node scripts/prepublishOnly.js",
@@ -72,9 +71,6 @@
72
71
  "clean": "rm -rf ./dist",
73
72
  "dist/build:prototyping": "webpack --config webpack/dist.prototyping.webpack.config.js",
74
73
  "build": "yarn dist/build:prototyping",
75
- "watch": "yarn dist/build:prototyping --watch",
76
- "bundlesize/verify-dist": "node scripts/verify-dist-structure.js",
77
- "bundlesize/gzipped": "node scripts/generate-bundlesize-config.js > configs/bundlesize-gzipped.json && bundlesize --config configs/bundlesize-gzipped.json",
78
- "bundlesize/raw": "node scripts/generate-bundlesize-config.js raw > configs/bundlesize-raw.json && bundlesize --config configs/bundlesize-raw.json"
74
+ "watch": "yarn dist/build:prototyping --watch"
79
75
  }
80
76
  }
@@ -90,23 +90,23 @@ document.addEventListener('click', (e) => {
90
90
  const isDropdownButton = e.target.matches('.aui-avatar-group-dropdown-button');
91
91
  const closestDropdown = e.target.closest('.aui-avatar-group-dropdown');
92
92
 
93
- if (!isDropdownButton && closestDropdown !== null) return;
93
+ if (!isDropdownButton && closestDropdown !== null) {return;}
94
94
 
95
95
  if (isDropdownButton) {
96
96
  closestDropdown.classList.contains('aui-avatar-group-dropdown-show') ? closeDropdown(closestDropdown) : openDropdown(closestDropdown);
97
97
  }
98
98
 
99
99
  document.querySelectorAll('.aui-avatar-group-dropdown-show').forEach(dropdown => {
100
- if (dropdown === closestDropdown) return;
100
+ if (dropdown === closestDropdown) {return;}
101
101
 
102
102
  closeDropdown(dropdown)
103
103
  })
104
104
  });
105
105
 
106
106
  document.addEventListener('keydown', (e) => {
107
- if (e.key !== 'Escape') return;
107
+ if (e.key !== 'Escape') {return;}
108
108
  const dropdown = document.querySelector('.aui-avatar-group-dropdown-show');
109
- if (!dropdown) return;
109
+ if (!dropdown) {return;}
110
110
 
111
111
  closeDropdown(dropdown);
112
112
  });
@@ -26,7 +26,7 @@ function createBannerElement({ body = '', type = 'error' }) {
26
26
  banner.className = `aui-banner aui-banner-${type}`;
27
27
  banner.setAttribute('role', 'alert');
28
28
  banner.innerHTML = body;
29
-
29
+
30
30
  const screenReaderInfo = document.createElement('div');
31
31
  screenReaderInfo.innerText = `${type}`;
32
32
  screenReaderInfo.classList.add('assistive')
@@ -57,4 +57,4 @@ function renderBannerElement(bannerElement, bannerContainer) {
57
57
 
58
58
  amdify('aui/banner', banner);
59
59
  globalize('banner', banner);
60
- export default banner;
60
+ export default banner;
@@ -334,14 +334,16 @@ const initPolyfill = function (datePicker) {
334
334
  // according to the spec...
335
335
  $field.attr('placeholder', options.placeholder);
336
336
 
337
- // Override the browser's default date field implementation.
338
- // There used to be a fix for AUI-3681 here, too, but my testing of Edge 15
339
- // shows that changing the `type` of input does not erase its value.
340
- // see https://codepen.io/chrisdarroch/pen/YzwgjyJ
341
- $field.prop('type', 'text');
342
- // Set default value on initialization to handle all date formats.
343
- // It is possible, because of changing type to text on the line above.
344
- $field.val($field.attr('value'));
337
+ if ($field.prop('type') !== 'text') {
338
+ // Override the browser's default date field implementation.
339
+ // There used to be a fix for AUI-3681 here, too, but my testing of Edge 15
340
+ // shows that changing the `type` of input does not erase its value.
341
+ // see https://codepen.io/chrisdarroch/pen/YzwgjyJ
342
+ $field.prop('type', 'text');
343
+ // Set default value on initialization to handle all date formats.
344
+ // It is possible, because of changing type to text on the line above.
345
+ $field.val($field.attr('value'));
346
+ }
345
347
  // Trigger change to update calendar popup value.
346
348
  $field.trigger('propertychange');
347
349
 
@@ -1,7 +1,7 @@
1
- import { setGlobalTheme } from "@atlaskit/tokens";
1
+ import { setGlobalTheme } from '@atlaskit/tokens';
2
2
 
3
3
  if (
4
4
  document.documentElement.hasAttribute('data-color-mode-auto')
5
5
  ) {
6
- setGlobalTheme({ colorMode: "auto" });
6
+ setGlobalTheme({ colorMode: 'auto' });
7
7
  }
@@ -1,9 +1,9 @@
1
- import TokenNames from "@atlaskit/tokens/token-names";
1
+ import TokenNames from '@atlaskit/tokens/token-names';
2
2
 
3
3
  const testingThemeTargetElement = document.documentElement;
4
4
  const testingColorVariableName = '--aui-theme-testing-color';
5
5
  const defaultTestingColor = 'color(srgb 1 0.75 0.8 / 0.6)';
6
- const testingThemeTargetClass = "aui-theme-testing";
6
+ const testingThemeTargetClass = 'aui-theme-testing';
7
7
  const testingThemeSelector =
8
8
  `html.${testingThemeTargetClass}[data-theme*="light:"], ` +
9
9
  `html.${testingThemeTargetClass}[data-theme*="dark:"]`;
@@ -15,7 +15,7 @@ const testingThemeSelector =
15
15
  */
16
16
  (function generateTestingTheme() {
17
17
 
18
- const initialComment = "This theme is autogenerated using AJS.DesignTokens.generateTestingTheme()."
18
+ const initialComment = 'This theme is autogenerated using AJS.DesignTokens.generateTestingTheme().'
19
19
 
20
20
  // If function called many times theme should be only added once
21
21
  const isThemeAlreadyInitialised = !document.querySelector(testingThemeSelector)
@@ -27,20 +27,20 @@ const testingThemeSelector =
27
27
  const colorDeclaration = `${testingColorVariableName}: ${defaultTestingColor};`
28
28
  const themeCSSDeclarations = Object.values(TokenNames)
29
29
  .map(token => `\t${token}: var(${testingColorVariableName});`);
30
- const allDeclarations = [ colorDeclaration, ...themeCSSDeclarations ];
30
+ const allDeclarations = [colorDeclaration, ...themeCSSDeclarations];
31
31
 
32
32
 
33
33
  const themeCSS = `/* ${initialComment} */\n${testingThemeSelector} {\n${allDeclarations.join('\n')}\n}`;
34
34
 
35
35
  const themeElement = document.createElement('style');
36
- themeElement.id = "aui-design-tokens-testing-theme";
36
+ themeElement.id = 'aui-design-tokens-testing-theme';
37
37
  themeElement.innerText = themeCSS;
38
38
 
39
39
  const head = document.querySelector('head');
40
40
  if (head) {
41
41
  head.appendChild(themeElement);
42
42
  }
43
- })();
43
+ }());
44
44
 
45
45
  /**
46
46
  * Overrides default testing color by setting css variable. If no color passed, will revert to default.
@@ -9,6 +9,7 @@ import escapeHtml from './escape-html';
9
9
  import { CLOSE_BUTTON } from './close-button';
10
10
  import { FOCUSABLE_QUERY } from './internal/a11y/focusable-query';
11
11
  import getFocusManager from './focus-manager';
12
+ import { I18n } from './i18n';
12
13
 
13
14
  const AUTO_CLOSE_TIME = 8000;
14
15
  const ID_FLAG_CONTAINER = 'aui-flag-container';
@@ -62,10 +63,28 @@ function extendFlagElement ($flag) {
62
63
  };
63
64
  }
64
65
 
65
- function renderFlagElement ({ body, title, close, type, ariaLive }) {
66
+ function getDefaultAriaLabelForFlagType(type) {
67
+ switch (type) {
68
+ case 'success':
69
+ return I18n.getText('aui.flag.default-aria-label.success');
70
+ case 'warning':
71
+ return I18n.getText('aui.flag.default-aria-label.warning');
72
+ case 'error':
73
+ return I18n.getText('aui.flag.default-aria-label.error');
74
+ default:
75
+ return I18n.getText('aui.flag.default-aria-label.info');
76
+ }
77
+ }
78
+
79
+ function renderFlagElement ({ body, title, close, type, ariaLive, ariaLabel, ariaDescription }) {
66
80
  const titleHtml = title ? `<p class="title"><strong>${escapeHtml(title)}</strong></p>` : '';
67
81
  const html = `<div class="aui-message">${titleHtml}</div>`;
68
- const ariaLabel = title ? escapeHtml(title) : '';
82
+ if (!ariaLabel) {
83
+ ariaLabel = getDefaultAriaLabelForFlagType(type);
84
+ }
85
+ if (!ariaDescription) {
86
+ ariaDescription = '';
87
+ }
69
88
 
70
89
  const $message = $(html)
71
90
  .append($.parseHTML(body || ''))
@@ -74,7 +93,16 @@ function renderFlagElement ({ body, title, close, type, ariaLive }) {
74
93
  const isFocusable = $message.find(FOCUSABLE_QUERY).length > 0;
75
94
  const ariaRole = isFocusable ? 'alertdialog' : 'alert';
76
95
 
77
- return $(`<div aui-focus-trap="${isFocusable}" class="aui-flag" aria-label="${ariaLabel}" aria-hidden="true" aria-live="${escapeHtml(ariaLive)}" role="${ariaRole}"></div>`).append($message);
96
+ return $('<div class="aui-flag"></div>')
97
+ .attr({
98
+ 'aui-focus-trap': `${isFocusable}`,
99
+ 'aria-label': escapeHtml(ariaLabel),
100
+ 'aria-hidden': 'true',
101
+ 'aria-live': escapeHtml(ariaLive),
102
+ 'role': ariaRole,
103
+ ...(!!ariaDescription ? {'aria-description': escapeHtml(ariaDescription)} : {}),
104
+ })
105
+ .append($message);
78
106
  }
79
107
 
80
108
  function makeCloseable ($flag) {
@@ -127,6 +127,51 @@ FocusManager.prototype.exit = function ($el) {
127
127
  }
128
128
  };
129
129
 
130
+ function findIndexOfNextTabbableElement(originElement, startingIndex, offset, $tabbableElements) {
131
+ function advance(index) {
132
+ return (index + offset) % $tabbableElements.length;
133
+ }
134
+
135
+ let nextIndex = advance(startingIndex);
136
+
137
+ if (originElement.type === 'radio' && originElement.name) {
138
+ // Advance to the element that's not another radio button of the same group.
139
+ while (
140
+ $tabbableElements.eq(nextIndex).attr('name') === originElement.name &&
141
+ // Stop at the start if we've wrapped around the whole list and everything is the same radio
142
+ // group.
143
+ nextIndex !== startingIndex
144
+ ) {
145
+ nextIndex = advance(nextIndex);
146
+ }
147
+ }
148
+
149
+ // Emulate the browser's behavior: jump to the selected radio of a group, or if none is selected, the
150
+ // first or last depending on the direction. Note: we assume the markup is sensible and doesn't
151
+ // interleave groups of radio buttons. Supporting that would complicate the code for a non-recommended
152
+ // use case.
153
+ if (nextIndex !== startingIndex && $tabbableElements.eq(nextIndex).attr('type') === 'radio') {
154
+ const name = $tabbableElements.eq(nextIndex).attr('name');
155
+ const $radiosOfGroup = $tabbableElements.filter(function () {
156
+ return this.type === 'radio' && this.name === name;
157
+ });
158
+ const $checkedElement = $radiosOfGroup.filter(':checked');
159
+
160
+ let $elementToFocus;
161
+ if ($checkedElement.length > 0) {
162
+ $elementToFocus = $checkedElement.first();
163
+ } else {
164
+ if (offset > 0) {
165
+ $elementToFocus = $radiosOfGroup.first();
166
+ } else {
167
+ $elementToFocus = $radiosOfGroup.last();
168
+ }
169
+ }
170
+ nextIndex = $tabbableElements.index($elementToFocus);
171
+ }
172
+ return nextIndex;
173
+ }
174
+
130
175
  function focusTrapHandler(focusTrapStack, event) {
131
176
  if (focusTrapStack.length === 0) {
132
177
  return;
@@ -209,7 +254,12 @@ function focusTrapHandler(focusTrapStack, event) {
209
254
 
210
255
  if (newFocusIdx > -1) {
211
256
  // wrap around the focus trap.
212
- newFocusIdx = (newFocusIdx + offset) % $tabbableElements.length;
257
+ newFocusIdx = findIndexOfNextTabbableElement(
258
+ focusOrigin,
259
+ newFocusIdx,
260
+ offset,
261
+ $tabbableElements
262
+ );
213
263
  } else {
214
264
  // we will focus the first element in the trap.
215
265
  newFocusIdx = 0;
@@ -78,5 +78,9 @@ export default {
78
78
  'ajs.datepicker.localisations.month-names.november': 'November',
79
79
  'ajs.datepicker.localisations.month-names.december': 'December',
80
80
  'ajs.datepicker.localisations.show-month-after-year': false,
81
- 'ajs.datepicker.localisations.year-suffix': ''
81
+ 'ajs.datepicker.localisations.year-suffix': '',
82
+ 'aui.flag.default-aria-label.info': 'New information message',
83
+ 'aui.flag.default-aria-label.success': 'New confirmation message',
84
+ 'aui.flag.default-aria-label.warning': 'New warning message',
85
+ 'aui.flag.default-aria-label.error': 'New error message',
82
86
  }
@@ -24,7 +24,7 @@
24
24
  @aui-notification-icon-outside-field-padding-right: 16px;
25
25
  @aui-notification-icon-outside-field-padding-top: 5px;
26
26
 
27
- @aui-notification-line-height: unit(18px / @aui-font-size-medium);
27
+ @aui-notification-line-height: unit((18px / @aui-font-size-medium));
28
28
 
29
29
  @aui-notification-info-icon: @aui-glyph-info-circle;
30
30
  @aui-notification-success-icon: @aui-glyph-check-circle;