@atlaskit/editor-toolbar 0.15.4 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/cjs/ui/ToolbarButton.js +2 -0
- package/dist/cjs/ui/ToolbarKeyboardNavigationProvider.js +75 -5
- package/dist/es2019/ui/ToolbarButton.js +2 -0
- package/dist/es2019/ui/ToolbarKeyboardNavigationProvider.js +73 -5
- package/dist/esm/ui/ToolbarButton.js +2 -0
- package/dist/esm/ui/ToolbarKeyboardNavigationProvider.js +75 -5
- package/dist/types/ui/ToolbarButton.d.ts +1 -0
- package/dist/types-ts4.5/ui/ToolbarButton.d.ts +1 -0
- package/package.json +7 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @atlaskit/editor-toolbar
|
|
2
2
|
|
|
3
|
+
## 0.16.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`238f9a879ab1d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/238f9a879ab1d) -
|
|
8
|
+
Add left and right arrow keyboard shortcuts to selection toolbar
|
|
9
|
+
|
|
10
|
+
## 0.16.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- [`0d64de95a912a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0d64de95a912a) -
|
|
15
|
+
Allow editor ToolbarButton to take id as a prop
|
|
16
|
+
|
|
3
17
|
## 0.15.4
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -31,6 +31,7 @@ var ToolbarButton = exports.ToolbarButton = /*#__PURE__*/(0, _react.forwardRef)(
|
|
|
31
31
|
onBlur = _ref.onBlur,
|
|
32
32
|
onFocus = _ref.onFocus,
|
|
33
33
|
testId = _ref.testId,
|
|
34
|
+
id = _ref.id,
|
|
34
35
|
isDisabled = _ref.isDisabled,
|
|
35
36
|
ariaKeyshortcuts = _ref.ariaKeyshortcuts,
|
|
36
37
|
label = _ref.label,
|
|
@@ -53,6 +54,7 @@ var ToolbarButton = exports.ToolbarButton = /*#__PURE__*/(0, _react.forwardRef)(
|
|
|
53
54
|
onBlur: onBlur,
|
|
54
55
|
onFocus: onFocus,
|
|
55
56
|
testId: testId,
|
|
57
|
+
id: id,
|
|
56
58
|
isDisabled: disabled,
|
|
57
59
|
onMouseDown: function onMouseDown(event) {
|
|
58
60
|
if (preventDefaultOnMouseDown) {
|
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.ToolbarKeyboardNavigationProvider = void 0;
|
|
8
8
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
var _browserApis = require("@atlaskit/browser-apis");
|
|
10
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
9
11
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
10
12
|
var ToolbarKeyboardNavigationProvider = exports.ToolbarKeyboardNavigationProvider = function ToolbarKeyboardNavigationProvider(_ref) {
|
|
11
13
|
var children = _ref.children,
|
|
@@ -22,16 +24,84 @@ var ToolbarKeyboardNavigationProvider = exports.ToolbarKeyboardNavigationProvide
|
|
|
22
24
|
return;
|
|
23
25
|
}
|
|
24
26
|
var element = wrapperRef.current;
|
|
27
|
+
var getFocusableElements = function getFocusableElements() {
|
|
28
|
+
if (!element) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
// Find all focusable elements within the toolbar that match the child component selector
|
|
32
|
+
var focusableSelectors = ['button:not([disabled])', '[role="button"]:not([disabled])', '[tabindex]:not([tabindex="-1"])'].join(',');
|
|
33
|
+
var allFocusable = Array.from(element.querySelectorAll(focusableSelectors));
|
|
34
|
+
|
|
35
|
+
// Filter to only include elements that are:
|
|
36
|
+
// 1. Within the child component selector
|
|
37
|
+
// 2. Visible (not hidden by display:none on itself or any parent)
|
|
38
|
+
return allFocusable.filter(function (el) {
|
|
39
|
+
if (!el.closest("".concat(childComponentSelector))) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Check if the element or any of its parents have display: none
|
|
44
|
+
var currentEl = el;
|
|
45
|
+
while (currentEl && currentEl !== element) {
|
|
46
|
+
var computedStyle = window.getComputedStyle(currentEl);
|
|
47
|
+
if (computedStyle.display === 'none' || computedStyle.visibility === 'hidden') {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
currentEl = currentEl.parentElement;
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
var moveFocus = function moveFocus(direction) {
|
|
56
|
+
var _focusableElements$ne;
|
|
57
|
+
var focusableElements = getFocusableElements();
|
|
58
|
+
if (focusableElements.length === 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
var doc = (0, _browserApis.getDocument)();
|
|
62
|
+
var currentIndex = focusableElements.findIndex(function (el) {
|
|
63
|
+
return el === (doc === null || doc === void 0 ? void 0 : doc.activeElement);
|
|
64
|
+
});
|
|
65
|
+
var nextIndex;
|
|
66
|
+
if (currentIndex === -1) {
|
|
67
|
+
// No element currently focused, focus the first one
|
|
68
|
+
nextIndex = 0;
|
|
69
|
+
} else if (direction === 'right') {
|
|
70
|
+
// Move right, wrap to beginning if at end
|
|
71
|
+
nextIndex = (currentIndex + 1) % focusableElements.length;
|
|
72
|
+
} else {
|
|
73
|
+
// Move left, wrap to end if at beginning
|
|
74
|
+
nextIndex = currentIndex === 0 ? focusableElements.length - 1 : currentIndex - 1;
|
|
75
|
+
}
|
|
76
|
+
(_focusableElements$ne = focusableElements[nextIndex]) === null || _focusableElements$ne === void 0 || _focusableElements$ne.focus();
|
|
77
|
+
};
|
|
25
78
|
var handleKeyDown = function handleKeyDown(event) {
|
|
26
79
|
var targetElement = event.target;
|
|
27
80
|
if (targetElement instanceof HTMLElement && !targetElement.closest("".concat(childComponentSelector))) {
|
|
28
81
|
return;
|
|
29
82
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
83
|
+
if ((0, _platformFeatureFlags.fg)('platform_editor_toolbar_aifc_patch_7')) {
|
|
84
|
+
switch (event.key) {
|
|
85
|
+
case 'Escape':
|
|
86
|
+
handleEscape(event);
|
|
87
|
+
break;
|
|
88
|
+
case 'ArrowLeft':
|
|
89
|
+
event.preventDefault();
|
|
90
|
+
moveFocus('left');
|
|
91
|
+
break;
|
|
92
|
+
case 'ArrowRight':
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
moveFocus('right');
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
switch (event.key) {
|
|
100
|
+
case 'Escape':
|
|
101
|
+
handleEscape(event);
|
|
102
|
+
break;
|
|
103
|
+
default:
|
|
104
|
+
}
|
|
35
105
|
}
|
|
36
106
|
};
|
|
37
107
|
var globalKeyDownHandler = function globalKeyDownHandler(event) {
|
|
@@ -23,6 +23,7 @@ export const ToolbarButton = /*#__PURE__*/forwardRef(({
|
|
|
23
23
|
onBlur,
|
|
24
24
|
onFocus,
|
|
25
25
|
testId,
|
|
26
|
+
id,
|
|
26
27
|
isDisabled,
|
|
27
28
|
ariaKeyshortcuts,
|
|
28
29
|
label,
|
|
@@ -47,6 +48,7 @@ export const ToolbarButton = /*#__PURE__*/forwardRef(({
|
|
|
47
48
|
onBlur: onBlur,
|
|
48
49
|
onFocus: onFocus,
|
|
49
50
|
testId: testId,
|
|
51
|
+
id: id,
|
|
50
52
|
isDisabled: disabled,
|
|
51
53
|
onMouseDown: event => {
|
|
52
54
|
if (preventDefaultOnMouseDown) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import React, { useLayoutEffect, useRef } from 'react';
|
|
2
|
+
import { getDocument } from '@atlaskit/browser-apis';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
2
4
|
export const ToolbarKeyboardNavigationProvider = ({
|
|
3
5
|
children,
|
|
4
6
|
childComponentSelector,
|
|
@@ -17,16 +19,82 @@ export const ToolbarKeyboardNavigationProvider = ({
|
|
|
17
19
|
const {
|
|
18
20
|
current: element
|
|
19
21
|
} = wrapperRef;
|
|
22
|
+
const getFocusableElements = () => {
|
|
23
|
+
if (!element) {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
// Find all focusable elements within the toolbar that match the child component selector
|
|
27
|
+
const focusableSelectors = ['button:not([disabled])', '[role="button"]:not([disabled])', '[tabindex]:not([tabindex="-1"])'].join(',');
|
|
28
|
+
const allFocusable = Array.from(element.querySelectorAll(focusableSelectors));
|
|
29
|
+
|
|
30
|
+
// Filter to only include elements that are:
|
|
31
|
+
// 1. Within the child component selector
|
|
32
|
+
// 2. Visible (not hidden by display:none on itself or any parent)
|
|
33
|
+
return allFocusable.filter(el => {
|
|
34
|
+
if (!el.closest(`${childComponentSelector}`)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check if the element or any of its parents have display: none
|
|
39
|
+
let currentEl = el;
|
|
40
|
+
while (currentEl && currentEl !== element) {
|
|
41
|
+
const computedStyle = window.getComputedStyle(currentEl);
|
|
42
|
+
if (computedStyle.display === 'none' || computedStyle.visibility === 'hidden') {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
currentEl = currentEl.parentElement;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
const moveFocus = direction => {
|
|
51
|
+
var _focusableElements$ne;
|
|
52
|
+
const focusableElements = getFocusableElements();
|
|
53
|
+
if (focusableElements.length === 0) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const doc = getDocument();
|
|
57
|
+
const currentIndex = focusableElements.findIndex(el => el === (doc === null || doc === void 0 ? void 0 : doc.activeElement));
|
|
58
|
+
let nextIndex;
|
|
59
|
+
if (currentIndex === -1) {
|
|
60
|
+
// No element currently focused, focus the first one
|
|
61
|
+
nextIndex = 0;
|
|
62
|
+
} else if (direction === 'right') {
|
|
63
|
+
// Move right, wrap to beginning if at end
|
|
64
|
+
nextIndex = (currentIndex + 1) % focusableElements.length;
|
|
65
|
+
} else {
|
|
66
|
+
// Move left, wrap to end if at beginning
|
|
67
|
+
nextIndex = currentIndex === 0 ? focusableElements.length - 1 : currentIndex - 1;
|
|
68
|
+
}
|
|
69
|
+
(_focusableElements$ne = focusableElements[nextIndex]) === null || _focusableElements$ne === void 0 ? void 0 : _focusableElements$ne.focus();
|
|
70
|
+
};
|
|
20
71
|
const handleKeyDown = event => {
|
|
21
72
|
const targetElement = event.target;
|
|
22
73
|
if (targetElement instanceof HTMLElement && !targetElement.closest(`${childComponentSelector}`)) {
|
|
23
74
|
return;
|
|
24
75
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
76
|
+
if (fg('platform_editor_toolbar_aifc_patch_7')) {
|
|
77
|
+
switch (event.key) {
|
|
78
|
+
case 'Escape':
|
|
79
|
+
handleEscape(event);
|
|
80
|
+
break;
|
|
81
|
+
case 'ArrowLeft':
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
moveFocus('left');
|
|
84
|
+
break;
|
|
85
|
+
case 'ArrowRight':
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
moveFocus('right');
|
|
88
|
+
break;
|
|
89
|
+
default:
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
switch (event.key) {
|
|
93
|
+
case 'Escape':
|
|
94
|
+
handleEscape(event);
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
}
|
|
30
98
|
}
|
|
31
99
|
};
|
|
32
100
|
const globalKeyDownHandler = event => {
|
|
@@ -23,6 +23,7 @@ export var ToolbarButton = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
23
23
|
onBlur = _ref.onBlur,
|
|
24
24
|
onFocus = _ref.onFocus,
|
|
25
25
|
testId = _ref.testId,
|
|
26
|
+
id = _ref.id,
|
|
26
27
|
isDisabled = _ref.isDisabled,
|
|
27
28
|
ariaKeyshortcuts = _ref.ariaKeyshortcuts,
|
|
28
29
|
label = _ref.label,
|
|
@@ -45,6 +46,7 @@ export var ToolbarButton = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
45
46
|
onBlur: onBlur,
|
|
46
47
|
onFocus: onFocus,
|
|
47
48
|
testId: testId,
|
|
49
|
+
id: id,
|
|
48
50
|
isDisabled: disabled,
|
|
49
51
|
onMouseDown: function onMouseDown(event) {
|
|
50
52
|
if (preventDefaultOnMouseDown) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import React, { useLayoutEffect, useRef } from 'react';
|
|
2
|
+
import { getDocument } from '@atlaskit/browser-apis';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
2
4
|
export var ToolbarKeyboardNavigationProvider = function ToolbarKeyboardNavigationProvider(_ref) {
|
|
3
5
|
var children = _ref.children,
|
|
4
6
|
childComponentSelector = _ref.childComponentSelector,
|
|
@@ -14,16 +16,84 @@ export var ToolbarKeyboardNavigationProvider = function ToolbarKeyboardNavigatio
|
|
|
14
16
|
return;
|
|
15
17
|
}
|
|
16
18
|
var element = wrapperRef.current;
|
|
19
|
+
var getFocusableElements = function getFocusableElements() {
|
|
20
|
+
if (!element) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
// Find all focusable elements within the toolbar that match the child component selector
|
|
24
|
+
var focusableSelectors = ['button:not([disabled])', '[role="button"]:not([disabled])', '[tabindex]:not([tabindex="-1"])'].join(',');
|
|
25
|
+
var allFocusable = Array.from(element.querySelectorAll(focusableSelectors));
|
|
26
|
+
|
|
27
|
+
// Filter to only include elements that are:
|
|
28
|
+
// 1. Within the child component selector
|
|
29
|
+
// 2. Visible (not hidden by display:none on itself or any parent)
|
|
30
|
+
return allFocusable.filter(function (el) {
|
|
31
|
+
if (!el.closest("".concat(childComponentSelector))) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Check if the element or any of its parents have display: none
|
|
36
|
+
var currentEl = el;
|
|
37
|
+
while (currentEl && currentEl !== element) {
|
|
38
|
+
var computedStyle = window.getComputedStyle(currentEl);
|
|
39
|
+
if (computedStyle.display === 'none' || computedStyle.visibility === 'hidden') {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
currentEl = currentEl.parentElement;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
var moveFocus = function moveFocus(direction) {
|
|
48
|
+
var _focusableElements$ne;
|
|
49
|
+
var focusableElements = getFocusableElements();
|
|
50
|
+
if (focusableElements.length === 0) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
var doc = getDocument();
|
|
54
|
+
var currentIndex = focusableElements.findIndex(function (el) {
|
|
55
|
+
return el === (doc === null || doc === void 0 ? void 0 : doc.activeElement);
|
|
56
|
+
});
|
|
57
|
+
var nextIndex;
|
|
58
|
+
if (currentIndex === -1) {
|
|
59
|
+
// No element currently focused, focus the first one
|
|
60
|
+
nextIndex = 0;
|
|
61
|
+
} else if (direction === 'right') {
|
|
62
|
+
// Move right, wrap to beginning if at end
|
|
63
|
+
nextIndex = (currentIndex + 1) % focusableElements.length;
|
|
64
|
+
} else {
|
|
65
|
+
// Move left, wrap to end if at beginning
|
|
66
|
+
nextIndex = currentIndex === 0 ? focusableElements.length - 1 : currentIndex - 1;
|
|
67
|
+
}
|
|
68
|
+
(_focusableElements$ne = focusableElements[nextIndex]) === null || _focusableElements$ne === void 0 || _focusableElements$ne.focus();
|
|
69
|
+
};
|
|
17
70
|
var handleKeyDown = function handleKeyDown(event) {
|
|
18
71
|
var targetElement = event.target;
|
|
19
72
|
if (targetElement instanceof HTMLElement && !targetElement.closest("".concat(childComponentSelector))) {
|
|
20
73
|
return;
|
|
21
74
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
75
|
+
if (fg('platform_editor_toolbar_aifc_patch_7')) {
|
|
76
|
+
switch (event.key) {
|
|
77
|
+
case 'Escape':
|
|
78
|
+
handleEscape(event);
|
|
79
|
+
break;
|
|
80
|
+
case 'ArrowLeft':
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
moveFocus('left');
|
|
83
|
+
break;
|
|
84
|
+
case 'ArrowRight':
|
|
85
|
+
event.preventDefault();
|
|
86
|
+
moveFocus('right');
|
|
87
|
+
break;
|
|
88
|
+
default:
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
switch (event.key) {
|
|
92
|
+
case 'Escape':
|
|
93
|
+
handleEscape(event);
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
}
|
|
27
97
|
}
|
|
28
98
|
};
|
|
29
99
|
var globalKeyDownHandler = function globalKeyDownHandler(event) {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"registry": "https://registry.npmjs.org/"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.16.1",
|
|
7
7
|
"description": "Common UI for Toolbars across the platform",
|
|
8
8
|
"atlassian": {
|
|
9
9
|
"team": "Editor: Jenga",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"atlaskit:src": "src/index.ts",
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@atlaskit/badge": "^18.2.0",
|
|
25
|
+
"@atlaskit/browser-apis": "^0.0.1",
|
|
25
26
|
"@atlaskit/button": "^23.5.0",
|
|
26
27
|
"@atlaskit/css": "^0.15.0",
|
|
27
28
|
"@atlaskit/dropdown-menu": "^16.3.0",
|
|
@@ -32,9 +33,9 @@
|
|
|
32
33
|
"@atlaskit/platform-feature-flags-react": "^0.3.0",
|
|
33
34
|
"@atlaskit/popup": "^4.4.0",
|
|
34
35
|
"@atlaskit/primitives": "^16.0.0",
|
|
35
|
-
"@atlaskit/tmp-editor-statsig": "^13.
|
|
36
|
+
"@atlaskit/tmp-editor-statsig": "^13.18.0",
|
|
36
37
|
"@atlaskit/tokens": "^7.0.0",
|
|
37
|
-
"@atlaskit/tooltip": "^20.
|
|
38
|
+
"@atlaskit/tooltip": "^20.6.0",
|
|
38
39
|
"@babel/runtime": "^7.0.0",
|
|
39
40
|
"@compiled/react": "^0.18.6",
|
|
40
41
|
"chromatism": "^2.6.0"
|
|
@@ -88,6 +89,9 @@
|
|
|
88
89
|
"platform-feature-flags": {
|
|
89
90
|
"platform_editor_ai_rovo_rebrand": {
|
|
90
91
|
"type": "boolean"
|
|
92
|
+
},
|
|
93
|
+
"platform_editor_toolbar_aifc_patch_7": {
|
|
94
|
+
"type": "boolean"
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
97
|
}
|