diff --git a/examples/basic-dom/Scene.tsx b/examples/basic-dom/Scene.tsx index 36c5e18..06a461c 100644 --- a/examples/basic-dom/Scene.tsx +++ b/examples/basic-dom/Scene.tsx @@ -6,6 +6,8 @@ import {types as t} from '@theatre/core' import type {UseDragOpts} from './useDrag' import useDrag from './useDrag' +studio.initialize() + const boxObjectConfig = t.compound({ x: t.number(0), y: t.number(0), diff --git a/examples/basic-dom/index.tsx b/examples/basic-dom/index.tsx index 7918432..e2aaf7a 100644 --- a/examples/basic-dom/index.tsx +++ b/examples/basic-dom/index.tsx @@ -4,7 +4,7 @@ import studio from '@theatre/studio' import {getProject} from '@theatre/core' import {Scene} from './Scene' -studio.ui +studio.initialize() ReactDOM.render( , diff --git a/examples/dom-cra/src/App.js b/examples/dom-cra/src/App.js index ae4f960..af705de 100644 --- a/examples/dom-cra/src/App.js +++ b/examples/dom-cra/src/App.js @@ -3,6 +3,8 @@ import {useLayoutEffect, useMemo, useState} from 'react' import {types as t} from '@theatre/core' import useDrag from './useDrag' +studio.initialize() + const boxObjectConfig = t.compound({ x: t.number(0), y: t.number(0), diff --git a/examples/dom-cra/src/index.js b/examples/dom-cra/src/index.js index 1625c86..91a7005 100644 --- a/examples/dom-cra/src/index.js +++ b/examples/dom-cra/src/index.js @@ -1,9 +1,11 @@ import ReactDOM from 'react-dom' import './index.css' import reportWebVitals from './reportWebVitals' -import '@theatre/studio' +import studio from '@theatre/studio' import {getProject} from '@theatre/core' +studio.initialize() + ReactDOM.render( diff --git a/packages/playground/src/dom/Scene.tsx b/packages/playground/src/dom/Scene.tsx index 1e22437..3bf6661 100644 --- a/packages/playground/src/dom/Scene.tsx +++ b/packages/playground/src/dom/Scene.tsx @@ -6,6 +6,8 @@ import type {IProject, ISheet, ISheetObject} from '@theatre/core' import {types as t} from '@theatre/core' import type {IScrub, IStudio} from '@theatre/studio' +studio.initialize() + const boxObjectConfig = t.compound({ x: t.number(0), y: t.number(0), @@ -44,7 +46,7 @@ const Box: React.FC<{ }, onDrag(x, y) { if (!firstOnDragCalled) { - studio.__experimental_setSelection([obj]) + studio.setSelection([obj]) firstOnDragCalled = true } scrub!.capture(({set}) => { @@ -67,7 +69,7 @@ const Box: React.FC<{ return (
{ - studio.__experimental_setSelection([obj]) + studio.setSelection([obj]) }} ref={setDivRef} style={{ @@ -94,7 +96,7 @@ export const Scene: React.FC<{project: IProject}> = ({project}) => { const [selection, setSelection] = useState() useLayoutEffect(() => { - return studio.__experimental_onSelectionChange((newState) => { + return studio.onSelectionChange((newState) => { setSelection(newState) }) }) diff --git a/packages/playground/src/dom/index.tsx b/packages/playground/src/dom/index.tsx index 7918432..e2aaf7a 100644 --- a/packages/playground/src/dom/index.tsx +++ b/packages/playground/src/dom/index.tsx @@ -4,7 +4,7 @@ import studio from '@theatre/studio' import {getProject} from '@theatre/core' import {Scene} from './Scene' -studio.ui +studio.initialize() ReactDOM.render( , diff --git a/packages/playground/src/redesign/Scene.tsx b/packages/playground/src/redesign/Scene.tsx index 9e3652c..dc143b1 100644 --- a/packages/playground/src/redesign/Scene.tsx +++ b/packages/playground/src/redesign/Scene.tsx @@ -6,6 +6,8 @@ import type {IProject, ISheet, ISheetObject} from '@theatre/core' import {types as t} from '@theatre/core' import type {IScrub, IStudio} from '@theatre/studio' +studio.initialize() + const boxObjectConfig = t.compound({ position: t.compound({ x: t.number(0), @@ -57,7 +59,7 @@ const Box: React.FC<{ }, onDrag(x, y) { if (!firstOnDragCalled) { - studio.__experimental_setSelection([obj]) + studio.setSelection([obj]) firstOnDragCalled = true } scrub!.capture(({set}) => { @@ -84,7 +86,7 @@ const Box: React.FC<{ return (
{ - studio.__experimental_setSelection([obj]) + studio.setSelection([obj]) }} ref={setDivRef} style={{ @@ -111,7 +113,7 @@ export const Scene: React.FC<{project: IProject}> = ({project}) => { const [selection, setSelection] = useState() useLayoutEffect(() => { - return studio.__experimental_onSelectionChange((newState) => { + return studio.onSelectionChange((newState) => { setSelection(newState) }) }) diff --git a/packages/playground/src/redesign/index.tsx b/packages/playground/src/redesign/index.tsx index bddcc27..29e6caf 100644 --- a/packages/playground/src/redesign/index.tsx +++ b/packages/playground/src/redesign/index.tsx @@ -5,7 +5,7 @@ import {getProject} from '@theatre/core' import {Scene} from './Scene' import bg from '../../xeno/bgs/8.png' -studio.ui +studio.initialize() document.body.style.cssText = ` background-image: url(${bg}); diff --git a/packages/playground/src/space-exploration/App.tsx b/packages/playground/src/space-exploration/App.tsx index b6ccbd7..0fdf655 100644 --- a/packages/playground/src/space-exploration/App.tsx +++ b/packages/playground/src/space-exploration/App.tsx @@ -5,6 +5,9 @@ import React, {Suspense} from 'react' import {Canvas} from '@react-three/fiber' import {useGLTF} from '@react-three/drei' import sceneGLB from './scene.glb' +import studio from '@theatre/studio' + +studio.initialize() document.body.style.backgroundColor = '#171717' diff --git a/packages/playground/src/turtle/TurtleRenderer.tsx b/packages/playground/src/turtle/TurtleRenderer.tsx index f74ded3..96696a3 100644 --- a/packages/playground/src/turtle/TurtleRenderer.tsx +++ b/packages/playground/src/turtle/TurtleRenderer.tsx @@ -13,6 +13,8 @@ import {types} from '@theatre/core' import type {ITurtle} from './turtle' import {drawTurtlePlan, makeTurtlePlan} from './turtle' +studio.initialize() + const objConfig = types.compound({ startingPoint: types.compound({ x: types.number(0.5, {range: [0, 1]}), diff --git a/packages/plugin-r3f/src/components/EditableProxy.tsx b/packages/plugin-r3f/src/components/EditableProxy.tsx index dea8c91..71991dc 100644 --- a/packages/plugin-r3f/src/components/EditableProxy.tsx +++ b/packages/plugin-r3f/src/components/EditableProxy.tsx @@ -172,7 +172,7 @@ const EditableProxy: VFC = ({ if (!theatreObject) { console.log('no theatre object for', uniqueName) } else { - studio.__experimental_setSelection([theatreObject]) + studio.setSelection([theatreObject]) } } }} @@ -206,7 +206,7 @@ const EditableProxy: VFC = ({ if (!theatreObject) { console.log('no theatre object for', uniqueName) } else { - studio.__experimental_setSelection([theatreObject]) + studio.setSelection([theatreObject]) } } }} diff --git a/packages/plugin-r3f/src/components/SnapshotEditor.tsx b/packages/plugin-r3f/src/components/SnapshotEditor.tsx index 71677ea..7a0d893 100644 --- a/packages/plugin-r3f/src/components/SnapshotEditor.tsx +++ b/packages/plugin-r3f/src/components/SnapshotEditor.tsx @@ -120,7 +120,7 @@ const SnapshotEditor: React.FC<{paneId: string}> = (props) => { }, [editorOpen]) const onPointerMissed = useCallback(() => { - if (sheet !== null) studio.__experimental_setSelection([sheet]) + if (sheet !== null) studio.setSelection([sheet]) }, [sheet]) if (!editorObject) return <> diff --git a/packages/plugin-r3f/src/components/useSelected.tsx b/packages/plugin-r3f/src/components/useSelected.tsx index 5f6718a..81b30e3 100644 --- a/packages/plugin-r3f/src/components/useSelected.tsx +++ b/packages/plugin-r3f/src/components/useSelected.tsx @@ -20,7 +20,7 @@ export function useSelected(): undefined | string { } } setFromStudio(studio.selection) - return studio.__experimental_onSelectionChange(setFromStudio) + return studio.onSelectionChange(setFromStudio) }, [sheet]) return state diff --git a/theatre/core/src/sheetObjects/SheetObject.ts b/theatre/core/src/sheetObjects/SheetObject.ts index 244c5e2..b2ef69b 100644 --- a/theatre/core/src/sheetObjects/SheetObject.ts +++ b/theatre/core/src/sheetObjects/SheetObject.ts @@ -64,10 +64,6 @@ export default class SheetObject implements IdentityDerivationProvider { this.template.overrideConfig(nativeObject, config) } - // getValues(): Record { - // return {} - // } - getValues(): IDerivation> { return this._cache.get('getValues()', () => prism(() => { diff --git a/theatre/core/src/sheetObjects/TheatreSheetObject.ts b/theatre/core/src/sheetObjects/TheatreSheetObject.ts index 76c788b..74623dc 100644 --- a/theatre/core/src/sheetObjects/TheatreSheetObject.ts +++ b/theatre/core/src/sheetObjects/TheatreSheetObject.ts @@ -19,8 +19,9 @@ export interface ISheetObject< Props extends PropTypeConfig_Compound<$IntentionalAny> = PropTypeConfig_Compound<$IntentionalAny>, > { readonly type: 'Theatre_SheetObject_PublicAPI' + /** - * The type of the values of the SheetObject. + * */ readonly value: Props['valueType'] readonly props: Pointer diff --git a/theatre/studio/src/TheatreStudio.ts b/theatre/studio/src/TheatreStudio.ts index 9a69086..bf5eba0 100644 --- a/theatre/studio/src/TheatreStudio.ts +++ b/theatre/studio/src/TheatreStudio.ts @@ -49,20 +49,42 @@ export type PaneInstance = { export interface IStudio { readonly ui: { - show(): void + /** + * Temporarily hides the studio + */ hide(): void - readonly showing: boolean + /** + * Whether the studio is currently visible or hidden + */ + readonly isHidden: boolean + /** + * Makes the studio visible again. + */ restore(): void } + /** + * Initializes the studio. Call this in your index.js/index.ts module. + * + * Usage with **tree-shaking**: + * ```ts + * import studio from '@theratre/studio' + * + * // Add this check if you wish to not include the studio in your production bundle + * if (process.env.NODE_ENV === "development") { + * studio.initialize() + * } + * ``` + */ + initialize(): void + transaction(fn: (api: ITransactionAPI) => void): void scrub(): IScrub debouncedScrub(threshhold: number): Pick - __experimental_setSelection(selection: Array): void - __experimental_onSelectionChange( - fn: (s: Array) => void, - ): VoidFunction + setSelection(selection: Array): void + + onSelectionChange(fn: (s: Array) => void): VoidFunction readonly selection: Array @@ -81,16 +103,12 @@ export interface IStudio { export default class TheatreStudio implements IStudio { readonly ui = { - show() { - getStudio().ui.show() - }, - hide() { getStudio().ui.hide() }, - get showing(): boolean { - return getStudio().ui._showing + get isHidden(): boolean { + return getStudio().ui.isHidden }, restore() { @@ -105,6 +123,10 @@ export default class TheatreStudio implements IStudio { */ constructor(internals: Studio) {} + initialize() { + getStudio().ui.render() + } + extend(extension: IExtension): void { getStudio().extend(extension) } @@ -129,7 +151,7 @@ export default class TheatreStudio implements IStudio { return this._getSelectionDerivation().getValue() } - __experimental_setSelection(selection: Array): void { + setSelection(selection: Array): void { const sanitizedSelection = [...selection] .filter((s) => isSheetObjectPublicAPI(s) || isSheetPublicAPI(s)) .map((s) => getStudio().corePrivateAPI!(s)) @@ -141,7 +163,7 @@ export default class TheatreStudio implements IStudio { }) } - __experimental_onSelectionChange(fn: (s: ISheetObject[]) => void): VoidFn { + onSelectionChange(fn: (s: ISheetObject[]) => void): VoidFn { return this._getSelectionDerivation().tapImmediate(studioTicker, fn) } diff --git a/theatre/studio/src/UI.ts b/theatre/studio/src/UI.ts index c66989a..07c31ee 100644 --- a/theatre/studio/src/UI.ts +++ b/theatre/studio/src/UI.ts @@ -3,10 +3,11 @@ import type {$IntentionalAny} from '@theatre/shared/utils/types' import React from 'react' import ReactDOM from 'react-dom' import type {Studio} from './Studio' +import {val} from '@theatre/dataverse' export default class UI { readonly containerEl = document.createElement('div') - _showing = false + private _rendered = false private _renderTimeout: NodeJS.Timer | undefined = undefined private _documentBodyUIIsRenderedIn: HTMLElement | undefined = undefined readonly containerShadow: ShadowRoot & HTMLElement @@ -27,20 +28,16 @@ export default class UI { this.containerShadow = this.containerEl.attachShadow({ mode: 'open', // To see why I had to cast this value to HTMLElement, take a look at its - // references. There are a few functions that actually work with a ShadowRoot - // but are typed to accept HTMLElement + // references of this prop. There are a few functions that actually work + // with a ShadowRoot but are typed to accept HTMLElement }) as $IntentionalAny as ShadowRoot & HTMLElement } - show() { - if (this._showing) { - if (this._documentBodyUIIsRenderedIn && document.body) { - this.hide() - } else { - return - } + render() { + if (this._rendered) { + return } - this._showing = true + this._rendered = true this._render() } @@ -60,24 +57,21 @@ export default class UI { } hide() { - if (!this._showing) return - this._showing = false - if (this._renderTimeout) { - clearTimeout(this._renderTimeout) - this._renderTimeout = undefined - } else { - ReactDOM.unmountComponentAtNode(this.containerShadow) - try { - this._documentBodyUIIsRenderedIn!.removeChild(this.containerEl) - this._documentBodyUIIsRenderedIn = undefined - } catch (e) {} - } + this.studio.transaction(({drafts}) => { + drafts.ahistoric.visibilityState = 'everythingIsHidden' + }) } restore() { - this.show() + this.render() this.studio.transaction(({drafts}) => { drafts.ahistoric.visibilityState = 'everythingIsVisible' }) } + + get isHidden() { + return ( + val(this.studio.atomP.ahistoric.visibilityState) === 'everythingIsHidden' + ) + } } diff --git a/theatre/studio/src/UIRoot/TheTrigger.tsx b/theatre/studio/src/UIRoot/TheTrigger.tsx deleted file mode 100644 index 4dcef66..0000000 --- a/theatre/studio/src/UIRoot/TheTrigger.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react' - -export default function TheTrigger() { - // @todo - return
The trigger
-} diff --git a/theatre/studio/src/UIRoot/UIRoot.tsx b/theatre/studio/src/UIRoot/UIRoot.tsx index 5819c06..b1f323d 100644 --- a/theatre/studio/src/UIRoot/UIRoot.tsx +++ b/theatre/studio/src/UIRoot/UIRoot.tsx @@ -5,7 +5,6 @@ import React from 'react' import styled, {createGlobalStyle, StyleSheetManager} from 'styled-components' import PanelsRoot from './PanelsRoot' import ProvideTheme from './ProvideTheme' -import TheTrigger from './TheTrigger' import GlobalToolbar from '@theatre/studio/toolbars/GlobalToolbar/GlobalToolbar' import useRefAndState from '@theatre/studio/utils/useRefAndState' import {PortalContext} from 'reakit' @@ -66,7 +65,6 @@ export default function UIRoot() { const visiblityState = val(studio.atomP.ahistoric.visibilityState) const initialised = val(studio.atomP.ephemeral.initialised) - const shouldShowTrigger = visiblityState === 'onlyTriggerIsVisible' const shouldShowPanels = visiblityState === 'everythingIsVisible' const shouldShowGlobalToolbar = visiblityState !== 'everythingIsHidden' @@ -83,7 +81,6 @@ export default function UIRoot() { {shouldShowGlobalToolbar && } - {shouldShowTrigger && } {shouldShowPanels && } diff --git a/theatre/studio/src/index.ts b/theatre/studio/src/index.ts index 13b8577..5264000 100644 --- a/theatre/studio/src/index.ts +++ b/theatre/studio/src/index.ts @@ -15,10 +15,6 @@ setStudio(studioPrivateAPI) export const studio = studioPrivateAPI.publicApi export default studio -if (process.env.NODE_ENV !== 'test') { - studio.ui.show() -} - registerStudioBundle() function registerStudioBundle() { diff --git a/theatre/studio/src/store/types/ahistoric.ts b/theatre/studio/src/store/types/ahistoric.ts index 3550909..bcc5fdc 100644 --- a/theatre/studio/src/store/types/ahistoric.ts +++ b/theatre/studio/src/store/types/ahistoric.ts @@ -2,10 +2,7 @@ import type {ProjectState} from '@theatre/core/projects/store/storeTypes' import type {IRange, StrictRecord} from '@theatre/shared/utils/types' export type StudioAhistoricState = { - visibilityState: - | 'everythingIsHidden' - | 'everythingIsVisible' - | 'onlyTriggerIsVisible' + visibilityState: 'everythingIsHidden' | 'everythingIsVisible' theTrigger: { position: {