More API docs
This commit is contained in:
parent
a86e220bdc
commit
7815fb2dc3
7 changed files with 442 additions and 96 deletions
|
@ -38,6 +38,15 @@ export interface IProject {
|
|||
* The project's address
|
||||
*/
|
||||
readonly address: ProjectAddress
|
||||
|
||||
/**
|
||||
* Creates a Sheet under the project
|
||||
* @param sheetId Sheets are identified by their `sheetId`, which must be a string longer than 3 characters
|
||||
* @param instanceId Optionally provide an `instanceId` if you want to create multiple instances of the same Sheet
|
||||
* @returns The newly created Sheet
|
||||
*
|
||||
* **Docs: https://docs.theatrejs.com/in-depth/#sheets**
|
||||
*/
|
||||
sheet(sheetId: string, instanceId?: string): ISheet
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type {$IntentionalAny} from '@theatre/shared/utils/types'
|
||||
import userReadableTypeOfValue from '@theatre/shared/utils/userReadableTypeOfValue'
|
||||
import type {
|
||||
IShorthandCompoundProps,
|
||||
IValidCompoundProps,
|
||||
|
@ -7,48 +8,123 @@ import type {
|
|||
import {sanitizeCompoundProps} from './internals'
|
||||
import {propTypeSymbol} from './internals'
|
||||
|
||||
const validateCommonOpts = (
|
||||
fnCallSignature: string,
|
||||
opts?: PropTypeConfigOpts,
|
||||
) => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (opts === undefined) return
|
||||
if (typeof opts !== 'object' || opts === null) {
|
||||
throw new Error(
|
||||
`opts in ${fnCallSignature} must either be undefined or an object.`,
|
||||
)
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(opts, 'label')) {
|
||||
const {label} = opts
|
||||
if (typeof label !== 'string') {
|
||||
throw new Error(
|
||||
`opts.label in ${fnCallSignature} should be a string. ${userReadableTypeOfValue(
|
||||
label,
|
||||
)} given.`,
|
||||
)
|
||||
}
|
||||
if (label.trim().length !== label.length) {
|
||||
throw new Error(
|
||||
`opts.label in ${fnCallSignature} should not start/end with whitespace. "${label}" given.`,
|
||||
)
|
||||
}
|
||||
if (label.length === 0) {
|
||||
throw new Error(
|
||||
`opts.label in ${fnCallSignature} should not be an empty string. If you wish to have no label, remove opts.label from opts.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a compound prop type (basically a JS object).
|
||||
* A compound prop type (basically a JS object).
|
||||
*
|
||||
* Usage:
|
||||
* ```ts
|
||||
* // the root prop type of an object is always a compound
|
||||
* const props = {
|
||||
* // compounds can be nested
|
||||
* position: t.compound({
|
||||
* x: t.number(0),
|
||||
* y: t.number(0)
|
||||
* })
|
||||
* // shorthand
|
||||
* const position = {
|
||||
* x: 0,
|
||||
* y: 0
|
||||
* }
|
||||
* assert(sheet.object('some object', position).value.x === 0)
|
||||
*
|
||||
* const obj = sheet.obj('key', props)
|
||||
* console.log(obj.value) // {position: {x: 10.3, y: -1}}
|
||||
* // nesting
|
||||
* const foo = {bar: {baz: {quo: 0}}}
|
||||
* assert(sheet.object('some object', foo).bar.baz.quo === 0)
|
||||
*
|
||||
* // With additional options:
|
||||
* const position = t.compound(
|
||||
* {x: 0, y: 0},
|
||||
* // a custom label for the prop:
|
||||
* {label: "Position"}
|
||||
* )
|
||||
* ```
|
||||
* @param props
|
||||
* @param extras
|
||||
* @param opts
|
||||
* @returns
|
||||
*
|
||||
*/
|
||||
export const compound = <Props extends IShorthandCompoundProps>(
|
||||
props: Props,
|
||||
extras?: PropTypeConfigExtras,
|
||||
opts?: PropTypeConfigOpts,
|
||||
): PropTypeConfig_Compound<
|
||||
ShorthandCompoundPropsToLonghandCompoundProps<Props>
|
||||
> => {
|
||||
validateCommonOpts('t.compound(props, opts)', opts)
|
||||
return {
|
||||
type: 'compound',
|
||||
props: sanitizeCompoundProps(props),
|
||||
valueType: null as $IntentionalAny,
|
||||
[propTypeSymbol]: 'TheatrePropType',
|
||||
label: extras?.label,
|
||||
label: opts?.label,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A number prop type.
|
||||
*
|
||||
* @param defaultValue
|
||||
* @param opts
|
||||
* @returns
|
||||
* Usage
|
||||
* ```ts
|
||||
* // shorthand:
|
||||
* const obj = sheet.object('key', {x: 0})
|
||||
*
|
||||
* // With options (equal to above)
|
||||
* const obj = sheet.object('key', {
|
||||
* x: t.number(0)
|
||||
* })
|
||||
*
|
||||
* // With a range (note that opts.range is just a visual guide, not a validation rule)
|
||||
* const x = t.number(0, {range: [0, 10]}) // limited to 0 and 10
|
||||
*
|
||||
* // With custom nudging
|
||||
* const x = t.number(0, {nudgeMultiplier: 0.1}) // nudging will happen in 0.1 increments
|
||||
*
|
||||
* // With custom nudging function
|
||||
* const x = t.number({
|
||||
* nudgeFn: (
|
||||
* // the mouse movement (in pixels)
|
||||
* deltaX: number,
|
||||
* // the movement as a fraction of the width of the number editor's input
|
||||
* deltaFraction: number,
|
||||
* // A multiplier that's usually 1, but might be another number if user wants to nudge slower/faster
|
||||
* magnitude: number,
|
||||
* // the configuration of the number
|
||||
* config: {nudgeMultiplier?: number; range?: [number, number]},
|
||||
* ): number => {
|
||||
* return deltaX * magnitude
|
||||
* },
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param defaultValue The default value (Must be a finite number)
|
||||
* @param opts The options (See usage examples)
|
||||
* @returns A number prop config
|
||||
*/
|
||||
export const number = (
|
||||
defaultValue: number,
|
||||
|
@ -56,8 +132,60 @@ export const number = (
|
|||
nudgeFn?: PropTypeConfig_Number['nudgeFn']
|
||||
range?: PropTypeConfig_Number['range']
|
||||
nudgeMultiplier?: number
|
||||
} & PropTypeConfigExtras,
|
||||
} & PropTypeConfigOpts,
|
||||
): PropTypeConfig_Number => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
validateCommonOpts('t.number(defaultValue, opts)', opts)
|
||||
if (typeof defaultValue !== 'number' || !isFinite(defaultValue)) {
|
||||
throw new Error(
|
||||
`Argument defaultValue in t.number(defaultValue) must be a number. ${userReadableTypeOfValue(
|
||||
defaultValue,
|
||||
)} given.`,
|
||||
)
|
||||
}
|
||||
if (typeof opts === 'object' && opts) {
|
||||
if (Object.prototype.hasOwnProperty.call(opts, 'range')) {
|
||||
if (!Array.isArray(opts.range)) {
|
||||
throw new Error(
|
||||
`opts.range in t.number(defaultValue, opts) must be a tuple of two numbers. ${userReadableTypeOfValue(
|
||||
opts.range,
|
||||
)} given.`,
|
||||
)
|
||||
}
|
||||
if (opts.range.length !== 2) {
|
||||
throw new Error(
|
||||
`opts.range in t.number(defaultValue, opts) must have two elements. ${opts.range.length} given.`,
|
||||
)
|
||||
}
|
||||
if (!opts.range.every((n) => typeof n === 'number' && isFinite(n))) {
|
||||
throw new Error(
|
||||
`opts.range in t.number(defaultValue, opts) must be a tuple of two finite numbers.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(opts, 'nudgeMultiplier')) {
|
||||
if (
|
||||
typeof opts!.nudgeMultiplier !== 'number' ||
|
||||
!isFinite(opts!.nudgeMultiplier)
|
||||
) {
|
||||
throw new Error(
|
||||
`opts.nudgeMultiplier in t.number(defaultValue, opts) must be a finite number. ${userReadableTypeOfValue(
|
||||
opts!.nudgeMultiplier,
|
||||
)} given.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(opts, 'nudgeFn')) {
|
||||
if (typeof opts?.nudgeFn !== 'function') {
|
||||
throw new Error(
|
||||
`opts.nudgeFn in t.number(defaultValue, opts) must be a function. ${userReadableTypeOfValue(
|
||||
opts!.nudgeFn,
|
||||
)} given.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: 'number',
|
||||
valueType: 0,
|
||||
|
@ -72,57 +200,117 @@ export const number = (
|
|||
}
|
||||
|
||||
/**
|
||||
* A boolean prop type
|
||||
*
|
||||
* @param defaultValue
|
||||
* @param extras
|
||||
* @returns
|
||||
* Usage:
|
||||
* ```ts
|
||||
* // shorthand:
|
||||
* const obj = sheet.object('key', {isOn: true})
|
||||
*
|
||||
* // with a label:
|
||||
* const obj = sheet.object('key', {
|
||||
* isOn: t.boolean(true, {
|
||||
* label: 'Enabled'
|
||||
* })
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param defaultValue The default value (must be a boolean)
|
||||
* @param opts Options (See usage examples)
|
||||
*/
|
||||
export const boolean = (
|
||||
defaultValue: boolean,
|
||||
extras?: PropTypeConfigExtras,
|
||||
opts?: PropTypeConfigOpts,
|
||||
): PropTypeConfig_Boolean => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
validateCommonOpts('t.boolean(defaultValue, opts)', opts)
|
||||
if (typeof defaultValue !== 'boolean') {
|
||||
throw new Error(
|
||||
`defaultValue in t.boolean(defaultValue) must be a boolean. ${userReadableTypeOfValue(
|
||||
defaultValue,
|
||||
)} given.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: 'boolean',
|
||||
default: defaultValue,
|
||||
valueType: null as $IntentionalAny,
|
||||
[propTypeSymbol]: 'TheatrePropType',
|
||||
label: extras?.label,
|
||||
label: opts?.label,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A string prop type
|
||||
*
|
||||
* @param defaultValue
|
||||
* @param extras
|
||||
* @returns
|
||||
* Usage:
|
||||
* ```ts
|
||||
* // shorthand:
|
||||
* const obj = sheet.object('key', {message: "Animation loading"})
|
||||
*
|
||||
* // with a label:
|
||||
* const obj = sheet.object('key', {
|
||||
* message: t.string("Animation Loading", {
|
||||
* label: 'The Message'
|
||||
* })
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param defaultValue The default value (must be a string)
|
||||
* @param opts The options (See usage examples)
|
||||
* @returns A string prop type
|
||||
*/
|
||||
export const string = (
|
||||
defaultValue: string,
|
||||
extras?: PropTypeConfigExtras,
|
||||
opts?: PropTypeConfigOpts,
|
||||
): PropTypeConfig_String => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
validateCommonOpts('t.string(defaultValue, opts)', opts)
|
||||
if (typeof defaultValue !== 'string') {
|
||||
throw new Error(
|
||||
`defaultValue in t.string(defaultValue) must be a string. ${userReadableTypeOfValue(
|
||||
defaultValue,
|
||||
)} given.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: 'string',
|
||||
default: defaultValue,
|
||||
valueType: null as $IntentionalAny,
|
||||
[propTypeSymbol]: 'TheatrePropType',
|
||||
label: extras?.label,
|
||||
label: opts?.label,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A stringLiteral prop type, useful for building menus or radio buttons.
|
||||
*
|
||||
* @param defaultValue
|
||||
* @param options
|
||||
* @param extras
|
||||
* @returns
|
||||
* Usage:
|
||||
* ```ts
|
||||
* // Basic usage
|
||||
* const obj = sheet.object('key', {
|
||||
* light: t.stringLiteral("r", {r: "Red", "g": "Green"})
|
||||
* })
|
||||
*
|
||||
* // Shown as a radio switch with a custom label
|
||||
* const obj = sheet.object('key', {
|
||||
* light: t.stringLiteral("r", {r: "Red", "g": "Green"})
|
||||
* }, {as: "switch", label: "Street Light"})
|
||||
* ```
|
||||
*
|
||||
* @param defaultValue A string
|
||||
* @param options An object like `{[value]: Label}`. Example: {r: "Red", "g": "Green"}
|
||||
* @param opts Extra opts
|
||||
* @param opts.as Determines if editor is shown as a menu or a switch. Either 'menu' or 'switch'. Default: 'menu'
|
||||
* @returns A stringLiteral prop type
|
||||
*
|
||||
*/
|
||||
export function stringLiteral<Opts extends {[key in string]: string}>(
|
||||
defaultValue: Extract<keyof Opts, string>,
|
||||
options: Opts,
|
||||
extras?: {as?: 'menu' | 'switch'} & PropTypeConfigExtras,
|
||||
opts?: {as?: 'menu' | 'switch'} & PropTypeConfigOpts,
|
||||
): PropTypeConfig_StringLiteral<Extract<keyof Opts, string>> {
|
||||
return {
|
||||
type: 'stringLiteral',
|
||||
|
@ -130,24 +318,11 @@ export function stringLiteral<Opts extends {[key in string]: string}>(
|
|||
options: {...options},
|
||||
[propTypeSymbol]: 'TheatrePropType',
|
||||
valueType: null as $IntentionalAny,
|
||||
as: extras?.as ?? 'menu',
|
||||
label: extras?.label,
|
||||
as: opts?.as ?? 'menu',
|
||||
label: opts?.label,
|
||||
}
|
||||
}
|
||||
|
||||
// export const rgba = (
|
||||
// defaultValue: {r: number; b: number; g: number; a: number},
|
||||
// extras?: PropTypeConfigExtras,
|
||||
// ): PropTypeConfig_CSSRGBA => {
|
||||
// return {
|
||||
// type: 'cssrgba',
|
||||
// valueType: null as $IntentionalAny,
|
||||
// [s]: 'TheatrePropType',
|
||||
// label: extras?.label,
|
||||
// default: defaultValue,
|
||||
// }
|
||||
// }
|
||||
|
||||
interface IBasePropType<ValueType> {
|
||||
valueType: ValueType
|
||||
[propTypeSymbol]: 'TheatrePropType'
|
||||
|
@ -190,7 +365,7 @@ export interface PropTypeConfig_Boolean extends IBasePropType<boolean> {
|
|||
default: boolean
|
||||
}
|
||||
|
||||
export interface PropTypeConfigExtras {
|
||||
export interface PropTypeConfigOpts {
|
||||
label?: string
|
||||
}
|
||||
export interface PropTypeConfig_String extends IBasePropType<string> {
|
||||
|
@ -206,12 +381,6 @@ export interface PropTypeConfig_StringLiteral<T extends string>
|
|||
as: 'menu' | 'switch'
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Determine if 'compound' is a clear term for what this is.
|
||||
* I didn't want to use 'object' as it could get confused with
|
||||
* SheetObject.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -221,12 +390,6 @@ export interface PropTypeConfig_Compound<Props extends IValidCompoundProps>
|
|||
props: Record<string, PropTypeConfig>
|
||||
}
|
||||
|
||||
// export interface PropTypeConfig_CSSRGBA
|
||||
// extends IBasePropType<{r: number; g: number; b: number; a: number}> {
|
||||
// type: 'cssrgba'
|
||||
// default: {r: number; g: number; b: number; a: number}
|
||||
// }
|
||||
|
||||
export interface PropTypeConfig_Enum extends IBasePropType<{}> {
|
||||
type: 'enum'
|
||||
cases: Record<string, PropTypeConfig>
|
||||
|
@ -238,7 +401,6 @@ export type PropTypeConfig_AllPrimitives =
|
|||
| PropTypeConfig_Boolean
|
||||
| PropTypeConfig_String
|
||||
| PropTypeConfig_StringLiteral<$IntentionalAny>
|
||||
// | PropTypeConfig_CSSRGBA
|
||||
|
||||
export type PropTypeConfig =
|
||||
| PropTypeConfig_AllPrimitives
|
||||
|
|
|
@ -28,6 +28,32 @@ export interface ISequence {
|
|||
* Starts playback of a sequence.
|
||||
* Returns a promise that either resolves to true when the playback completes,
|
||||
* or resolves to false if playback gets interrupted (for example by calling sequence.pause())
|
||||
*
|
||||
* @returns A promise that resolves when the playback is finished, or rejects if interruped
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // plays the sequence from the current position to sequence.length
|
||||
* sheet.sequence.play()
|
||||
*
|
||||
* // plays the sequence at 2.4x speed
|
||||
* sheet.sequence.play({rate: 2.4})
|
||||
*
|
||||
* // plays the sequence from second 1 to 4
|
||||
* sheet.sequence.play({range: [1, 4]})
|
||||
*
|
||||
* // plays the sequence 4 times
|
||||
* sheet.sequence.play({iterationCount: 4})
|
||||
*
|
||||
* // plays the sequence in reverse
|
||||
* sheet.sequence.play({direction: 'reverse'})
|
||||
*
|
||||
* // plays the sequence back and forth forever (until interrupted)
|
||||
* sheet.sequence.play({iterationCount: Infinity, direction: 'alternateReverse})
|
||||
*
|
||||
* // plays the sequence and logs "done" once playback is finished
|
||||
* sheet.sequence.play().then(() => console.log('done'))
|
||||
* ```
|
||||
*/
|
||||
play(conf?: {
|
||||
/**
|
||||
|
@ -57,13 +83,29 @@ export interface ISequence {
|
|||
|
||||
/**
|
||||
* The current position of the playhead.
|
||||
* In a time-based sequence, this represents the current time.
|
||||
* In a time-based sequence, this represents the current time in seconds.
|
||||
*/
|
||||
position: number
|
||||
|
||||
/**
|
||||
* Attaches an audio source to the sequence. Playing the sequence automatically
|
||||
* plays the audio source and their times are kept in sync.
|
||||
*
|
||||
* @param args
|
||||
* @returns A promise that resolves once the audio source is loaded and decoded
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Loads and decodes audio from the URL and then attaches it to the sequence
|
||||
* await sheet.sequence.attachAudio({source: "https://localhost/audio.ogg"})
|
||||
* sheet.sequence.play()
|
||||
*
|
||||
* // Providing your own AudioAPI Context, destination, etc
|
||||
* const audioContext: AudioContext = {...} // create an AudioContext using the Audio API
|
||||
* const audioBuffer: AudioBuffer = {...} // create an AudioBuffer
|
||||
* const destinationNode = audioContext.destination
|
||||
*
|
||||
* await sheet.sequence.attachAudio({source: audioBuffer, audioContext, destinationNode})
|
||||
* ```
|
||||
*/
|
||||
attachAudio(args: IAttachAudioArgs): Promise<void>
|
||||
}
|
||||
|
|
|
@ -18,20 +18,82 @@ import type {
|
|||
} from '@theatre/core/propTypes/internals'
|
||||
|
||||
export interface ISheetObject<Props extends IShorthandCompoundProps = {}> {
|
||||
/**
|
||||
* All Objects will have `object.type === 'Theatre_SheetObject_PublicAPI'`
|
||||
*/
|
||||
readonly type: 'Theatre_SheetObject_PublicAPI'
|
||||
|
||||
/**
|
||||
* The current values of the props.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const obj = sheet.object("obj", {x: 0})
|
||||
* console.log(obj.value.x) // prints 0 or the current numeric value
|
||||
* ```
|
||||
*/
|
||||
readonly value: ShorthandPropToLonghandProp<Props>['valueType']
|
||||
|
||||
/**
|
||||
* A Pointer to the props of the object.
|
||||
*
|
||||
* More documentation soon.
|
||||
*/
|
||||
readonly props: Pointer<this['value']>
|
||||
|
||||
/**
|
||||
* The instance of Sheet the Object belongs to
|
||||
*/
|
||||
readonly sheet: ISheet
|
||||
|
||||
/**
|
||||
* The Project the project belongs to
|
||||
*/
|
||||
readonly project: IProject
|
||||
|
||||
/**
|
||||
* An object representing the address of the Object
|
||||
*/
|
||||
readonly address: SheetObjectAddress
|
||||
|
||||
/**
|
||||
* Calls `fn` every time the value of the props change.
|
||||
*
|
||||
* @returns an Unsubscribe function
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const obj = sheet.object("Box", {position: {x: 0, y: 0}})
|
||||
* const div = document.getElementById("box")
|
||||
*
|
||||
* const unsubscribe = obj.onValuesChange((newValues) => {
|
||||
* div.style.left = newValues.position.x + 'px'
|
||||
* div.style.top = newValues.position.y + 'px'
|
||||
* })
|
||||
*
|
||||
* // you can call unsubscribe() to stop listening to changes
|
||||
* ```
|
||||
*/
|
||||
onValuesChange(fn: (values: this['value']) => void): VoidFn
|
||||
// prettier-ignore
|
||||
|
||||
/**
|
||||
* Sets the initial value of the object. This value overrides the default
|
||||
* values defined in the prop types, but would itself be overridden if the user
|
||||
* overrides it in the UI with a static or animated value.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const obj = sheet.object("obj", {position: {x: 0, y: 0}})
|
||||
*
|
||||
* obj.value // {position: {x: 0, y: 0}}
|
||||
*
|
||||
* // here, we only override position.x
|
||||
* obj.initialValue = {position: {x: 2}}
|
||||
*
|
||||
* obj.value // {position: {x: 2, y: 0}}
|
||||
* ```
|
||||
*/
|
||||
set initialValue(value: DeepPartialOfSerializableValue<this['value']>)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,15 +20,55 @@ export type SheetObjectConfig<
|
|||
> = Props
|
||||
|
||||
export interface ISheet {
|
||||
/**
|
||||
* All sheets have `sheet.type === 'Theatre_Sheet_PublicAPI'`
|
||||
*/
|
||||
readonly type: 'Theatre_Sheet_PublicAPI'
|
||||
|
||||
/**
|
||||
* The Project this Sheet belongs to
|
||||
*/
|
||||
readonly project: IProject
|
||||
|
||||
/**
|
||||
* The address of the Sheet
|
||||
*/
|
||||
readonly address: SheetAddress
|
||||
|
||||
/**
|
||||
* Creates a child object for the sheet
|
||||
*
|
||||
* **Docs: https://docs.theatrejs.com/in-depth/#objects**
|
||||
*
|
||||
* @param key Each object is identified by a key, which is a non-empty string
|
||||
* @param props The props of the object. See examples
|
||||
*
|
||||
* @returns An Object
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Create an object named "a unique key" with no props
|
||||
* const obj = sheet.object("a unique key", {})
|
||||
* obj.address.objectKey // "a unique key"
|
||||
*
|
||||
*
|
||||
* // Create an object with {x: 0}
|
||||
* const obj = sheet.object("obj", {x: 0})
|
||||
* obj.value.x // returns 0 or the current number that the user has set
|
||||
*
|
||||
* // Create an object with nested props
|
||||
* const obj = sheet.object("obj", {position: {x: 0, y: 0}})
|
||||
* obj.value.position // {x: 0, y: 0}
|
||||
* ```
|
||||
*/
|
||||
object<Props extends IShorthandCompoundProps>(
|
||||
key: string,
|
||||
config: Props,
|
||||
props: Props,
|
||||
): ISheetObject<Props>
|
||||
|
||||
/**
|
||||
* The Sequence of this Sheet
|
||||
*/
|
||||
readonly sequence: ISequence
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,32 @@ import type {
|
|||
SerializableMap,
|
||||
SerializableValue,
|
||||
} from '@theatre/shared/utils/types'
|
||||
|
||||
/**
|
||||
* Represents the address to a project
|
||||
*/
|
||||
export interface ProjectAddress {
|
||||
projectId: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the address to a specific instance of a Sheet
|
||||
*
|
||||
* ```ts
|
||||
* const sheet = project.sheet('a sheet', 'some instance id')
|
||||
* sheet.address.sheetId === 'a sheet'
|
||||
* sheet.address.sheetInstanceId === 'sheetInstanceId'
|
||||
* ```
|
||||
*/
|
||||
export interface SheetAddress extends ProjectAddress {
|
||||
sheetId: string
|
||||
sheetInstanceId: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes `sheetInstanceId` from an address, making it refer to
|
||||
* all instances of a certain `sheetId`
|
||||
*/
|
||||
export type WithoutSheetInstance<T extends SheetAddress> = Omit<
|
||||
T,
|
||||
'sheetInstanceId'
|
||||
|
@ -20,7 +37,18 @@ export type WithoutSheetInstance<T extends SheetAddress> = Omit<
|
|||
export type SheetInstanceOptional<T extends SheetAddress> =
|
||||
WithoutSheetInstance<T> & {sheetInstanceId?: string | undefined}
|
||||
|
||||
/**
|
||||
* Represents the address to a Sheet's Object
|
||||
*/
|
||||
export interface SheetObjectAddress extends SheetAddress {
|
||||
/**
|
||||
* The key of the object.
|
||||
*
|
||||
* ```ts
|
||||
* const obj = sheet.object('foo', {})
|
||||
* obj.address.objectKey === 'foo'
|
||||
* ```
|
||||
*/
|
||||
objectKey: string
|
||||
}
|
||||
|
||||
|
@ -34,6 +62,9 @@ export const encodePathToProp = (p: PathToProp): PathToProp_Encoded =>
|
|||
export const decodePathToProp = (s: PathToProp_Encoded): PathToProp =>
|
||||
JSON.parse(s)
|
||||
|
||||
/**
|
||||
* Represents the path to a certain prop of an object
|
||||
*/
|
||||
export interface PropAddress extends SheetObjectAddress {
|
||||
pathToProp: PathToProp
|
||||
}
|
||||
|
|
|
@ -110,38 +110,38 @@ const Connector: React.FC<IProps> = (props) => {
|
|||
const modifiedS = orig // window.prompt('As cubic-bezier()', orig)
|
||||
if (modifiedS && modifiedS !== orig) {
|
||||
return
|
||||
const modified = JSON.parse(modifiedS)
|
||||
getStudio()!.transaction(({stateEditors}) => {
|
||||
const {replaceKeyframes} =
|
||||
stateEditors.coreByProject.historic.sheetsById.sequence
|
||||
// const modified = JSON.parse(modifiedS)
|
||||
// getStudio()!.transaction(({stateEditors}) => {
|
||||
// const {replaceKeyframes} =
|
||||
// stateEditors.coreByProject.historic.sheetsById.sequence
|
||||
|
||||
replaceKeyframes({
|
||||
...props.leaf.sheetObject.address,
|
||||
snappingFunction: val(props.layoutP.sheet).getSequence()
|
||||
.closestGridPosition,
|
||||
trackId: props.leaf.trackId,
|
||||
keyframes: [
|
||||
{
|
||||
...cur,
|
||||
handles: [
|
||||
cur.handles[0],
|
||||
cur.handles[1],
|
||||
modified[0],
|
||||
modified[1],
|
||||
],
|
||||
},
|
||||
{
|
||||
...next,
|
||||
handles: [
|
||||
modified[2],
|
||||
modified[3],
|
||||
next.handles[2],
|
||||
next.handles[3],
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
// replaceKeyframes({
|
||||
// ...props.leaf.sheetObject.address,
|
||||
// snappingFunction: val(props.layoutP.sheet).getSequence()
|
||||
// .closestGridPosition,
|
||||
// trackId: props.leaf.trackId,
|
||||
// keyframes: [
|
||||
// {
|
||||
// ...cur,
|
||||
// handles: [
|
||||
// cur.handles[0],
|
||||
// cur.handles[1],
|
||||
// modified[0],
|
||||
// modified[1],
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// ...next,
|
||||
// handles: [
|
||||
// modified[2],
|
||||
// modified[3],
|
||||
// next.handles[2],
|
||||
// next.handles[3],
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// })
|
||||
// })
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
|
|
Loading…
Reference in a new issue