@textbus/collaborate 2.0.0-beta.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,42 +1,100 @@
1
- import { Injectable } from '@tanbo/di'
2
- import { merge, microTask, Observable, Subject, Subscription } from '@tanbo/stream'
1
+ import { Inject, Injectable } from '@tanbo/di'
2
+ import { delay, filter, map, Observable, Subject, Subscription } from '@tanbo/stream'
3
3
  import {
4
- RootComponentRef,
5
- Starter,
6
- Translator,
4
+ ChangeOrigin,
5
+ ComponentInstance,
6
+ ContentType, Controller,
7
+ Formats,
8
+ History, HISTORY_STACK_SIZE,
9
+ makeError,
7
10
  Registry,
11
+ RootComponentRef,
12
+ Scheduler,
8
13
  Selection,
9
14
  SelectionPaths,
10
- History, Renderer, Slot, ComponentInstance, makeError, Formats
15
+ Slot,
16
+ Starter,
17
+ Translator
11
18
  } from '@textbus/core'
12
19
  import {
20
+ Array as YArray,
13
21
  Doc as YDoc,
14
22
  Map as YMap,
23
+ RelativePosition,
15
24
  Text as YText,
16
- Array as YArray,
25
+ Transaction,
17
26
  UndoManager,
18
- Transaction
27
+ createAbsolutePositionFromRelativePosition,
28
+ createRelativePositionFromTypeIndex
19
29
  } from 'yjs'
20
30
 
21
31
  import { CollaborateCursor, RemoteSelection } from './collaborate-cursor'
32
+ import { createUnknownComponent } from './unknown.component'
22
33
 
23
34
  const collaborateErrorFn = makeError('Collaborate')
24
35
 
36
+ interface CursorPosition {
37
+ anchor: RelativePosition
38
+ focus: RelativePosition
39
+ }
40
+
41
+ class ContentMap {
42
+ private slotAndYTextMap = new WeakMap<Slot, YText>()
43
+ private yTextAndSLotMap = new WeakMap<YText, Slot>()
44
+
45
+ set(key: Slot, value: YText): void
46
+ set(key: YText, value: Slot): void
47
+ set(key: any, value: any) {
48
+ if (key instanceof Slot) {
49
+ this.slotAndYTextMap.set(key, value)
50
+ this.yTextAndSLotMap.set(value, key)
51
+ } else {
52
+ this.slotAndYTextMap.set(value, key)
53
+ this.yTextAndSLotMap.set(key, value)
54
+ }
55
+ }
56
+
57
+ get(key: Slot): YText | null
58
+ get(key: YText): Slot | null
59
+ get(key: any) {
60
+ if (key instanceof Slot) {
61
+ return this.slotAndYTextMap.get(key) || null
62
+ }
63
+ return this.yTextAndSLotMap.get(key) || null
64
+ }
65
+
66
+ delete(key: Slot | YText) {
67
+ if (key instanceof Slot) {
68
+ const v = this.slotAndYTextMap.get(key)
69
+ this.slotAndYTextMap.delete(key)
70
+ if (v) {
71
+ this.yTextAndSLotMap.delete(v)
72
+ }
73
+ } else {
74
+ const v = this.yTextAndSLotMap.get(key)
75
+ this.yTextAndSLotMap.delete(key)
76
+ if (v) {
77
+ this.slotAndYTextMap.delete(v)
78
+ }
79
+ }
80
+ }
81
+ }
82
+
25
83
  @Injectable()
26
84
  export class Collaborate implements History {
27
85
  onSelectionChange: Observable<SelectionPaths>
28
86
  yDoc = new YDoc()
29
87
  onBack: Observable<void>
30
88
  onForward: Observable<void>
31
- onChange: Observable<any>
89
+ onChange: Observable<void>
32
90
  onPush: Observable<void>
33
91
 
34
92
  get canBack() {
35
- return this.manager?.canUndo()
93
+ return this.manager?.canUndo() || false
36
94
  }
37
95
 
38
96
  get canForward() {
39
- return this.manager?.canRedo()
97
+ return this.manager?.canRedo() || false
40
98
  }
41
99
 
42
100
  private backEvent = new Subject<void>()
@@ -44,7 +102,7 @@ export class Collaborate implements History {
44
102
  private changeEvent = new Subject<void>()
45
103
  private pushEvent = new Subject<void>()
46
104
 
47
- private manager!: UndoManager
105
+ private manager: UndoManager | null = null
48
106
 
49
107
  private subscriptions: Subscription[] = []
50
108
  private updateFromRemote = false
@@ -55,87 +113,179 @@ export class Collaborate implements History {
55
113
  private componentStateSyncCaches = new WeakMap<ComponentInstance, () => void>()
56
114
 
57
115
  private selectionChangeEvent = new Subject<SelectionPaths>()
116
+ private contentMap = new ContentMap()
58
117
 
59
118
  private updateRemoteActions: Array<() => void> = []
60
119
 
61
- constructor(private rootComponentRef: RootComponentRef,
120
+ constructor(@Inject(HISTORY_STACK_SIZE) private stackSize: number,
121
+ private rootComponentRef: RootComponentRef,
62
122
  private collaborateCursor: CollaborateCursor,
123
+ private controller: Controller,
124
+ private scheduler: Scheduler,
63
125
  private translator: Translator,
64
- private renderer: Renderer,
65
126
  private registry: Registry,
66
127
  private selection: Selection,
67
128
  private starter: Starter) {
68
- this.onSelectionChange = this.selectionChangeEvent.asObservable()
129
+ this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(delay())
69
130
  this.onBack = this.backEvent.asObservable()
70
131
  this.onForward = this.forwardEvent.asObservable()
71
132
  this.onChange = this.changeEvent.asObservable()
72
133
  this.onPush = this.pushEvent.asObservable()
73
134
  }
74
135
 
75
- setup() {
136
+ listen() {
137
+ const root = this.yDoc.getMap('RootComponent')
138
+ const rootComponent = this.rootComponentRef.component!
139
+ this.manager = new UndoManager(root, {
140
+ trackedOrigins: new Set<any>([this.yDoc])
141
+ })
142
+ const cursorKey = 'cursor-position'
143
+ this.manager.on('stack-item-added', event => {
144
+ event.stackItem.meta.set(cursorKey, this.getRelativeCursorLocation())
145
+ if (this.manager!.undoStack.length > this.stackSize) {
146
+ this.manager!.undoStack.shift()
147
+ }
148
+ if (event.origin === this.yDoc) {
149
+ this.pushEvent.next()
150
+ }
151
+ this.changeEvent.next()
152
+ })
153
+ this.manager.on('stack-item-popped', event => {
154
+ const position = event.stackItem.meta.get(cursorKey) as CursorPosition
155
+ if (position) {
156
+ this.restoreCursorLocation(position)
157
+ }
158
+ })
76
159
  this.subscriptions.push(
77
- this.starter.onReady.subscribe(() => {
78
- this.listen2()
79
- }),
80
160
  this.selection.onChange.subscribe(() => {
81
161
  const paths = this.selection.getPaths()
82
162
  this.selectionChangeEvent.next(paths)
163
+ }),
164
+ this.scheduler.onDocChanged.pipe(
165
+ map(item => {
166
+ return item.filter(i => {
167
+ return i.from !== ChangeOrigin.Remote
168
+ })
169
+ }),
170
+ filter(item => {
171
+ return item.length
172
+ })
173
+ ).subscribe(() => {
174
+ this.yDoc.transact(() => {
175
+ this.updateRemoteActions.forEach(fn => {
176
+ fn()
177
+ })
178
+ this.updateRemoteActions = []
179
+ }, this.yDoc)
83
180
  })
84
181
  )
182
+ this.syncRootComponent(root, rootComponent)
85
183
  }
86
184
 
87
185
  updateRemoteSelection(paths: RemoteSelection[]) {
88
186
  this.collaborateCursor.draw(paths)
89
187
  }
90
188
 
91
- listen() {
92
- //
93
- }
94
-
95
189
  back() {
96
190
  if (this.canBack) {
97
- this.manager.undo()
191
+ this.manager?.undo()
192
+ this.backEvent.next()
98
193
  }
99
194
  }
100
195
 
101
196
  forward() {
102
197
  if (this.canForward) {
103
- this.manager.redo()
198
+ this.manager?.redo()
199
+ this.forwardEvent.next()
104
200
  }
105
201
  }
106
202
 
203
+ clear() {
204
+ this.manager?.clear()
205
+ this.changeEvent.next()
206
+ }
207
+
107
208
  destroy() {
108
209
  this.subscriptions.forEach(i => i.unsubscribe())
210
+ this.collaborateCursor.destroy()
211
+ this.manager?.destroy()
109
212
  }
110
213
 
111
- private listen2() {
112
- const root = this.yDoc.getText('content')
113
- const rootComponent = this.rootComponentRef.component!
114
- this.manager = new UndoManager(root, {
115
- trackedOrigins: new Set<any>([this.yDoc])
116
- })
117
- this.syncContent(root, rootComponent.slots.get(0)!)
118
-
119
- this.subscriptions.push(
120
- merge(
121
- rootComponent.changeMarker.onForceChange,
122
- rootComponent.changeMarker.onChange
123
- ).pipe(
124
- microTask()
125
- ).subscribe(() => {
126
- this.yDoc.transact(() => {
127
- this.updateRemoteActions.forEach(fn => {
128
- fn()
129
- })
130
- this.updateRemoteActions = []
131
- }, this.yDoc)
132
- this.renderer.render()
133
- this.selection.restore()
214
+ private syncRootComponent(root: YMap<any>, rootComponent: ComponentInstance) {
215
+ let slots = root.get('slots') as YArray<YMap<any>>
216
+ if (!slots) {
217
+ slots = new YArray()
218
+ rootComponent.slots.toArray().forEach(i => {
219
+ const sharedSlot = this.createSharedSlotBySlot(i)
220
+ slots.push([sharedSlot])
134
221
  })
135
- )
222
+ this.yDoc.transact(() => {
223
+ root.set('state', rootComponent.state)
224
+ root.set('slots', slots)
225
+ })
226
+ } else if (slots.length === 0) {
227
+ rootComponent.updateState(() => {
228
+ return root.get('state')
229
+ })
230
+ this.yDoc.transact(() => {
231
+ rootComponent.slots.toArray().forEach(i => {
232
+ const sharedSlot = this.createSharedSlotBySlot(i)
233
+ slots.push([sharedSlot])
234
+ })
235
+ })
236
+ } else {
237
+ rootComponent.updateState(() => {
238
+ return root.get('state')
239
+ })
240
+ rootComponent.slots.clean()
241
+ slots.forEach(sharedSlot => {
242
+ const slot = this.createSlotBySharedSlot(sharedSlot)
243
+ this.syncContent(sharedSlot.get('content'), slot)
244
+ this.syncSlot(sharedSlot, slot)
245
+ rootComponent.slots.insert(slot)
246
+ })
247
+ }
248
+ this.syncComponent(root, rootComponent)
249
+ this.syncSlots(slots, rootComponent)
250
+ }
251
+
252
+ private restoreCursorLocation(position: CursorPosition) {
253
+ const anchorPosition = createAbsolutePositionFromRelativePosition(position.anchor, this.yDoc)
254
+ const focusPosition = createAbsolutePositionFromRelativePosition(position.focus, this.yDoc)
255
+ if (anchorPosition && focusPosition) {
256
+ const focusSlot = this.contentMap.get(focusPosition.type as YText)
257
+ const anchorSlot = this.contentMap.get(anchorPosition.type as YText)
258
+ if (focusSlot && anchorSlot) {
259
+ this.selection.setBaseAndExtent(anchorSlot, anchorPosition.index, focusSlot, focusPosition.index)
260
+ return
261
+ }
262
+ }
263
+ this.selection.unSelect()
264
+ }
265
+
266
+ private getRelativeCursorLocation(): CursorPosition | null {
267
+ const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection
268
+ if (anchorSlot) {
269
+ const anchorYText = this.contentMap.get(anchorSlot)
270
+ if (anchorYText) {
271
+ const anchorPosition = createRelativePositionFromTypeIndex(anchorYText, anchorOffset!)
272
+ if (focusSlot) {
273
+ const focusYText = this.contentMap.get(focusSlot)
274
+ if (focusYText) {
275
+ const focusPosition = createRelativePositionFromTypeIndex(focusYText, focusOffset!)
276
+ return {
277
+ focus: focusPosition,
278
+ anchor: anchorPosition
279
+ }
280
+ }
281
+ }
282
+ }
283
+ }
284
+ return null
136
285
  }
137
286
 
138
287
  private syncContent(content: YText, slot: Slot) {
288
+ this.contentMap.set(slot, content)
139
289
  const syncRemote = (ev, tr) => {
140
290
  this.runRemoteUpdate(tr, () => {
141
291
  slot.retain(0)
@@ -146,6 +296,7 @@ export class Collaborate implements History {
146
296
  if (formats.length) {
147
297
  slot.retain(action.retain!, formats)
148
298
  }
299
+ slot.retain(slot.index + action.retain)
149
300
  } else {
150
301
  slot.retain(action.retain)
151
302
  }
@@ -157,17 +308,18 @@ export class Collaborate implements History {
157
308
  slot.insert(action.insert, makeFormats(this.registry, action.attributes))
158
309
  } else {
159
310
  const sharedComponent = action.insert as YMap<any>
160
- const component = this.createComponentBySharedComponent(sharedComponent)
311
+ const canInsertInlineComponent = slot.schema.includes(ContentType.InlineComponent)
312
+ const component = this.createComponentBySharedComponent(sharedComponent, canInsertInlineComponent)
161
313
  this.syncSlots(sharedComponent.get('slots'), component)
162
314
  this.syncComponent(sharedComponent, component)
163
315
  slot.insert(component)
164
316
  }
165
317
  if (this.selection.isSelected) {
166
- if (slot === this.selection.startSlot && this.selection.startOffset! >= index) {
167
- this.selection.setStart(slot, this.selection.startOffset! + length)
318
+ if (slot === this.selection.anchorSlot && this.selection.anchorOffset! > index) {
319
+ this.selection.setAnchor(slot, this.selection.anchorOffset! + length)
168
320
  }
169
- if (slot === this.selection.endSlot && this.selection.endOffset! >= index) {
170
- this.selection.setEnd(slot, this.selection.endOffset! + length)
321
+ if (slot === this.selection.focusSlot && this.selection.focusOffset! > index) {
322
+ this.selection.setFocus(slot, this.selection.focusOffset! + length)
171
323
  }
172
324
  }
173
325
  } else if (action.delete) {
@@ -175,16 +327,20 @@ export class Collaborate implements History {
175
327
  slot.retain(slot.index)
176
328
  slot.delete(action.delete)
177
329
  if (this.selection.isSelected) {
178
- if (slot === this.selection.startSlot && this.selection.startOffset! >= index) {
179
- this.selection.setStart(slot, this.selection.startOffset! - action.delete)
330
+ if (slot === this.selection.anchorSlot && this.selection.anchorOffset! >= index) {
331
+ this.selection.setAnchor(slot, this.selection.startOffset! - action.delete)
180
332
  }
181
- if (slot === this.selection.endSlot && this.selection.endOffset! >= index) {
182
- this.selection.setEnd(slot, this.selection.endOffset! - action.delete)
333
+ if (slot === this.selection.focusSlot && this.selection.focusOffset! >= index) {
334
+ this.selection.setFocus(slot, this.selection.focusOffset! - action.delete)
183
335
  }
184
336
  }
185
337
  } else if (action.attributes) {
186
338
  slot.updateState(draft => {
187
- Object.assign(draft, action.attributes)
339
+ if (typeof draft === 'object' && draft !== null) {
340
+ Object.assign(draft, action.attributes)
341
+ } else {
342
+ return action.attributes
343
+ }
188
344
  })
189
345
  }
190
346
  })
@@ -219,23 +375,22 @@ export class Collaborate implements History {
219
375
  const isEmpty = delta.length === 1 && delta[0].insert === Slot.emptyPlaceholder
220
376
  if (typeof action.content === 'string') {
221
377
  length = action.content.length
222
- content.insert(offset, action.content)
378
+ content.insert(offset, action.content, action.formats || {})
223
379
  } else {
224
380
  length = 1
225
- const component = slot.getContentAtIndex(offset) as ComponentInstance
226
- const sharedComponent = this.createSharedComponentByComponent(component)
381
+ const sharedComponent = this.createSharedComponentByComponent(action.ref as ComponentInstance)
227
382
  content.insertEmbed(offset, sharedComponent)
228
383
  }
229
- if (action.formats) {
230
- content.format(offset, length, action.formats)
231
- }
384
+
232
385
  if (isEmpty && offset === 0) {
233
386
  content.delete(content.length - 1, 1)
234
387
  }
235
388
  offset += length
236
389
  } else if (action.type === 'delete') {
237
390
  const delta = content.toDelta()
238
- content.delete(offset, action.count)
391
+ if (content.length) {
392
+ content.delete(offset, action.count)
393
+ }
239
394
  if (content.length === 0) {
240
395
  content.insert(0, '\n', delta[0]?.attributes)
241
396
  }
@@ -243,6 +398,12 @@ export class Collaborate implements History {
243
398
  }
244
399
  })
245
400
  })
401
+
402
+ sub.add(slot.onChildComponentRemove.subscribe(components => {
403
+ components.forEach(c => {
404
+ this.cleanSubscriptionsByComponent(c)
405
+ })
406
+ }))
246
407
  this.contentSyncCaches.set(slot, () => {
247
408
  content.unobserve(syncRemote)
248
409
  sub.unsubscribe()
@@ -256,7 +417,11 @@ export class Collaborate implements History {
256
417
  if (key === 'state') {
257
418
  const state = (ev.target as YMap<any>).get('state')
258
419
  slot.updateState(draft => {
259
- Object.assign(draft, state)
420
+ if (typeof draft === 'object' && draft !== null) {
421
+ Object.assign(draft, state)
422
+ } else {
423
+ return state
424
+ }
260
425
  })
261
426
  }
262
427
  })
@@ -281,18 +446,21 @@ export class Collaborate implements History {
281
446
  const slots = component.slots
282
447
  const syncRemote = (ev, tr) => {
283
448
  this.runRemoteUpdate(tr, () => {
449
+ let index = 0
284
450
  ev.delta.forEach(action => {
285
451
  if (Reflect.has(action, 'retain')) {
286
- slots.retain(action.retain!)
452
+ index += action.retain
453
+ slots.retain(index)
287
454
  } else if (action.insert) {
288
455
  (action.insert as Array<YMap<any>>).forEach(item => {
289
456
  const slot = this.createSlotBySharedSlot(item)
290
457
  slots.insert(slot)
291
458
  this.syncContent(item.get('content'), slot)
292
459
  this.syncSlot(item, slot)
460
+ index++
293
461
  })
294
462
  } else if (action.delete) {
295
- slots.retain(slots.index)
463
+ slots.retain(index)
296
464
  slots.delete(action.delete)
297
465
  }
298
466
  })
@@ -308,20 +476,22 @@ export class Collaborate implements History {
308
476
  if (action.type === 'retain') {
309
477
  index = action.offset
310
478
  } else if (action.type === 'insertSlot') {
311
- const slot = slots.get(index)!
312
- const sharedSlot = this.createSharedSlotBySlot(slot)
479
+ const sharedSlot = this.createSharedSlotBySlot(action.ref)
313
480
  remoteSlots.insert(index, [sharedSlot])
314
481
  index++
315
482
  } else if (action.type === 'delete') {
316
- slots.slice(index, index + action.count).forEach(slot => {
317
- this.cleanSubscriptionsBySlot(slot)
318
- })
319
483
  remoteSlots.delete(index, action.count)
320
484
  }
321
485
  })
322
486
  })
323
487
  })
324
488
 
489
+ sub.add(slots.onChildSlotRemove.subscribe(slots => {
490
+ slots.forEach(slot => {
491
+ this.cleanSubscriptionsBySlot(slot)
492
+ })
493
+ }))
494
+
325
495
  this.slotsSyncCaches.set(component, () => {
326
496
  remoteSlots.unobserve(syncRemote)
327
497
  sub.unsubscribe()
@@ -335,7 +505,11 @@ export class Collaborate implements History {
335
505
  if (key === 'state') {
336
506
  const state = (ev.target as YMap<any>).get('state')
337
507
  component.updateState(draft => {
338
- Object.assign(draft, state)
508
+ if (typeof draft === 'object' && draft !== null) {
509
+ Object.assign(draft, state)
510
+ } else {
511
+ return state
512
+ }
339
513
  })
340
514
  }
341
515
  })
@@ -355,7 +529,7 @@ export class Collaborate implements History {
355
529
  }
356
530
 
357
531
  private runLocalUpdate(fn: () => void) {
358
- if (this.updateFromRemote) {
532
+ if (this.updateFromRemote || this.controller.readonly) {
359
533
  return
360
534
  }
361
535
  this.updateRemoteActions.push(fn)
@@ -366,7 +540,11 @@ export class Collaborate implements History {
366
540
  return
367
541
  }
368
542
  this.updateFromRemote = true
369
- fn()
543
+ if (tr.origin === this.manager) {
544
+ this.scheduler.historyApplyTransact(fn)
545
+ } else {
546
+ this.scheduler.remoteUpdateTransact(fn)
547
+ }
370
548
  this.updateFromRemote = false
371
549
  }
372
550
 
@@ -414,7 +592,7 @@ export class Collaborate implements History {
414
592
  return sharedSlot
415
593
  }
416
594
 
417
- private createComponentBySharedComponent(yMap: YMap<any>): ComponentInstance {
595
+ private createComponentBySharedComponent(yMap: YMap<any>, canInsertInlineComponent: boolean): ComponentInstance {
418
596
  const sharedSlots = yMap.get('slots') as YArray<YMap<any>>
419
597
  const slots: Slot[] = []
420
598
  sharedSlots.forEach(sharedSlot => {
@@ -438,7 +616,7 @@ export class Collaborate implements History {
438
616
  })
439
617
  return instance
440
618
  }
441
- throw collaborateErrorFn(`cannot find component factory \`${name}\`.`)
619
+ return createUnknownComponent(name, canInsertInlineComponent).createInstance(this.starter)
442
620
  }
443
621
 
444
622
  private createSlotBySharedSlot(sharedSlot: YMap<any>): Slot {
@@ -458,7 +636,8 @@ export class Collaborate implements History {
458
636
  slot.insert(action.insert, makeFormats(this.registry, action.attributes))
459
637
  } else {
460
638
  const sharedComponent = action.insert as YMap<any>
461
- const component = this.createComponentBySharedComponent(sharedComponent)
639
+ const canInsertInlineComponent = slot.schema.includes(ContentType.InlineComponent)
640
+ const component = this.createComponentBySharedComponent(sharedComponent, canInsertInlineComponent)
462
641
  slot.insert(component)
463
642
  this.syncSlots(sharedComponent.get('slots'), component)
464
643
  this.syncComponent(sharedComponent, component)
@@ -471,6 +650,7 @@ export class Collaborate implements History {
471
650
  }
472
651
 
473
652
  private cleanSubscriptionsBySlot(slot: Slot) {
653
+ this.contentMap.delete(slot);
474
654
  [this.contentSyncCaches.get(slot), this.slotStateSyncCaches.get(slot)].forEach(fn => {
475
655
  if (fn) {
476
656
  fn()
@@ -498,7 +678,7 @@ export class Collaborate implements History {
498
678
  function makeFormats(registry: Registry, attrs?: any) {
499
679
  const formats: Formats = []
500
680
  if (attrs) {
501
- Object.keys(attrs).map(key => {
681
+ Object.keys(attrs).forEach(key => {
502
682
  const formatter = registry.getFormatter(key)
503
683
  if (formatter) {
504
684
  formats.push([formatter, attrs[key]])
package/src/public-api.ts CHANGED
@@ -1,2 +1,18 @@
1
+ import { History, Module } from '@textbus/core'
2
+
3
+ import { Collaborate } from './collaborate'
4
+ import { CollaborateCursor } from './collaborate-cursor'
5
+
1
6
  export * from './collaborate'
2
7
  export * from './collaborate-cursor'
8
+
9
+ export const collaborateModule: Module = {
10
+ providers: [
11
+ Collaborate,
12
+ CollaborateCursor,
13
+ {
14
+ provide: History,
15
+ useClass: Collaborate
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,22 @@
1
+ import { ContentType, defineComponent, VElement } from '@textbus/core'
2
+
3
+ export function createUnknownComponent(factoryName: string, canInsertInlineComponent: boolean) {
4
+ const unknownComponent = defineComponent({
5
+ type: canInsertInlineComponent ? ContentType.InlineComponent : ContentType.BlockComponent,
6
+ name: 'UnknownComponent',
7
+ setup() {
8
+ console.error(`cannot find component factory \`${factoryName}\`.`)
9
+ return {
10
+ render() {
11
+ return VElement.createElement('textbus-unknown-component', {
12
+ style: {
13
+ display: canInsertInlineComponent ? 'inline' : 'block',
14
+ color: '#f00'
15
+ }
16
+ }, unknownComponent.name)
17
+ }
18
+ }
19
+ }
20
+ })
21
+ return unknownComponent
22
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "declaration": true,
4
- "useDefineForClassFields": true,
4
+ "useDefineForClassFields": false,
5
5
  "emitDecoratorMetadata": true,
6
6
  "experimentalDecorators": true,
7
7
  "allowSyntheticDefaultImports": true,