1- import { computed , DestroyRef , Directive , effect , ElementRef , inject , input , signal } from '@angular/core' ;
1+ import { computed , DestroyRef , Directive , effect , ElementRef , inject , input } from '@angular/core' ;
22import { NgtAnyRecord , resolveInstanceKey , resolveRef } from 'angular-three' ;
33import { THEATRE_STUDIO } from '../studio/studio-token' ;
44import { getDefaultTransformer } from '../transformers/default-transformer' ;
@@ -7,7 +7,7 @@ import { TheatreSheetObject } from './sheet-object';
77
88const updateProjectionMatrixKeys = [ 'fov' , 'near' , 'far' , 'zoom' , 'left' , 'right' , 'top' , 'bottom' , 'aspect' ] ;
99
10- @Directive ( { selector : '[sync]' } )
10+ @Directive ( { selector : '[sync]' , exportAs : 'sync' } )
1111export class TheatreSheetObjectSync < TObject extends object > {
1212 parent = input . required < TObject | ElementRef < TObject > | ( ( ) => TObject | ElementRef < TObject > | undefined | null ) > ( {
1313 alias : 'sync' ,
@@ -16,7 +16,8 @@ export class TheatreSheetObjectSync<TObject extends object> {
1616 Array < string | [ string , string | { label ?: string ; key ?: string ; transformer ?: TheatreTransformer } ] >
1717 > ( [ ] , { alias : 'syncProps' } ) ;
1818
19- private sheetObject = inject ( TheatreSheetObject ) ;
19+ private theatreSheetObject = inject ( TheatreSheetObject ) ;
20+ sheetObject = computed ( ( ) => this . theatreSheetObject . sheetObject ( ) ) ;
2021 private studio = inject ( THEATRE_STUDIO , { optional : true } ) ;
2122
2223 private parentRef = computed ( ( ) => {
@@ -46,48 +47,52 @@ export class TheatreSheetObjectSync<TObject extends object> {
4647 ) ;
4748 } ) ;
4849
49- private init = signal ( false ) ;
50- private propsMapping : Record < string , { path : string ; transformer : TheatreTransformer } > = { } ;
50+ private propsToAdd = computed ( ( ) => {
51+ const parent = this . parentRef ( ) ;
52+ if ( ! parent ) return null ;
5153
52- constructor ( ) {
53- effect ( ( ) => {
54- const parent = this . parentRef ( ) ;
55- if ( ! parent ) return ;
54+ const propsToAdd : NgtAnyRecord = { } ;
55+ const resolvedProps = this . resolvedProps ( ) ;
56+ resolvedProps . forEach ( ( [ propName , { key, label, transformer } ] ) => {
57+ const { root, targetKey } = resolveInstanceKey ( parent , propName ) ;
58+ const rawValue = root [ targetKey ] ;
59+ const valueTransformer = transformer ?? getDefaultTransformer ( root , targetKey , propName ) ;
60+ const value = valueTransformer . transform ( rawValue ) ;
61+
62+ value . label = label ?? key ;
5663
57- const propsToAdd : NgtAnyRecord = { } ;
58- const resolvedProps = this . resolvedProps ( ) ;
59- resolvedProps . forEach ( ( [ propName , { key, label, transformer } ] ) => {
60- const { root, targetKey, targetProp } = resolveInstanceKey ( parent , propName ) ;
61- const rawValue = root [ targetKey ] ;
62- const valueTransformer = transformer ?? getDefaultTransformer ( root , targetKey , propName ) ;
63- const value = valueTransformer . transform ( rawValue ) ;
64+ this . propsMapping [ key ] = { path : propName , transformer : valueTransformer } ;
65+ propsToAdd [ key ] = value ;
66+ } ) ;
6467
65- value . label = label ?? key ;
68+ return propsToAdd ;
69+ } ) ;
6670
67- this . propsMapping [ key ] = { path : propName , transformer : valueTransformer } ;
68- propsToAdd [ key ] = value ;
69- } ) ;
71+ private propsMapping : Record < string , { path : string ; transformer : TheatreTransformer } > = { } ;
7072
71- this . sheetObject . addProps ( propsToAdd ) ;
72- this . init . set ( true ) ;
73+ constructor ( ) {
74+ effect ( ( ) => {
75+ const propsToAdd = this . propsToAdd ( ) ;
76+ if ( ! propsToAdd ) return ;
77+ this . theatreSheetObject . addProps ( propsToAdd ) ;
7378 } ) ;
7479
7580 effect ( ( onCleanup ) => {
7681 const parent = this . parentRef ( ) ;
7782 if ( ! parent ) return ;
7883
79- const init = this . init ( ) ;
80- if ( ! init ) return ;
84+ const propsToAdd = this . propsToAdd ( ) ;
85+ if ( ! propsToAdd ) return ;
8186
82- const sheetObject = this . sheetObject . sheetObject ( ) ;
87+ const sheetObject = this . sheetObject ( ) ;
8388 const cleanup = sheetObject . onValuesChange ( ( newValues ) => {
8489 Object . keys ( newValues ) . forEach ( ( key ) => {
8590 // first, check if the prop is mapped in this component
8691 const propMapping = this . propsMapping [ key ] ;
8792 if ( ! propMapping ) return ;
8893
8994 // we're using the addedProps map to infer the target property name from the property name on values
90- const { root, targetProp , targetKey } = resolveInstanceKey ( parent , propMapping . path ) ;
95+ const { root, targetKey } = resolveInstanceKey ( parent , propMapping . path ) ;
9196
9297 // use a transformer to apply value
9398 const transformer = propMapping . transformer ;
@@ -103,10 +108,39 @@ export class TheatreSheetObjectSync<TObject extends object> {
103108 } ) ;
104109
105110 inject ( DestroyRef ) . onDestroy ( ( ) => {
106- this . sheetObject . removeProps ( Object . keys ( this . propsMapping ) ) ;
111+ this . theatreSheetObject . removeProps ( Object . keys ( this . propsMapping ) ) ;
107112 } ) ;
108113 }
109114
115+ capture ( ) {
116+ const studio = this . studio ?.( ) ;
117+ if ( ! studio ) return ;
118+
119+ const parent = this . parentRef ( ) ;
120+ if ( ! parent ) return ;
121+
122+ const sheetObject = this . sheetObject ( ) ;
123+ if ( ! sheetObject ) return ;
124+
125+ const scrub = studio . scrub ( ) ;
126+
127+ Object . keys ( sheetObject . value ) . forEach ( ( key ) => {
128+ // first, check if the prop is mapped in this component
129+ const propMapping = this . propsMapping [ key ] ;
130+ if ( ! propMapping ) return ;
131+
132+ // we're using the addedProps map to infer the target property name from the property name on values
133+ const { targetProp } = resolveInstanceKey ( parent , propMapping . path ) ;
134+ const value = propMapping . transformer . transform ( targetProp ) . default ;
135+
136+ scrub . capture ( ( { set } ) => {
137+ set ( sheetObject . props [ key ] , value ) ;
138+ } ) ;
139+ } ) ;
140+
141+ scrub . commit ( ) ;
142+ }
143+
110144 private resolvePropertyPath ( propPath : string ) {
111145 return (
112146 propPath
0 commit comments