Phase 6
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { h } from 'preact';
|
||||
import { useState, useEffect } from 'preact/hooks';
|
||||
import { getSignalStore } from '../lib/stores';
|
||||
import type { Widget, SignalValue } from '../lib/types';
|
||||
|
||||
const DEFAULT_VALUE: SignalValue = { value: null, quality: 'unknown', ts: null };
|
||||
|
||||
function getBit(val: number, bit: number): boolean {
|
||||
return (val & (1 << bit)) !== 0;
|
||||
}
|
||||
|
||||
interface Props { widget: Widget; onContextMenu?: (e: MouseEvent) => void; }
|
||||
|
||||
export default function MultiLed({ widget, onContextMenu }: Props) {
|
||||
const sigRef = widget.signals[0];
|
||||
const [sv, setSv] = useState<SignalValue>(DEFAULT_VALUE);
|
||||
|
||||
useEffect(() => {
|
||||
if (!sigRef) return;
|
||||
const unsub = getSignalStore(sigRef).subscribe(setSv);
|
||||
return unsub;
|
||||
}, [sigRef?.ds, sigRef?.name]);
|
||||
|
||||
const bits = parseInt(widget.options['bits'] ?? '8', 10);
|
||||
const labelsRaw = widget.options['labels'] ?? '';
|
||||
const colorsTrueRaw = widget.options['colorsTrue'] ?? '';
|
||||
const colorsFalseRaw = widget.options['colorsFalse'] ?? '';
|
||||
|
||||
const labelArr = labelsRaw ? labelsRaw.split(',') : [];
|
||||
const colorsTrueArr = colorsTrueRaw ? colorsTrueRaw.split(',') : [];
|
||||
const colorsFalseArr = colorsFalseRaw ? colorsFalseRaw.split(',') : [];
|
||||
|
||||
const quality = sv.quality;
|
||||
const isUncertain = quality === 'uncertain' || quality === 'unknown';
|
||||
|
||||
const rawV = sv.value;
|
||||
const intValue = rawV === null || rawV === undefined ? 0
|
||||
: typeof rawV === 'number' ? Math.floor(rawV) : parseInt(String(rawV), 10);
|
||||
|
||||
const bitStates = Array.from({ length: bits }, (_, i) => getBit(intValue, i));
|
||||
|
||||
return (
|
||||
<div
|
||||
class="multiled-widget"
|
||||
style={`left:${widget.x}px;top:${widget.y}px;width:${widget.w}px;height:${widget.h}px;`}
|
||||
onContextMenu={onContextMenu}
|
||||
>
|
||||
{bitStates.map((on, i) => {
|
||||
const trueColor = colorsTrueArr[i] ?? '#22c55e';
|
||||
const falseColor = colorsFalseArr[i] ?? '#ef4444';
|
||||
const color = on ? trueColor : falseColor;
|
||||
const bitLabel = labelArr[i] ?? String(i);
|
||||
return (
|
||||
<div key={i} class="bit-item">
|
||||
<div
|
||||
class={`led-circle${isUncertain ? ' blink' : ''}`}
|
||||
style={`background:${color};box-shadow:0 0 6px ${color}88;`}
|
||||
/>
|
||||
<div class="bit-label">{bitLabel}</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user