From f6cf3711f4d195025ac6d3d61696c7ccf6c1bfaf Mon Sep 17 00:00:00 2001 From: Aria Minaei Date: Mon, 6 Sep 2021 11:26:00 +0200 Subject: [PATCH] More progress on shorthand types --- examples/basic-dom/Scene.tsx | 9 +++-- examples/dom-cra/src/App.js | 9 +++-- packages/playground/src/dom/Scene.tsx | 9 +++-- packages/playground/src/redesign/Scene.tsx | 35 +++++++++---------- .../playground/src/turtle/TurtleRenderer.tsx | 8 ++--- packages/r3f/src/components/editorStuff.ts | 4 +-- packages/r3f/src/components/useSelected.tsx | 6 ++-- .../components/useSnapshotEditorCamera.tsx | 24 +++++++------ packages/r3f/src/store.ts | 16 ++++----- theatre/core/src/propTypes/index.ts | 4 +-- theatre/core/src/propTypes/internals.ts | 23 ++++++------ .../src/sheetObjects/TheatreSheetObject.ts | 30 ++++++++-------- theatre/core/src/sheets/TheatreSheet.ts | 18 +++++++--- theatre/shared/src/testUtils.ts | 17 ++++----- 14 files changed, 109 insertions(+), 103 deletions(-) diff --git a/examples/basic-dom/Scene.tsx b/examples/basic-dom/Scene.tsx index 06a461c..f3b6ce8 100644 --- a/examples/basic-dom/Scene.tsx +++ b/examples/basic-dom/Scene.tsx @@ -2,16 +2,15 @@ import type {IScrub, IStudio} from '@theatre/studio' import studio from '@theatre/studio' import React, {useLayoutEffect, useMemo, useState} from 'react' import type {ISheet, ISheetObject, IProject} from '@theatre/core' -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), -}) +const boxObjectConfig = { + x: 0, + y: 0, +} const Box: React.FC<{ id: string diff --git a/examples/dom-cra/src/App.js b/examples/dom-cra/src/App.js index af705de..969da1c 100644 --- a/examples/dom-cra/src/App.js +++ b/examples/dom-cra/src/App.js @@ -1,14 +1,13 @@ import studio from '@theatre/studio' 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), -}) +const boxObjectConfig = { + x: 0, + y: 0, +} const Box = ({id, sheet, selectedObject}) => { // This is cheap to call and always returns the same value, so no need for useMemo() diff --git a/packages/playground/src/dom/Scene.tsx b/packages/playground/src/dom/Scene.tsx index 9bee6e5..e08d92b 100644 --- a/packages/playground/src/dom/Scene.tsx +++ b/packages/playground/src/dom/Scene.tsx @@ -3,15 +3,14 @@ import type {UseDragOpts} from './useDrag' import useDrag from './useDrag' import React, {useLayoutEffect, useMemo, useState} from 'react' import type {IProject, ISheet} 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), -}) +const boxObjectConfig = { + x: 0, + y: 0, +} const Box: React.FC<{ id: string diff --git a/packages/playground/src/redesign/Scene.tsx b/packages/playground/src/redesign/Scene.tsx index 18e8726..2886473 100644 --- a/packages/playground/src/redesign/Scene.tsx +++ b/packages/playground/src/redesign/Scene.tsx @@ -3,28 +3,27 @@ import useDrag from '@theatre/studio/uiComponents/useDrag' import React, {useLayoutEffect, useMemo, useState} from 'react' import studio from '@theatre/studio' import type {IProject, ISheet} 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), - y: t.number(0), - z: t.number(0), - }), - scale: t.compound({ - x: t.number(0), - y: t.number(0), - z: t.number(0), - origin: t.compound({ - x: t.number(0), - y: t.number(0), - }), - w: t.number(0), - }), -}) +const boxObjectConfig = { + position: { + x: 0, + y: 0, + z: 0, + }, + scale: { + x: 0, + y: 0, + z: 0, + origin: { + x: 0, + y: 0, + }, + w: 0, + }, +} const Box: React.FC<{ id: string diff --git a/packages/playground/src/turtle/TurtleRenderer.tsx b/packages/playground/src/turtle/TurtleRenderer.tsx index 1314909..f52afbd 100644 --- a/packages/playground/src/turtle/TurtleRenderer.tsx +++ b/packages/playground/src/turtle/TurtleRenderer.tsx @@ -15,13 +15,13 @@ import {drawTurtlePlan, makeTurtlePlan} from './turtle' studio.initialize() -const objConfig = types.compound({ - startingPoint: types.compound({ +const objConfig = { + startingPoint: { x: types.number(0.5, {range: [0, 1]}), y: types.number(0.5, {range: [0, 1]}), - }), + }, scale: types.number(1, {range: [0.1, 1000]}), -}) +} const TurtleRenderer: React.FC<{ sheet: ISheet diff --git a/packages/r3f/src/components/editorStuff.ts b/packages/r3f/src/components/editorStuff.ts index 267c2fa..a039679 100644 --- a/packages/r3f/src/components/editorStuff.ts +++ b/packages/r3f/src/components/editorStuff.ts @@ -6,7 +6,7 @@ let sheet: ISheet | undefined = undefined let sheetObject: ISheetObject | undefined = undefined -const editorSheetObjectConfig = types.compound({ +const editorSheetObjectConfig = { viewport: types.compound( { showAxes: types.boolean(true, {label: 'Axes'}), @@ -47,7 +47,7 @@ const editorSheetObjectConfig = types.compound({ }, {label: 'Transform Controls'}, ), -}) +} export function getEditorSheet(): ISheet { if (!sheet) { diff --git a/packages/r3f/src/components/useSelected.tsx b/packages/r3f/src/components/useSelected.tsx index 12339b2..fa13a97 100644 --- a/packages/r3f/src/components/useSelected.tsx +++ b/packages/r3f/src/components/useSelected.tsx @@ -2,6 +2,7 @@ import {useLayoutEffect, useRef, useState} from 'react' import {allRegisteredObjects} from '../store' import studio from '@theatre/studio' import type {ISheetObject} from '@theatre/core' +import type {$IntentionalAny} from '../types' export function useSelected(): undefined | string { const [state, set] = useState(undefined) @@ -13,7 +14,7 @@ export function useSelected(): undefined | string { const item = selection.find( (s): s is ISheetObject => s.type === 'Theatre_SheetObject_PublicAPI' && - allRegisteredObjects.has(s), + allRegisteredObjects.has(s as $IntentionalAny), ) if (!item) { set(undefined) @@ -31,7 +32,8 @@ export function useSelected(): undefined | string { export function getSelected(): undefined | string { const item = studio.selection.find( (s): s is ISheetObject => - s.type === 'Theatre_SheetObject_PublicAPI' && allRegisteredObjects.has(s), + s.type === 'Theatre_SheetObject_PublicAPI' && + allRegisteredObjects.has(s as $IntentionalAny), ) if (!item) { return undefined diff --git a/packages/r3f/src/components/useSnapshotEditorCamera.tsx b/packages/r3f/src/components/useSnapshotEditorCamera.tsx index 0ecefab..8e81d50 100644 --- a/packages/r3f/src/components/useSnapshotEditorCamera.tsx +++ b/packages/r3f/src/components/useSnapshotEditorCamera.tsx @@ -11,20 +11,20 @@ import {types} from '@theatre/core' import type {ISheetObject} from '@theatre/core' import {useThree} from '@react-three/fiber' -const camConf = types.compound({ - transform: types.compound({ - position: types.compound({ +const camConf = { + transform: { + position: { x: types.number(10), y: types.number(10), z: types.number(0), - }), - target: types.compound({ + }, + target: { x: types.number(0), y: types.number(0), z: types.number(0), - }), - }), - lens: types.compound({ + }, + }, + lens: { zoom: types.number(1, {range: [0.0001, 10]}), fov: types.number(50, {range: [1, 1000]}), near: types.number(0.1, {range: [0, Infinity]}), @@ -32,8 +32,8 @@ const camConf = types.compound({ focus: types.number(10, {range: [0, Infinity]}), filmGauge: types.number(35, {range: [0, Infinity]}), filmOffset: types.number(0, {range: [0, Infinity]}), - }), -}) + }, +} export default function useSnapshotEditorCamera( snapshotEditorSheet: ISheet, @@ -144,7 +144,9 @@ function usePassValuesFromTheatreToCamera( if (!cam || orbitControls === null) return const obj = objRef.current! - const setFromTheatre = (props: typeof camConf['valueType']): void => { + const setFromTheatre = ( + props: ISheetObject['value'], + ): void => { const {position, target} = props.transform cam.zoom = props.lens.zoom cam.fov = props.lens.fov diff --git a/packages/r3f/src/store.ts b/packages/r3f/src/store.ts index 86c626e..0de458b 100644 --- a/packages/r3f/src/store.ts +++ b/packages/r3f/src/store.ts @@ -22,23 +22,23 @@ const positionComp = types.number(1, {nudgeMultiplier: 0.1}) const rotationComp = types.number(1, {nudgeMultiplier: 0.02}) const scaleComp = types.number(1, {nudgeMultiplier: 0.1}) -export const baseSheetObjectType = types.compound({ - position: types.compound({ +export const baseSheetObjectType = { + position: { x: positionComp, y: positionComp, z: positionComp, - }), - rotation: types.compound({ + }, + rotation: { x: rotationComp, y: rotationComp, z: rotationComp, - }), - scale: types.compound({ + }, + scale: { x: scaleComp, y: scaleComp, z: scaleComp, - }), -}) + }, +} export type BaseSheetObjectType = ISheetObject diff --git a/theatre/core/src/propTypes/index.ts b/theatre/core/src/propTypes/index.ts index 24ad99f..f7e31ab 100644 --- a/theatre/core/src/propTypes/index.ts +++ b/theatre/core/src/propTypes/index.ts @@ -12,13 +12,13 @@ import {propTypeSymbol} from './internals' * Usage: * ```ts * // the root prop type of an object is always a compound - * const props = t.compound({ + * const props = { * // compounds can be nested * position: t.compound({ * x: t.number(0), * y: t.number(0) * }) - * }) + * } * * const obj = sheet.obj('key', props) * console.log(obj.value) // {position: {x: 10.3, y: -1}} diff --git a/theatre/core/src/propTypes/internals.ts b/theatre/core/src/propTypes/internals.ts index 5f2fa22..125cc45 100644 --- a/theatre/core/src/propTypes/internals.ts +++ b/theatre/core/src/propTypes/internals.ts @@ -28,17 +28,18 @@ export type IShorthandCompoundProps = { [K in string]: IShorthandProp } -type ShorthandPropToLonghandProp

= P extends string - ? PropTypeConfig_String - : P extends number - ? PropTypeConfig_Number - : P extends boolean - ? PropTypeConfig_Boolean - : P extends PropTypeConfig - ? P - : P extends IShorthandCompoundProps - ? PropTypeConfig_Compound> - : never +export type ShorthandPropToLonghandProp

= + P extends string + ? PropTypeConfig_String + : P extends number + ? PropTypeConfig_Number + : P extends boolean + ? PropTypeConfig_Boolean + : P extends PropTypeConfig + ? P + : P extends IShorthandCompoundProps + ? PropTypeConfig_Compound> + : never export type ShorthandCompoundPropsToLonghandCompoundProps< P extends IShorthandCompoundProps, diff --git a/theatre/core/src/sheetObjects/TheatreSheetObject.ts b/theatre/core/src/sheetObjects/TheatreSheetObject.ts index 74623dc..6c0e777 100644 --- a/theatre/core/src/sheetObjects/TheatreSheetObject.ts +++ b/theatre/core/src/sheetObjects/TheatreSheetObject.ts @@ -6,37 +6,37 @@ import type {SheetObjectAddress} from '@theatre/shared/utils/addresses' import SimpleCache from '@theatre/shared/utils/SimpleCache' import type { $FixMe, - $IntentionalAny, DeepPartialOfSerializableValue, VoidFn, } from '@theatre/shared/utils/types' import type {IDerivation, Pointer} from '@theatre/dataverse' import {prism, val} from '@theatre/dataverse' -import type {PropTypeConfig_Compound} from '@theatre/core/propTypes' import type SheetObject from './SheetObject' +import type { + IShorthandCompoundProps, + ShorthandPropToLonghandProp, +} from '@theatre/core/propTypes/internals' -export interface ISheetObject< - Props extends PropTypeConfig_Compound<$IntentionalAny> = PropTypeConfig_Compound<$IntentionalAny>, -> { +export interface ISheetObject { readonly type: 'Theatre_SheetObject_PublicAPI' /** * */ - readonly value: Props['valueType'] - readonly props: Pointer + readonly value: ShorthandPropToLonghandProp['valueType'] + readonly props: Pointer readonly sheet: ISheet readonly project: IProject readonly address: SheetObjectAddress - onValuesChange(fn: (values: Props['valueType']) => void): VoidFn + onValuesChange(fn: (values: this['value']) => void): VoidFn // prettier-ignore - set initialValue(value: DeepPartialOfSerializableValue) + set initialValue(value: DeepPartialOfSerializableValue) } export default class TheatreSheetObject< - Props extends PropTypeConfig_Compound<$IntentionalAny>, + Props extends IShorthandCompoundProps = {}, > implements ISheetObject { get type(): 'Theatre_SheetObject_PublicAPI' { @@ -51,7 +51,7 @@ export default class TheatreSheetObject< setPrivateAPI(this, internals) } - get props(): Pointer { + get props(): Pointer { return privateAPI(this).propsP as $FixMe } @@ -67,7 +67,7 @@ export default class TheatreSheetObject< return {...privateAPI(this).address} } - private _valuesDerivation(): IDerivation { + private _valuesDerivation(): IDerivation { return this._cache.get('onValuesChangeDerivation', () => { const sheetObject = privateAPI(this) const d: IDerivation = prism(() => { @@ -77,15 +77,15 @@ export default class TheatreSheetObject< }) } - onValuesChange(fn: (values: Props['valueType']) => void): VoidFn { + onValuesChange(fn: (values: this['value']) => void): VoidFn { return this._valuesDerivation().tapImmediate(coreTicker, fn) } - get value(): Props['valueType'] { + get value(): ShorthandPropToLonghandProp['valueType'] { return this._valuesDerivation().getValue() } - set initialValue(val: DeepPartialOfSerializableValue) { + set initialValue(val: DeepPartialOfSerializableValue) { privateAPI(this).setInitialValue(val) } } diff --git a/theatre/core/src/sheets/TheatreSheet.ts b/theatre/core/src/sheets/TheatreSheet.ts index 554a77d..66ad3b1 100644 --- a/theatre/core/src/sheets/TheatreSheet.ts +++ b/theatre/core/src/sheets/TheatreSheet.ts @@ -3,6 +3,7 @@ import type {IProject} from '@theatre/core/projects/TheatreProject' import type TheatreSequence from '@theatre/core/sequences/TheatreSequence' import type {ISequence} from '@theatre/core/sequences/TheatreSequence' import type {PropTypeConfig_Compound} from '@theatre/core/propTypes' +import {compound} from '@theatre/core/propTypes' import type {ISheetObject} from '@theatre/core/sheetObjects/TheatreSheetObject' import type Sheet from '@theatre/core/sheets/Sheet' import type {SheetAddress} from '@theatre/shared/utils/addresses' @@ -11,6 +12,7 @@ import {validateAndSanitiseSlashedPathOrThrow} from '@theatre/shared/utils/slash import type {$IntentionalAny} from '@theatre/shared/utils/types' import userReadableTypeOfValue from '@theatre/shared/utils/userReadableTypeOfValue' import deepEqual from 'fast-deep-equal' +import type {IShorthandCompoundProps} from '@theatre/core/propTypes/internals' export type SheetObjectConfig< Props extends PropTypeConfig_Compound<$IntentionalAny>, @@ -21,14 +23,16 @@ export interface ISheet { readonly project: IProject readonly address: SheetAddress - object>( + object( key: string, - config: SheetObjectConfig, + config: Props, ): ISheetObject readonly sequence: ISequence } +const weakMapOfUnsanitizedProps = new WeakMap() + export default class TheatreSheet implements ISheet { get type(): 'Theatre_Sheet_PublicAPI' { return 'Theatre_Sheet_PublicAPI' @@ -40,9 +44,9 @@ export default class TheatreSheet implements ISheet { setPrivateAPI(this, sheet) } - object>( + object( key: string, - config: SheetObjectConfig, + config: Props, ): ISheetObject { const internal = privateAPI(this) const sanitizedPath = validateAndSanitiseSlashedPathOrThrow( @@ -67,7 +71,11 @@ export default class TheatreSheet implements ISheet { return existingObject.publicApi as $IntentionalAny } else { - const object = internal.createObject(sanitizedPath, nativeObject, config) + const object = internal.createObject( + sanitizedPath, + nativeObject, + compound(config), + ) return object.publicApi as $IntentionalAny } } diff --git a/theatre/shared/src/testUtils.ts b/theatre/shared/src/testUtils.ts index b67e0c1..3fa8817 100644 --- a/theatre/shared/src/testUtils.ts +++ b/theatre/shared/src/testUtils.ts @@ -31,16 +31,13 @@ export async function setupTestSheet(sheetState: SheetState_Historic) { ticker.tick() await project.ready const sheetPublicAPI = project.sheet('Sheet') - const objPublicAPI = sheetPublicAPI.object( - 'obj', - t.compound({ - position: { - x: 0, - y: t.number(1), - z: t.number(2), - }, - }), - ) + const objPublicAPI = sheetPublicAPI.object('obj', { + position: { + x: 0, + y: t.number(1), + z: t.number(2), + }, + }) const obj = privateAPI(objPublicAPI)