diff --git a/packages/playground/src/shared/hello-world-extension-dataverse/App.tsx b/packages/playground/src/shared/hello-world-extension-dataverse/App.tsx new file mode 100644 index 0000000..4d85034 --- /dev/null +++ b/packages/playground/src/shared/hello-world-extension-dataverse/App.tsx @@ -0,0 +1,37 @@ +import {editable as e, SheetProvider} from '@theatre/r3f' +import {Stars, TorusKnot} from '@react-three/drei' +import {getProject} from '@theatre/core' +import React from 'react' +import {Canvas} from '@react-three/fiber' + +function App() { + return ( +
{ + // return setBgIndex((bgIndex) => (bgIndex + 1) % bgs.length) + }} + style={{ + height: '100vh', + }} + > + + + + + + + + + + + +
+ ) +} + +export default App diff --git a/packages/playground/src/shared/hello-world-extension-dataverse/index.tsx b/packages/playground/src/shared/hello-world-extension-dataverse/index.tsx new file mode 100644 index 0000000..2ee1c43 --- /dev/null +++ b/packages/playground/src/shared/hello-world-extension-dataverse/index.tsx @@ -0,0 +1,70 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import App from './App' +import type {ToolsetConfig} from '@theatre/studio' +import studio from '@theatre/studio' +import extension from '@theatre/r3f/dist/extension' +import {Box, prism, Ticker, val} from '@theatre/dataverse' + +/** + * Let's take a look at how we can use `prism`, `Ticker`, and `val` from Theatre.js's Dataverse library + * to create a switch with state that is updated automatically, + * and is even stored in a Theatre.js object. + * + * Without going into the details of `prism`, `Ticker`, and `val`, note that by wrapping our `ToolsetConfig` in a prism, our + * ```ts + * ... .tapImmediate(Ticker.raf, (toolset) => { + * set(toolset) + * }) + * ``` + * code will be called whenever `val(obj.props.exampleProp)` changes (whenever the user clicks the switch and the `onChange` callback is called). + * This will ensure that our switch's value matches its state and is reflected in the UI via `set(toolset)`. + */ + +studio.extend(extension) +studio.extend({ + id: '@theatre/hello-world-extension', + toolbars: { + global(set, studio) { + const exampleBox = new Box('mobile') + + const untapFn = prism(() => [ + { + type: 'Switch', + value: val(exampleBox.derivation), + onChange: (value) => exampleBox.set(value), + options: [ + { + value: 'mobile', + label: 'view mobile version', + svgSource: '😀', + }, + { + value: 'desktop', + label: 'view desktop version', + svgSource: '🪢', + }, + ], + }, + { + type: 'Icon', + title: 'Example Icon', + svgSource: '👁‍🗨', + onClick: () => { + console.log('hello') + }, + }, + ]) + // listen to changes to this derivation using the requestAnimationFrame shared ticker + .tapImmediate(Ticker.raf, (value) => { + set(value) + }) + + return untapFn + }, + }, + panes: [], +}) +studio.initialize() + +ReactDOM.render(, document.getElementById('root')) diff --git a/packages/playground/src/shared/hello-world-extension-using-sheet-object/App.tsx b/packages/playground/src/shared/hello-world-extension-using-sheet-object/App.tsx new file mode 100644 index 0000000..4d85034 --- /dev/null +++ b/packages/playground/src/shared/hello-world-extension-using-sheet-object/App.tsx @@ -0,0 +1,37 @@ +import {editable as e, SheetProvider} from '@theatre/r3f' +import {Stars, TorusKnot} from '@react-three/drei' +import {getProject} from '@theatre/core' +import React from 'react' +import {Canvas} from '@react-three/fiber' + +function App() { + return ( +
{ + // return setBgIndex((bgIndex) => (bgIndex + 1) % bgs.length) + }} + style={{ + height: '100vh', + }} + > + + + + + + + + + + + +
+ ) +} + +export default App diff --git a/packages/playground/src/shared/hello-world-extension-using-sheet-object/index.tsx b/packages/playground/src/shared/hello-world-extension-using-sheet-object/index.tsx new file mode 100644 index 0000000..d32c4b3 --- /dev/null +++ b/packages/playground/src/shared/hello-world-extension-using-sheet-object/index.tsx @@ -0,0 +1,63 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import App from './App' +import type {ISheetObject} from '@theatre/core'; +import { onChange, types, val} from '@theatre/core' +import studio from '@theatre/studio' +import extension from '@theatre/r3f/dist/extension' + +const dataConfig = { + exampleProp: types.stringLiteral('yes', { + no: 'no', + yes: 'yes', + }), +} + +studio.extend(extension) +studio.extend({ + id: '@theatre/hello-world-extension', + toolbars: { + global(set, studio) { + // A sheet object used by this extension + const obj: ISheetObject = studio + .getStudioProject() + .sheet('example extension UI') + .object('editor', dataConfig) + + const updateToolset = () => + set([ + { + type: 'Switch', + value: val(obj.props.exampleProp), + onChange: (value) => + studio.transaction(({set}) => set(obj.props.exampleProp, value)), + options: [ + { + value: 'no', + label: 'say no', + svgSource: '👎', + }, + { + value: 'yes', + label: 'say yes', + svgSource: '👍', + }, + ], + }, + ]) + + const untapFn = onChange(obj.props.exampleProp, () => { + updateToolset() + }) + + // initial update + updateToolset() + + return untapFn + }, + }, + panes: [], +}) +studio.initialize() + +ReactDOM.render(, document.getElementById('root')) diff --git a/packages/playground/src/shared/hello-world-extension/index.tsx b/packages/playground/src/shared/hello-world-extension/index.tsx index 451d46d..ea029b8 100644 --- a/packages/playground/src/shared/hello-world-extension/index.tsx +++ b/packages/playground/src/shared/hello-world-extension/index.tsx @@ -1,46 +1,52 @@ import React from 'react' import ReactDOM from 'react-dom' import App from './App' -import type {ToolsetConfig} from '@theatre/studio' import studio from '@theatre/studio' import extension from '@theatre/r3f/dist/extension' -import {Box, prism, Ticker, val} from '@theatre/dataverse' studio.extend(extension) studio.extend({ id: '@theatre/hello-world-extension', toolbars: { global(set, studio) { - const exampleBox = new Box('mobile') - return prism(() => [ - { - type: 'Switch', - value: val(exampleBox.derivation), - onChange: (value) => exampleBox.set(value), - options: [ - { - value: 'mobile', - label: 'view mobile version', - svgSource: '😀', + let switchValue = 'mobile' + const updateToolset = () => + set([ + { + type: 'Switch', + value: switchValue, + onChange: (value) => { + switchValue = value + updateToolset() }, - { - value: 'desktop', - label: 'view desktop version', - svgSource: '🪢', - }, - ], - }, - { - type: 'Icon', - title: 'Example Icon', - svgSource: '👁‍🗨', - onClick: () => { - console.log('hello') + options: [ + { + value: 'mobile', + label: 'view mobile version', + svgSource: '😀', + }, + { + value: 'desktop', + label: 'view desktop version', + svgSource: '🪢', + }, + ], }, - }, - ]).tapImmediate(Ticker.raf, (value) => { - set(value) - }) + { + type: 'Icon', + title: 'Example Icon', + svgSource: '👁‍🗨', + onClick: () => { + console.log('hello') + }, + }, + ]) + + updateToolset() + + return () => { + // remove any listeners if necessary when the extension is unloaded + } }, }, panes: [],