API tweaks

This commit is contained in:
Aria Minaei 2021-09-03 19:29:21 +02:00
parent 58e46620cc
commit 9955730876
4 changed files with 44 additions and 14 deletions

View file

@ -2,7 +2,7 @@ import studio from '@theatre/studio'
import type {UseDragOpts} from '@theatre/studio/uiComponents/useDrag' import type {UseDragOpts} from '@theatre/studio/uiComponents/useDrag'
import useDrag from '@theatre/studio/uiComponents/useDrag' import useDrag from '@theatre/studio/uiComponents/useDrag'
import React, {useLayoutEffect, useMemo, useState} from 'react' import React, {useLayoutEffect, useMemo, useState} from 'react'
import type {IProject, ISheet, ISheetObject} from '@theatre/core' import type {IProject, ISheet} from '@theatre/core'
import {types as t} from '@theatre/core' import {types as t} from '@theatre/core'
import type {IScrub, IStudio} from '@theatre/studio' import type {IScrub, IStudio} from '@theatre/studio'
@ -16,7 +16,7 @@ const boxObjectConfig = t.compound({
const Box: React.FC<{ const Box: React.FC<{
id: string id: string
sheet: ISheet sheet: ISheet
selection: ISheetObject[] selection: IStudio['selection']
}> = ({id, sheet, selection}) => { }> = ({id, sheet, selection}) => {
// This is cheap to call and always returns the same value, so no need for useMemo() // This is cheap to call and always returns the same value, so no need for useMemo()
const obj = sheet.object(id, boxObjectConfig) const obj = sheet.object(id, boxObjectConfig)

View file

@ -2,7 +2,7 @@ import type {UseDragOpts} from '@theatre/studio/uiComponents/useDrag'
import useDrag from '@theatre/studio/uiComponents/useDrag' import useDrag from '@theatre/studio/uiComponents/useDrag'
import React, {useLayoutEffect, useMemo, useState} from 'react' import React, {useLayoutEffect, useMemo, useState} from 'react'
import studio from '@theatre/studio' import studio from '@theatre/studio'
import type {IProject, ISheet, ISheetObject} from '@theatre/core' import type {IProject, ISheet} from '@theatre/core'
import {types as t} from '@theatre/core' import {types as t} from '@theatre/core'
import type {IScrub, IStudio} from '@theatre/studio' import type {IScrub, IStudio} from '@theatre/studio'
@ -29,7 +29,7 @@ const boxObjectConfig = t.compound({
const Box: React.FC<{ const Box: React.FC<{
id: string id: string
sheet: ISheet sheet: ISheet
selection: ISheetObject[] selection: IStudio['selection']
}> = ({id, sheet, selection: selection}) => { }> = ({id, sheet, selection: selection}) => {
// This is cheap to call and always returns the same value, so no need for useMemo() // This is cheap to call and always returns the same value, so no need for useMemo()
const obj = sheet.object('object ' + id, boxObjectConfig) const obj = sheet.object('object ' + id, boxObjectConfig)

View file

@ -2,6 +2,7 @@ import {useLayoutEffect, useRef, useState} from 'react'
import {useEditorStore} from '../store' import {useEditorStore} from '../store'
import shallow from 'zustand/shallow' import shallow from 'zustand/shallow'
import studio from '@theatre/studio' import studio from '@theatre/studio'
import type {ISheetObject} from '@theatre/core'
export function useSelected(): undefined | string { export function useSelected(): undefined | string {
const [state, set] = useState<string | undefined>(undefined) const [state, set] = useState<string | undefined>(undefined)
@ -12,7 +13,10 @@ export function useSelected(): undefined | string {
useLayoutEffect(() => { useLayoutEffect(() => {
const setFromStudio = (selection: typeof studio.selection) => { const setFromStudio = (selection: typeof studio.selection) => {
const item = selection.find((s) => s.sheet === sheet) const item = selection.find(
(s): s is ISheetObject =>
s.type === 'Theatre_SheetObject_PublicAPI' && s.sheet === sheet,
)
if (!item) { if (!item) {
set(undefined) set(undefined)
} else { } else {
@ -29,7 +33,10 @@ export function useSelected(): undefined | string {
export function getSelected(): undefined | string { export function getSelected(): undefined | string {
const sheet = useEditorStore.getState().sheet const sheet = useEditorStore.getState().sheet
if (!sheet) return undefined if (!sheet) return undefined
const item = studio.selection.find((s) => s.sheet === sheet) const item = studio.selection.find(
(s): s is ISheetObject =>
s.type === 'Theatre_SheetObject_PublicAPI' && s.sheet === sheet,
)
if (!item) { if (!item) {
return undefined return undefined
} else { } else {

View file

@ -17,6 +17,7 @@ import getStudio from './getStudio'
import type React from 'react' import type React from 'react'
import type {PropTypeConfig_Compound} from '@theatre/core/propTypes' import type {PropTypeConfig_Compound} from '@theatre/core/propTypes'
import {debounce} from 'lodash-es' import {debounce} from 'lodash-es'
import type Sheet from '@theatre/core/sheets/Sheet'
export interface ITransactionAPI { export interface ITransactionAPI {
set<V>(pointer: Pointer<V>, value: V): void set<V>(pointer: Pointer<V>, value: V): void
@ -82,11 +83,30 @@ export interface IStudio {
scrub(): IScrub scrub(): IScrub
debouncedScrub(threshhold: number): Pick<IScrub, 'capture'> debouncedScrub(threshhold: number): Pick<IScrub, 'capture'>
/**
* Sets the current selection.
*
* Usage:
* ```ts
* const sheet1: ISheet = ...
* const obj1: ISheetObject<any> = ...
*
* studio.setSelection([sheet1, obj1])
* ```
*
* You can read the current selection from studio.selection
*/
setSelection(selection: Array<ISheetObject | ISheet>): void setSelection(selection: Array<ISheetObject | ISheet>): void
onSelectionChange(fn: (s: Array<ISheetObject>) => void): VoidFunction /**
* Calls fn every time the current selection changes.
*/
onSelectionChange(fn: (s: Array<ISheetObject | ISheet>) => void): VoidFunction
readonly selection: Array<ISheetObject> /**
* The current selection, consisting of Sheets and Sheet Objects
*/
readonly selection: Array<ISheetObject | ISheet>
extend(extension: IExtension): void extend(extension: IExtension): void
@ -137,17 +157,20 @@ export default class TheatreStudio implements IStudio {
}) })
} }
private _getSelectionDerivation(): IDerivation<ISheetObject[]> { private _getSelectionDerivation(): IDerivation<(ISheetObject | ISheet)[]> {
return this._cache.get('_getStateDerivation()', () => return this._cache.get('_getStateDerivation()', () =>
prism((): ISheetObject[] => { prism((): (ISheetObject | ISheet)[] => {
return getOutlineSelection() return getOutlineSelection()
.filter((s): s is SheetObject => s.type === 'Theatre_SheetObject') .filter(
(s): s is SheetObject | Sheet =>
s.type === 'Theatre_SheetObject' || s.type === 'Theatre_Sheet',
)
.map((s) => s.publicApi) .map((s) => s.publicApi)
}), }),
) )
} }
private _getSelection(): ISheetObject[] { private _getSelection(): (ISheetObject | ISheet)[] {
return this._getSelectionDerivation().getValue() return this._getSelectionDerivation().getValue()
} }
@ -163,11 +186,11 @@ export default class TheatreStudio implements IStudio {
}) })
} }
onSelectionChange(fn: (s: ISheetObject[]) => void): VoidFn { onSelectionChange(fn: (s: (ISheetObject | ISheet)[]) => void): VoidFn {
return this._getSelectionDerivation().tapImmediate(studioTicker, fn) return this._getSelectionDerivation().tapImmediate(studioTicker, fn)
} }
get selection(): ISheetObject[] { get selection(): (ISheetObject | ISheet)[] {
return this._getSelection() return this._getSelection()
} }