diff --git a/package.json b/package.json
index d2f4b81e8..03b12da14 100755
--- a/package.json
+++ b/package.json
@@ -20,10 +20,11 @@
"prop-types": "15.7.2",
"react": "16.9.0",
"react-dom": "16.9.0",
+ "react-focus-lock": "2.1.1",
"spatial-navigation-polyfill": "git+ssh://git@github.com/NikolaBorislavovHristov/spatial-navigation.git#964d09bf2b0853e27af6c25924b595d6621a019d",
"stremio-colors": "git+ssh://git@github.com/Stremio/stremio-colors.git#v2.0.4",
- "stremio-icons": "git+ssh://git@github.com/Stremio/stremio-icons.git#v1.0.11",
"stremio-core-web": "git+ssh://git@github.com/stremio/stremio-core-web.git#v0.6.0",
+ "stremio-icons": "git+ssh://git@github.com/Stremio/stremio-icons.git#v1.0.11",
"vtt.js": "0.13.0"
},
"devDependencies": {
@@ -54,4 +55,4 @@
"webpack-cli": "3.3.9",
"webpack-dev-server": "3.8.1"
}
-}
\ No newline at end of file
+}
diff --git a/src/router/FocusableContext/FocusableContext.js b/src/router/FocusableContext/FocusableContext.js
deleted file mode 100644
index 5fbec1a1f..000000000
--- a/src/router/FocusableContext/FocusableContext.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const React = require('react');
-
-const FocusableContext = React.createContext(false);
-
-FocusableContext.displayName = 'FocusableContext';
-
-module.exports = FocusableContext;
diff --git a/src/router/FocusableContext/FocusableProvider.js b/src/router/FocusableContext/FocusableProvider.js
deleted file mode 100644
index 3bf6bafab..000000000
--- a/src/router/FocusableContext/FocusableProvider.js
+++ /dev/null
@@ -1,57 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const { useModalsContainer } = require('../ModalsContainerContext');
-const { useRoutesContainer } = require('../RoutesContainerContext');
-const FocusableContext = require('./FocusableContext');
-
-const FocusableProvider = ({ children, onRoutesContainerChildrenChange, onModalsContainerChildrenChange }) => {
- const routesContainer = useRoutesContainer();
- const modalsContainer = useModalsContainer();
- const contentContainerRef = React.useRef(null);
- const [focusable, setFocusable] = React.useState(false);
- React.useEffect(() => {
- const onContainerChildrenChange = () => {
- setFocusable(
- onRoutesContainerChildrenChange({
- routesContainer: routesContainer,
- contentContainer: contentContainerRef.current
- })
- &&
- onModalsContainerChildrenChange({
- modalsContainer: modalsContainer,
- contentContainer: contentContainerRef.current
- })
- );
- };
- const routesContainerChildrenObserver = new MutationObserver(onContainerChildrenChange);
- const modalsContainerChildrenObserver = new MutationObserver(onContainerChildrenChange);
- routesContainerChildrenObserver.observe(routesContainer, { childList: true });
- modalsContainerChildrenObserver.observe(modalsContainer, { childList: true });
- onContainerChildrenChange();
- return () => {
- routesContainerChildrenObserver.disconnect();
- modalsContainerChildrenObserver.disconnect();
- };
- }, [routesContainer, modalsContainer, onRoutesContainerChildrenChange, onModalsContainerChildrenChange]);
- React.useEffect(() => {
- if (focusable && !contentContainerRef.current.contains(document.activeElement)) {
- contentContainerRef.current.focus();
- }
- }, [focusable]);
- return (
-
- {React.cloneElement(React.Children.only(children), {
- ref: contentContainerRef,
- tabIndex: -1
- })}
-
- );
-};
-
-FocusableProvider.propTypes = {
- children: PropTypes.node.isRequired,
- onRoutesContainerChildrenChange: PropTypes.func.isRequired,
- onModalsContainerChildrenChange: PropTypes.func.isRequired
-};
-
-module.exports = FocusableProvider;
diff --git a/src/router/FocusableContext/index.js b/src/router/FocusableContext/index.js
deleted file mode 100644
index 2e8686ca1..000000000
--- a/src/router/FocusableContext/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const FocusableProvider = require('./FocusableProvider');
-const useFocusable = require('./useFocusable');
-
-module.exports = {
- FocusableProvider,
- useFocusable
-};
diff --git a/src/router/FocusableContext/useFocusable.js b/src/router/FocusableContext/useFocusable.js
deleted file mode 100644
index 751eb1d25..000000000
--- a/src/router/FocusableContext/useFocusable.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const React = require('react');
-const FocusableContext = require('./FocusableContext');
-
-const useFocusable = () => {
- return React.useContext(FocusableContext);
-};
-
-module.exports = useFocusable;
diff --git a/src/router/FocusedRouteContext/FocusedRouteContext.js b/src/router/FocusedRouteContext/FocusedRouteContext.js
new file mode 100644
index 000000000..d1323e8e9
--- /dev/null
+++ b/src/router/FocusedRouteContext/FocusedRouteContext.js
@@ -0,0 +1,7 @@
+const React = require('react');
+
+const FocusedRouteContext = React.createContext(false);
+
+FocusedRouteContext.displayName = 'FocusedRouteContext';
+
+module.exports = FocusedRouteContext;
diff --git a/src/router/FocusedRouteContext/index.js b/src/router/FocusedRouteContext/index.js
new file mode 100644
index 000000000..5163ca12c
--- /dev/null
+++ b/src/router/FocusedRouteContext/index.js
@@ -0,0 +1,7 @@
+const FocusedRouteContext = require('./FocusedRouteContext');
+const useFocusedRoute = require('./useFocusedRoute');
+
+module.exports = {
+ FocusedRouteProvider: FocusedRouteContext.Provider,
+ useFocusedRoute
+};
diff --git a/src/router/FocusedRouteContext/useFocusedRoute.js b/src/router/FocusedRouteContext/useFocusedRoute.js
new file mode 100644
index 000000000..3c893f027
--- /dev/null
+++ b/src/router/FocusedRouteContext/useFocusedRoute.js
@@ -0,0 +1,8 @@
+const React = require('react');
+const FocusedRouteContext = require('./FocusedRouteContext');
+
+const useFocusedRoute = () => {
+ return React.useContext(FocusedRouteContext);
+};
+
+module.exports = useFocusedRoute;
diff --git a/src/router/Modal/Modal.js b/src/router/Modal/Modal.js
index 89bb8d1e5..115b7aaab 100644
--- a/src/router/Modal/Modal.js
+++ b/src/router/Modal/Modal.js
@@ -1,21 +1,15 @@
const React = require('react');
const ReactDOM = require('react-dom');
const classnames = require('classnames');
-const { FocusableProvider } = require('../FocusableContext');
+const FocusLock = require('react-focus-lock').default;
const { useModalsContainer } = require('../ModalsContainerContext');
-const Modal = (props) => {
+const Modal = ({ className, children, ...props }) => {
const modalsContainer = useModalsContainer();
- const onRoutesContainerChildrenChange = React.useCallback(({ routesContainer, contentContainer }) => {
- return routesContainer.lastElementChild.contains(contentContainer);
- }, []);
- const onModalsContainerChildrenChange = React.useCallback(({ modalsContainer, contentContainer }) => {
- return modalsContainer.lastElementChild === contentContainer;
- }, []);
return ReactDOM.createPortal(
-
-
- ,
+
+ {children}
+ ,
modalsContainer
);
};
diff --git a/src/router/Route/Route.js b/src/router/Route/Route.js
index 81d978396..440b20bb0 100644
--- a/src/router/Route/Route.js
+++ b/src/router/Route/Route.js
@@ -1,21 +1,15 @@
const React = require('react');
const PropTypes = require('prop-types');
-const { FocusableProvider } = require('../FocusableContext');
+const FocusLock = require('react-focus-lock').default;
const { ModalsContainerProvider } = require('../ModalsContainerContext');
const Route = ({ children }) => {
- const onRoutesContainerChildrenChange = React.useCallback(({ routesContainer, contentContainer }) => {
- return routesContainer.lastElementChild.contains(contentContainer);
- }, []);
- const onModalsContainerChildrenChange = React.useCallback(({ modalsContainer }) => {
- return modalsContainer.childElementCount === 0;
- }, []);
return (
-
- {children}
-
+
+ {children}
+
);
diff --git a/src/router/Router/Router.js b/src/router/Router/Router.js
index 50bbab579..e8617bfca 100644
--- a/src/router/Router/Router.js
+++ b/src/router/Router/Router.js
@@ -1,9 +1,10 @@
const React = require('react');
const ReactIs = require('react-is');
const PropTypes = require('prop-types');
+const classnames = require('classnames');
const UrlUtils = require('url');
+const { FocusedRouteProvider } = require('../FocusedRouteContext');
const Route = require('../Route');
-const { RoutesContainerProvider } = require('../RoutesContainerContext');
const Router = ({ className, onPathNotMatch, ...props }) => {
const [{ homePath, viewsConfig }] = React.useState(() => ({
@@ -96,17 +97,19 @@ const Router = ({ className, onPathNotMatch, ...props }) => {
};
}, [onPathNotMatch]);
return (
-
+
{
views
.filter(view => view !== null)
- .map(({ key, component, urlParams, queryParams }) => (
-
- {React.createElement(component, { urlParams, queryParams })}
-
+ .map(({ key, component, urlParams, queryParams }, index, views) => (
+
+
+ {React.createElement(component, { urlParams, queryParams })}
+
+
))
}
-
+
);
};
diff --git a/src/router/RoutesContainerContext/RoutesContainerContext.js b/src/router/RoutesContainerContext/RoutesContainerContext.js
deleted file mode 100644
index 4c1adcbb5..000000000
--- a/src/router/RoutesContainerContext/RoutesContainerContext.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const React = require('react');
-
-const RoutesContainerContext = React.createContext(null);
-
-RoutesContainerContext.displayName = 'RoutesContainerContext';
-
-module.exports = RoutesContainerContext;
diff --git a/src/router/RoutesContainerContext/RoutesContainerProvider.js b/src/router/RoutesContainerContext/RoutesContainerProvider.js
deleted file mode 100644
index 7f04b062c..000000000
--- a/src/router/RoutesContainerContext/RoutesContainerProvider.js
+++ /dev/null
@@ -1,25 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const classnames = require('classnames');
-const RoutesContainerContext = require('./RoutesContainerContext');
-
-const RoutesContainerProvider = ({ className, children }) => {
- const [container, setContainer] = React.useState(null);
- return (
-
-
- {container instanceof HTMLElement ? children : null}
-
-
- );
-};
-
-RoutesContainerProvider.propTypes = {
- className: PropTypes.string,
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node
- ])
-};
-
-module.exports = RoutesContainerProvider;
diff --git a/src/router/RoutesContainerContext/index.js b/src/router/RoutesContainerContext/index.js
deleted file mode 100644
index b96f7dc8b..000000000
--- a/src/router/RoutesContainerContext/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const RoutesContainerProvider = require('./RoutesContainerProvider');
-const useRoutesContainer = require('./useRoutesContainer');
-
-module.exports = {
- RoutesContainerProvider,
- useRoutesContainer
-};
diff --git a/src/router/RoutesContainerContext/useRoutesContainer.js b/src/router/RoutesContainerContext/useRoutesContainer.js
deleted file mode 100644
index 046b294fc..000000000
--- a/src/router/RoutesContainerContext/useRoutesContainer.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const React = require('react');
-const RoutesContainerContext = require('./RoutesContainerContext');
-
-const useRoutesContainer = () => {
- return React.useContext(RoutesContainerContext);
-};
-
-module.exports = useRoutesContainer;
diff --git a/src/router/index.js b/src/router/index.js
index 9407ff0da..71623af39 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,9 +1,9 @@
-const { useFocusable } = require('./FocusableContext');
+const { useFocusedRoute } = require('./FocusedRouteContext');
const Modal = require('./Modal');
const Router = require('./Router');
module.exports = {
- useFocusable,
+ useFocusedRoute,
Modal,
Router
};
diff --git a/yarn.lock b/yarn.lock
index dc8ca098e..7fcc217df 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4404,7 +4404,7 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
-focus-lock@^0.6.3:
+focus-lock@^0.6.3, focus-lock@^0.6.5:
version "0.6.5"
resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.5.tgz#f6eb37832a9b1b205406175f5277396a28c0fce1"
integrity sha512-i/mVBOoa9o+tl+u9owOJUF8k8L85odZNIsctB+JAK2HFT8jckiBwmk+3uydlm6FN8czgnkIwQtBv6yyAbrzXjw==
@@ -7662,7 +7662,7 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-react-clientside-effect@^1.2.0:
+react-clientside-effect@^1.2.0, react-clientside-effect@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz#6212fb0e07b204e714581dd51992603d1accc837"
integrity sha512-nRmoyxeok5PBO6ytPvSjKp9xwXg9xagoTK1mMjwnQxqM9Hd7MNPl+LS1bOSOe+CV2+4fnEquc7H/S8QD3q697A==
@@ -7761,6 +7761,17 @@ react-fast-compare@2.0.4:
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
+react-focus-lock@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.1.1.tgz#49762377119ecd52eb56519ddd10a87c0c1ddd98"
+ integrity sha512-IKfloS8Ifx5v+Gwm64hoTqT0NmzXksTKYROOAq+HlBIxUqUS2yA5NNzQJtuOsx3nyPs7wrgycbVsffRfcA5OTw==
+ dependencies:
+ "@babel/runtime" "^7.0.0"
+ focus-lock "^0.6.5"
+ prop-types "^15.6.2"
+ react-clientside-effect "^1.2.2"
+ use-sidecar "^1.0.1"
+
react-focus-lock@^1.18.3:
version "1.19.1"
resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-1.19.1.tgz#2f3429793edaefe2d077121f973ce5a3c7a0651a"
@@ -9132,7 +9143,7 @@ ts-pnp@^1.1.2:
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.4.tgz#ae27126960ebaefb874c6d7fa4729729ab200d90"
integrity sha512-1J/vefLC+BWSo+qe8OnJQfWTYRS6ingxjwqmHMqaMxXMj7kFtKLgAaYW3JeX3mktjgUL+etlU8/B4VUAUI9QGw==
-tslib@^1.9.0:
+tslib@^1.9.0, tslib@^1.9.3:
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
@@ -9330,6 +9341,14 @@ url@^0.11.0:
punycode "1.3.2"
querystring "0.2.0"
+use-sidecar@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.1.tgz#75c7a5fdacc14bd3ab64992c638e45a396ad2fad"
+ integrity sha512-CLTDS2AZmUcXXFnxP/h/OadtvBOoHHnLYMMpKGntb5vKOQT94icrXMXX0mEdGiMhQU8vxHlndB72sRwRBHXTzw==
+ dependencies:
+ detect-node "^2.0.4"
+ tslib "^1.9.3"
+
use@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"