Build dashboards you can actually look at and press
Widgets bind to a message name and read it live off the socket the editor already had — lifted out of the flow editor so a dashboard route gets the same values, which also gives the home page live data for free. The input widgets close the loop the other way: a slider publishes into the graph and whatever consumes that message runs. Verified end to end in the running app — moving a slider set a flow input, and the stat bound to what the flow computed from it followed. View mode is plain CSS grid. A wall panel that only displays should not download the code that lets someone drag things around, and it now does not. Editing is a widget picker, a per-widget width control and a settings card fed by the message catalog. No new dependencies: the slider is a range input, the gauge is an arc, and the markdown is a five-line subset. Charts are the one widget still missing — they need a charting library and the chart tokens the design guidelines reserved — so they are stored and validated but not offered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011LF61rxW1FG5YCD2J9YqjY
This commit is contained in:
@@ -6,6 +6,9 @@ import { type LogLine, liveStore } from "./liveStore"
|
||||
import { flowKeys } from "./queries"
|
||||
|
||||
const RECONNECT_MIN = 1000
|
||||
|
||||
/** How many components want the socket open. */
|
||||
let mounted = 0
|
||||
const RECONNECT_MAX = 30000
|
||||
|
||||
type FlowEvent =
|
||||
@@ -52,6 +55,14 @@ export function useFlowSocket(onAuthFailure?: () => void): void {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
useEffect(() => {
|
||||
// The editor and a dashboard can both be mounted; one socket serves both,
|
||||
// and the second caller just rides along.
|
||||
mounted += 1
|
||||
if (mounted > 1) {
|
||||
return () => {
|
||||
mounted -= 1
|
||||
}
|
||||
}
|
||||
closed.current = false
|
||||
|
||||
const connect = () => {
|
||||
@@ -126,6 +137,7 @@ export function useFlowSocket(onAuthFailure?: () => void): void {
|
||||
connect()
|
||||
|
||||
return () => {
|
||||
mounted -= 1
|
||||
closed.current = true
|
||||
if (timer.current) clearTimeout(timer.current)
|
||||
socket.current?.close()
|
||||
|
||||
Reference in New Issue
Block a user