diff --git a/.size-limit b/.size-limit index b4895c9..085d896 100644 --- a/.size-limit +++ b/.size-limit @@ -1,7 +1,17 @@ [ { path: "dist/es2015/index.js", - limit: "7 KB", - ignore: ["prop-types", "react-dom", "tslib"] + ignore: ["react-dom", "tslib", "use-sidecar"], + limit: "6 KB" + }, + { + path: "dist/es2015/sidecar.js", + ignore: ["react-dom", "tslib", "use-sidecar"], + limit: "5 KB" + }, + { + path: "dist/es2015/UI.js", + ignore: ["react-dom", "tslib", "use-sidecar"], + limit: "2 KB" } -] +] \ No newline at end of file diff --git a/UI/UI.d.ts b/UI/UI.d.ts new file mode 100644 index 0000000..7a3a16e --- /dev/null +++ b/UI/UI.d.ts @@ -0,0 +1 @@ +export * from '../dist/es2015/UI' \ No newline at end of file diff --git a/UI/package.json b/UI/package.json new file mode 100644 index 0000000..c0b3c81 --- /dev/null +++ b/UI/package.json @@ -0,0 +1,8 @@ +{ + "private": true, + "main": "../dist/cjs/UI.js", + "jsnext:main": "../dist/es2015/UI.js", + "module": "../dist/es2015/UI.js", + "types": "UI.d.ts", + "sideEffects": false +} diff --git a/example/app.tsx b/example/app.tsx index 06261b0..6e68a3d 100644 --- a/example/app.tsx +++ b/example/app.tsx @@ -1,9 +1,7 @@ import * as React from 'react'; import {Component} from 'react'; -import {GHCorner} from 'react-gh-corner'; import {Toggle} from 'react-powerplug'; -import {AppWrapper} from './styled'; -import {FocusOn, AutoFocusInside, MoveFocusInside, InFocusGuard, classNames} from "../src"; +import {FocusOn, MoveFocusInside, InFocusGuard, classNames} from "../src"; export interface AppState { enabled: boolean; @@ -38,9 +36,8 @@ export default class App extends Component <{}, AppState> { return ( {({on, toggle}) => ( - + - outside outside alert('ok')}>test outside event @@ -89,7 +86,7 @@ export default class App extends Component <{}, AppState> { ) } - + )} ) diff --git a/example/styled.ts b/example/styled.ts deleted file mode 100644 index b5b5b1e..0000000 --- a/example/styled.ts +++ /dev/null @@ -1,16 +0,0 @@ -import styled, {injectGlobal} from 'styled-components'; - -injectGlobal` - body { - font-family: Helvetica; - background-color: #D8D1F5; - } - - * { - box-sizing: content-box; - } -`; - -export const AppWrapper = styled.div` - -`; \ No newline at end of file diff --git a/package.json b/package.json index e39a002..d18c46f 100644 --- a/package.json +++ b/package.json @@ -15,32 +15,48 @@ "static": "ts-react-toolbox publish", "format": "ts-react-toolbox format", "analyze": "ts-react-toolbox analyze", - "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s" + "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", + "size": "npx size-limit", + "link:rfl": "rsync -av ../react-focus-lock node_modules/ --exclude node_modules --exclude .git", + "link:rf": "rsync -av ../react-remove-scroll node_modules/ --exclude node_modules --exclude .git", + "link:sb": "rsync -av ../react-remove-scroll-bar node_modules/ --exclude node_modules --exclude .git", + "link:fl": "rsync -av ../focus-lock node_modules/ --exclude node_modules --exclude .git", + "link:ss": "rsync -av ../react-remove-scroll-bar/node_modules/react-style-singleton node_modules/ --exclude node_modules --exclude .git", + "link:all": "yarn link:fl & yarn link:rfl & yarn link:ss & yarn link:rf & yarn link:sb" }, + "sideEffects": [ + "**/sidecar.js" + ], "author": "Anton Korzunov ", "license": "MIT", "devDependencies": { + "@types/react": "^16.8.19", "conventional-changelog-cli": "^2.0.12", + "react": "^16.8.6", + "react-dom": "^16.8.6", "react-powerplug": "^1.0.0", - "size-limit": "^0.21.1", - "ts-react-toolbox": "^0.1.22" + "ts-react-toolbox": "^0.2.2" }, "dependencies": { "aria-hidden": "^1.1.1", - "react-focus-lock": "^1.18.2", - "react-remove-scroll": "^1.0.8" + "react-focus-lock": "^2.0.1", + "react-remove-scroll": "^2.0.1", + "react-style-singleton": "^2.0.0", + "use-sidecar": "^1.0.1" }, "engines": { "node": ">=8.5.0" }, "peerDependencies": { - "react": "^16.3.0" + "react": "^16.8.0" }, "jsnext:main": "dist/es2015/index.js", "module": "dist/es2015/index.js", "types": "dist/es5/index.d.ts", "files": [ - "dist" + "dist", + "UI", + "sidecar" ], "keywords": [ "react", @@ -49,5 +65,8 @@ "scroll", "isolation" ], + "resolutions": { + "typescript": "^3.0.0" + }, "homepage": "https://github.com/theKashey/react-focus-on#readme" } diff --git a/sidecar/package.json b/sidecar/package.json new file mode 100644 index 0000000..866e90c --- /dev/null +++ b/sidecar/package.json @@ -0,0 +1,7 @@ +{ + "private": true, + "main": "../dist/cjs/sidecar.js", + "jsnext:main": "../dist/es2015/sidecar.js", + "module": "../dist/es2015/sidecar.js", + "types": "sidecar.d.ts" +} diff --git a/sidecar/sidecar.d.ts b/sidecar/sidecar.d.ts new file mode 100644 index 0000000..864c9f5 --- /dev/null +++ b/sidecar/sidecar.d.ts @@ -0,0 +1,5 @@ +import * as React from 'react'; + +declare var sidecar: React.SFC; + +export default sidecar; diff --git a/src/Combination.tsx b/src/Combination.tsx new file mode 100644 index 0000000..bb71797 --- /dev/null +++ b/src/Combination.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; +import {FocusOn as ReactFocusOn} from "./UI"; +import {ReactFocusOnProps} from './types'; + +import sideCar from './sidecar'; + +export function FocusOn(props: ReactFocusOnProps) { + return ( + + ); +} \ No newline at end of file diff --git a/src/Effect.tsx b/src/Effect.tsx new file mode 100644 index 0000000..0701692 --- /dev/null +++ b/src/Effect.tsx @@ -0,0 +1,92 @@ +import * as React from 'react'; + +import {hideOthers} from 'aria-hidden'; + +import {InteractivityDisabler} from "./InteractivityDisabler"; +import {EffectProps} from "./types"; +import {focusHiddenMarker} from "./medium"; + +const extractRef = (ref: React.RefObject | HTMLElement): HTMLElement => ( + ('current' in ref) ? ref.current : ref +); + +export function Effect( + { + setLockProps, + + onEscapeKey, + onClickOutside, + shards, + + onActivation, + onDeactivation, + noIsolation + }: EffectProps) { + React.useEffect(() => { + let _undo = () => { + return + }; + let lastEventTarget: EventTarget; + + const onKeyPress = (event: KeyboardEvent) => { + if (event.defaultPrevented) { + return; + } + const code = event.key || event.keyCode; + if ((event.code === 'Escape' || code === 'Escape' || code === 27) && onEscapeKey) { + onEscapeKey(event); + } + }; + + const onClick = (event: MouseEvent) => { + if (event.defaultPrevented || event.target === lastEventTarget) { + return; + } + if ( + shards + .map(extractRef) + .some(node => node && node.contains(event.target as any) || node === event.target) + ) { + return; + } + if (onClickOutside) { + onClickOutside(); + } + }; + + const onNodeActivation = (node: HTMLElement) => { + _undo = hideOthers( + [node, ...(shards || []).map(extractRef)], + document.body, + noIsolation ? undefined : focusHiddenMarker + ); + if (onActivation) { + onActivation(node); + } + document.addEventListener('keyup', onKeyPress); + document.addEventListener('click', onClick); + }; + + const onNodeDeactivation = () => { + _undo(); + if (onDeactivation) { + onDeactivation(); + } + document.removeEventListener('keyup', onKeyPress); + document.removeEventListener('click', onClick); + }; + + setLockProps({ + onClick: (e: React.MouseEvent) => { + lastEventTarget = e.target + }, + onActivation: onNodeActivation, + onDeactivation: onNodeDeactivation, + }); + + }, []); + + return ( + + ); +} diff --git a/src/InteractivityDisabler.tsx b/src/InteractivityDisabler.tsx index afa525f..2c7aa3a 100644 --- a/src/InteractivityDisabler.tsx +++ b/src/InteractivityDisabler.tsx @@ -1,9 +1,8 @@ import * as React from 'react'; -import {styleSinglentone} from 'react-style-singleton'; +import {styleSingleton} from 'react-style-singleton'; +import {focusHiddenMarker} from "./medium"; -const Style = styleSinglentone(); - -export const focusHiddenMarker = 'data-focus-on-hidden'; +const Style = styleSingleton(); const styles = ` [${focusHiddenMarker}] { @@ -13,4 +12,4 @@ const styles = ` export const InteractivityDisabler: React.SFC = () => (