Hooks: useController
Reuse existing ReactiveController
s in your haunted component without adding @lit/reactive-element
to your bundle.
import { component, html, useController, useEffect } from 'haunted'
import { MouseController } from './mouse-controller.js';
function TrackMouse(element) {
const { pos, down } = useController(host => new MouseController(host));
useEffect(() => {
const x = pos.x - element.clientLeft;
const y = pos.y - element.clientTop;
if (x > element.clientWidth || y > element.clientHeight) return;
const hue = Math.floor((x / element.clientWidth) * 360);
const saturation = 100 - Math.floor((y / element.clientHeight) * 100);
element.style.setProperty('--x', `${x}px`);
element.style.setProperty('--y', `${y}px`);
element.style.setProperty('--hue', hue);
element.style.setProperty('--saturation', `${saturation}%`);
element.style.setProperty('--loupe-border-color', down ? 'white' : 'black');
if (down) {
element.color = getComputedStyle(element.shadowRoot.getElementById('loupe')).getPropertyValue('background-color');
element.shadowRoot.getElementById('alert').textContent = element.color;
element.shadowRoot.getElementById('alert').setAttribute("aria-hidden", "false");
element.dispatchEvent(new CustomEvent('pick'));
}
}, [pos, down]);
return html`
<link rel="stylesheet" href="color-picker.css">
<div id="loupe" role="button" aria-label="color picker"></div>
<div id="alert" role="alert" aria-hidden="true"></div>
`;
}
customElements.define('use-controller', component(TrackMouse));
:host {
display: block;
min-height: 100px;
min-width: 100px;
cursor: crosshair;
background:
linear-gradient(to bottom, transparent, hsl(0 0% 50%)),
linear-gradient(
to right,
hsl(0 100% 50%) 0%,
hsl(0.2turn 100% 50%) 20%,
hsl(0.3turn 100% 50%) 30%,
hsl(0.4turn 100% 50%) 40%,
hsl(0.5turn 100% 50%) 50%,
hsl(0.6turn 100% 50%) 60%,
hsl(0.7turn 100% 50%) 70%,
hsl(0.8turn 100% 50%) 80%,
hsl(0.9turn 100% 50%) 90%,
hsl(1turn 100% 50%) 100%
);
}
#loupe {
display: block;
height: 40px;
width: 40px;
border: 3px solid var(--loupe-border-color, black);
border-radius: 100%;
background: hsl(var(--hue, 0) var(--saturation, 100%) 50%);
transform: translate(var(--x, 0), var(--y, 0));
transition: border-color 0.1s ease-in-out;
will-change: background, transform;
}
#alert {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
export class MouseController {
down = false;
pos = { x: 0, y: 0 };
onMousemove = e => {
this.pos = { x: e.clientX, y: e.clientY };
this.host.requestUpdate();
};
onMousedown = e => {
this.down = true;
this.host.requestUpdate();
};
onMouseup = e => {
this.down = false;
this.host.requestUpdate();
};
constructor(host) {
this.host = host;
host.addController(this);
}
hostConnected() {
window.addEventListener('mousemove', this.onMousemove);
window.addEventListener('mousedown', this.onMousedown);
window.addEventListener('mouseup', this.onMouseup);
}
hostDisconnected() {
window.removeEventListener('mousemove', this.onMousemove);
window.removeEventListener('mousedown', this.onMousedown);
window.removeEventListener('mouseup', this.onMouseup);
}
}
<script type="module" src="use-controller.js"></script>
<use-controller></use-controller>
<output></output>
<script>
document.querySelector('use-controller')
.addEventListener('pick', event => {
document
.querySelector('output')
.style
.setProperty('background-color', event.target.color);
});
</script>
<style>
body {
margin: 0;
display: grid;
height: 100vh;
grid-template-rows: 2fr 1fr;
}
</style>
API
useController
Creates and stores a stateful ReactiveController instance and provides it with a ReactiveControllerHost that drives the controller lifecycle.
Use this hook to convert a ReactiveController into a Haunted hook.
Parameters
createController
<C extends ReactiveController>(host: ReactiveControllerHost) => C
A function that creates a controller instance. This function is given a HauntedControllerHost to pass to the controller. The create function is only called once per component.
Returns
ReactiveController
Exports
import { useController } from 'haunted/lib/use-controller';