import { Component, ComponentChildren, ContextType } from "preact"; import { SettingsCtx } from "./SettingsContext.tsx"; import type { ConfigType } from "../config.ts"; import TextField from "preact-material-components/TextField.js"; import { Ref, StateUpdater, useRef } from "preact/hooks"; interface TextType { text: string; password: string; number: number; } interface DataType { text: never; password: never; number: number; } export type SettingsTextProps = { value: TextType[T]; name: keyof ConfigType; description: string; type: T; label?: string; helpertext?: string; textarea?: boolean; fullwidth?: boolean; disabled?: boolean; children?: ComponentChildren; set_value?: StateUpdater; min?: DataType[T]; max?: DataType[T]; outlined?: boolean; }; export default class SettingsText extends Component, unknown> { static contextType = SettingsCtx; ref: Ref | undefined; declare context: ContextType; update(value: TextType[T]) { const e = this.ref?.current; if (e) { const b = e.base; if (b) { const t = b as HTMLElement; const d = t.querySelector("input"); if (d) { const type = this.props.type; // @ts-ignore Checked if (type === "text" || type === "password") d.value = value; // @ts-ignore Checked else d.valueAsNumber = value; } } } } set_changed() { if (this.context) { this.context.set_changed((v) => { v.add(this.props.name); return v; }); } } set_value(value: TextType[T]) { if (this.props.set_value) { this.props.set_value(value); this.set_changed(); } else if (this.context) { this.context.set_settings((v) => { if (v) { const t: Record = v; t[this.props.name] = value; this.set_changed(); return t as ConfigType; } }); } } componentDidMount() { this.update(this.props.value); } componentWillUpdate( nextProps: Readonly>, _nextState: Readonly, _nextContext: unknown, ) { this.update(nextProps.value); } get_value(e: HTMLInputElement): TextType[T] { const type = this.props.type; // @ts-ignore Checked if (type === "text" || type === "password") return e.value; // @ts-ignore Checked return e.valueAsNumber; } render() { this.ref = useRef(); const id = `s-${this.props.name}`; let cn = "text"; if (this.props.helpertext) cn += " helper"; if (this.props.outlined) cn += " outlined"; if (this.props.label) cn += " label"; return (
{ if (ev.target) { const e = ev.target as HTMLInputElement; this.set_value(this.get_value(e)); } }} min={this.props.min} max={this.props.max} outlined={this.props.outlined} /> {this.props.children}
); } }