diff --git a/libs/orchestra/index.js b/libs/orchestra/index.js index 7408a3ac..0556590a 100644 --- a/libs/orchestra/index.js +++ b/libs/orchestra/index.js @@ -1,49 +1,84 @@ -import { broadcast } from 'libs/zustand-broadcast' -import { useEffect, useState } from 'react' -import { create } from 'zustand' +import { shared } from 'libs/zustand-shared' +// import { create } from 'zustand' import { createJSONStorage, persist } from 'zustand/middleware' +import { createStore } from 'zustand/vanilla' -// avoid to display debug tools on orchestra page -let isOrchestraPage = false - -const useOrchestraStore = create( +const ID = 'orchestra' +let store = createStore( persist(() => ({}), { - name: 'orchestra', + name: ID, storage: createJSONStorage(() => localStorage), }), ) -broadcast(useOrchestraStore, 'orchestra') - -export function useOrchestra() { - const values = useOrchestraStore() +store = shared(store, ID) - const [isVisible, setIsVisible] = useState(false) +class Toggle { + constructor(id, content) { + this.id = id + this.content = content + this.domElement = document.createElement('button') + this.domElement.innerText = content + this.domElement.title = id + this.domElement.style.fontSize = '64px' + this.domElement.addEventListener('click', this.onToggle, false) + } - useEffect(() => { - setIsVisible(!isOrchestraPage) - }, []) + onToggle = () => { + store.setState((state) => ({ ...state, [this.id]: !state[this.id] })) + } - return isVisible && values + destroy() { + this.domElement.removeEventListener('click', this.onToggle, false) + this.domElement.remove() + } } -// to be added to debug pages -export function OrchestraToggle({ children, title, id }) { - isOrchestraPage = true - - return ( - - ) +class Orchestra { + constructor() { + this.domElement = document.createElement('div') + + this.isDebug = false + this.toggles = [] + } + + get state() { + return !this.isDebug && store.getState() + } + + subscribe(callback) { + if (!this.isDebug) store.subscribe(callback) + } + + add(id, content) { + // check if already exists + if (this.toggles.find((toggle) => toggle.id === id)) return this + + const toggle = new Toggle(id, content) + this.toggles.push(toggle) + this.domElement.appendChild(toggle.domElement) + + return this + } + + remove(id) { + const toggle = this.toggles.find((toggle) => toggle.id === id) + // this.domElement.removeChild(toggle.domElement) + toggle.destroy() + this.toggles = this.toggles.filter((toggle) => toggle.id !== id) + + return this + } } + +const isClient = typeof window !== 'undefined' + +export default isClient && new Orchestra() + +// To be added to debug page +// Orchestra.isDebug = true +// Orchestra.add('studio', '⚙️') +// Orchestra.add('stats', '📈') +// Orchestra.add('grid', '🌐') +// Orchestra.add('dev', '🚧') +// document.body.appendChild(Orchestra.domElement) diff --git a/libs/orchestra/react.js b/libs/orchestra/react.js new file mode 100644 index 00000000..05a2f2bf --- /dev/null +++ b/libs/orchestra/react.js @@ -0,0 +1,34 @@ +import { useEffect, useRef, useState } from 'react' +import Orchestra from '.' + +export function useOrchestra() { + const [state, setState] = useState({}) + + useEffect(() => { + setState(Orchestra.state) + Orchestra.subscribe((state) => { + setState(state) + }) + }, []) + + return state +} + +export function OrchestraToggle({ id, children }) { + if (Orchestra) Orchestra.isDebug = true + + const elementRef = useRef() + + useEffect(() => { + Orchestra.add(id, children) + const toggle = Orchestra.toggles.find((toggle) => toggle.id === id) + elementRef.current.appendChild(toggle.domElement) + + return () => { + Orchestra.remove(id) + toggle.domElement.remove() + } + }, [id, children]) + + return +} diff --git a/libs/orchestra/react.old.js b/libs/orchestra/react.old.js new file mode 100644 index 00000000..1ec59040 --- /dev/null +++ b/libs/orchestra/react.old.js @@ -0,0 +1,42 @@ +import { useEffect, useState } from 'react' + +// avoid to display debug tools on orchestra page +let isOrchestraPage = false + +let useOrchestraStore = create( + persist(() => ({}), { + name: 'orchestra', + storage: createJSONStorage(() => localStorage), + }), +) + +useOrchestraStore = shared(useOrchestraStore, 'orchestra') + +export function useOrchestra() { + const values = useOrchestraStore() + + const [isVisible, setIsVisible] = useState(false) + + useEffect(() => { + setIsVisible(!isOrchestraPage) + }, []) + + return isVisible && values +} + +// to be added to debug pages +export function OrchestraToggle({ children, title, id }) { + isOrchestraPage = true + + return ( + + ) +} diff --git a/libs/theatre/hooks/use-studio.js b/libs/theatre/hooks/use-studio.js index 12bf2005..034313cc 100644 --- a/libs/theatre/hooks/use-studio.js +++ b/libs/theatre/hooks/use-studio.js @@ -1,4 +1,4 @@ -import { useOrchestra } from 'libs/orchestra' +import { useOrchestra } from 'libs/orchestra/react' import { useEffect, useState } from 'react' let studioPackage diff --git a/libs/zustand-broadcast.js b/libs/zustand-shared.js similarity index 84% rename from libs/zustand-broadcast.js rename to libs/zustand-shared.js index 0a10b5d1..9d7db36e 100644 --- a/libs/zustand-broadcast.js +++ b/libs/zustand-shared.js @@ -1,4 +1,4 @@ -export function broadcast(store, id = 'zustand-broadcast') { +export function shared(store, id = 'zustand-broadcast') { if ('BroadcastChannel' in globalThis) { let justReceived = false const channel = new BroadcastChannel(id) @@ -15,4 +15,6 @@ export function broadcast(store, id = 'zustand-broadcast') { } }) } + + return store } diff --git a/pages/_app.js b/pages/_app.js index 70f441be..d6e250af 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -5,7 +5,7 @@ import { DeviceDetectionProvider } from 'components/device-detection' import { gsap } from 'gsap' import { ScrollTrigger } from 'gsap/dist/ScrollTrigger' import { GTM_ID } from 'libs/analytics' -import { useOrchestra } from 'libs/orchestra' +import { useOrchestra } from 'libs/orchestra/react' import { useStore } from 'libs/store' import { ProjectProvider, RafDriverProvider } from 'libs/theatre' import dynamic from 'next/dynamic' diff --git a/pages/_debug/orchestra/index.js b/pages/_debug/orchestra/index.js index 382fbd28..04292629 100644 --- a/pages/_debug/orchestra/index.js +++ b/pages/_debug/orchestra/index.js @@ -1,23 +1,15 @@ -import { OrchestraToggle } from 'libs/orchestra' +import { OrchestraToggle } from 'libs/orchestra/react' import { forwardRef } from 'react' -const Orchestra = forwardRef(function Orchestra({}) { +const OrchestraPage = forwardRef(function OrchestraPage({}) { return ( <> - - ⚙️ - - - 📈 - - - 🌐 - - - 🚧 - + ⚙️ + 📈 + 🌐 + 🚧 ) }) -export default Orchestra +export default OrchestraPage