@react-aria/toolbar 3.0.0-beta.21 → 3.0.0-beta.23
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/dist/useToolbar.main.js
CHANGED
|
@@ -38,7 +38,7 @@ function $b132ee173e26a273$export$fa142eb1681c520(props, ref) {
|
|
|
38
38
|
let focusManager = (0, $37ePF$reactariafocus.createFocusManager)(ref);
|
|
39
39
|
const onKeyDown = (e)=>{
|
|
40
40
|
// don't handle portalled events
|
|
41
|
-
if (!e.currentTarget
|
|
41
|
+
if (!(0, $37ePF$reactariautils.nodeContains)(e.currentTarget, e.target)) return;
|
|
42
42
|
if (orientation === 'horizontal' && e.key === 'ArrowRight' || orientation === 'vertical' && e.key === 'ArrowDown') {
|
|
43
43
|
if (shouldReverse) focusManager.focusPrevious();
|
|
44
44
|
else focusManager.focusNext();
|
|
@@ -64,14 +64,13 @@ function $b132ee173e26a273$export$fa142eb1681c520(props, ref) {
|
|
|
64
64
|
// Record the last focused child when focus moves out of the toolbar.
|
|
65
65
|
const lastFocused = (0, $37ePF$react.useRef)(null);
|
|
66
66
|
const onBlur = (e)=>{
|
|
67
|
-
if (!e.currentTarget
|
|
67
|
+
if (!(0, $37ePF$reactariautils.nodeContains)(e.currentTarget, e.relatedTarget) && !lastFocused.current) lastFocused.current = e.target;
|
|
68
68
|
};
|
|
69
69
|
// Restore focus to the last focused child when focus returns into the toolbar.
|
|
70
70
|
// If the element was removed, do nothing, either the first item in the first group,
|
|
71
71
|
// or the last item in the last group will be focused, depending on direction.
|
|
72
72
|
const onFocus = (e)=>{
|
|
73
|
-
|
|
74
|
-
if (lastFocused.current && !e.currentTarget.contains(e.relatedTarget) && ((_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.contains(e.target))) {
|
|
73
|
+
if (lastFocused.current && !(0, $37ePF$reactariautils.nodeContains)(e.currentTarget, e.relatedTarget) && (0, $37ePF$reactariautils.nodeContains)(ref.current, e.target)) {
|
|
75
74
|
var _lastFocused_current;
|
|
76
75
|
(_lastFocused_current = lastFocused.current) === null || _lastFocused_current === void 0 ? void 0 : _lastFocused_current.focus();
|
|
77
76
|
lastFocused.current = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;AA6BM,SAAS,yCAAW,KAAuB,EAAE,GAAkC;IACpF,MAAM,EACJ,cAAc,SAAS,EACvB,mBAAmB,cAAc,eACjC,cAAc,cACf,GAAG;IACJ,IAAI,CAAC,aAAa,aAAa,GAAG,CAAA,GAAA,qBAAO,EAAE;IAC3C,4FAA4F;IAC5F,mFAAmF;IACnF,uDAAuD;IACvD,CAAA,GAAA,qCAAc,EAAE;YACiB;QAA/B,aAAa,CAAC,CAAE,CAAA,IAAI,OAAO,MAAI,6BAAA,IAAI,OAAO,CAAC,aAAa,cAAzB,iDAAA,2BAA2B,OAAO,CAAC,oBAAkB;IACtF;IACA,MAAM,aAAC,SAAS,EAAC,GAAG,CAAA,GAAA,8BAAQ;IAC5B,MAAM,gBAAgB,cAAc,SAAS,gBAAgB;IAC7D,IAAI,eAAe,CAAA,GAAA,wCAAiB,EAAE;IAEtC,MAAM,YAAkC,CAAC;QACvC,gCAAgC;QAChC,IAAI,CAAC,
|
|
1
|
+
{"mappings":";;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;AA6BM,SAAS,yCAAW,KAAuB,EAAE,GAAkC;IACpF,MAAM,EACJ,cAAc,SAAS,EACvB,mBAAmB,cAAc,eACjC,cAAc,cACf,GAAG;IACJ,IAAI,CAAC,aAAa,aAAa,GAAG,CAAA,GAAA,qBAAO,EAAE;IAC3C,4FAA4F;IAC5F,mFAAmF;IACnF,uDAAuD;IACvD,CAAA,GAAA,qCAAc,EAAE;YACiB;QAA/B,aAAa,CAAC,CAAE,CAAA,IAAI,OAAO,MAAI,6BAAA,IAAI,OAAO,CAAC,aAAa,cAAzB,iDAAA,2BAA2B,OAAO,CAAC,oBAAkB;IACtF;IACA,MAAM,aAAC,SAAS,EAAC,GAAG,CAAA,GAAA,8BAAQ;IAC5B,MAAM,gBAAgB,cAAc,SAAS,gBAAgB;IAC7D,IAAI,eAAe,CAAA,GAAA,wCAAiB,EAAE;IAEtC,MAAM,YAAkC,CAAC;QACvC,gCAAgC;QAChC,IAAI,CAAC,CAAA,GAAA,kCAAW,EAAE,EAAE,aAAa,EAAE,EAAE,MAAM,GACzC;QAEF,IACE,AAAC,gBAAgB,gBAAgB,EAAE,GAAG,KAAK,gBACvC,gBAAgB,cAAc,EAAE,GAAG,KAAK;YAC5C,IAAI,eACF,aAAa,aAAa;iBAE1B,aAAa,SAAS;eAEnB,IACL,AAAC,gBAAgB,gBAAgB,EAAE,GAAG,KAAK,eACvC,gBAAgB,cAAc,EAAE,GAAG,KAAK;YAC5C,IAAI,eACF,aAAa,SAAS;iBAEtB,aAAa,aAAa;eAEvB,IAAI,EAAE,GAAG,KAAK,OAAO;YAC1B,qDAAqD;YACrD,oDAAoD;YACpD,oDAAoD;YACpD,kDAAkD;YAClD,EAAE,eAAe;YACjB,YAAY,OAAO,GAAG,SAAS,aAAa;YAC5C,IAAI,EAAE,QAAQ,EACZ,aAAa,UAAU;iBAEvB,aAAa,SAAS;YAExB;QACF,OACE,wEAAwE;QACxE;QAGF,iEAAiE;QACjE,EAAE,eAAe;QACjB,EAAE,cAAc;IAClB;IAEA,qEAAqE;IACrE,MAAM,cAAc,CAAA,GAAA,mBAAK,EAAsB;IAC/C,MAAM,SAAS,CAAC;QACd,IAAI,CAAC,CAAA,GAAA,kCAAW,EAAE,EAAE,aAAa,EAAE,EAAE,aAAa,KAAK,CAAC,YAAY,OAAO,EACzE,YAAY,OAAO,GAAG,EAAE,MAAM;IAElC;IAEA,+EAA+E;IAC/E,oFAAoF;IACpF,8EAA8E;IAC9E,MAAM,UAAU,CAAC;QACf,IAAI,YAAY,OAAO,IAAI,CAAC,CAAA,GAAA,kCAAW,EAAE,EAAE,aAAa,EAAE,EAAE,aAAa,KAAK,CAAA,GAAA,kCAAW,EAAE,IAAI,OAAO,EAAE,EAAE,MAAM,GAAG;gBACjH;aAAA,uBAAA,YAAY,OAAO,cAAnB,2CAAA,qBAAqB,KAAK;YAC1B,YAAY,OAAO,GAAG;QACxB;IACF;IAEA,OAAO;QACL,cAAc;YACZ,GAAG,CAAA,GAAA,oCAAa,EAAE,OAAO;gBAAC,WAAW;YAAI,EAAE;YAC3C,MAAM,CAAC,cAAc,YAAY;YACjC,oBAAoB;YACpB,cAAc;YACd,mBAAmB,aAAa,OAAO,iBAAiB;YACxD,kBAAkB,CAAC,cAAc,YAAY;YAC7C,gBAAgB,CAAC,cAAc,UAAU;YACzC,eAAe,CAAC,cAAc,SAAS;QACzC;IACF;AACF","sources":["packages/@react-aria/toolbar/src/useToolbar.ts"],"sourcesContent":["/*\n * Copyright 2023 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaLabelingProps, Orientation, RefObject} from '@react-types/shared';\nimport {createFocusManager} from '@react-aria/focus';\nimport {filterDOMProps, nodeContains, useLayoutEffect} from '@react-aria/utils';\nimport {HTMLAttributes, KeyboardEventHandler, useRef, useState} from 'react';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface AriaToolbarProps extends AriaLabelingProps {\n /**\n * The orientation of the entire toolbar.\n * @default 'horizontal'\n */\n orientation?: Orientation\n}\n\nexport interface ToolbarAria {\n /**\n * Props for the toolbar container.\n */\n toolbarProps: HTMLAttributes<HTMLElement>\n}\n\n/**\n * Provides the behavior and accessibility implementation for a toolbar.\n * A toolbar is a container for a set of interactive controls with arrow key navigation.\n * @param props - Props to be applied to the toolbar.\n * @param ref - A ref to a DOM element for the toolbar.\n */\nexport function useToolbar(props: AriaToolbarProps, ref: RefObject<HTMLElement | null>): ToolbarAria {\n const {\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n orientation = 'horizontal'\n } = props;\n let [isInToolbar, setInToolbar] = useState(false);\n // should be safe because re-calling set state with the same value it already has is a no-op\n // this will allow us to react should a parent re-render and change its role though\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(() => {\n setInToolbar(!!(ref.current && ref.current.parentElement?.closest('[role=\"toolbar\"]')));\n });\n const {direction} = useLocale();\n const shouldReverse = direction === 'rtl' && orientation === 'horizontal';\n let focusManager = createFocusManager(ref);\n\n const onKeyDown: KeyboardEventHandler = (e) => {\n // don't handle portalled events\n if (!nodeContains(e.currentTarget, e.target as HTMLElement)) {\n return;\n }\n if (\n (orientation === 'horizontal' && e.key === 'ArrowRight')\n || (orientation === 'vertical' && e.key === 'ArrowDown')) {\n if (shouldReverse) {\n focusManager.focusPrevious();\n } else {\n focusManager.focusNext();\n }\n } else if (\n (orientation === 'horizontal' && e.key === 'ArrowLeft')\n || (orientation === 'vertical' && e.key === 'ArrowUp')) {\n if (shouldReverse) {\n focusManager.focusNext();\n } else {\n focusManager.focusPrevious();\n }\n } else if (e.key === 'Tab') {\n // When the tab key is pressed, we want to move focus\n // out of the entire toolbar. To do this, move focus\n // to the first or last focusable child, and let the\n // browser handle the Tab key as usual from there.\n e.stopPropagation();\n lastFocused.current = document.activeElement as HTMLElement;\n if (e.shiftKey) {\n focusManager.focusFirst();\n } else {\n focusManager.focusLast();\n }\n return;\n } else {\n // if we didn't handle anything, return early so we don't preventDefault\n return;\n }\n\n // Prevent arrow keys from being handled by nested action groups.\n e.stopPropagation();\n e.preventDefault();\n };\n\n // Record the last focused child when focus moves out of the toolbar.\n const lastFocused = useRef<HTMLElement | null>(null);\n const onBlur = (e) => {\n if (!nodeContains(e.currentTarget, e.relatedTarget) && !lastFocused.current) {\n lastFocused.current = e.target;\n }\n };\n\n // Restore focus to the last focused child when focus returns into the toolbar.\n // If the element was removed, do nothing, either the first item in the first group,\n // or the last item in the last group will be focused, depending on direction.\n const onFocus = (e) => {\n if (lastFocused.current && !nodeContains(e.currentTarget, e.relatedTarget) && nodeContains(ref.current, e.target)) {\n lastFocused.current?.focus();\n lastFocused.current = null;\n }\n };\n\n return {\n toolbarProps: {\n ...filterDOMProps(props, {labelable: true}),\n role: !isInToolbar ? 'toolbar' : 'group',\n 'aria-orientation': orientation,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabel == null ? ariaLabelledBy : undefined,\n onKeyDownCapture: !isInToolbar ? onKeyDown : undefined,\n onFocusCapture: !isInToolbar ? onFocus : undefined,\n onBlurCapture: !isInToolbar ? onBlur : undefined\n }\n };\n}\n"],"names":[],"version":3,"file":"useToolbar.main.js.map"}
|
package/dist/useToolbar.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {createFocusManager as $k3LOe$createFocusManager} from "@react-aria/focus";
|
|
2
|
-
import {useLayoutEffect as $k3LOe$useLayoutEffect, filterDOMProps as $k3LOe$filterDOMProps} from "@react-aria/utils";
|
|
2
|
+
import {useLayoutEffect as $k3LOe$useLayoutEffect, nodeContains as $k3LOe$nodeContains, filterDOMProps as $k3LOe$filterDOMProps} from "@react-aria/utils";
|
|
3
3
|
import {useState as $k3LOe$useState, useRef as $k3LOe$useRef} from "react";
|
|
4
4
|
import {useLocale as $k3LOe$useLocale} from "@react-aria/i18n";
|
|
5
5
|
|
|
@@ -32,7 +32,7 @@ function $2680b1829e803644$export$fa142eb1681c520(props, ref) {
|
|
|
32
32
|
let focusManager = (0, $k3LOe$createFocusManager)(ref);
|
|
33
33
|
const onKeyDown = (e)=>{
|
|
34
34
|
// don't handle portalled events
|
|
35
|
-
if (!e.currentTarget
|
|
35
|
+
if (!(0, $k3LOe$nodeContains)(e.currentTarget, e.target)) return;
|
|
36
36
|
if (orientation === 'horizontal' && e.key === 'ArrowRight' || orientation === 'vertical' && e.key === 'ArrowDown') {
|
|
37
37
|
if (shouldReverse) focusManager.focusPrevious();
|
|
38
38
|
else focusManager.focusNext();
|
|
@@ -58,14 +58,13 @@ function $2680b1829e803644$export$fa142eb1681c520(props, ref) {
|
|
|
58
58
|
// Record the last focused child when focus moves out of the toolbar.
|
|
59
59
|
const lastFocused = (0, $k3LOe$useRef)(null);
|
|
60
60
|
const onBlur = (e)=>{
|
|
61
|
-
if (!e.currentTarget
|
|
61
|
+
if (!(0, $k3LOe$nodeContains)(e.currentTarget, e.relatedTarget) && !lastFocused.current) lastFocused.current = e.target;
|
|
62
62
|
};
|
|
63
63
|
// Restore focus to the last focused child when focus returns into the toolbar.
|
|
64
64
|
// If the element was removed, do nothing, either the first item in the first group,
|
|
65
65
|
// or the last item in the last group will be focused, depending on direction.
|
|
66
66
|
const onFocus = (e)=>{
|
|
67
|
-
|
|
68
|
-
if (lastFocused.current && !e.currentTarget.contains(e.relatedTarget) && ((_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.contains(e.target))) {
|
|
67
|
+
if (lastFocused.current && !(0, $k3LOe$nodeContains)(e.currentTarget, e.relatedTarget) && (0, $k3LOe$nodeContains)(ref.current, e.target)) {
|
|
69
68
|
var _lastFocused_current;
|
|
70
69
|
(_lastFocused_current = lastFocused.current) === null || _lastFocused_current === void 0 ? void 0 : _lastFocused_current.focus();
|
|
71
70
|
lastFocused.current = null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {createFocusManager as $k3LOe$createFocusManager} from "@react-aria/focus";
|
|
2
|
-
import {useLayoutEffect as $k3LOe$useLayoutEffect, filterDOMProps as $k3LOe$filterDOMProps} from "@react-aria/utils";
|
|
2
|
+
import {useLayoutEffect as $k3LOe$useLayoutEffect, nodeContains as $k3LOe$nodeContains, filterDOMProps as $k3LOe$filterDOMProps} from "@react-aria/utils";
|
|
3
3
|
import {useState as $k3LOe$useState, useRef as $k3LOe$useRef} from "react";
|
|
4
4
|
import {useLocale as $k3LOe$useLocale} from "@react-aria/i18n";
|
|
5
5
|
|
|
@@ -32,7 +32,7 @@ function $2680b1829e803644$export$fa142eb1681c520(props, ref) {
|
|
|
32
32
|
let focusManager = (0, $k3LOe$createFocusManager)(ref);
|
|
33
33
|
const onKeyDown = (e)=>{
|
|
34
34
|
// don't handle portalled events
|
|
35
|
-
if (!e.currentTarget
|
|
35
|
+
if (!(0, $k3LOe$nodeContains)(e.currentTarget, e.target)) return;
|
|
36
36
|
if (orientation === 'horizontal' && e.key === 'ArrowRight' || orientation === 'vertical' && e.key === 'ArrowDown') {
|
|
37
37
|
if (shouldReverse) focusManager.focusPrevious();
|
|
38
38
|
else focusManager.focusNext();
|
|
@@ -58,14 +58,13 @@ function $2680b1829e803644$export$fa142eb1681c520(props, ref) {
|
|
|
58
58
|
// Record the last focused child when focus moves out of the toolbar.
|
|
59
59
|
const lastFocused = (0, $k3LOe$useRef)(null);
|
|
60
60
|
const onBlur = (e)=>{
|
|
61
|
-
if (!e.currentTarget
|
|
61
|
+
if (!(0, $k3LOe$nodeContains)(e.currentTarget, e.relatedTarget) && !lastFocused.current) lastFocused.current = e.target;
|
|
62
62
|
};
|
|
63
63
|
// Restore focus to the last focused child when focus returns into the toolbar.
|
|
64
64
|
// If the element was removed, do nothing, either the first item in the first group,
|
|
65
65
|
// or the last item in the last group will be focused, depending on direction.
|
|
66
66
|
const onFocus = (e)=>{
|
|
67
|
-
|
|
68
|
-
if (lastFocused.current && !e.currentTarget.contains(e.relatedTarget) && ((_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.contains(e.target))) {
|
|
67
|
+
if (lastFocused.current && !(0, $k3LOe$nodeContains)(e.currentTarget, e.relatedTarget) && (0, $k3LOe$nodeContains)(ref.current, e.target)) {
|
|
69
68
|
var _lastFocused_current;
|
|
70
69
|
(_lastFocused_current = lastFocused.current) === null || _lastFocused_current === void 0 ? void 0 : _lastFocused_current.focus();
|
|
71
70
|
lastFocused.current = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;AAAA;;;;;;;;;;CAUC;;;;AA6BM,SAAS,yCAAW,KAAuB,EAAE,GAAkC;IACpF,MAAM,EACJ,cAAc,SAAS,EACvB,mBAAmB,cAAc,eACjC,cAAc,cACf,GAAG;IACJ,IAAI,CAAC,aAAa,aAAa,GAAG,CAAA,GAAA,eAAO,EAAE;IAC3C,4FAA4F;IAC5F,mFAAmF;IACnF,uDAAuD;IACvD,CAAA,GAAA,sBAAc,EAAE;YACiB;QAA/B,aAAa,CAAC,CAAE,CAAA,IAAI,OAAO,MAAI,6BAAA,IAAI,OAAO,CAAC,aAAa,cAAzB,iDAAA,2BAA2B,OAAO,CAAC,oBAAkB;IACtF;IACA,MAAM,aAAC,SAAS,EAAC,GAAG,CAAA,GAAA,gBAAQ;IAC5B,MAAM,gBAAgB,cAAc,SAAS,gBAAgB;IAC7D,IAAI,eAAe,CAAA,GAAA,yBAAiB,EAAE;IAEtC,MAAM,YAAkC,CAAC;QACvC,gCAAgC;QAChC,IAAI,CAAC,
|
|
1
|
+
{"mappings":";;;;;AAAA;;;;;;;;;;CAUC;;;;AA6BM,SAAS,yCAAW,KAAuB,EAAE,GAAkC;IACpF,MAAM,EACJ,cAAc,SAAS,EACvB,mBAAmB,cAAc,eACjC,cAAc,cACf,GAAG;IACJ,IAAI,CAAC,aAAa,aAAa,GAAG,CAAA,GAAA,eAAO,EAAE;IAC3C,4FAA4F;IAC5F,mFAAmF;IACnF,uDAAuD;IACvD,CAAA,GAAA,sBAAc,EAAE;YACiB;QAA/B,aAAa,CAAC,CAAE,CAAA,IAAI,OAAO,MAAI,6BAAA,IAAI,OAAO,CAAC,aAAa,cAAzB,iDAAA,2BAA2B,OAAO,CAAC,oBAAkB;IACtF;IACA,MAAM,aAAC,SAAS,EAAC,GAAG,CAAA,GAAA,gBAAQ;IAC5B,MAAM,gBAAgB,cAAc,SAAS,gBAAgB;IAC7D,IAAI,eAAe,CAAA,GAAA,yBAAiB,EAAE;IAEtC,MAAM,YAAkC,CAAC;QACvC,gCAAgC;QAChC,IAAI,CAAC,CAAA,GAAA,mBAAW,EAAE,EAAE,aAAa,EAAE,EAAE,MAAM,GACzC;QAEF,IACE,AAAC,gBAAgB,gBAAgB,EAAE,GAAG,KAAK,gBACvC,gBAAgB,cAAc,EAAE,GAAG,KAAK;YAC5C,IAAI,eACF,aAAa,aAAa;iBAE1B,aAAa,SAAS;eAEnB,IACL,AAAC,gBAAgB,gBAAgB,EAAE,GAAG,KAAK,eACvC,gBAAgB,cAAc,EAAE,GAAG,KAAK;YAC5C,IAAI,eACF,aAAa,SAAS;iBAEtB,aAAa,aAAa;eAEvB,IAAI,EAAE,GAAG,KAAK,OAAO;YAC1B,qDAAqD;YACrD,oDAAoD;YACpD,oDAAoD;YACpD,kDAAkD;YAClD,EAAE,eAAe;YACjB,YAAY,OAAO,GAAG,SAAS,aAAa;YAC5C,IAAI,EAAE,QAAQ,EACZ,aAAa,UAAU;iBAEvB,aAAa,SAAS;YAExB;QACF,OACE,wEAAwE;QACxE;QAGF,iEAAiE;QACjE,EAAE,eAAe;QACjB,EAAE,cAAc;IAClB;IAEA,qEAAqE;IACrE,MAAM,cAAc,CAAA,GAAA,aAAK,EAAsB;IAC/C,MAAM,SAAS,CAAC;QACd,IAAI,CAAC,CAAA,GAAA,mBAAW,EAAE,EAAE,aAAa,EAAE,EAAE,aAAa,KAAK,CAAC,YAAY,OAAO,EACzE,YAAY,OAAO,GAAG,EAAE,MAAM;IAElC;IAEA,+EAA+E;IAC/E,oFAAoF;IACpF,8EAA8E;IAC9E,MAAM,UAAU,CAAC;QACf,IAAI,YAAY,OAAO,IAAI,CAAC,CAAA,GAAA,mBAAW,EAAE,EAAE,aAAa,EAAE,EAAE,aAAa,KAAK,CAAA,GAAA,mBAAW,EAAE,IAAI,OAAO,EAAE,EAAE,MAAM,GAAG;gBACjH;aAAA,uBAAA,YAAY,OAAO,cAAnB,2CAAA,qBAAqB,KAAK;YAC1B,YAAY,OAAO,GAAG;QACxB;IACF;IAEA,OAAO;QACL,cAAc;YACZ,GAAG,CAAA,GAAA,qBAAa,EAAE,OAAO;gBAAC,WAAW;YAAI,EAAE;YAC3C,MAAM,CAAC,cAAc,YAAY;YACjC,oBAAoB;YACpB,cAAc;YACd,mBAAmB,aAAa,OAAO,iBAAiB;YACxD,kBAAkB,CAAC,cAAc,YAAY;YAC7C,gBAAgB,CAAC,cAAc,UAAU;YACzC,eAAe,CAAC,cAAc,SAAS;QACzC;IACF;AACF","sources":["packages/@react-aria/toolbar/src/useToolbar.ts"],"sourcesContent":["/*\n * Copyright 2023 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaLabelingProps, Orientation, RefObject} from '@react-types/shared';\nimport {createFocusManager} from '@react-aria/focus';\nimport {filterDOMProps, nodeContains, useLayoutEffect} from '@react-aria/utils';\nimport {HTMLAttributes, KeyboardEventHandler, useRef, useState} from 'react';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface AriaToolbarProps extends AriaLabelingProps {\n /**\n * The orientation of the entire toolbar.\n * @default 'horizontal'\n */\n orientation?: Orientation\n}\n\nexport interface ToolbarAria {\n /**\n * Props for the toolbar container.\n */\n toolbarProps: HTMLAttributes<HTMLElement>\n}\n\n/**\n * Provides the behavior and accessibility implementation for a toolbar.\n * A toolbar is a container for a set of interactive controls with arrow key navigation.\n * @param props - Props to be applied to the toolbar.\n * @param ref - A ref to a DOM element for the toolbar.\n */\nexport function useToolbar(props: AriaToolbarProps, ref: RefObject<HTMLElement | null>): ToolbarAria {\n const {\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n orientation = 'horizontal'\n } = props;\n let [isInToolbar, setInToolbar] = useState(false);\n // should be safe because re-calling set state with the same value it already has is a no-op\n // this will allow us to react should a parent re-render and change its role though\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(() => {\n setInToolbar(!!(ref.current && ref.current.parentElement?.closest('[role=\"toolbar\"]')));\n });\n const {direction} = useLocale();\n const shouldReverse = direction === 'rtl' && orientation === 'horizontal';\n let focusManager = createFocusManager(ref);\n\n const onKeyDown: KeyboardEventHandler = (e) => {\n // don't handle portalled events\n if (!nodeContains(e.currentTarget, e.target as HTMLElement)) {\n return;\n }\n if (\n (orientation === 'horizontal' && e.key === 'ArrowRight')\n || (orientation === 'vertical' && e.key === 'ArrowDown')) {\n if (shouldReverse) {\n focusManager.focusPrevious();\n } else {\n focusManager.focusNext();\n }\n } else if (\n (orientation === 'horizontal' && e.key === 'ArrowLeft')\n || (orientation === 'vertical' && e.key === 'ArrowUp')) {\n if (shouldReverse) {\n focusManager.focusNext();\n } else {\n focusManager.focusPrevious();\n }\n } else if (e.key === 'Tab') {\n // When the tab key is pressed, we want to move focus\n // out of the entire toolbar. To do this, move focus\n // to the first or last focusable child, and let the\n // browser handle the Tab key as usual from there.\n e.stopPropagation();\n lastFocused.current = document.activeElement as HTMLElement;\n if (e.shiftKey) {\n focusManager.focusFirst();\n } else {\n focusManager.focusLast();\n }\n return;\n } else {\n // if we didn't handle anything, return early so we don't preventDefault\n return;\n }\n\n // Prevent arrow keys from being handled by nested action groups.\n e.stopPropagation();\n e.preventDefault();\n };\n\n // Record the last focused child when focus moves out of the toolbar.\n const lastFocused = useRef<HTMLElement | null>(null);\n const onBlur = (e) => {\n if (!nodeContains(e.currentTarget, e.relatedTarget) && !lastFocused.current) {\n lastFocused.current = e.target;\n }\n };\n\n // Restore focus to the last focused child when focus returns into the toolbar.\n // If the element was removed, do nothing, either the first item in the first group,\n // or the last item in the last group will be focused, depending on direction.\n const onFocus = (e) => {\n if (lastFocused.current && !nodeContains(e.currentTarget, e.relatedTarget) && nodeContains(ref.current, e.target)) {\n lastFocused.current?.focus();\n lastFocused.current = null;\n }\n };\n\n return {\n toolbarProps: {\n ...filterDOMProps(props, {labelable: true}),\n role: !isInToolbar ? 'toolbar' : 'group',\n 'aria-orientation': orientation,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabel == null ? ariaLabelledBy : undefined,\n onKeyDownCapture: !isInToolbar ? onKeyDown : undefined,\n onFocusCapture: !isInToolbar ? onFocus : undefined,\n onBlurCapture: !isInToolbar ? onBlur : undefined\n }\n };\n}\n"],"names":[],"version":3,"file":"useToolbar.module.js.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-aria/toolbar",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.23",
|
|
4
4
|
"description": "Spectrum UI components in React",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"url": "https://github.com/adobe/react-spectrum"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@react-aria/focus": "^3.21.
|
|
30
|
-
"@react-aria/i18n": "^3.12.
|
|
31
|
-
"@react-aria/utils": "^3.
|
|
32
|
-
"@react-types/shared": "^3.
|
|
29
|
+
"@react-aria/focus": "^3.21.4",
|
|
30
|
+
"@react-aria/i18n": "^3.12.15",
|
|
31
|
+
"@react-aria/utils": "^3.33.0",
|
|
32
|
+
"@react-types/shared": "^3.33.0",
|
|
33
33
|
"@swc/helpers": "^0.5.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"publishConfig": {
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "66e51757606b43a89ed02c574ca24517323a2ab9"
|
|
43
43
|
}
|
package/src/useToolbar.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import {AriaLabelingProps, Orientation, RefObject} from '@react-types/shared';
|
|
14
14
|
import {createFocusManager} from '@react-aria/focus';
|
|
15
|
-
import {filterDOMProps, useLayoutEffect} from '@react-aria/utils';
|
|
15
|
+
import {filterDOMProps, nodeContains, useLayoutEffect} from '@react-aria/utils';
|
|
16
16
|
import {HTMLAttributes, KeyboardEventHandler, useRef, useState} from 'react';
|
|
17
17
|
import {useLocale} from '@react-aria/i18n';
|
|
18
18
|
|
|
@@ -56,7 +56,7 @@ export function useToolbar(props: AriaToolbarProps, ref: RefObject<HTMLElement |
|
|
|
56
56
|
|
|
57
57
|
const onKeyDown: KeyboardEventHandler = (e) => {
|
|
58
58
|
// don't handle portalled events
|
|
59
|
-
if (!e.currentTarget
|
|
59
|
+
if (!nodeContains(e.currentTarget, e.target as HTMLElement)) {
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
62
|
if (
|
|
@@ -101,7 +101,7 @@ export function useToolbar(props: AriaToolbarProps, ref: RefObject<HTMLElement |
|
|
|
101
101
|
// Record the last focused child when focus moves out of the toolbar.
|
|
102
102
|
const lastFocused = useRef<HTMLElement | null>(null);
|
|
103
103
|
const onBlur = (e) => {
|
|
104
|
-
if (!e.currentTarget
|
|
104
|
+
if (!nodeContains(e.currentTarget, e.relatedTarget) && !lastFocused.current) {
|
|
105
105
|
lastFocused.current = e.target;
|
|
106
106
|
}
|
|
107
107
|
};
|
|
@@ -110,7 +110,7 @@ export function useToolbar(props: AriaToolbarProps, ref: RefObject<HTMLElement |
|
|
|
110
110
|
// If the element was removed, do nothing, either the first item in the first group,
|
|
111
111
|
// or the last item in the last group will be focused, depending on direction.
|
|
112
112
|
const onFocus = (e) => {
|
|
113
|
-
if (lastFocused.current && !e.currentTarget
|
|
113
|
+
if (lastFocused.current && !nodeContains(e.currentTarget, e.relatedTarget) && nodeContains(ref.current, e.target)) {
|
|
114
114
|
lastFocused.current?.focus();
|
|
115
115
|
lastFocused.current = null;
|
|
116
116
|
}
|