UNPKG

@pmndrs/uikit

Version:

Build performant 3D user interfaces with Three.js and yoga.

84 lines (83 loc) 3.42 kB
import { Object3D } from 'three'; import { createParentContextSignal, setupParentContextSignal, bindHandlers, Component } from './utils.js'; import { effect, signal, untracked } from '@preact/signals-core'; import { setupContent, createContentState } from '../components/index.js'; export class Content extends Component { mergedProperties; contentContainer; styleSignal = signal(undefined); propertiesSignal; defaultPropertiesSignal; parentContextSignal = createParentContextSignal(); unsubscribe; internals; constructor(properties, defaultProperties) { super(); this.matrixAutoUpdate = false; setupParentContextSignal(this.parentContextSignal, this); this.propertiesSignal = signal(properties); this.defaultPropertiesSignal = signal(defaultProperties); //setting up the threejs elements this.contentContainer = new Object3D(); this.contentContainer.matrixAutoUpdate = false; super.add(this.contentContainer); this.unsubscribe = effect(() => { const parentContext = this.parentContextSignal.value?.value; if (parentContext == null) { return; } const abortController = new AbortController(); const state = createContentState(parentContext, this.styleSignal, this.propertiesSignal, this.defaultPropertiesSignal, { current: this.contentContainer }); this.internals = state; this.mergedProperties = state.mergedProperties; //setup content with state setupContent(state, parentContext, this.styleSignal, this.propertiesSignal, this, this.contentContainer, abortController.signal); //setup events super.add(this.internals.interactionPanel); bindHandlers(state.handlers, this, abortController.signal); this.addEventListener('childadded', state.remeasureContent); this.addEventListener('childremoved', state.remeasureContent); return () => { this.remove(this.internals.interactionPanel); abortController.abort(); this.removeEventListener('childadded', state.remeasureContent); this.removeEventListener('childremoved', state.remeasureContent); }; }); } add(...objects) { const objectsLength = objects.length; for (let i = 0; i < objectsLength; i++) { const object = objects[i]; this.contentContainer.add(object); } return this; } remove(...objects) { const objectsLength = objects.length; for (let i = 0; i < objectsLength; i++) { const object = objects[i]; this.contentContainer.remove(object); } return this; } getComputedProperty(key) { return untracked(() => this.mergedProperties?.value.read(key, undefined)); } getStyle() { return this.styleSignal.peek(); } setStyle(style, replace) { this.styleSignal.value = replace ? style : { ...this.styleSignal.value, ...style }; } setProperties(properties) { this.propertiesSignal.value = properties; } setDefaultProperties(properties) { this.defaultPropertiesSignal.value = properties; } destroy() { this.parent?.remove(this); this.unsubscribe(); } }