Skip to content

Commit

Permalink
feat: use forwardRef, and allow custom as prop
Browse files Browse the repository at this point in the history
  • Loading branch information
theKashey committed Oct 9, 2019
1 parent fb9c601 commit af0e560
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 32 deletions.
7 changes: 3 additions & 4 deletions UI/UI.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import {ReactFocusLockProps, AutoFocusProps, FreeFocusProps, InFocusGuardProps}
/**
* Traps Focus inside a Lock
*/
export default class ReactFocusLock extends React.Component<ReactFocusLockProps & {
sideCar: React.SFC<any>
}> {
}
declare const ReactFocusLock:React.FC<ReactFocusLockProps & {sideCar: React.SFC<any>}>;

export default ReactFocusLock;

/**
* Autofocus on children on Lock activation
Expand Down
14 changes: 13 additions & 1 deletion _tests/FocusLock.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ describe('react-focus-lock', () => {
expect(inner.current.innerHTML).to.include('Button 2');
});

it('should work with as prop', () => {
const inner = React.createRef();
const Comp = React.forwardRef((_, ref) => <button ref={ref}>t2 - Button 2</button>);
mount(
<div>
<button >t1 - Button 1</button>
<FocusLock as={Comp} ref={inner}/>
</div>
);
expect(inner.current).to.be.equal(document.activeElement);
expect(document.activeElement.innerHTML).to.include('Button 2');
});

it('Should not focus on inputs', () => {
const wrapper = mount((
Expand Down Expand Up @@ -1070,7 +1082,7 @@ describe('react-focus-lock', () => {
});
});

describe('Hooks', () => {
describe('Hooks', () => {
it('onActivation/Deactivation', () => {
const onActivation = sinon.spy();
const onDeactivation = sinon.spy();
Expand Down
11 changes: 7 additions & 4 deletions interfaces.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import {Ref} from "react";

export interface ReactFocusLockProps {
export interface ReactFocusLockProps<ChildrenType = React.ReactNode, LockProps=Record<string, any>> {
disabled?: boolean;

/**
Expand Down Expand Up @@ -58,8 +59,10 @@ export interface ReactFocusLockProps {
/**
* Component to use, defaults to 'div'
*/
as?: React.ReactType,
lockProps?: { [key: string]: any },
as?: string | React.ElementType<LockProps & {children: ChildrenType}>,
lockProps?: LockProps,

ref: Ref<HTMLElement>;

/**
* Controls focus lock working areas. Lock will silently ignore all the events from `not allowed` areas
Expand All @@ -73,7 +76,7 @@ export interface ReactFocusLockProps {
*/
shards?: Array<React.RefObject<any> | HTMLElement>;

children: React.ReactNode;
children?: ChildrenType;
}

export interface AutoFocusProps {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"focus-lock": "^0.6.5",
"prop-types": "^15.6.2",
"react-clientside-effect": "^1.2.2",
"use-callback-ref": "^1.1.0",
"use-sidecar": "^1.0.1"
}
}
5 changes: 3 additions & 2 deletions react-focus-lock.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import {ReactFocusLockProps, AutoFocusProps, FreeFocusProps, InFocusGuardProps}
/**
* Traps Focus inside a Lock
*/
export default class ReactFocusLock extends React.Component<ReactFocusLockProps> {
}
declare const ReactFocusLock:React.FC<ReactFocusLockProps>;

export default ReactFocusLock;

/**
* Autofocus on children on Lock activation
Expand Down
5 changes: 3 additions & 2 deletions src/Combination.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ const RequireSideCar = (props) => {
};
*/

const FocusLockCombination = props => (
const FocusLockCombination = React.forwardRef((props, ref) => (
<FocusLockUI
sideCar={FocusTrap}
ref={ref}
{...props}
/>
);
));

const { sideCar, ...propTypes } = FocusLockUI.propTypes || {};

Expand Down
47 changes: 28 additions & 19 deletions src/Lock.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import {
node, bool, string, any, arrayOf, oneOfType, object, func,
} from 'prop-types';
import * as constants from 'focus-lock/constants';
import { mergeRefs } from 'use-callback-ref';
import { hiddenGuard } from './FocusGuard';
import { mediumFocus, mediumBlur, mediumSidecar } from './medium';

const emptyArray = [];

function FocusLock(props) {
const FocusLock = React.forwardRef((props, parentRef) => {
const [realObserved, setObserved] = useState();
const observed = useRef();
const isActive = useRef(false);
Expand Down Expand Up @@ -97,6 +98,13 @@ function FocusLock(props) {
// eslint-disable-next-line no-console
console.warn('React-Focus-Lock: allowTextSelection is deprecated and enabled by default');
}

React.useEffect(() => {
if (!observed.current) {
// eslint-disable-next-line no-console
console.error('FocusLock: could not obtain ref to internal node');
}
}, []);
}

const lockProps = {
Expand All @@ -114,28 +122,28 @@ function FocusLock(props) {
<div key="guard-first" data-focus-guard tabIndex={disabled ? -1 : 0} style={hiddenGuard} />, // nearest focus guard
<div key="guard-nearest" data-focus-guard tabIndex={disabled ? -1 : 1} style={hiddenGuard} />, // first tabbed element guard
]}
{!disabled && (
<SideCar
id={id}
sideCar={mediumSidecar}
observed={realObserved}
disabled={disabled}
persistentFocus={persistentFocus}
autoFocus={autoFocus}
whiteList={whiteList}
shards={shards}
onActivation={onActivation}
onDeactivation={onDeactivation}
returnFocus={returnFocus}
/>
)}
<Container
ref={setObserveNode}
ref={mergeRefs([parentRef, setObserveNode])}
{...lockProps}
className={className}
onBlur={onBlur}
onFocus={onFocus}
>
{!disabled && (
<SideCar
id={id}
sideCar={mediumSidecar}
observed={realObserved}
disabled={disabled}
persistentFocus={persistentFocus}
autoFocus={autoFocus}
whiteList={whiteList}
shards={shards}
onActivation={onActivation}
onDeactivation={onDeactivation}
returnFocus={returnFocus}
/>
)}
{children}
</Container>
{
Expand All @@ -144,10 +152,10 @@ function FocusLock(props) {
}
</React.Fragment>
);
}
});

FocusLock.propTypes = {
children: node.isRequired,
children: node,
disabled: bool,
returnFocus: oneOfType([bool, object]),
noFocusGuards: bool,
Expand All @@ -172,6 +180,7 @@ FocusLock.propTypes = {
};

FocusLock.defaultProps = {
children: undefined,
disabled: false,
returnFocus: false,
noFocusGuards: false,
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14989,6 +14989,11 @@ url@^0.11.0:
punycode "1.3.2"
querystring "0.2.0"

use-callback-ref@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.1.0.tgz#e41d2b29aea8a568a6dbefe0af56155eac1b6884"
integrity sha512-a2j1dVM9UTxdIfZjbdhcD8nCDMDBkTp9rFasSBj3QPcVclYdpKbmLzqLddH3R6WuOff9W6Xo50VedPoVNu8z8A==

use-sidecar@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.1.tgz#75c7a5fdacc14bd3ab64992c638e45a396ad2fad"
Expand Down

0 comments on commit af0e560

Please sign in to comment.