WIP - Implement dynamic prop types
TODO: Tests
This commit is contained in:
parent
e708463377
commit
d260f74c06
9 changed files with 50 additions and 29 deletions
|
@ -166,6 +166,7 @@ export default class SheetObject implements IdentityDerivationProvider {
|
|||
|
||||
const tracksToProcess = val(tracksToProcessD)
|
||||
const valsAtom = new Atom<SheetObjectPropsValue>({})
|
||||
const config = val(this.template.configPointer)
|
||||
|
||||
prism.effect(
|
||||
'processTracks',
|
||||
|
@ -175,7 +176,7 @@ export default class SheetObject implements IdentityDerivationProvider {
|
|||
for (const {trackId, pathToProp} of tracksToProcess) {
|
||||
const derivation = this._trackIdToDerivation(trackId)
|
||||
const propConfig = getPropConfigByPath(
|
||||
this.template.config,
|
||||
config,
|
||||
pathToProp,
|
||||
)! as Extract<PropTypeConfig, {interpolate: $IntentionalAny}>
|
||||
|
||||
|
@ -222,7 +223,7 @@ export default class SheetObject implements IdentityDerivationProvider {
|
|||
}
|
||||
}
|
||||
},
|
||||
tracksToProcess,
|
||||
[config, ...tracksToProcess],
|
||||
)
|
||||
|
||||
return valsAtom.pointer
|
||||
|
|
|
@ -61,10 +61,14 @@ export default class SheetObjectTemplate {
|
|||
readonly _cache = new SimpleCache()
|
||||
readonly project: Project
|
||||
|
||||
get config() {
|
||||
get staticConfig() {
|
||||
return this._config.getState()
|
||||
}
|
||||
|
||||
get configPointer() {
|
||||
return this._config.pointer
|
||||
}
|
||||
|
||||
constructor(
|
||||
readonly sheetTemplate: SheetTemplate,
|
||||
objectKey: ObjectAddressKey,
|
||||
|
@ -95,7 +99,7 @@ export default class SheetObjectTemplate {
|
|||
getDefaultValues(): IDerivation<SerializableMap> {
|
||||
return this._cache.get('getDefaultValues()', () =>
|
||||
prism(() => {
|
||||
const config = val(this._config.pointer)
|
||||
const config = val(this.configPointer)
|
||||
return getPropDefaultsOfSheetObject(config)
|
||||
}),
|
||||
)
|
||||
|
@ -119,7 +123,7 @@ export default class SheetObjectTemplate {
|
|||
],
|
||||
) ?? {}
|
||||
|
||||
const config = val(this._config.pointer)
|
||||
const config = val(this.configPointer)
|
||||
const deserialized = config.deserializeAndSanitize(json) || {}
|
||||
return deserialized
|
||||
}),
|
||||
|
@ -154,12 +158,14 @@ export default class SheetObjectTemplate {
|
|||
|
||||
if (!trackIdByPropPath) return emptyArray as $IntentionalAny
|
||||
|
||||
const objectConfig = val(this.configPointer)
|
||||
|
||||
const _entries = Object.entries(trackIdByPropPath)
|
||||
for (const [pathToPropInString, trackId] of _entries) {
|
||||
const pathToProp = parsePathToProp(pathToPropInString)
|
||||
if (!pathToProp) continue
|
||||
|
||||
const propConfig = getPropConfigByPath(this.config, pathToProp)
|
||||
const propConfig = getPropConfigByPath(objectConfig, pathToProp)
|
||||
|
||||
const isSequencable = propConfig && isPropConfSequencable(propConfig)
|
||||
|
||||
|
@ -168,7 +174,7 @@ export default class SheetObjectTemplate {
|
|||
arrayOfIds.push({pathToProp, trackId: trackId!})
|
||||
}
|
||||
|
||||
const mapping = getOrderingOfPropTypeConfig(this.config)
|
||||
const mapping = getOrderingOfPropTypeConfig(objectConfig)
|
||||
|
||||
arrayOfIds.sort((a, b) => {
|
||||
const pathToPropA = a.pathToProp
|
||||
|
|
|
@ -45,6 +45,7 @@ export interface ISheet {
|
|||
*
|
||||
* @param key - Each object is identified by a key, which is a non-empty string
|
||||
* @param props - The props of the object. See examples
|
||||
* @param options - TODO
|
||||
*
|
||||
* @returns An Object
|
||||
*
|
||||
|
@ -68,6 +69,7 @@ export interface ISheet {
|
|||
object<Props extends UnknownShorthandCompoundProps>(
|
||||
key: string,
|
||||
props: Props,
|
||||
options?: {override?: boolean},
|
||||
): ISheetObject<Props>
|
||||
|
||||
/**
|
||||
|
@ -95,6 +97,7 @@ export default class TheatreSheet implements ISheet {
|
|||
object<Props extends UnknownShorthandCompoundProps>(
|
||||
key: string,
|
||||
config: Props,
|
||||
opts?: {override?: boolean},
|
||||
): ISheetObject<Props> {
|
||||
const internal = privateAPI(this)
|
||||
const sanitizedPath = validateAndSanitiseSlashedPathOrThrow(
|
||||
|
@ -118,11 +121,19 @@ export default class TheatreSheet implements ISheet {
|
|||
const prevConfig = weakMapOfUnsanitizedProps.get(existingObject)
|
||||
if (prevConfig) {
|
||||
if (!deepEqual(config, prevConfig)) {
|
||||
throw new Error(
|
||||
`You seem to have called sheet.object("${key}", config) twice, with different values for \`config\`. ` +
|
||||
`This is disallowed because changing the config of an object on the fly would make it difficult to reason about.\n\n` +
|
||||
`You can fix this by either re-using the existing object, or calling sheet.object("${key}", config) with the same config.`,
|
||||
)
|
||||
if (opts?.override === true) {
|
||||
const sanitizedConfig = compound(config)
|
||||
existingObject.template.overrideConfig(sanitizedConfig)
|
||||
weakMapOfUnsanitizedProps.set(existingObject, config)
|
||||
return existingObject.publicApi as $IntentionalAny
|
||||
} else {
|
||||
throw new Error(
|
||||
`You seem to have called sheet.object("${key}", config) twice, with different values for \`config\`. ` +
|
||||
`This is disallowed because changing the config of an object on the fly would make it difficult to reason about.\n\n` +
|
||||
`You can fix this by either re-using the existing object, or calling sheet.object("${key}", config) with the same config.\n\n` +
|
||||
`If you mean to override the object's config, set \`{override: true}\` in sheet.object("${key}", config, {override: true})`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ export default function createTransactionPrivateApi(
|
|||
.getMapOfValidSequenceTracks_forStudio()
|
||||
.getValue()
|
||||
|
||||
const propConfig = getPropConfigByPath(root.template.config, path)
|
||||
const propConfig = getPropConfigByPath(root.template.staticConfig, path)
|
||||
|
||||
if (!propConfig) {
|
||||
throw new Error(
|
||||
|
@ -205,7 +205,7 @@ export default function createTransactionPrivateApi(
|
|||
)
|
||||
|
||||
const propConfig = getPropConfigByPath(
|
||||
root.template.config,
|
||||
root.template.staticConfig,
|
||||
path,
|
||||
) as PropTypeConfig
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import type {
|
|||
PropTypeConfig_AllSimples,
|
||||
} from '@theatre/core/propTypes'
|
||||
import type SheetObject from '@theatre/core/sheetObjects/SheetObject'
|
||||
import {getPropTypeByPointer} from '@theatre/studio/propEditors/utils/getPropTypeByPointer'
|
||||
import {simplePropEditorByPropType} from '@theatre/studio/propEditors/simpleEditors/simplePropEditorByPropType'
|
||||
import type {PropConfigForType} from '@theatre/studio/propEditors/utils/PropConfigForType'
|
||||
import type {ISimplePropEditorReactProps} from '@theatre/studio/propEditors/simpleEditors/ISimplePropEditorReactProps'
|
||||
|
@ -24,16 +23,13 @@ import DetailSimplePropEditor from './DeterminePropEditorForDetail/DetailSimpleP
|
|||
*/
|
||||
const DeterminePropEditorForDetail: React.VFC<
|
||||
IDeterminePropEditorForDetailProps<PropTypeConfig['type']>
|
||||
> = (p) => {
|
||||
const propConfig =
|
||||
p.propConfig ?? getPropTypeByPointer(p.pointerToProp, p.obj)
|
||||
|
||||
> = ({propConfig, visualIndentation, pointerToProp, obj}) => {
|
||||
if (propConfig.type === 'compound') {
|
||||
return (
|
||||
<DetailCompoundPropEditor
|
||||
obj={p.obj}
|
||||
visualIndentation={p.visualIndentation}
|
||||
pointerToProp={p.pointerToProp}
|
||||
obj={obj}
|
||||
visualIndentation={visualIndentation}
|
||||
pointerToProp={pointerToProp}
|
||||
propConfig={propConfig}
|
||||
/>
|
||||
)
|
||||
|
@ -50,9 +46,9 @@ const DeterminePropEditorForDetail: React.VFC<
|
|||
ISimplePropEditorReactProps<PropTypeConfig_AllSimples>
|
||||
>
|
||||
}
|
||||
obj={p.obj}
|
||||
visualIndentation={p.visualIndentation}
|
||||
pointerToProp={p.pointerToProp}
|
||||
obj={obj}
|
||||
visualIndentation={visualIndentation}
|
||||
pointerToProp={pointerToProp}
|
||||
propConfig={propConfig}
|
||||
/>
|
||||
)
|
||||
|
@ -60,6 +56,7 @@ const DeterminePropEditorForDetail: React.VFC<
|
|||
}
|
||||
|
||||
export default DeterminePropEditorForDetail
|
||||
|
||||
type IDeterminePropEditorForDetailProps<K extends PropTypeConfig['type']> =
|
||||
IDetailEditablePropertyProps<K> & {
|
||||
visualIndentation: number
|
||||
|
|
|
@ -3,6 +3,7 @@ import type SheetObject from '@theatre/core/sheetObjects/SheetObject'
|
|||
import type {Pointer} from '@theatre/dataverse'
|
||||
import type {$FixMe} from '@theatre/shared/utils/types'
|
||||
import DeterminePropEditorForDetail from './DeterminePropEditorForDetail'
|
||||
import {useVal} from '@theatre/react'
|
||||
|
||||
const ObjectDetails: React.FC<{
|
||||
/** TODO: add support for multiple objects (it would show their common props) */
|
||||
|
@ -10,13 +11,14 @@ const ObjectDetails: React.FC<{
|
|||
}> = ({objects}) => {
|
||||
const obj = objects[0]
|
||||
const key = useMemo(() => JSON.stringify(obj.address), [obj])
|
||||
const config = useVal(obj.template.configPointer)
|
||||
|
||||
return (
|
||||
<DeterminePropEditorForDetail
|
||||
key={key}
|
||||
obj={obj}
|
||||
pointerToProp={obj.propsP as Pointer<$FixMe>}
|
||||
propConfig={obj.template.config}
|
||||
propConfig={config}
|
||||
visualIndentation={1}
|
||||
/>
|
||||
)
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
valueInProp,
|
||||
} from '@theatre/shared/propTypes/utils'
|
||||
import type {PropTypeConfig_AllSimples} from '@theatre/core/propTypes'
|
||||
import {useVal} from '@theatre/react'
|
||||
|
||||
export type ExtremumSpace = {
|
||||
fromValueSpace: (v: number) => number
|
||||
|
@ -36,7 +37,7 @@ const BasicKeyframedTrack: React.VFC<{
|
|||
}> = React.memo(
|
||||
({layoutP, trackData, sheetObject, trackId, color, pathToProp}) => {
|
||||
const propConfig = getPropConfigByPath(
|
||||
sheetObject.template.config,
|
||||
useVal(sheetObject.template.configPointer),
|
||||
pathToProp,
|
||||
)! as PropTypeConfig_AllSimples
|
||||
|
||||
|
|
|
@ -157,6 +157,7 @@ export const calculateSequenceEditorTree = (
|
|||
const trackSetups = val(
|
||||
sheetObject.template.getMapOfValidSequenceTracks_forStudio(),
|
||||
)
|
||||
const objectConfig = val(sheetObject.template.configPointer)
|
||||
|
||||
if (Object.keys(trackSetups).length === 0) return
|
||||
|
||||
|
@ -192,7 +193,7 @@ export const calculateSequenceEditorTree = (
|
|||
sheetObject,
|
||||
trackSetups,
|
||||
[],
|
||||
sheetObject.template.config,
|
||||
objectConfig,
|
||||
row.children,
|
||||
level + 1,
|
||||
shouldRender && !isCollapsed,
|
||||
|
|
|
@ -3,6 +3,8 @@ import type SheetObject from '@theatre/core/sheetObjects/SheetObject'
|
|||
import {getPointerParts} from '@theatre/dataverse'
|
||||
|
||||
/**
|
||||
* @deprecated because it uses obj.template.staticConfig
|
||||
*
|
||||
* Returns the PropTypeConfig by path. Assumes `path` is a valid prop path and that
|
||||
* it exists in obj.
|
||||
*
|
||||
|
@ -20,7 +22,7 @@ export function getPropTypeByPointer(
|
|||
pointerToProp: SheetObject['propsP'],
|
||||
obj: SheetObject,
|
||||
): PropTypeConfig {
|
||||
const rootConf = obj.template.config
|
||||
const rootConf = obj.template.staticConfig
|
||||
|
||||
const p = getPointerParts(pointerToProp).path
|
||||
let conf = rootConf as PropTypeConfig
|
||||
|
|
Loading…
Reference in a new issue