Skip to content

Commit

Permalink
feat: add groupRegister for component space (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
LastLeaf committed Jul 21, 2023
1 parent ab57364 commit cca67e9
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 5 deletions.
53 changes: 49 additions & 4 deletions glass-easel/src/component_space.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
NormalizedComponentOptions,
} from './global_options'
import { StyleScopeManager } from './class_list'
import { GeneralBackendContext } from '.'
import { GeneralBackendContext, safeCallback } from '.'
import { TraitBehavior } from './trait_behaviors'

const normalizePath = (path: string, basePath: string): string => {
Expand Down Expand Up @@ -146,6 +146,10 @@ export class ComponentSpace {
[path: string]: ComponentWaitingList
}
/** @internal */
private _$groupingListWaiting:
| { waiting: ComponentWaitingList; comp: GeneralComponentDefinition }[]
| null = null
/** @internal */
_$componentWaitingListener:
| ((isPub: boolean, alias: string, owner: GeneralComponent) => void)
| null = null
Expand Down Expand Up @@ -373,10 +377,14 @@ export class ComponentSpace {
_$registerComponent(is: string, comp: GeneralComponentDefinition) {
this._$list[is] = comp
this._$behaviorList[is] = comp.behavior as unknown as GeneralBehavior
const arr = this._$listWaiting[is]
if (arr) {
const waiting = this._$listWaiting[is]
if (waiting) {
delete this._$listWaiting[is]
arr.call(comp)
if (this._$groupingListWaiting) {
this._$groupingListWaiting.push({ waiting, comp })
} else {
waiting.call(comp)
}
}
}

Expand All @@ -385,6 +393,43 @@ export class ComponentSpace {
this._$behaviorList[is] = beh
}

/**
* Start a series of components and behaviors registration
*
* In most cases, `groupRegister` is prefered.
*/
startGroupRegister() {
this._$groupingListWaiting = []
}

/**
* End a series of components and behaviors registration
*
* In most cases, `groupRegister` is prefered.
*/
endGroupRegister() {
const arr = this._$groupingListWaiting
if (!arr) return
this._$groupingListWaiting = null
for (let i = 0; i < arr.length; i += 1) {
const { waiting, comp } = arr[i]!
waiting.call(comp)
}
}

/**
* Group a series of components and behaviors registration
*
* If any placeholder should be replaced,
* the replacement will happen after the whole series of registration.
*/
groupRegister<R>(cb: () => R): R | undefined {
this.startGroupRegister()
const ret = safeCallback('group register', cb, this, [])
this.endGroupRegister()
return ret
}

/**
* Assign a public alias to a component
*
Expand Down
38 changes: 37 additions & 1 deletion glass-easel/tests/core/placeholder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('placeholder', () => {
matchElementWithDom(elem)
})

test('using other component as placeholder', () => {
test('using another component as placeholder', () => {
const componentSpace = new glassEasel.ComponentSpace()
const viewDef = componentSpace.define('view').registerComponent()
componentSpace.setGlobalUsingComponent('view', viewDef)
Expand All @@ -101,6 +101,42 @@ describe('placeholder', () => {
matchElementWithDom(elem)
})

test('group register other components as placeholders', () => {
const componentSpace = new glassEasel.ComponentSpace()
componentSpace.define('').registerComponent()

const def = componentSpace
.define()
.placeholders({
parent: '',
})
.definition({
using: {
parent: 'parent',
},
template: tmpl('<parent />'),
})
.registerComponent()
const elem = glassEasel.Component.createWithContext('root', def.general(), domBackend)
expect(domHtml(elem)).toBe('<parent></parent>')
matchElementWithDom(elem)

componentSpace.groupRegister(() => {
const parentDef = componentSpace
.define('parent')
.usingComponents({
child: 'child',
})
.template(tmpl('<child />'))
.registerComponent()
componentSpace.setGlobalUsingComponent('parent', parentDef)
const childDef = componentSpace.define('child').template(tmpl('CHILD')).registerComponent()
componentSpace.setGlobalUsingComponent('child', childDef)
})
expect(domHtml(elem)).toBe('<parent><child>CHILD</child></parent>')
matchElementWithDom(elem)
})

test('using placeholder across component spaces and waiting', () => {
const mainCs = new glassEasel.ComponentSpace()
mainCs.defineComponent({ is: '' })
Expand Down

0 comments on commit cca67e9

Please sign in to comment.