@elliemae/ds-hooks-keyboard-navigation 3.27.0-next.9 → 3.27.0
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/cjs/DSHooksKeyboardNavigation.js +27 -8
- package/dist/cjs/DSHooksKeyboardNavigation.js.map +2 -2
- package/dist/cjs/react-desc-prop-types.js +9 -5
- package/dist/cjs/react-desc-prop-types.js.map +2 -2
- package/dist/esm/DSHooksKeyboardNavigation.js +27 -8
- package/dist/esm/DSHooksKeyboardNavigation.js.map +2 -2
- package/dist/esm/react-desc-prop-types.js +9 -5
- package/dist/esm/react-desc-prop-types.js.map +2 -2
- package/dist/types/react-desc-prop-types.d.ts +4 -3
- package/package.json +4 -4
|
@@ -37,8 +37,15 @@ var import_react = require("react");
|
|
|
37
37
|
var import_ds_utilities = require("@elliemae/ds-utilities");
|
|
38
38
|
var import_ds_props_helpers = require("@elliemae/ds-props-helpers");
|
|
39
39
|
var import_react_desc_prop_types2 = require("./react-desc-prop-types.js");
|
|
40
|
+
const defaultFocusCriteria = () => true;
|
|
40
41
|
const useKeyboardNavigation = (props) => {
|
|
41
|
-
const {
|
|
42
|
+
const {
|
|
43
|
+
options,
|
|
44
|
+
direction = "agnostic",
|
|
45
|
+
disableRoving = false,
|
|
46
|
+
focusCriteria = defaultFocusCriteria,
|
|
47
|
+
onKeyDown: userOnKeyDown
|
|
48
|
+
} = props;
|
|
42
49
|
const [focusedOption, setFocusedOption] = (0, import_react.useState)(null);
|
|
43
50
|
const previousFocusedOption = (0, import_react.useRef)(null);
|
|
44
51
|
const focusedOptionMutable = (0, import_react.useRef)(null);
|
|
@@ -52,25 +59,37 @@ const useKeyboardNavigation = (props) => {
|
|
|
52
59
|
[focusedOption]
|
|
53
60
|
);
|
|
54
61
|
const handleParentOnBlur = (0, import_ds_utilities.useOnBlurOut)(config);
|
|
55
|
-
const
|
|
56
|
-
(
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
const prevArrowKeys = (0, import_react.useMemo)(() => {
|
|
63
|
+
if (direction === "vertical")
|
|
64
|
+
return ["ArrowUp"];
|
|
65
|
+
if (direction === "horizontal")
|
|
66
|
+
return ["ArrowLeft"];
|
|
67
|
+
return ["ArrowUp", "ArrowLeft"];
|
|
68
|
+
}, [direction]);
|
|
69
|
+
const nextArrowKeys = (0, import_react.useMemo)(() => {
|
|
70
|
+
if (direction === "vertical")
|
|
71
|
+
return ["ArrowDown"];
|
|
72
|
+
if (direction === "horizontal")
|
|
73
|
+
return ["ArrowRight"];
|
|
74
|
+
return ["ArrowDown", "ArrowRight"];
|
|
75
|
+
}, [direction]);
|
|
59
76
|
const onKeyDown = (0, import_react.useCallback)(
|
|
60
77
|
(e) => {
|
|
78
|
+
if (userOnKeyDown)
|
|
79
|
+
userOnKeyDown(e);
|
|
61
80
|
const { key } = e;
|
|
62
81
|
const index = options.findIndex((option) => option === focusedOptionMutable.current);
|
|
63
|
-
if (key
|
|
82
|
+
if (prevArrowKeys.includes(key)) {
|
|
64
83
|
e.preventDefault();
|
|
65
84
|
const previous = (0, import_ds_utilities.findInCircularList)(options, index, focusCriteria, -1);
|
|
66
85
|
setFocusedOption(options[previous]);
|
|
67
|
-
} else if (key
|
|
86
|
+
} else if (nextArrowKeys.includes(key)) {
|
|
68
87
|
e.preventDefault();
|
|
69
88
|
const next = (0, import_ds_utilities.findInCircularList)(options, index, focusCriteria, 1);
|
|
70
89
|
setFocusedOption(options[next]);
|
|
71
90
|
}
|
|
72
91
|
},
|
|
73
|
-
[
|
|
92
|
+
[userOnKeyDown, options, prevArrowKeys, nextArrowKeys, focusCriteria]
|
|
74
93
|
);
|
|
75
94
|
const getItemProps = (0, import_react.useCallback)(
|
|
76
95
|
(dsId) => ({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/DSHooksKeyboardNavigation.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import { useCallback, useMemo, useRef, useState } from 'react';\nimport { useOnBlurOut, findInCircularList } from '@elliemae/ds-utilities';\nimport { describe } from '@elliemae/ds-props-helpers';\nimport { type DSHooksKeyboardNaviationT } from './react-desc-prop-types.js';\nimport { propTypes } from './react-desc-prop-types.js';\nconst useKeyboardNavigation = (props: DSHooksKeyboardNaviationT.Props) => {\n const {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAuD;AACvD,0BAAiD;AACjD,8BAAyB;AAEzB,IAAAA,gCAA0B;AAC1B,MAAM,wBAAwB,CAAC,UAA2C;AACxE,QAAM,
|
|
4
|
+
"sourcesContent": ["import { useCallback, useMemo, useRef, useState } from 'react';\nimport { useOnBlurOut, findInCircularList } from '@elliemae/ds-utilities';\nimport { describe } from '@elliemae/ds-props-helpers';\nimport { type DSHooksKeyboardNaviationT } from './react-desc-prop-types.js';\nimport { propTypes } from './react-desc-prop-types.js';\nconst defaultFocusCriteria = () => true;\nconst useKeyboardNavigation = (props: DSHooksKeyboardNaviationT.Props) => {\n const {\n options,\n direction = 'agnostic',\n disableRoving = false,\n focusCriteria = defaultFocusCriteria,\n onKeyDown: userOnKeyDown,\n } = props;\n const [focusedOption, setFocusedOption] = useState<string | null>(null);\n const previousFocusedOption = useRef<string | null>(null);\n const focusedOptionMutable = useRef<string | null>(null);\n\n const config = useMemo(\n () => ({\n onBlur: () => {\n previousFocusedOption.current = focusedOption;\n setFocusedOption(null);\n },\n }),\n [focusedOption],\n );\n const handleParentOnBlur = useOnBlurOut(config);\n\n const prevArrowKeys = useMemo(() => {\n if (direction === 'vertical') return ['ArrowUp'];\n if (direction === 'horizontal') return ['ArrowLeft'];\n return ['ArrowUp', 'ArrowLeft'];\n }, [direction]);\n const nextArrowKeys = useMemo(() => {\n if (direction === 'vertical') return ['ArrowDown'];\n if (direction === 'horizontal') return ['ArrowRight'];\n return ['ArrowDown', 'ArrowRight'];\n }, [direction]);\n const onKeyDown: React.KeyboardEventHandler = useCallback(\n (e) => {\n if (userOnKeyDown) userOnKeyDown(e);\n const { key } = e;\n const index = options.findIndex((option) => option === focusedOptionMutable.current);\n if (prevArrowKeys.includes(key)) {\n e.preventDefault();\n const previous = findInCircularList(options, index, focusCriteria, -1);\n setFocusedOption(options[previous]);\n } else if (nextArrowKeys.includes(key)) {\n e.preventDefault();\n const next = findInCircularList(options, index, focusCriteria, 1);\n setFocusedOption(options[next]);\n }\n },\n [userOnKeyDown, options, prevArrowKeys, nextArrowKeys, focusCriteria],\n );\n\n const getItemProps = useCallback(\n (dsId: string) => ({\n innerRef: (el: HTMLElement | null) => {\n if (el && dsId === focusedOption && focusedOptionMutable.current !== dsId) {\n el?.focus();\n focusedOptionMutable.current = dsId;\n }\n },\n onFocus: () => setFocusedOption(dsId),\n tabIndex: (disableRoving ||\n dsId === focusedOptionMutable.current ||\n (previousFocusedOption.current === dsId && focusedOptionMutable.current === null) ||\n (dsId === options[0] && focusedOptionMutable.current === null && previousFocusedOption.current === null)\n ? 0\n : -1) as WCAGTabIndex,\n }),\n [disableRoving, focusedOption, options],\n );\n\n const getWrapperProps = useCallback(\n () => ({\n onKeyDown,\n onBlur: handleParentOnBlur,\n }),\n [onKeyDown, handleParentOnBlur],\n );\n\n return useMemo(\n () => ({ getWrapperProps, getItemProps, focusedOption, setFocusedOption }),\n [focusedOption, getWrapperProps, getItemProps],\n );\n};\n\nconst UseKeyboardNavigationWithSchema = describe(useKeyboardNavigation);\nUseKeyboardNavigationWithSchema.propTypes = propTypes;\n\nexport { useKeyboardNavigation, UseKeyboardNavigationWithSchema };\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAuD;AACvD,0BAAiD;AACjD,8BAAyB;AAEzB,IAAAA,gCAA0B;AAC1B,MAAM,uBAAuB,MAAM;AACnC,MAAM,wBAAwB,CAAC,UAA2C;AACxE,QAAM;AAAA,IACJ;AAAA,IACA,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,WAAW;AAAA,EACb,IAAI;AACJ,QAAM,CAAC,eAAe,gBAAgB,QAAI,uBAAwB,IAAI;AACtE,QAAM,4BAAwB,qBAAsB,IAAI;AACxD,QAAM,2BAAuB,qBAAsB,IAAI;AAEvD,QAAM,aAAS;AAAA,IACb,OAAO;AAAA,MACL,QAAQ,MAAM;AACZ,8BAAsB,UAAU;AAChC,yBAAiB,IAAI;AAAA,MACvB;AAAA,IACF;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AACA,QAAM,yBAAqB,kCAAa,MAAM;AAE9C,QAAM,oBAAgB,sBAAQ,MAAM;AAClC,QAAI,cAAc;AAAY,aAAO,CAAC,SAAS;AAC/C,QAAI,cAAc;AAAc,aAAO,CAAC,WAAW;AACnD,WAAO,CAAC,WAAW,WAAW;AAAA,EAChC,GAAG,CAAC,SAAS,CAAC;AACd,QAAM,oBAAgB,sBAAQ,MAAM;AAClC,QAAI,cAAc;AAAY,aAAO,CAAC,WAAW;AACjD,QAAI,cAAc;AAAc,aAAO,CAAC,YAAY;AACpD,WAAO,CAAC,aAAa,YAAY;AAAA,EACnC,GAAG,CAAC,SAAS,CAAC;AACd,QAAM,gBAAwC;AAAA,IAC5C,CAAC,MAAM;AACL,UAAI;AAAe,sBAAc,CAAC;AAClC,YAAM,EAAE,IAAI,IAAI;AAChB,YAAM,QAAQ,QAAQ,UAAU,CAAC,WAAW,WAAW,qBAAqB,OAAO;AACnF,UAAI,cAAc,SAAS,GAAG,GAAG;AAC/B,UAAE,eAAe;AACjB,cAAM,eAAW,wCAAmB,SAAS,OAAO,eAAe,EAAE;AACrE,yBAAiB,QAAQ,QAAQ,CAAC;AAAA,MACpC,WAAW,cAAc,SAAS,GAAG,GAAG;AACtC,UAAE,eAAe;AACjB,cAAM,WAAO,wCAAmB,SAAS,OAAO,eAAe,CAAC;AAChE,yBAAiB,QAAQ,IAAI,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,IACA,CAAC,eAAe,SAAS,eAAe,eAAe,aAAa;AAAA,EACtE;AAEA,QAAM,mBAAe;AAAA,IACnB,CAAC,UAAkB;AAAA,MACjB,UAAU,CAAC,OAA2B;AACpC,YAAI,MAAM,SAAS,iBAAiB,qBAAqB,YAAY,MAAM;AACzE,cAAI,MAAM;AACV,+BAAqB,UAAU;AAAA,QACjC;AAAA,MACF;AAAA,MACA,SAAS,MAAM,iBAAiB,IAAI;AAAA,MACpC,UAAW,iBACX,SAAS,qBAAqB,WAC7B,sBAAsB,YAAY,QAAQ,qBAAqB,YAAY,QAC3E,SAAS,QAAQ,CAAC,KAAK,qBAAqB,YAAY,QAAQ,sBAAsB,YAAY,OAC/F,IACA;AAAA,IACN;AAAA,IACA,CAAC,eAAe,eAAe,OAAO;AAAA,EACxC;AAEA,QAAM,sBAAkB;AAAA,IACtB,OAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,IACA,CAAC,WAAW,kBAAkB;AAAA,EAChC;AAEA,aAAO;AAAA,IACL,OAAO,EAAE,iBAAiB,cAAc,eAAe,iBAAiB;AAAA,IACxE,CAAC,eAAe,iBAAiB,YAAY;AAAA,EAC/C;AACF;AAEA,MAAM,sCAAkC,kCAAS,qBAAqB;AACtE,gCAAgC,YAAY;",
|
|
6
6
|
"names": ["import_react_desc_prop_types"]
|
|
7
7
|
}
|
|
@@ -35,12 +35,16 @@ var React = __toESM(require("react"));
|
|
|
35
35
|
var import_ds_utilities = require("@elliemae/ds-utilities");
|
|
36
36
|
const propTypes = {
|
|
37
37
|
options: import_ds_utilities.PropTypes.arrayOf(import_ds_utilities.PropTypes.string).description("Array of strings to be items ids.").isRequired,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
direction: import_ds_utilities.PropTypes.oneOf(["horizontal", "vertical", "agnostic"]).description(
|
|
39
|
+
`The direction of the navigation.
|
|
40
|
+
If horizontal, "Left" triggers "previous" and "Right" triggers "next".
|
|
41
|
+
If vertical, "Up" triggers "previous" and "Down" triggers "next".
|
|
42
|
+
If agnostic, "Left" and "Up" trigger "previous" and "Right" and "Down" trigger "next".
|
|
43
|
+
Defaults to "agnostic".`
|
|
44
|
+
).defaultValue("agnostic"),
|
|
45
|
+
disableRoving: import_ds_utilities.PropTypes.bool.description("If true, the roving tab index will not be applied to the items.").defaultValue(false),
|
|
42
46
|
focusCriteria: import_ds_utilities.PropTypes.func.description(
|
|
43
|
-
"Function that returns a boolean to determine if the element should be focused."
|
|
47
|
+
"Function that returns a boolean to determine if the element should be focused.When not provided, all elements will be accounted as focusable."
|
|
44
48
|
)
|
|
45
49
|
};
|
|
46
50
|
//# sourceMappingURL=react-desc-prop-types.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/react-desc-prop-types.ts", "../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-empty-interface */\n\nimport type
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,0BAA0B;
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-empty-interface */\n\nimport type React from 'react';\nimport { PropTypes } from '@elliemae/ds-utilities';\nimport { type useKeyboardNavigation } from './DSHooksKeyboardNavigation.js';\nexport declare namespace DSHooksKeyboardNaviationT {\n interface Props {\n options: string[];\n direction?: 'horizontal' | 'vertical' | 'agnostic';\n disableRoving?: boolean;\n focusCriteria?: (dsId: string) => boolean;\n onKeyDown?: React.KeyboardEventHandler;\n }\n\n type UseKeyboardNavigationReturnType = ReturnType<typeof useKeyboardNavigation>;\n type ItemPropsT = ReturnType<UseKeyboardNavigationReturnType['getItemProps']>;\n type WrapperPropsT = ReturnType<UseKeyboardNavigationReturnType['getWrapperProps']>;\n}\n\nexport const propTypes = {\n options: PropTypes.arrayOf(PropTypes.string).description('Array of strings to be items ids.').isRequired,\n direction: PropTypes.oneOf(['horizontal', 'vertical', 'agnostic'])\n .description(\n `The direction of the navigation.\n If horizontal, \"Left\" triggers \"previous\" and \"Right\" triggers \"next\".\n If vertical, \"Up\" triggers \"previous\" and \"Down\" triggers \"next\".\n If agnostic, \"Left\" and \"Up\" trigger \"previous\" and \"Right\" and \"Down\" trigger \"next\".\nDefaults to \"agnostic\".`,\n )\n .defaultValue('agnostic'),\n disableRoving: PropTypes.bool\n .description('If true, the roving tab index will not be applied to the items.')\n .defaultValue(false),\n focusCriteria: PropTypes.func.description(\n 'Function that returns a boolean to determine if the element should be focused.When not provided, all elements will be accounted as focusable.',\n ),\n} as React.WeakValidationMap<unknown>;\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADGvB,0BAA0B;AAgBnB,MAAM,YAAY;AAAA,EACvB,SAAS,8BAAU,QAAQ,8BAAU,MAAM,EAAE,YAAY,mCAAmC,EAAE;AAAA,EAC9F,WAAW,8BAAU,MAAM,CAAC,cAAc,YAAY,UAAU,CAAC,EAC9D;AAAA,IACC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKF,EACC,aAAa,UAAU;AAAA,EAC1B,eAAe,8BAAU,KACtB,YAAY,iEAAiE,EAC7E,aAAa,KAAK;AAAA,EACrB,eAAe,8BAAU,KAAK;AAAA,IAC5B;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,8 +3,15 @@ import { useCallback, useMemo, useRef, useState } from "react";
|
|
|
3
3
|
import { useOnBlurOut, findInCircularList } from "@elliemae/ds-utilities";
|
|
4
4
|
import { describe } from "@elliemae/ds-props-helpers";
|
|
5
5
|
import { propTypes } from "./react-desc-prop-types.js";
|
|
6
|
+
const defaultFocusCriteria = () => true;
|
|
6
7
|
const useKeyboardNavigation = (props) => {
|
|
7
|
-
const {
|
|
8
|
+
const {
|
|
9
|
+
options,
|
|
10
|
+
direction = "agnostic",
|
|
11
|
+
disableRoving = false,
|
|
12
|
+
focusCriteria = defaultFocusCriteria,
|
|
13
|
+
onKeyDown: userOnKeyDown
|
|
14
|
+
} = props;
|
|
8
15
|
const [focusedOption, setFocusedOption] = useState(null);
|
|
9
16
|
const previousFocusedOption = useRef(null);
|
|
10
17
|
const focusedOptionMutable = useRef(null);
|
|
@@ -18,25 +25,37 @@ const useKeyboardNavigation = (props) => {
|
|
|
18
25
|
[focusedOption]
|
|
19
26
|
);
|
|
20
27
|
const handleParentOnBlur = useOnBlurOut(config);
|
|
21
|
-
const
|
|
22
|
-
(
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
const prevArrowKeys = useMemo(() => {
|
|
29
|
+
if (direction === "vertical")
|
|
30
|
+
return ["ArrowUp"];
|
|
31
|
+
if (direction === "horizontal")
|
|
32
|
+
return ["ArrowLeft"];
|
|
33
|
+
return ["ArrowUp", "ArrowLeft"];
|
|
34
|
+
}, [direction]);
|
|
35
|
+
const nextArrowKeys = useMemo(() => {
|
|
36
|
+
if (direction === "vertical")
|
|
37
|
+
return ["ArrowDown"];
|
|
38
|
+
if (direction === "horizontal")
|
|
39
|
+
return ["ArrowRight"];
|
|
40
|
+
return ["ArrowDown", "ArrowRight"];
|
|
41
|
+
}, [direction]);
|
|
25
42
|
const onKeyDown = useCallback(
|
|
26
43
|
(e) => {
|
|
44
|
+
if (userOnKeyDown)
|
|
45
|
+
userOnKeyDown(e);
|
|
27
46
|
const { key } = e;
|
|
28
47
|
const index = options.findIndex((option) => option === focusedOptionMutable.current);
|
|
29
|
-
if (key
|
|
48
|
+
if (prevArrowKeys.includes(key)) {
|
|
30
49
|
e.preventDefault();
|
|
31
50
|
const previous = findInCircularList(options, index, focusCriteria, -1);
|
|
32
51
|
setFocusedOption(options[previous]);
|
|
33
|
-
} else if (key
|
|
52
|
+
} else if (nextArrowKeys.includes(key)) {
|
|
34
53
|
e.preventDefault();
|
|
35
54
|
const next = findInCircularList(options, index, focusCriteria, 1);
|
|
36
55
|
setFocusedOption(options[next]);
|
|
37
56
|
}
|
|
38
57
|
},
|
|
39
|
-
[
|
|
58
|
+
[userOnKeyDown, options, prevArrowKeys, nextArrowKeys, focusCriteria]
|
|
40
59
|
);
|
|
41
60
|
const getItemProps = useCallback(
|
|
42
61
|
(dsId) => ({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/DSHooksKeyboardNavigation.tsx"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { useCallback, useMemo, useRef, useState } from 'react';\nimport { useOnBlurOut, findInCircularList } from '@elliemae/ds-utilities';\nimport { describe } from '@elliemae/ds-props-helpers';\nimport { type DSHooksKeyboardNaviationT } from './react-desc-prop-types.js';\nimport { propTypes } from './react-desc-prop-types.js';\nconst useKeyboardNavigation = (props: DSHooksKeyboardNaviationT.Props) => {\n const {
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,aAAa,SAAS,QAAQ,gBAAgB;AACvD,SAAS,cAAc,0BAA0B;AACjD,SAAS,gBAAgB;AAEzB,SAAS,iBAAiB;AAC1B,MAAM,wBAAwB,CAAC,UAA2C;AACxE,QAAM,
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { useCallback, useMemo, useRef, useState } from 'react';\nimport { useOnBlurOut, findInCircularList } from '@elliemae/ds-utilities';\nimport { describe } from '@elliemae/ds-props-helpers';\nimport { type DSHooksKeyboardNaviationT } from './react-desc-prop-types.js';\nimport { propTypes } from './react-desc-prop-types.js';\nconst defaultFocusCriteria = () => true;\nconst useKeyboardNavigation = (props: DSHooksKeyboardNaviationT.Props) => {\n const {\n options,\n direction = 'agnostic',\n disableRoving = false,\n focusCriteria = defaultFocusCriteria,\n onKeyDown: userOnKeyDown,\n } = props;\n const [focusedOption, setFocusedOption] = useState<string | null>(null);\n const previousFocusedOption = useRef<string | null>(null);\n const focusedOptionMutable = useRef<string | null>(null);\n\n const config = useMemo(\n () => ({\n onBlur: () => {\n previousFocusedOption.current = focusedOption;\n setFocusedOption(null);\n },\n }),\n [focusedOption],\n );\n const handleParentOnBlur = useOnBlurOut(config);\n\n const prevArrowKeys = useMemo(() => {\n if (direction === 'vertical') return ['ArrowUp'];\n if (direction === 'horizontal') return ['ArrowLeft'];\n return ['ArrowUp', 'ArrowLeft'];\n }, [direction]);\n const nextArrowKeys = useMemo(() => {\n if (direction === 'vertical') return ['ArrowDown'];\n if (direction === 'horizontal') return ['ArrowRight'];\n return ['ArrowDown', 'ArrowRight'];\n }, [direction]);\n const onKeyDown: React.KeyboardEventHandler = useCallback(\n (e) => {\n if (userOnKeyDown) userOnKeyDown(e);\n const { key } = e;\n const index = options.findIndex((option) => option === focusedOptionMutable.current);\n if (prevArrowKeys.includes(key)) {\n e.preventDefault();\n const previous = findInCircularList(options, index, focusCriteria, -1);\n setFocusedOption(options[previous]);\n } else if (nextArrowKeys.includes(key)) {\n e.preventDefault();\n const next = findInCircularList(options, index, focusCriteria, 1);\n setFocusedOption(options[next]);\n }\n },\n [userOnKeyDown, options, prevArrowKeys, nextArrowKeys, focusCriteria],\n );\n\n const getItemProps = useCallback(\n (dsId: string) => ({\n innerRef: (el: HTMLElement | null) => {\n if (el && dsId === focusedOption && focusedOptionMutable.current !== dsId) {\n el?.focus();\n focusedOptionMutable.current = dsId;\n }\n },\n onFocus: () => setFocusedOption(dsId),\n tabIndex: (disableRoving ||\n dsId === focusedOptionMutable.current ||\n (previousFocusedOption.current === dsId && focusedOptionMutable.current === null) ||\n (dsId === options[0] && focusedOptionMutable.current === null && previousFocusedOption.current === null)\n ? 0\n : -1) as WCAGTabIndex,\n }),\n [disableRoving, focusedOption, options],\n );\n\n const getWrapperProps = useCallback(\n () => ({\n onKeyDown,\n onBlur: handleParentOnBlur,\n }),\n [onKeyDown, handleParentOnBlur],\n );\n\n return useMemo(\n () => ({ getWrapperProps, getItemProps, focusedOption, setFocusedOption }),\n [focusedOption, getWrapperProps, getItemProps],\n );\n};\n\nconst UseKeyboardNavigationWithSchema = describe(useKeyboardNavigation);\nUseKeyboardNavigationWithSchema.propTypes = propTypes;\n\nexport { useKeyboardNavigation, UseKeyboardNavigationWithSchema };\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,aAAa,SAAS,QAAQ,gBAAgB;AACvD,SAAS,cAAc,0BAA0B;AACjD,SAAS,gBAAgB;AAEzB,SAAS,iBAAiB;AAC1B,MAAM,uBAAuB,MAAM;AACnC,MAAM,wBAAwB,CAAC,UAA2C;AACxE,QAAM;AAAA,IACJ;AAAA,IACA,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,WAAW;AAAA,EACb,IAAI;AACJ,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAwB,IAAI;AACtE,QAAM,wBAAwB,OAAsB,IAAI;AACxD,QAAM,uBAAuB,OAAsB,IAAI;AAEvD,QAAM,SAAS;AAAA,IACb,OAAO;AAAA,MACL,QAAQ,MAAM;AACZ,8BAAsB,UAAU;AAChC,yBAAiB,IAAI;AAAA,MACvB;AAAA,IACF;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AACA,QAAM,qBAAqB,aAAa,MAAM;AAE9C,QAAM,gBAAgB,QAAQ,MAAM;AAClC,QAAI,cAAc;AAAY,aAAO,CAAC,SAAS;AAC/C,QAAI,cAAc;AAAc,aAAO,CAAC,WAAW;AACnD,WAAO,CAAC,WAAW,WAAW;AAAA,EAChC,GAAG,CAAC,SAAS,CAAC;AACd,QAAM,gBAAgB,QAAQ,MAAM;AAClC,QAAI,cAAc;AAAY,aAAO,CAAC,WAAW;AACjD,QAAI,cAAc;AAAc,aAAO,CAAC,YAAY;AACpD,WAAO,CAAC,aAAa,YAAY;AAAA,EACnC,GAAG,CAAC,SAAS,CAAC;AACd,QAAM,YAAwC;AAAA,IAC5C,CAAC,MAAM;AACL,UAAI;AAAe,sBAAc,CAAC;AAClC,YAAM,EAAE,IAAI,IAAI;AAChB,YAAM,QAAQ,QAAQ,UAAU,CAAC,WAAW,WAAW,qBAAqB,OAAO;AACnF,UAAI,cAAc,SAAS,GAAG,GAAG;AAC/B,UAAE,eAAe;AACjB,cAAM,WAAW,mBAAmB,SAAS,OAAO,eAAe,EAAE;AACrE,yBAAiB,QAAQ,QAAQ,CAAC;AAAA,MACpC,WAAW,cAAc,SAAS,GAAG,GAAG;AACtC,UAAE,eAAe;AACjB,cAAM,OAAO,mBAAmB,SAAS,OAAO,eAAe,CAAC;AAChE,yBAAiB,QAAQ,IAAI,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,IACA,CAAC,eAAe,SAAS,eAAe,eAAe,aAAa;AAAA,EACtE;AAEA,QAAM,eAAe;AAAA,IACnB,CAAC,UAAkB;AAAA,MACjB,UAAU,CAAC,OAA2B;AACpC,YAAI,MAAM,SAAS,iBAAiB,qBAAqB,YAAY,MAAM;AACzE,cAAI,MAAM;AACV,+BAAqB,UAAU;AAAA,QACjC;AAAA,MACF;AAAA,MACA,SAAS,MAAM,iBAAiB,IAAI;AAAA,MACpC,UAAW,iBACX,SAAS,qBAAqB,WAC7B,sBAAsB,YAAY,QAAQ,qBAAqB,YAAY,QAC3E,SAAS,QAAQ,CAAC,KAAK,qBAAqB,YAAY,QAAQ,sBAAsB,YAAY,OAC/F,IACA;AAAA,IACN;AAAA,IACA,CAAC,eAAe,eAAe,OAAO;AAAA,EACxC;AAEA,QAAM,kBAAkB;AAAA,IACtB,OAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,IACA,CAAC,WAAW,kBAAkB;AAAA,EAChC;AAEA,SAAO;AAAA,IACL,OAAO,EAAE,iBAAiB,cAAc,eAAe,iBAAiB;AAAA,IACxE,CAAC,eAAe,iBAAiB,YAAY;AAAA,EAC/C;AACF;AAEA,MAAM,kCAAkC,SAAS,qBAAqB;AACtE,gCAAgC,YAAY;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -2,12 +2,16 @@ import * as React from "react";
|
|
|
2
2
|
import { PropTypes } from "@elliemae/ds-utilities";
|
|
3
3
|
const propTypes = {
|
|
4
4
|
options: PropTypes.arrayOf(PropTypes.string).description("Array of strings to be items ids.").isRequired,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
direction: PropTypes.oneOf(["horizontal", "vertical", "agnostic"]).description(
|
|
6
|
+
`The direction of the navigation.
|
|
7
|
+
If horizontal, "Left" triggers "previous" and "Right" triggers "next".
|
|
8
|
+
If vertical, "Up" triggers "previous" and "Down" triggers "next".
|
|
9
|
+
If agnostic, "Left" and "Up" trigger "previous" and "Right" and "Down" trigger "next".
|
|
10
|
+
Defaults to "agnostic".`
|
|
11
|
+
).defaultValue("agnostic"),
|
|
12
|
+
disableRoving: PropTypes.bool.description("If true, the roving tab index will not be applied to the items.").defaultValue(false),
|
|
9
13
|
focusCriteria: PropTypes.func.description(
|
|
10
|
-
"Function that returns a boolean to determine if the element should be focused."
|
|
14
|
+
"Function that returns a boolean to determine if the element should be focused.When not provided, all elements will be accounted as focusable."
|
|
11
15
|
)
|
|
12
16
|
};
|
|
13
17
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/react-desc-prop-types.ts"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-empty-interface */\n\nimport type
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACGvB,SAAS,iBAAiB;
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-empty-interface */\n\nimport type React from 'react';\nimport { PropTypes } from '@elliemae/ds-utilities';\nimport { type useKeyboardNavigation } from './DSHooksKeyboardNavigation.js';\nexport declare namespace DSHooksKeyboardNaviationT {\n interface Props {\n options: string[];\n direction?: 'horizontal' | 'vertical' | 'agnostic';\n disableRoving?: boolean;\n focusCriteria?: (dsId: string) => boolean;\n onKeyDown?: React.KeyboardEventHandler;\n }\n\n type UseKeyboardNavigationReturnType = ReturnType<typeof useKeyboardNavigation>;\n type ItemPropsT = ReturnType<UseKeyboardNavigationReturnType['getItemProps']>;\n type WrapperPropsT = ReturnType<UseKeyboardNavigationReturnType['getWrapperProps']>;\n}\n\nexport const propTypes = {\n options: PropTypes.arrayOf(PropTypes.string).description('Array of strings to be items ids.').isRequired,\n direction: PropTypes.oneOf(['horizontal', 'vertical', 'agnostic'])\n .description(\n `The direction of the navigation.\n If horizontal, \"Left\" triggers \"previous\" and \"Right\" triggers \"next\".\n If vertical, \"Up\" triggers \"previous\" and \"Down\" triggers \"next\".\n If agnostic, \"Left\" and \"Up\" trigger \"previous\" and \"Right\" and \"Down\" trigger \"next\".\nDefaults to \"agnostic\".`,\n )\n .defaultValue('agnostic'),\n disableRoving: PropTypes.bool\n .description('If true, the roving tab index will not be applied to the items.')\n .defaultValue(false),\n focusCriteria: PropTypes.func.description(\n 'Function that returns a boolean to determine if the element should be focused.When not provided, all elements will be accounted as focusable.',\n ),\n} as React.WeakValidationMap<unknown>;\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACGvB,SAAS,iBAAiB;AAgBnB,MAAM,YAAY;AAAA,EACvB,SAAS,UAAU,QAAQ,UAAU,MAAM,EAAE,YAAY,mCAAmC,EAAE;AAAA,EAC9F,WAAW,UAAU,MAAM,CAAC,cAAc,YAAY,UAAU,CAAC,EAC9D;AAAA,IACC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKF,EACC,aAAa,UAAU;AAAA,EAC1B,eAAe,UAAU,KACtB,YAAY,iEAAiE,EAC7E,aAAa,KAAK;AAAA,EACrB,eAAe,UAAU,KAAK;AAAA,IAC5B;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type React from 'react';
|
|
2
2
|
import { type useKeyboardNavigation } from './DSHooksKeyboardNavigation.js';
|
|
3
3
|
export declare namespace DSHooksKeyboardNaviationT {
|
|
4
4
|
interface Props {
|
|
5
5
|
options: string[];
|
|
6
|
-
|
|
6
|
+
direction?: 'horizontal' | 'vertical' | 'agnostic';
|
|
7
7
|
disableRoving?: boolean;
|
|
8
8
|
focusCriteria?: (dsId: string) => boolean;
|
|
9
|
+
onKeyDown?: React.KeyboardEventHandler;
|
|
9
10
|
}
|
|
10
11
|
type UseKeyboardNavigationReturnType = ReturnType<typeof useKeyboardNavigation>;
|
|
11
12
|
type ItemPropsT = ReturnType<UseKeyboardNavigationReturnType['getItemProps']>;
|
|
12
13
|
type WrapperPropsT = ReturnType<UseKeyboardNavigationReturnType['getWrapperProps']>;
|
|
13
14
|
}
|
|
14
|
-
export declare const propTypes: WeakValidationMap<unknown>;
|
|
15
|
+
export declare const propTypes: React.WeakValidationMap<unknown>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elliemae/ds-hooks-keyboard-navigation",
|
|
3
|
-
"version": "3.27.0
|
|
3
|
+
"version": "3.27.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "ICE MT - Dimsum - Hooks Keyboaord Navigation",
|
|
6
6
|
"files": [
|
|
@@ -35,15 +35,15 @@
|
|
|
35
35
|
"indent": 4
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@elliemae/ds-props-helpers": "3.27.0
|
|
39
|
-
"@elliemae/ds-utilities": "3.27.0
|
|
38
|
+
"@elliemae/ds-props-helpers": "3.27.0",
|
|
39
|
+
"@elliemae/ds-utilities": "3.27.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@elliemae/pui-cli": "~9.0.0-next.31",
|
|
43
43
|
"@xstyled/system": "3.7.0",
|
|
44
44
|
"styled-components": "~5.3.9",
|
|
45
45
|
"styled-system": "~5.1.5",
|
|
46
|
-
"@elliemae/ds-monorepo-devops": "3.27.0
|
|
46
|
+
"@elliemae/ds-monorepo-devops": "3.27.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"lodash": "^4.17.21",
|