A reusable lit controller for adding debouncing behaviour to components.
```ts
/**
* Example showing how to use InputTimingController in other Lit components
*/
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators.js";
import {
InputTimingController,
type InputTimingOptions,
} from "./input-timing-controller.ts";
@customElement("example-search-input")
export class ExampleSearchInput extends LitElement {
static override styles = css`
input {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
`;
@property({ type: String })
value = "";
@property({ type: String })
placeholder = "Search...";
// Use the timing controller with debouncing for search
private inputTiming = new InputTimingController(this, {
strategy: "debounce",
delay: 500, // Wait 500ms after user stops typing
});
override render() {
return html`
`;
}
private handleInput(event: Event) {
const input = event.target as HTMLInputElement;
this.value = input.value;
// Schedule the search event with debouncing
this.inputTiming.schedule(() => {
this.dispatchEvent(
new CustomEvent("search", {
detail: { query: this.value },
bubbles: true,
}),
);
});
}
private handleFocus() {
this.inputTiming.onFocus();
}
private handleBlur() {
this.inputTiming.onBlur();
}
}
@customElement("example-throttled-slider")
export class ExampleThrottledSlider extends LitElement {
static override styles = css`
input[type="range"] {
width: 100%;
}
`;
@property({ type: Number })
value = 50;
@property({ type: Number })
min = 0;
@property({ type: Number })
max = 100;
// Use throttling for slider updates
private inputTiming = new InputTimingController(this, {
strategy: "throttle",
delay: 100, // Update at most every 100ms
});
override render() {
return html`
`;
}
private handleInput(event: Event) {
const input = event.target as HTMLInputElement;
this.value = parseInt(input.value);
// Schedule the value change event with throttling
this.inputTiming.schedule(() => {
this.dispatchEvent(
new CustomEvent("value-change", {
detail: { value: this.value },
bubbles: true,
}),
);
});
}
}
@customElement("example-form-field")
export class ExampleFormField extends LitElement {
@property({ type: String })
value = "";
@property({ type: String })
placeholder = "";
// Use blur strategy for form validation
private inputTiming = new InputTimingController(this, {
strategy: "blur", // Only validate when user leaves the field
});
override render() {
return html`
`;
}
private handleInput(event: Event) {
const input = event.target as HTMLInputElement;
this.value = input.value;
// Schedule validation to run on blur
this.inputTiming.schedule(() => {
this.validateAndDispatch();
});
}
private handleFocus() {
this.inputTiming.onFocus();
}
private handleBlur() {
this.inputTiming.onBlur();
}
private validateAndDispatch() {
const isValid = this.value.length > 0; // Simple validation
this.dispatchEvent(
new CustomEvent("validation", {
detail: { value: this.value, isValid },
bubbles: true,
}),
);
}
}
// Usage examples:
/*
console.log('Search:', e.detail.query)}
>
console.log('Value:', e.detail.value)}
>
console.log('Valid:', e.detail.isValid)}
>
*/
```