New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

react-roving-tabindex

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-roving-tabindex - npm Package Compare versions

Comparing version 2.1.0 to 2.2.0-beta-1

dist/__tests__/Provider.test.d.ts

5

CHANGELOG.md
# Changelog
## 2.2.0
- Add an optional `initialTabElementSelector` string prop to the provider.
- Add an optional `onTabElementSelected` callback prop to the provider.
## 2.1.0

@@ -4,0 +9,0 @@

53

dist/index.es.js

@@ -58,2 +58,3 @@ import React, { createContext, useReducer, useEffect, useMemo, useRef, useContext, useCallback } from 'react';

ActionType["DIRECTION_UPDATED"] = "DIRECTION_UPDATED";
ActionType["SET_INITIAL_TAB_ELEMENT"] = "SET_INITIAL_TAB_ELEMENT";
})(ActionType || (ActionType = {}));

@@ -310,2 +311,8 @@

}
case ActionType.SET_INITIAL_TAB_ELEMENT: {
var selector_1 = action.payload.selector;
var tabStop = state.tabStops.find(function (tabStop) { var _a; return (_a = tabStop.domElementRef.current) === null || _a === void 0 ? void 0 : _a.matches(selector_1); });
return tabStop && !tabStop.disabled
? __assign(__assign({}, state), { selectedId: tabStop.id }) : state;
}
default:

@@ -375,3 +382,3 @@ return state;

function selectTabStop(state, tabStop, rowStartMap) {
return __assign(__assign({}, state), { allowFocusing: true, selectedId: tabStop.id, rowStartMap: rowStartMap || state.rowStartMap });
return __assign(__assign({}, state), { allowFocusing: true, selectedId: tabStop.id, lastSelectedElement: { domElementRef: tabStop.domElementRef }, rowStartMap: rowStartMap || state.rowStartMap });
}

@@ -392,2 +399,3 @@ // Creates the row start index lookup map

selectedId: null,
lastSelectedElement: null,
allowFocusing: false,

@@ -420,5 +428,24 @@ tabStops: [],

* at any time.
* @param {string} initialTabElementSelector An optional selector for
* selecting the element in the roving tab index that will be
* the initially selected one. Normally the first registered
* element will be the initially tabbable element in the index.
* However, you might want to save the last tabbed-to element
* so that you can restore it the next time the index is mounted.
* The selector will be passed to the
* [`Element.matches()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches)
* method, so the likeliest value would be an ID (e.g., `'#bar'`)
* or a data selector (e.g., `'[data-foo-id="bar"]'`).
* The value of this prop should remain the same for the lifetime
* of this component.
* @param {(element: Element) => void} onTabElementSelected
* An optional callback so you can be notified when the user
* changes the selected element in the roving tab index. This is useful to
* extract the information you would need to subsequently pass as the
* `initialTabElementSelector` prop. The value of this prop should remain
* the same for the lifetime of this component. This might require
* use of `React.useCallback` to create a stable callback function.
*/
var Provider = function (_a) {
var children = _a.children, _b = _a.direction, direction = _b === void 0 ? "horizontal" : _b;
var children = _a.children, _b = _a.direction, direction = _b === void 0 ? "horizontal" : _b, initialTabElementSelector = _a.initialTabElementSelector, onTabElementSelected = _a.onTabElementSelected;
var _c = useReducer(reducer, __assign(__assign({}, INITIAL_STATE), { direction: direction })), state = _c[0], dispatch = _c[1];

@@ -429,3 +456,23 @@ // Update the direction whenever it changes:

}, [direction]);
// Create a cached object to use as the context value:
// If given, set the initial tab element:
useEffect(function () {
if (initialTabElementSelector) {
dispatch({
type: ActionType.SET_INITIAL_TAB_ELEMENT,
payload: { selector: initialTabElementSelector }
});
}
}, [initialTabElementSelector]);
// Invoke the onTabElementSelected callback when the user
// selects an element in the index:
useEffect(function () {
var _a;
if (!onTabElementSelected ||
!((_a = state.lastSelectedElement) === null || _a === void 0 ? void 0 : _a.domElementRef.current)) {
return;
}
onTabElementSelected(state.lastSelectedElement.domElementRef.current);
}, [onTabElementSelected, state.lastSelectedElement]);
// Create a memoized object to use as the context's value.
// This prevents unnecessary renders.
var context = useMemo(function () { return ({ state: state, dispatch: dispatch }); }, [state]);

@@ -432,0 +479,0 @@ return (React.createElement(RovingTabIndexContext.Provider, { value: context }, children));

@@ -64,2 +64,3 @@ 'use strict';

ActionType["DIRECTION_UPDATED"] = "DIRECTION_UPDATED";
ActionType["SET_INITIAL_TAB_ELEMENT"] = "SET_INITIAL_TAB_ELEMENT";
})(exports.ActionType || (exports.ActionType = {}));

@@ -316,2 +317,8 @@

}
case exports.ActionType.SET_INITIAL_TAB_ELEMENT: {
var selector_1 = action.payload.selector;
var tabStop = state.tabStops.find(function (tabStop) { var _a; return (_a = tabStop.domElementRef.current) === null || _a === void 0 ? void 0 : _a.matches(selector_1); });
return tabStop && !tabStop.disabled
? __assign(__assign({}, state), { selectedId: tabStop.id }) : state;
}
default:

@@ -381,3 +388,3 @@ return state;

function selectTabStop(state, tabStop, rowStartMap) {
return __assign(__assign({}, state), { allowFocusing: true, selectedId: tabStop.id, rowStartMap: rowStartMap || state.rowStartMap });
return __assign(__assign({}, state), { allowFocusing: true, selectedId: tabStop.id, lastSelectedElement: { domElementRef: tabStop.domElementRef }, rowStartMap: rowStartMap || state.rowStartMap });
}

@@ -398,2 +405,3 @@ // Creates the row start index lookup map

selectedId: null,
lastSelectedElement: null,
allowFocusing: false,

@@ -426,5 +434,24 @@ tabStops: [],

* at any time.
* @param {string} initialTabElementSelector An optional selector for
* selecting the element in the roving tab index that will be
* the initially selected one. Normally the first registered
* element will be the initially tabbable element in the index.
* However, you might want to save the last tabbed-to element
* so that you can restore it the next time the index is mounted.
* The selector will be passed to the
* [`Element.matches()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches)
* method, so the likeliest value would be an ID (e.g., `'#bar'`)
* or a data selector (e.g., `'[data-foo-id="bar"]'`).
* The value of this prop should remain the same for the lifetime
* of this component.
* @param {(element: Element) => void} onTabElementSelected
* An optional callback so you can be notified when the user
* changes the selected element in the roving tab index. This is useful to
* extract the information you would need to subsequently pass as the
* `initialTabElementSelector` prop. The value of this prop should remain
* the same for the lifetime of this component. This might require
* use of `React.useCallback` to create a stable callback function.
*/
var Provider = function (_a) {
var children = _a.children, _b = _a.direction, direction = _b === void 0 ? "horizontal" : _b;
var children = _a.children, _b = _a.direction, direction = _b === void 0 ? "horizontal" : _b, initialTabElementSelector = _a.initialTabElementSelector, onTabElementSelected = _a.onTabElementSelected;
var _c = React.useReducer(reducer, __assign(__assign({}, INITIAL_STATE), { direction: direction })), state = _c[0], dispatch = _c[1];

@@ -435,3 +462,23 @@ // Update the direction whenever it changes:

}, [direction]);
// Create a cached object to use as the context value:
// If given, set the initial tab element:
React.useEffect(function () {
if (initialTabElementSelector) {
dispatch({
type: exports.ActionType.SET_INITIAL_TAB_ELEMENT,
payload: { selector: initialTabElementSelector }
});
}
}, [initialTabElementSelector]);
// Invoke the onTabElementSelected callback when the user
// selects an element in the index:
React.useEffect(function () {
var _a;
if (!onTabElementSelected ||
!((_a = state.lastSelectedElement) === null || _a === void 0 ? void 0 : _a.domElementRef.current)) {
return;
}
onTabElementSelected(state.lastSelectedElement.domElementRef.current);
}, [onTabElementSelected, state.lastSelectedElement]);
// Create a memoized object to use as the context's value.
// This prevents unnecessary renders.
var context = React.useMemo(function () { return ({ state: state, dispatch: dispatch }); }, [state]);

@@ -438,0 +485,0 @@ return (React__default['default'].createElement(RovingTabIndexContext.Provider, { value: context }, children));

33

dist/Provider.d.ts

@@ -1,3 +0,3 @@

import React, { ReactElement, ReactNode } from "react";
import { Action, KeyDirection, RowStartMap, State } from "./types";
import React, { ReactElement } from "react";
import { Action, ProviderProps, RowStartMap, State } from "./types";
export declare function reducer(state: State, action: Action): State;

@@ -7,2 +7,5 @@ export declare const RovingTabIndexContext: React.Context<Readonly<{

selectedId: string | null;
lastSelectedElement: {
domElementRef: React.RefObject<Element>;
} | null;
allowFocusing: boolean;

@@ -15,3 +18,3 @@ tabStops: readonly Readonly<{

}>[];
direction: KeyDirection;
direction: import("./types").KeyDirection;
rowStartMap: RowStartMap | null;

@@ -38,6 +41,22 @@ }>;

* at any time.
* @param {string} initialTabElementSelector An optional selector for
* selecting the element in the roving tab index that will be
* the initially selected one. Normally the first registered
* element will be the initially tabbable element in the index.
* However, you might want to save the last tabbed-to element
* so that you can restore it the next time the index is mounted.
* The selector will be passed to the
* [`Element.matches()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches)
* method, so the likeliest value would be an ID (e.g., `'#bar'`)
* or a data selector (e.g., `'[data-foo-id="bar"]'`).
* The value of this prop should remain the same for the lifetime
* of this component.
* @param {(element: Element) => void} onTabElementSelected
* An optional callback so you can be notified when the user
* changes the selected element in the roving tab index. This is useful to
* extract the information you would need to subsequently pass as the
* `initialTabElementSelector` prop. The value of this prop should remain
* the same for the lifetime of this component. This might require
* use of `React.useCallback` to create a stable callback function.
*/
export declare const Provider: ({ children, direction }: {
children: ReactNode;
direction?: "horizontal" | "vertical" | "both" | undefined;
}) => ReactElement;
export declare const Provider: ({ children, direction, initialTabElementSelector, onTabElementSelected }: ProviderProps) => ReactElement;

@@ -1,2 +0,2 @@

/// <reference types="react" />
import type { ReactNode } from "react";
export declare enum EventKey {

@@ -30,2 +30,5 @@ ArrowLeft = "ArrowLeft",

selectedId: string | null;
lastSelectedElement: {
domElementRef: TabStop["domElementRef"];
} | null;
allowFocusing: boolean;

@@ -42,3 +45,4 @@ tabStops: readonly TabStop[];

TAB_STOP_UPDATED = "TAB_STOP_UPDATED",
DIRECTION_UPDATED = "DIRECTION_UPDATED"
DIRECTION_UPDATED = "DIRECTION_UPDATED",
SET_INITIAL_TAB_ELEMENT = "SET_INITIAL_TAB_ELEMENT"
}

@@ -77,2 +81,7 @@ export declare type Action = {

};
} | {
type: ActionType.SET_INITIAL_TAB_ELEMENT;
payload: {
selector: string;
};
};

@@ -83,2 +92,8 @@ export declare type Context = Readonly<{

}>;
export declare type ProviderProps = {
children: ReactNode;
direction?: KeyDirection;
initialTabElementSelector?: string | null;
onTabElementSelected?: (element: Element) => void;
};
export declare type HookResponse = [

@@ -85,0 +100,0 @@ number,

{
"name": "react-roving-tabindex",
"version": "2.1.0",
"version": "2.2.0-beta-1",
"description": "React implementation of a roving tabindex, now with grid support",

@@ -34,19 +34,8 @@ "author": "stevejay",

"deploy-storybook": "storybook-to-ghpages",
"eslint": "eslint --max-warnings 0 \"src/**/*.{js,jsx,ts,tsx}\"",
"lint": "yarn eslint",
"lint": "yarn lint:code && yarn lint:ts && yarn lint:prettier",
"lint:ts": "tsc --strict --noEmit --project ./tsconfig.json",
"lint:code": "eslint --max-warnings 0 --ignore-path .gitignore ./src",
"lint:prettier": "prettier --check --ignore-path .gitignore ./src",
"lint-staged": "lint-staged"
},
"prettier": {
"trailingComma": "none"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,jsx,tsx,ts}": [
"eslint --fix --max-warnings 0 \"src/**/*.{js,jsx,ts,tsx}\""
]
},
"dependencies": {

@@ -124,4 +113,5 @@ "warning": "^4.0.3"

"/dist/"
]
],
"clearMocks": true
}
}

@@ -145,2 +145,10 @@ # react-roving-tabindex

#### Initial tab element
You may want to set a particular element in the roving tabindex to be the initially tabbable element (i.e., the element that has a `tabindex` of `0`). This could be because you remember the state of the UI and restore it when the user next uses the app.
To facilitate this, the `RovingTabIndexProvider` has an optional `initialTabElementSelector` prop. This takes a selector string that is used to identify the tab element that should be the initially tabbable element. Each tab element is tested using [`Element.matches()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches). This requires that the selector identifies the tabbable element itself (rather than, say, a child element). Thus the selector is most likely to be an ID (e.g., `'#bar'`) or a data selector (e.g., `'[data-foo-id="bar"]'`). If used, the value of this prop should remain the same for the lifetime of the component.
To help with tracking the currently tabbable element in the roving tabindex, the `RovingTabIndexProvider` offers an optional `onTabElementSelected` callback prop. This callback is invoked whenever the user clicks on or uses the keyboard to select a tab element in the roving tabindex. The callback is invoked with that element. This allows you to get some information from that element, e.g., its ID or a data attribute. This information could be used later to provide the value for the `initialTabElementSelector` prop. If used, the value of this prop should remain the same for the lifetime of the component. This might require that you use `React.useCallback` to create a stable callback function.
### Grid usage

@@ -198,2 +206,2 @@

- For beta versions: `npm publish --tag next`.
- For releases: `npm publish`.
- For releases: `npm publish --tag latest`.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc