diff --git a/blocksuite/framework/store/src/__tests__/block.unit.spec.ts b/blocksuite/framework/store/src/__tests__/block.unit.spec.ts index 6806714c9..f6175f668 100644 --- a/blocksuite/framework/store/src/__tests__/block.unit.spec.ts +++ b/blocksuite/framework/store/src/__tests__/block.unit.spec.ts @@ -51,6 +51,7 @@ const flatTableSchema = defineBlockSchema({ textCols: {} as Record, rows: {} as Record, labels: [] as Array, + optional: undefined as string | undefined, }), metadata: { role: 'content', @@ -494,6 +495,16 @@ describe('flat', () => { expect(model.props.textCols$.value.a.toDelta()).toEqual([ { insert: 'test' }, ]); + + onChange.mockClear(); + expect(model.props).not.toHaveProperty('optional'); + expect(model.props).toHaveProperty('optional$'); + model.props.optional$.value = 'test'; + expect(model.props.optional).toBe('test'); + expect(model.props.optional$.value).toBe('test'); + expect(onChange).toHaveBeenCalledTimes(1); + expect(onChange).toHaveBeenCalledWith(expect.anything(), 'optional', true); + expect(yBlock.get('prop:optional')).toBe('test'); }); test('stash and pop', () => { diff --git a/blocksuite/framework/store/src/model/block/flat-sync-controller.ts b/blocksuite/framework/store/src/model/block/flat-sync-controller.ts index 293410b05..a8231c4a3 100644 --- a/blocksuite/framework/store/src/model/block/flat-sync-controller.ts +++ b/blocksuite/framework/store/src/model/block/flat-sync-controller.ts @@ -47,6 +47,7 @@ export class FlatSyncController { } const model = schema.model.toModel?.() ?? new BlockModel(); + const defaultProps = schema.model.props?.(internalPrimitives); model.schema = schema; model.id = this.id; @@ -55,7 +56,8 @@ export class FlatSyncController { const reactive = new ReactiveFlatYMap( this.yBlock, model.deleted, - this.onChange + this.onChange, + defaultProps ); this._reactive = reactive; const proxy = reactive.proxy; @@ -66,17 +68,6 @@ export class FlatSyncController { model.store = this.doc; } - const defaultProps = schema.model.props?.(internalPrimitives); - if (defaultProps) { - Object.entries(defaultProps).forEach(([key, value]) => { - if (key in proxy) { - return; - } - if (value === undefined) return; - proxy[key] = value; - }); - } - return model; } diff --git a/blocksuite/framework/store/src/reactive/flat-native-y/index.ts b/blocksuite/framework/store/src/reactive/flat-native-y/index.ts index 7bee39560..6fb9b707b 100644 --- a/blocksuite/framework/store/src/reactive/flat-native-y/index.ts +++ b/blocksuite/framework/store/src/reactive/flat-native-y/index.ts @@ -99,7 +99,8 @@ export class ReactiveFlatYMap extends BaseReactiveYData< constructor( protected readonly _ySource: YMap, private readonly _onDispose: Subject, - private readonly _onChange?: OnChange + private readonly _onChange?: OnChange, + defaultProps?: Record ) { super(); this._initialized = false; @@ -112,7 +113,7 @@ export class ReactiveFlatYMap extends BaseReactiveYData< const proxy = this._getProxy(source, source); - Object.entries(source).forEach(([key, value]) => { + const initSignals = (key: string, value: unknown) => { const signalData = signal(value); source[`${key}$`] = signalData; const unsubscribe = signalData.subscribe(next => { @@ -128,11 +129,30 @@ export class ReactiveFlatYMap extends BaseReactiveYData< subscription.unsubscribe(); unsubscribe(); }); + }; + + Object.entries(source).forEach(([key, value]) => { + initSignals(key, value); }); + if (defaultProps) { + Object.entries(defaultProps).forEach(([key, value]) => { + if (!(key in proxy) && value === undefined) { + initSignals(key, value); + } + }); + } + this._proxy = proxy; this._ySource.observe(this._observer); this._initialized = true; + + if (defaultProps) { + Object.entries(defaultProps).forEach(([key, value]) => { + if (key in proxy || value === undefined) return; + proxy[key] = value; + }); + } } pop = (prop: string): void => {