From f0c2df678ecfaeba7824d455bbf189dc69bfe44a Mon Sep 17 00:00:00 2001 From: Alaric Baraou Date: Sun, 31 Oct 2021 23:27:24 +0100 Subject: [PATCH 1/3] save --- src/A11y.tsx | 41 +++++++++++++++++++++++++++++++++++++++++ src/Html.tsx | 34 +++++++++++++++------------------- src/a11yStore.tsx | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 19 deletions(-) create mode 100644 src/a11yStore.tsx diff --git a/src/A11y.tsx b/src/A11y.tsx index bd2846b..9df4da9 100644 --- a/src/A11y.tsx +++ b/src/A11y.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useRef, useState, useContext } from 'react'; import { useThree } from '@react-three/fiber'; import useAnnounceStore from './announceStore'; +import useA11yStore from './a11yStore'; import { useA11ySectionContext } from './A11ySection'; import { stylesHiddenButScreenreadable } from './A11yConsts'; import { Html } from './Html'; @@ -115,24 +116,37 @@ export const A11y: React.FC = ({ hovered: false, focused: false, pressed: startPressed ? startPressed : false, + autoUpdate: false, + needUpdate: false, }); const a11yScreenReader = useAnnounceStore(state => state.a11yScreenReader); + const registerA11YObj = useA11yStore(state => state.registerA11YObj); const overHtml = useRef(false); const overMesh = useRef(false); + const refHtml = useRef(null); const domElement = useThree(state => state.gl.domElement); // temporary fix to prevent error -> keep track of our component's mounted state const componentIsMounted = useRef(true); useEffect(() => { + registerA11YObj(setA11yState); return () => { domElement.style.cursor = 'default'; componentIsMounted.current = false; }; }, []); // Using an empty dependency array ensures this on + useEffect(() => { + if (refHtml.current) { + // @ts-ignore + refHtml.current.needUpdate = a11yState.needUpdate; + } + return () => {}; + }, [a11yState.needUpdate]); + React.Children.only(children); // @ts-ignore const handleOnPointerOver = e => { @@ -149,6 +163,8 @@ export const A11y: React.FC = ({ hovered: true, focused: a11yState.focused, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); } }; @@ -166,6 +182,8 @@ export const A11y: React.FC = ({ hovered: false, focused: a11yState.focused, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); } } @@ -191,6 +209,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: a11yState.focused, pressed: !a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); if (typeof actionCall === 'function') actionCall(); } @@ -231,6 +251,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} onBlur={() => { @@ -238,6 +260,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} > @@ -273,6 +297,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} onBlur={() => { @@ -280,6 +306,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} > @@ -311,6 +339,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} onBlur={() => { @@ -318,6 +348,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} > @@ -350,6 +382,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} onFocus={() => { @@ -358,6 +392,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} /> @@ -381,6 +417,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} onFocus={() => { @@ -389,6 +427,8 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, + autoUpdate: a11yState.autoUpdate, + needUpdate: a11yState.needUpdate, }); }} > @@ -482,6 +522,7 @@ export const A11y: React.FC = ({ children.props.position ? children.props.position : 0 } {...portal} + ref={refHtml} > {AltText} {HtmlAccessibleElement} diff --git a/src/Html.tsx b/src/Html.tsx index 501926c..31cfaf6 100644 --- a/src/Html.tsx +++ b/src/Html.tsx @@ -82,22 +82,23 @@ export const Html = React.forwardRef( zIndexRange = [16777271, 0], ...props }: HtmlProps, - ref: React.Ref + ref: React.Ref ) => { const gl = useThree(({ gl }) => gl); const camera = useThree(({ camera }) => camera); const scene = useThree(({ scene }) => scene); const size = useThree(({ size }) => size); const [el] = React.useState(() => document.createElement('div')); - const group = React.useRef(null); const oldZoom = React.useRef(0); const oldPosition = React.useRef([0, 0]); const target = portal?.current ?? gl.domElement.parentNode; React.useEffect(() => { - if (group.current) { + //@ts-ignore + if (ref.current) { scene.updateMatrixWorld(); - const vec = calculatePosition(group.current, camera, size); + //@ts-ignore + const vec = calculatePosition(ref.current, camera, size); el.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(${vec[0]}px,${vec[1]}px,0);transform-origin:0 0;`; if (target) { target.appendChild(el); @@ -120,34 +121,29 @@ export const Html = React.forwardRef( React.useLayoutEffect(() => { ReactDOM.render( -
, +
, el ); }); useFrame(() => { - if (group.current) { + //@ts-ignore + if (ref.current && ref.current.a11yNeedUpdate) { camera.updateMatrixWorld(); - const vec = calculatePosition(group.current, camera, size); + //@ts-ignore + const vec = calculatePosition(ref.current, camera, size); if ( Math.abs(oldZoom.current - camera.zoom) > eps || Math.abs(oldPosition.current[0] - vec[0]) > eps || Math.abs(oldPosition.current[1] - vec[1]) > eps ) { - el.style.display = !isObjectBehindCamera(group.current, camera) + //@ts-ignore + el.style.display = !isObjectBehindCamera(ref.current, camera) ? 'block' : 'none'; - el.style.zIndex = `${objectZIndex( - group.current, - camera, - zIndexRange - )}`; + //@ts-ignore + el.style.zIndex = `${objectZIndex(ref.current, camera, zIndexRange)}`; el.style.transform = `translate3d(${vec[0]}px,${vec[1]}px,0) scale(1)`; oldPosition.current = vec; oldZoom.current = camera.zoom; @@ -155,6 +151,6 @@ export const Html = React.forwardRef( } }); - return ; + return ; } ); diff --git a/src/a11yStore.tsx b/src/a11yStore.tsx new file mode 100644 index 0000000..66409e8 --- /dev/null +++ b/src/a11yStore.tsx @@ -0,0 +1,44 @@ +import create from 'zustand'; + +type State = { + a11yObj: Array< + React.Dispatch< + React.SetStateAction<{ + hovered: boolean; + focused: boolean; + pressed: boolean; + autoUpdate: boolean; + needUpdate: boolean; + }> + > + >; + registerA11YObj: ( + a11yObj: React.Dispatch< + React.SetStateAction<{ + hovered: boolean; + focused: boolean; + pressed: boolean; + autoUpdate: boolean; + needUpdate: boolean; + }> + > + ) => void; +}; + +const useA11yStore = create(set => { + return { + a11yObj: [], + registerA11YObj: a11yObj => { + set(state => { + let newA11yObj = state.a11yObj; + newA11yObj.push(a11yObj); + + return { + a11yObj: newA11yObj, + }; + }); + }, + }; +}); + +export default useA11yStore; From 03a9057c028f7ff9370d508830e65e3305ef658d Mon Sep 17 00:00:00 2001 From: Alaric Baraou Date: Mon, 1 Nov 2021 00:08:44 +0100 Subject: [PATCH 2/3] save --- example/src/App.js | 8 +++++++- src/A11y.tsx | 10 ++-------- src/Html.tsx | 10 ++++++++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/example/src/App.js b/example/src/App.js index b6dce62..98546e6 100644 --- a/example/src/App.js +++ b/example/src/App.js @@ -19,8 +19,14 @@ const geometries = [ function ToggleButton(props) { const a11y = useA11y() + console.log(a11y) return ( - + { + console.log(a11y) + a11y.refHtml.a11yNeedUpdate = true + }}> diff --git a/src/A11y.tsx b/src/A11y.tsx index 9df4da9..6f7f51c 100644 --- a/src/A11y.tsx +++ b/src/A11y.tsx @@ -76,6 +76,7 @@ const A11yContext = React.createContext({ focus: false, hover: false, pressed: false, + refHtml: null, }); A11yContext.displayName = 'A11yContext'; @@ -139,14 +140,6 @@ export const A11y: React.FC = ({ }; }, []); // Using an empty dependency array ensures this on - useEffect(() => { - if (refHtml.current) { - // @ts-ignore - refHtml.current.needUpdate = a11yState.needUpdate; - } - return () => {}; - }, [a11yState.needUpdate]); - React.Children.only(children); // @ts-ignore const handleOnPointerOver = e => { @@ -494,6 +487,7 @@ export const A11y: React.FC = ({ hover: a11yState.hovered, focus: a11yState.focused, pressed: a11yState.pressed, + refHtml: refHtml.current, }} > { - //@ts-ignore - if (ref.current && ref.current.a11yNeedUpdate) { + if ( + //@ts-ignore + (ref.current && ref.current.a11yAutoUpdate) || + //@ts-ignore + ref.current.a11yNeedUpdate + ) { camera.updateMatrixWorld(); //@ts-ignore const vec = calculatePosition(ref.current, camera, size); @@ -148,6 +152,8 @@ export const Html = React.forwardRef( oldPosition.current = vec; oldZoom.current = camera.zoom; } + //@ts-ignore + ref.current.a11yNeedUpdate = false; } }); From 7d45a8e6170da7e51985f4ed0d65bfc4029e2040 Mon Sep 17 00:00:00 2001 From: Alaric Baraou Date: Mon, 1 Nov 2021 00:30:39 +0100 Subject: [PATCH 3/3] save --- src/A11y.tsx | 30 +----------------------------- src/a11yStore.tsx | 25 +++---------------------- 2 files changed, 4 insertions(+), 51 deletions(-) diff --git a/src/A11y.tsx b/src/A11y.tsx index 6f7f51c..3a5f856 100644 --- a/src/A11y.tsx +++ b/src/A11y.tsx @@ -117,8 +117,6 @@ export const A11y: React.FC = ({ hovered: false, focused: false, pressed: startPressed ? startPressed : false, - autoUpdate: false, - needUpdate: false, }); const a11yScreenReader = useAnnounceStore(state => state.a11yScreenReader); @@ -133,7 +131,7 @@ export const A11y: React.FC = ({ // temporary fix to prevent error -> keep track of our component's mounted state const componentIsMounted = useRef(true); useEffect(() => { - registerA11YObj(setA11yState); + registerA11YObj(refHtml.current); return () => { domElement.style.cursor = 'default'; componentIsMounted.current = false; @@ -156,8 +154,6 @@ export const A11y: React.FC = ({ hovered: true, focused: a11yState.focused, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); } }; @@ -175,8 +171,6 @@ export const A11y: React.FC = ({ hovered: false, focused: a11yState.focused, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); } } @@ -202,8 +196,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: a11yState.focused, pressed: !a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); if (typeof actionCall === 'function') actionCall(); } @@ -244,8 +236,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} onBlur={() => { @@ -253,8 +243,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} > @@ -290,8 +278,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} onBlur={() => { @@ -299,8 +285,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} > @@ -332,8 +316,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} onBlur={() => { @@ -341,8 +323,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} > @@ -375,8 +355,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} onFocus={() => { @@ -385,8 +363,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} /> @@ -410,8 +386,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: false, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} onFocus={() => { @@ -420,8 +394,6 @@ export const A11y: React.FC = ({ hovered: a11yState.hovered, focused: true, pressed: a11yState.pressed, - autoUpdate: a11yState.autoUpdate, - needUpdate: a11yState.needUpdate, }); }} > diff --git a/src/a11yStore.tsx b/src/a11yStore.tsx index 66409e8..b931327 100644 --- a/src/a11yStore.tsx +++ b/src/a11yStore.tsx @@ -1,28 +1,9 @@ +import { Group } from 'three'; import create from 'zustand'; type State = { - a11yObj: Array< - React.Dispatch< - React.SetStateAction<{ - hovered: boolean; - focused: boolean; - pressed: boolean; - autoUpdate: boolean; - needUpdate: boolean; - }> - > - >; - registerA11YObj: ( - a11yObj: React.Dispatch< - React.SetStateAction<{ - hovered: boolean; - focused: boolean; - pressed: boolean; - autoUpdate: boolean; - needUpdate: boolean; - }> - > - ) => void; + a11yObj: Array>; + registerA11YObj: (a11yObj: React.Ref) => void; }; const useA11yStore = create(set => {