@pmndrs/uikit
Version:
Build performant 3D user interfaces with Three.js and yoga.
84 lines (83 loc) • 3.42 kB
JavaScript
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();
}
}