UNPKG

@pionjs/pion

Version:

Hooks for web components

59 lines (58 loc) 1.85 kB
import { hook, Hook } from "./hook"; const UPPER = /([A-Z])/gu; export const useProperty = hook(class extends Hook { property; eventName; constructor(id, state, property, initialValue) { super(id, state); if (this.state.virtual) { throw new Error("Can't be used with virtual components."); } this.updater = this.updater.bind(this); this.property = property; this.eventName = property.replace(UPPER, "-$1").toLowerCase() + "-changed"; // set the initial value only if it was not already set by the parent if (this.state.host[this.property] != null) return; if (typeof initialValue === "function") { const initFn = initialValue; initialValue = initFn(); } if (initialValue == null) return; this.updateProp(initialValue); } update(ignored, ignored2) { return [this.state.host[this.property], this.updater]; } updater(value) { const previousValue = this.state.host[this.property]; if (typeof value === "function") { const updaterFn = value; value = updaterFn(previousValue); } if (Object.is(previousValue, value)) { return; } this.updateProp(value); } updateProp(value) { const ev = this.notify(value); if (ev.defaultPrevented) return; this.state.host[this.property] = value; } notify(value) { const ev = new CustomEvent(this.eventName, { detail: { value, path: this.property }, cancelable: true, }); this.state.host.dispatchEvent(ev); return ev; } }); export const lift = (setter) => (ev) => { ev.preventDefault(); setter(ev.detail.value); };