@devicechain/widgets 0.24.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/absolute-range-picker.d.ts +22 -0
- package/dist/binding-policy.d.ts +1 -0
- package/dist/builtin-descriptors.d.ts +69 -0
- package/dist/builtin-registry.d.ts +68 -0
- package/dist/chunks/absolute-range-picker-E57G2TPX.js +139 -0
- package/dist/chunks/absolute-range-picker-E57G2TPX.js.map +7 -0
- package/dist/chunks/{aggregate-feed-4FSBQYJL.js → aggregate-feed-XX36GNY6.js} +2 -2
- package/dist/chunks/{aggregate-widgets-2ZQBW3YF.js → aggregate-widgets-72HMPMBU.js} +99 -57
- package/dist/chunks/aggregate-widgets-72HMPMBU.js.map +7 -0
- package/dist/chunks/{chunk-USRYKW2J.js → chunk-7BUCJQFP.js} +10 -2
- package/dist/chunks/chunk-7BUCJQFP.js.map +7 -0
- package/dist/chunks/chunk-AF4M5OXQ.js +23 -0
- package/dist/chunks/chunk-AF4M5OXQ.js.map +7 -0
- package/dist/chunks/{chunk-XQQQNTBX.js → chunk-EQOWBDS7.js} +1 -1
- package/dist/chunks/{chunk-XQQQNTBX.js.map → chunk-EQOWBDS7.js.map} +1 -1
- package/dist/chunks/chunk-JVC6JYUR.js +48 -0
- package/dist/chunks/chunk-JVC6JYUR.js.map +7 -0
- package/dist/chunks/{chunk-JFH4QMLA.js → chunk-NYHNQ5VR.js} +5 -1
- package/dist/chunks/{chunk-JFH4QMLA.js.map → chunk-NYHNQ5VR.js.map} +2 -2
- package/dist/chunks/chunk-VTGKDO44.js +87 -0
- package/dist/chunks/chunk-VTGKDO44.js.map +7 -0
- package/dist/chunks/chunk-XJ7UF2CP.js +90 -0
- package/dist/chunks/chunk-XJ7UF2CP.js.map +7 -0
- package/dist/chunks/{compare-feed-AY3CVKUZ.js → compare-feed-5OLZHFRL.js} +48 -23
- package/dist/chunks/compare-feed-5OLZHFRL.js.map +7 -0
- package/dist/chunks/{event-markers-feed-GEGTIHXT.js → event-markers-feed-B3MVFYUT.js} +4 -4
- package/dist/chunks/export-rows-OEWIBIUY.js +11 -0
- package/dist/chunks/{fleet-feed-2SKDR6ZQ.js → fleet-feed-D4T3LC25.js} +10 -10
- package/dist/chunks/history-widgets-NSNXDKEC.js +336 -0
- package/dist/chunks/history-widgets-NSNXDKEC.js.map +7 -0
- package/dist/chunks/{level-widgets-MJB7TOLU.js → level-widgets-HE6EDSWC.js} +13 -9
- package/dist/chunks/level-widgets-HE6EDSWC.js.map +7 -0
- package/dist/chunks/no-reading-B4MPXAS2.js +22 -0
- package/dist/chunks/no-reading-B4MPXAS2.js.map +7 -0
- package/dist/chunks/{presence-widgets-2LIUKN4Y.js → presence-widgets-M5VGG3OO.js} +12 -8
- package/dist/chunks/presence-widgets-M5VGG3OO.js.map +7 -0
- package/dist/chunks/table-CEVB3JZS.js +8 -0
- package/dist/chunks/table-CEVB3JZS.js.map +7 -0
- package/dist/compare-model.d.ts +1 -1
- package/dist/documented-descriptors.d.ts +206 -0
- package/dist/export-rows.d.ts +24 -0
- package/dist/history-feed.d.ts +10 -0
- package/dist/history-model.d.ts +45 -0
- package/dist/history-strings.d.ts +20 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +544 -189
- package/dist/index.js.map +4 -4
- package/dist/level-reading.d.ts +1 -0
- package/dist/no-reading-core.d.ts +25 -0
- package/dist/no-reading.d.ts +10 -0
- package/dist/time-range-bar.d.ts +26 -2
- package/dist/widgets/history-lazy.d.ts +70 -0
- package/dist/widgets/history-table.d.ts +7 -0
- package/dist/widgets/history-widgets.d.ts +2 -0
- package/dist/widgets/no-reading-lazy.d.ts +7 -0
- package/package.json +8 -8
- package/dist/chunks/aggregate-widgets-2ZQBW3YF.js.map +0 -7
- package/dist/chunks/chunk-USRYKW2J.js.map +0 -7
- package/dist/chunks/compare-feed-AY3CVKUZ.js.map +0 -7
- package/dist/chunks/level-widgets-MJB7TOLU.js.map +0 -7
- package/dist/chunks/presence-widgets-2LIUKN4Y.js.map +0 -7
- package/dist/chunks/table-6EVV7QZH.js +0 -7
- /package/dist/chunks/{aggregate-feed-4FSBQYJL.js.map → aggregate-feed-XX36GNY6.js.map} +0 -0
- /package/dist/chunks/{event-markers-feed-GEGTIHXT.js.map → event-markers-feed-B3MVFYUT.js.map} +0 -0
- /package/dist/chunks/{table-6EVV7QZH.js.map → export-rows-OEWIBIUY.js.map} +0 -0
- /package/dist/chunks/{fleet-feed-2SKDR6ZQ.js.map → fleet-feed-D4T3LC25.js.map} +0 -0
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/compare-feed.tsx", "../../src/compare-model.ts", "../../src/compare-strings.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The multi-device compare chart: ONE measurement, a line per member of a group, over the board's\n// span. Its own lazy chunk, loaded from the fleet feed's entry only when a time-series chart is set\n// to one line per device -- a board without one never downloads it.\n//\n// - ONE live subscription (hub.subscribeMembers), then one history read per DRAWN member through\n// hub.readMemberSeeds: bounded hub-wide (MEMBER_SEED_CONCURRENCY) and shared with any widget\n// asking the same question. There is no batched history read in the platform (the store\n// aggregates one device at a time), so the cost of the chart is the number of lines it draws --\n// which is why that number is capped (`maxSeries`) and the cap is said on the chart.\n// - A history read is the measurement alone (the store narrows by name), over the board's span (or\n// the chart's pinned one) ending at the last minute boundary, in buckets of bucketSecondsFor(span):\n// one point per bucket, the bucket's AVERAGE. The chart says so (the badge), and says that\n// threshold lines are references, never a reading of a bucket.\n// - Live readings extend each line past the history's end. While the board is paused the view is\n// cut at the freeze instant; the buffer keeps filling and the chart catches up on resume.\n// - A member stream that resumes after an interruption re-reads the histories, at once and again\n// just after the next minute boundary (as the fleet feed does).\n//\n// Rebuilding the state per sample would re-render the chart hundreds of times a second, so changes\n// are folded into a store and flushed at most once per FLUSH_MS.\n\nimport {\n DEFAULT_TIME_RANGE_SECONDS,\n spanLabel,\n type MemberRoster,\n type MeasurementSample,\n type WidgetDataSource,\n type WidgetDescriptor,\n type WidgetInstance,\n} from '@devicechain/dashboards';\nimport {\n css,\n fontVar,\n optNumber,\n optString,\n optThresholds,\n resolveStaleAfterSeconds,\n spaceVar,\n useWidgetScale,\n useWidgetTimeRange,\n WidgetFrame,\n WidgetFreshnessProvider,\n} from '@devicechain/widget-sdk';\nimport { buildLineOption, EChart, useChartTheme } from '@devicechain/widget-sdk/echarts';\nimport { useEffect, useMemo, useReducer, useRef, useState, type ComponentType } from 'react';\n\nimport { measurementSpan } from './binding-policy';\nimport { bucketSamples, capMembers, composeSeries, memberLabels, pushLive, seriesLimit, type CappedMembers, type MemberHistory } from './compare-model';\nimport { compareStrings } from './compare-strings';\nimport { seedWindow } from './fleet-model';\nimport { fleetStrings } from './fleet-strings';\nimport { LevelEmpty } from './level-readout';\n\nexport const FLUSH_MS = 250;\nconst MINUTE_MS = 60_000;\n// How long past a minute boundary the second re-read after an interruption waits (the fleet feed's).\nconst RESEED_SETTLE_MS = 2_000;\n// A reading ages out of the span with no event to say so.\nconst AGE_OUT_MS = 30_000;\n// Below this width or height (px) the notes under the chart are said in a line.\nconst COMPACT_WIDTH = 320;\nconst COMPACT_HEIGHT = 200;\n\ninterface Store {\n key: string | null;\n roster: MemberRoster | null;\n live: Map<string, MeasurementSample[]>;\n history: Map<string, MemberHistory | 'failed'>;\n forbidden: boolean;\n error: unknown | null;\n}\n\nconst emptyStore = (key: string | null): Store => ({ key, roster: null, live: new Map(), history: new Map(), forbidden: false, error: null });\n\nexport interface CompareFeedProps {\n hub: WidgetDataSource;\n widget: WidgetInstance;\n descriptor: WidgetDescriptor;\n ErrorFrame: ComponentType<{ widget: WidgetInstance; error: unknown }>;\n}\n\nexport default function CompareFeed({ hub, widget, descriptor, ErrorFrame }: CompareFeedProps) {\n const range = useWidgetTimeRange();\n const now = useMemo(() => (hub.now ? () => hub.now!() : Date.now), [hub]);\n const spanSeconds = measurementSpan(descriptor, widget, range?.spanSeconds) ?? range?.spanSeconds ?? DEFAULT_TIME_RANGE_SECONDS;\n const pausedAt = range?.paused ? range.pausedAt : undefined;\n const measurement = optString(widget.options, 'measurement') ?? widget.datasource?.measurements[0];\n const limit = seriesLimit(optNumber(widget.options, 'maxSeries'));\n // The datasource the live feed is asked for: the one measurement, so the hub delivers no other.\n const ds = widget.datasource && measurement ? { ...widget.datasource, measurements: [measurement] } : undefined;\n const dsKey = JSON.stringify(ds ?? null);\n const supported = hub.subscribeMembers !== undefined && hub.readMemberSeeds !== undefined;\n\n const store = useRef<Store>(emptyStore(dsKey));\n const [version, bump] = useReducer((n: number) => n + 1, 0);\n const [rosterKey, setRosterKey] = useState<string | null>(null);\n const generation = useRef(0);\n const flushTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const boundaryTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const [resumes, resumed] = useReducer((n: number) => n + 1, 0);\n // The tokens drawn, which the live feed filters by.\n const drawn = useRef<Set<string>>(new Set());\n\n const schedule = (): void => {\n if (flushTimer.current !== undefined) return;\n flushTimer.current = setTimeout(() => {\n flushTimer.current = undefined;\n bump();\n }, FLUSH_MS);\n };\n\n useEffect(() => {\n const s = emptyStore(dsKey);\n store.current = s;\n drawn.current = new Set();\n setRosterKey(null);\n bump();\n const gen = ++generation.current;\n if (!ds || !supported) return;\n const dispose = hub.subscribeMembers!(ds, {\n roster: (roster) => {\n s.roster = roster;\n drawn.current = new Set(capMembers(roster, limit).shown.map((m) => m.token));\n setRosterKey(`${gen}\\n${[...drawn.current].join('\\n')}`);\n schedule();\n },\n next: (sample) => {\n if (!drawn.current.has(sample.deviceToken)) return;\n let buffer = s.live.get(sample.deviceToken);\n if (!buffer) s.live.set(sample.deviceToken, (buffer = []));\n pushLive(buffer, sample);\n schedule();\n },\n forbidden: () => {\n s.forbidden = true;\n schedule();\n },\n error: (err) => {\n s.error = err;\n schedule();\n },\n reconnected: () => {\n resumed();\n if (boundaryTimer.current !== undefined) return;\n const at = now();\n boundaryTimer.current = setTimeout(() => {\n boundaryTimer.current = undefined;\n resumed();\n }, MINUTE_MS - (at % MINUTE_MS) + RESEED_SETTLE_MS);\n },\n });\n return () => {\n dispose();\n if (flushTimer.current !== undefined) clearTimeout(flushTimer.current);\n flushTimer.current = undefined;\n if (boundaryTimer.current !== undefined) clearTimeout(boundaryTimer.current);\n boundaryTimer.current = undefined;\n };\n // `ds` is read through `dsKey` (value identity); a new limit re-draws from the same roster below.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hub, dsKey, supported, limit]);\n\n // One history read per drawn member, again when the span or the freeze instant changes.\n useEffect(() => {\n const s = store.current;\n if (!supported || !s.roster || rosterKey === null || !measurement) return;\n const tokens = capMembers(s.roster, limit).shown.map((m) => m.token);\n if (tokens.length === 0) return;\n const window = seedWindow(spanSeconds, pausedAt ?? now());\n const end = Date.parse(window.endTime);\n let cancelled = false;\n void hub.readMemberSeeds!(\n tokens,\n {\n // The plan reads the one measurement over the span and keeps its buckets; the seed it returns\n // is empty because this chart draws the history itself, not a \"latest\" cell.\n seed: async (token, read) => {\n const buckets = await read({ startTime: window.startTime, endTime: window.endTime, intervalSeconds: window.intervalSeconds, name: measurement });\n // A read this effect no longer wants (the span, the freeze instant or the roster moved on\n // while it was in flight) must not overwrite the newer one's history when it lands last.\n if (!cancelled) s.history.set(token, { samples: bucketSamples(token, measurement, buckets), end });\n return { latest: {}, observed: [] };\n },\n },\n (token, seed, failure) => {\n if (cancelled) return;\n if (failure === 'forbidden') s.forbidden = true;\n // A re-read that failed keeps the history it would have replaced: those points are still true.\n else if (!seed && !s.history.has(token)) s.history.set(token, 'failed');\n schedule();\n },\n () => cancelled,\n );\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hub, supported, dsKey, rosterKey, spanSeconds, pausedAt, limit, resumes]);\n\n // A reading ages out of the span with no event to say so.\n useEffect(() => {\n if (pausedAt !== undefined) return;\n const id = setInterval(bump, AGE_OUT_MS);\n return () => clearInterval(id);\n }, [pausedAt]);\n\n const view = useMemo(() => {\n const s = store.current.key === dsKey ? store.current : emptyStore(dsKey);\n const capped = s.roster ? capMembers(s.roster, limit) : undefined;\n const labels = capped ? memberLabels(capped.shown) : new Map<string, string>();\n const until = pausedAt ?? now();\n const composed =\n capped && measurement\n ? composeSeries({ shown: capped.shown, labels, measurement, history: s.history, live: s.live, since: until - spanSeconds * 1000, until })\n : undefined;\n return { s, capped, labels, composed };\n // `version` is the store's change counter; the store itself is mutable.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [version, dsKey, limit, spanSeconds, pausedAt, now, measurement]);\n\n const { s, capped, labels, composed } = view;\n const freshness = useMemo(\n () => (descriptor.freshness === true ? { at: composed?.newest, staleAfterSeconds: resolveStaleAfterSeconds(widget.options) } : undefined),\n [descriptor, widget.options, composed?.newest],\n );\n if (s.error) return <ErrorFrame widget={widget} error={s.error} />;\n\n const title = optString(widget.options, 'title');\n const strings = fleetStrings();\n const empty = (message: string) => (\n <WidgetFrame title={title}>\n <LevelEmpty message={message} />\n </WidgetFrame>\n );\n if (!measurement) return empty(strings.noMeasurement);\n if (!supported) return empty(strings.unsupported);\n if (s.forbidden) return empty(strings.forbidden);\n if (ds?.kind === 'unbound') return empty(strings.unbound);\n if (!capped) return empty(strings.loading);\n if (capped.shown.length === 0) return empty(strings.noMembers);\n\n return (\n <WidgetFreshnessProvider freshness={freshness}>\n <WidgetFrame title={title} flush>\n <CompareBody\n widget={widget}\n names={capped.shown.map((m) => labels.get(m.token) ?? m.token)}\n samples={composed?.samples ?? []}\n bucketSeconds={seedWindow(spanSeconds, pausedAt ?? now()).intervalSeconds}\n capped={capped}\n historyFailed={composed?.historyFailed ?? 0}\n />\n </WidgetFrame>\n </WidgetFreshnessProvider>\n );\n}\n\nfunction CompareBody({\n widget,\n names,\n samples,\n bucketSeconds,\n capped,\n historyFailed,\n}: {\n widget: WidgetInstance;\n names: string[];\n samples: MeasurementSample[];\n bucketSeconds: number;\n capped: CappedMembers;\n historyFailed: number;\n}) {\n const theme = useChartTheme();\n const { size, scale } = useWidgetScale();\n const strings = compareStrings();\n const unit = optString(widget.options, 'unit');\n const precision = optNumber(widget.options, 'precision');\n const thresholds = useMemo(() => optThresholds(widget.options, 'thresholds'), [widget.options]);\n const min = optNumber(widget.options, 'min');\n const max = optNumber(widget.options, 'max');\n const namesKey = names.join('\\n');\n const option = useMemo(\n () => buildLineOption(samples, theme, { measurements: names, unit, precision, thresholds, scale, min, max }, size),\n // `names` is read through `namesKey` (value identity): the array is rebuilt on every render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [samples, theme, namesKey, unit, precision, thresholds, scale, size, min, max],\n );\n const bucket = spanLabel(bucketSeconds);\n // The sentences, or (in a box too narrow for them: the widget's smallest span is 4 cells) the same\n // facts in a line, with the sentences in its title. Nothing is dropped, only shortened.\n const compact = (size.width > 0 && size.width < COMPACT_WIDTH) || (size.height > 0 && size.height < COMPACT_HEIGHT);\n const facts: Array<{ full: string; short: string }> = [];\n if (capped.capped) {\n const full = capped.pagedBySource ? strings.cappedPage(capped.shown.length, capped.read, capped.total) : strings.capped(capped.shown.length, capped.total);\n facts.push({ full, short: strings.cappedShort(capped.shown.length, capped.total) });\n }\n if (historyFailed > 0) facts.push({ full: strings.historyFailed(historyFailed), short: strings.historyFailedShort(historyFailed) });\n if (thresholds.length > 0) facts.push({ full: strings.thresholdNote, short: strings.thresholdShort });\n const badge = (\n <span\n data-compare-bucket={bucket}\n title={strings.bucketedTitle(bucket)}\n style={{\n padding: `0 ${spaceVar(1)}`,\n fontSize: fontVar('xs'),\n whiteSpace: 'nowrap',\n color: css('muted-foreground'),\n background: css('muted'),\n borderRadius: 4,\n }}\n >\n {strings.bucketed(bucket)}\n </span>\n );\n const noteStyle = { flexShrink: 0, padding: `${spaceVar(1)} ${spaceVar(2)}`, fontSize: fontVar('xs'), color: css('muted-foreground') } as const;\n return (\n <div style={{ display: 'flex', flexDirection: 'column', width: '100%', height: '100%' }} data-compare-chart=\"\">\n <div style={{ position: 'relative', flex: 1, minHeight: 0 }}>\n <EChart option={option} />\n </div>\n {/* Under the chart, never over it: a corner of the plot is where the legend runs once it fills\n the width (five devices on a phone) and where a threshold's label sits, and the badge\n covered both. */}\n {compact ? (\n <div data-compare-notes={facts.length > 0 ? '' : undefined} data-compare-compact=\"\" title={facts.map((f) => f.full).join(' ')} style={noteStyle}>\n {badge}\n {facts.map((f) => ` \u00B7 ${f.short}`).join('')}\n </div>\n ) : (\n <div data-compare-notes={facts.length > 0 ? '' : undefined} title={facts.length > 0 ? facts.map((f) => f.full).join(' ') : undefined} style={noteStyle}>\n <div>{badge}</div>\n {facts.map((f) => (\n <div key={f.full}>{f.full}</div>\n ))}\n </div>\n )}\n </div>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The multi-device compare chart's state, decided apart from the drawing and from the hub: which\n// members get a line, what each line is called, and which readings make it up. Pure, so each rule\n// is a test.\n//\n// A line is one member's readings of ONE measurement over the span: its stored history (one point\n// per bucket, the bucket's AVERAGE) followed by the readings that arrived live after the history\n// was read (raw). Everything is keyed by device; nothing here looks a value up by name alone.\n\nimport type { MeasurementBucket, MeasurementSample, MemberRef } from '@devicechain/dashboards';\n\n// The lines drawn when the author sets no limit: the chart palette's width, so no two lines share\n// a colour. The most an author may ask for: a comparison past this is a table, not a chart.\nexport const DEFAULT_MAX_SERIES = 5;\nexport const MAX_SERIES_LIMIT = 12;\n\n// Live readings kept per member. A comparison is a few lines over a span; this bounds the memory of\n// a chatty device (a reading a second over a week) without touching the stored history, which is\n// already bucketed to at most a couple of hundred points.\nexport const LIVE_PER_MEMBER = 600;\n\n// The limit as the author set it, held to what the chart supports. Unset, or anything that is not a\n// whole number of at least one, is the default: a typo must not turn into a different chart.\nexport function seriesLimit(value: number | undefined): number {\n if (value === undefined || !Number.isInteger(value) || value < 1) return DEFAULT_MAX_SERIES;\n return Math.min(value, MAX_SERIES_LIMIT);\n}\n\nexport interface CappedMembers {\n shown: MemberRef[];\n // The size of the group, as the source reports it. Never less than the members read.\n total: number;\n // True when lines were left out, for either reason: the author's limit, or a group larger than\n // the page the source read (shown + not drawn < total).\n capped: boolean;\n // True when the source itself read less than the group: the total is then the group's size and\n // `read` the members it listed.\n pagedBySource: boolean;\n read: number;\n}\n\n// The first `limit` members of the roster, in the roster's order (a stable order, so a line keeps\n// its colour as readings arrive). Which members are left out is the roster's, not the readings':\n// choosing \"the busiest\" would reshuffle the chart as data moves.\nexport function capMembers(roster: { members: readonly MemberRef[]; total: number }, limit: number): CappedMembers {\n const read = roster.members.length;\n const total = Math.max(roster.total, read);\n const shown = roster.members.slice(0, limit);\n return { shown, total, capped: shown.length < total, pagedBySource: total > read, read };\n}\n\n// A name per member: its device name, else its token. Two members with the same name get their\n// token appended, so two lines never carry one legend entry.\nexport function memberLabels(members: readonly MemberRef[]): Map<string, string> {\n const base = members.map((m) => m.name?.trim() || m.token);\n const count = new Map<string, number>();\n for (const b of base) count.set(b, (count.get(b) ?? 0) + 1);\n const labels = new Map<string, string>();\n members.forEach((m, i) => labels.set(m.token, (count.get(base[i]) ?? 0) > 1 && base[i] !== m.token ? `${base[i]} (${m.token})` : base[i]));\n return labels;\n}\n\n// One member's stored history as samples: a point per bucket that has an average, stamped at the\n// bucket's start, oldest first. A bucket with no readings has no average and no point.\nexport function bucketSamples(token: string, measurement: string, buckets: readonly MeasurementBucket[]): MeasurementSample[] {\n return buckets\n .filter((b) => b.name === measurement && b.avg != null)\n .map((b) => ({\n id: `cmp-${token}-${b.name}-${b.bucketStart}`,\n deviceToken: token,\n eventType: 0,\n occurredTime: b.bucketStart,\n name: b.name,\n value: b.avg,\n classifier: null,\n }))\n .sort((a, b) => Date.parse(a.occurredTime as string) - Date.parse(b.occurredTime as string));\n}\n\n// A member's stored history once read: the points, and the instant the read ended (epoch ms), after\n// which live readings are the only source.\nexport interface MemberHistory {\n samples: MeasurementSample[];\n end: number;\n}\n\n// Appends a live reading to a member's buffer: newest wins on a repeat id, and the buffer keeps the\n// newest LIVE_PER_MEMBER.\nexport function pushLive(buffer: MeasurementSample[], sample: MeasurementSample): void {\n if (buffer.some((s) => s.id === sample.id)) return;\n buffer.push(sample);\n if (buffer.length > LIVE_PER_MEMBER) buffer.splice(0, buffer.length - LIVE_PER_MEMBER);\n}\n\nexport interface ComposeInputs {\n shown: readonly MemberRef[];\n labels: ReadonlyMap<string, string>;\n measurement: string;\n history: ReadonlyMap<string, MemberHistory | 'failed'>;\n live: ReadonlyMap<string, readonly MeasurementSample[]>;\n // The span, epoch ms: nothing before `since` or after `until` is drawn (the board's freeze\n // instant while paused).\n since: number;\n until: number;\n}\n\nexport interface Composed {\n // One sample per point, named by the member's LABEL so the line chart draws one line per member.\n samples: MeasurementSample[];\n // Members whose stored history could not be read: their lines hold live readings only.\n historyFailed: number;\n // The newest reading drawn, epoch ms, for the frame's age.\n newest: number | undefined;\n}\n\nexport function composeSeries(i: ComposeInputs): Composed {\n const samples: MeasurementSample[] = [];\n let historyFailed = 0;\n let newest: number | undefined;\n for (const m of i.shown) {\n const label = i.labels.get(m.token) ?? m.token;\n const h = i.history.get(m.token);\n if (h === 'failed') historyFailed += 1;\n const stored = h && h !== 'failed' ? h.samples : [];\n // Live readings count only after the stored history's read ended: before it, the history holds\n // them already (as an average), and drawing both would put two values on one instant.\n const after = h && h !== 'failed' ? h.end : Number.NEGATIVE_INFINITY;\n const live = (i.live.get(m.token) ?? []).filter((s) => s.name === i.measurement && s.value != null && s.occurredTime != null && Date.parse(s.occurredTime) > after);\n const points = [...stored, ...live]\n .filter((s) => {\n const t = Date.parse(s.occurredTime as string);\n return t >= i.since && t <= i.until;\n })\n .sort((a, b) => Date.parse(a.occurredTime as string) - Date.parse(b.occurredTime as string));\n for (const s of points) {\n samples.push({ ...s, name: label });\n const t = Date.parse(s.occurredTime as string);\n if (newest === undefined || t > newest) newest = t;\n }\n }\n return { samples, historyFailed, newest };\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The fixed words the multi-device compare chart renders itself. The widget packages carry no i18n\n// runtime, so this is the one small per-language table (modelled on fleet-strings.ts); the option\n// labels are translated in the console's catalogs, not here. Loaded with the compare feed (a lazy\n// chunk), never by a board without a compare chart.\n\nimport { viewerLocale } from '@devicechain/widget-sdk';\n\nexport interface CompareStrings {\n // The group is larger than the lines drawn: say how many, and which ones.\n capped: (shown: number, total: number) => string;\n // The group was larger than what the resolver read: the total is a floor, not the size.\n cappedPage: (shown: number, read: number, total: number) => string;\n // History is a per-bucket average; the live tail is the raw readings.\n bucketed: (bucket: string) => string;\n bucketedTitle: (bucket: string) => string;\n // A threshold line is a reference drawn at a value, never a verdict on an average.\n thresholdNote: string;\n // Some devices' history could not be read: their lines hold only what arrived live.\n historyFailed: (n: number) => string;\n // The same facts for a box too narrow for the sentences above; the full text stays in the title.\n cappedShort: (shown: number, total: number) => string;\n thresholdShort: string;\n historyFailedShort: (n: number) => string;\n}\n\nexport const COMPARE_STRINGS: Record<'en' | 'es', CompareStrings> = {\n en: {\n capped: (shown, total) => `Showing ${shown} of ${total} devices (the first ${shown}); raise Most lines, up to 12, to see more.`,\n cappedPage: (shown, read, total) =>\n `Showing ${shown} of ${total} devices: the group is larger than the ${read} devices read, and the first ${shown} are drawn.`,\n bucketed: (bucket) => `avg per ${bucket}`,\n bucketedTitle: (bucket) =>\n `Stored history is drawn as the average of each ${bucket} bucket, one point per bucket; readings that arrived live since are drawn as they came, unaveraged.`,\n thresholdNote: 'Thresholds are reference lines; a plotted history point is a bucket average, not a reading.',\n historyFailed: (n) => (n === 1 ? '1 device\u2019s history could not be read; its line starts from live readings.' : `${n} devices\u2019 history could not be read; their lines start from live readings.`),\n cappedShort: (shown, total) => `${shown} of ${total} devices`,\n thresholdShort: 'thresholds are references',\n historyFailedShort: (n) => `${n} unread`,\n },\n es: {\n capped: (shown, total) =>\n `Mostrando ${shown} de ${total} dispositivos (los primeros ${shown}); aumente M\u00E1ximo de l\u00EDneas, hasta 12, para ver m\u00E1s.`,\n cappedPage: (shown, read, total) =>\n `Mostrando ${shown} de ${total} dispositivos: el grupo es mayor que los ${read} dispositivos le\u00EDdos, y se dibujan los primeros ${shown}.`,\n bucketed: (bucket) => `prom. por ${bucket}`,\n bucketedTitle: (bucket) =>\n `El historial almacenado se dibuja como el promedio de cada intervalo de ${bucket}, un punto por intervalo; las lecturas llegadas en vivo desde entonces se dibujan tal cual, sin promediar.`,\n thresholdNote: 'Los umbrales son l\u00EDneas de referencia; un punto de historial es un promedio por intervalo, no una lectura.',\n historyFailed: (n) =>\n n === 1 ? 'No se pudo leer el historial de 1 dispositivo; su l\u00EDnea parte de lecturas en vivo.' : `No se pudo leer el historial de ${n} dispositivos; sus l\u00EDneas parten de lecturas en vivo.`,\n cappedShort: (shown, total) => `${shown} de ${total} dispositivos`,\n thresholdShort: 'umbrales son referencias',\n historyFailedShort: (n) => `${n} sin leer`,\n },\n};\n\nexport function compareStrings(locale: string | undefined = viewerLocale()): CompareStrings {\n return locale?.toLowerCase().split('-')[0] === 'es' ? COMPARE_STRINGS.es : COMPARE_STRINGS.en;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["s", "capped", "labels", "composed"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/widgets/battery.tsx", "../../src/level-reading.ts", "../../src/level-strings.ts", "../../src/widgets/compass.tsx", "../../src/heading.ts", "../../src/widgets/level-gauge.tsx", "../../src/widgets/linear-gauge.tsx", "../../src/widgets/progress-ring.tsx", "../../src/widgets/signal-bars.tsx", "../../src/widgets/status-light.tsx"],
|
|
4
|
-
"sourcesContent": ["// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// battery \u2014 the charge of a device as a battery glyph filled to value% of its scale. The scale\n// is the documented percent default (0..100) unless the options set another, so a voltage can\n// be shown by configuring min and max. The fill takes the colour of the threshold band the\n// value is in (\"critical below 15\") and keeps the neutral accent in a `normal` band.\n\nimport { useMemo } from 'react';\n\nimport {\n css,\n optNumber,\n optString,\n optThresholds,\n WidgetFrame,\n type WidgetProps,\n type WidgetScale,\n} from '@devicechain/widget-sdk';\n\nimport { emptyReason, useLevelReading, type LevelReading } from '../level-reading';\nimport { LevelEmpty, LevelReadout } from '../level-readout';\nimport { readRange } from '../value-scale';\n\n// The percent scale the battery uses when the options set none, stated in its descriptor.\nexport const BATTERY_DEFAULT_RANGE = { min: 0, max: 100 } as const;\n\n// The glyph's own geometry, in its viewBox: a body, a terminal nub on the right, and the fill\n// inset inside the body.\nconst VIEW = { w: 120, h: 60 };\nconst BODY = { x: 3, y: 3, w: 104, h: 54, r: 9 };\nconst NUB = { x: 110, y: 20, w: 8, h: 20, r: 3 };\nconst INSET = 7;\nexport const BATTERY_FILL_WIDTH = BODY.w - INSET * 2;\n\nexport function Battery({ widget, data }: WidgetProps) {\n const thresholds = useMemo(() => optThresholds(widget.options, 'thresholds'), [widget.options]);\n const reading = useLevelReading(widget, data, {\n thresholds,\n unit: optString(widget.options, 'unit'),\n precision: optNumber(widget.options, 'precision'),\n range: readRange(optNumber(widget.options, 'min'), optNumber(widget.options, 'max'), BATTERY_DEFAULT_RANGE),\n });\n const title = optString(widget.options, 'title') ?? reading.name;\n return (\n <WidgetFrame title={title} sampleTime={reading.sample?.occurredTime ?? null}>\n {(scale) => <BatteryBody reading={reading} scale={scale} />}\n </WidgetFrame>\n );\n}\n\nfunction BatteryBody({ reading: r, scale: ws }: { reading: LevelReading; scale: WidgetScale }) {\n const reason = emptyReason(r);\n if (reason !== undefined || !r.range?.ok || !r.fill) return <LevelEmpty message={reason ?? r.strings.noData} />;\n const range = r.range.range;\n const fill = r.fill;\n // The readout takes the lower share of the box; the glyph keeps the rest, scaled to fit it.\n const readoutHeight = Math.max(ws.px('font-md') * 1.6, ws.size.height * 0.4);\n return (\n <div\n data-threshold-level={r.band?.level}\n data-out-of-range={fill.position === 'within' ? undefined : fill.position}\n data-fill={fill.fraction}\n style={{ height: '100%', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', gap: ws.px('space-1') }}\n >\n <div style={{ flex: '1 1 0', minHeight: 0 }}>\n <svg\n role=\"meter\"\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n aria-valuenow={range.min + fill.fraction * (range.max - range.min)}\n aria-valuetext={`${r.display}${r.unit ? ` ${r.unit}` : ''}`}\n viewBox={`0 0 ${VIEW.w} ${VIEW.h}`}\n preserveAspectRatio=\"xMidYMid meet\"\n style={{ width: '100%', height: '100%', display: 'block' }}\n >\n <rect\n x={BODY.x}\n y={BODY.y}\n width={BODY.w}\n height={BODY.h}\n rx={BODY.r}\n style={{ fill: 'none', stroke: css('muted-foreground'), strokeWidth: 4 }}\n />\n <rect x={NUB.x} y={NUB.y} width={NUB.w} height={NUB.h} rx={NUB.r} style={{ fill: css('muted-foreground') }} />\n {fill.fraction > 0 ? (\n <rect\n data-fill-bar=\"\"\n x={BODY.x + INSET}\n y={BODY.y + INSET}\n width={BATTERY_FILL_WIDTH * fill.fraction}\n height={BODY.h - INSET * 2}\n rx={3}\n style={{ fill: r.fillColor }}\n />\n ) : null}\n </svg>\n </div>\n <div style={{ flex: '0 0 auto', height: readoutHeight, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <LevelReadout\n text={r.display}\n unit={r.unit}\n color={r.levelColor}\n position={fill.position}\n size={{ width: ws.size.width, height: readoutHeight }}\n scale={ws.scale}\n strings={r.strings}\n />\n </div>\n </div>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// What every level-and-indicator widget reads off its options and data, once: the sample it\n// shows, how it formats, the threshold band the value is in and that band's colour, the scale\n// and the fill on it. A widget adds its own drawing on top.\n\nimport {\n bandAt,\n css,\n formatValue,\n levelColor,\n pickSample,\n primaryMeasurementName,\n useSeverityColors,\n type MeasurementStreamState,\n type SeverityLevel,\n type Threshold,\n} from '@devicechain/widget-sdk';\nimport type { MeasurementSample, WidgetInstance } from '@devicechain/dashboards';\n\nimport { levelStrings, type LevelStrings } from './level-strings';\nimport { fillOf, type Fill, type RangeResult } from './value-scale';\n\nexport interface LevelReading {\n // The measurement shown (the title's fallback).\n name: string | undefined;\n sample: MeasurementSample | undefined;\n value: number | undefined;\n unit: string | undefined;\n precision: number | undefined;\n display: string;\n thresholds: Threshold[];\n band: Threshold | undefined;\n // The band's severity colour; undefined for no band and for `normal`, so the widget draws its\n // OWN neutral. `fillColor` below is that choice made for the common case.\n levelColor: string | undefined;\n // The colour a given level resolves to (undefined for `normal`), for drawing the bands themselves.\n colorOf: (level: SeverityLevel | undefined) => string | undefined;\n // The colour of a lit or filled part: the band's, else the chart accent (never a hue of its own).\n fillColor: string;\n range: RangeResult | undefined;\n fill: Fill | undefined;\n strings: LevelStrings;\n}\n\n// What a widget reads off its own options and hands in: the hook reads none itself, so each\n// widget's source states every option it honors (options.test.ts holds that to the schema).\n// `range` is the widget's scale, read with readRange; an indicator with no scale omits it.\nexport interface LevelInput {\n thresholds: Threshold[];\n unit: string | undefined;\n precision: number | undefined;\n range?: RangeResult;\n // Maps the sample's raw value to the one the widget shows (a compass folds a heading onto\n // 0..360); undefined means \"no usable value\". Band, display and fill all read the mapped value.\n normalize?: (raw: number | undefined) => number | undefined;\n}\n\nexport function useLevelReading(widget: WidgetInstance, data: MeasurementStreamState, input: LevelInput): LevelReading {\n const severity = useSeverityColors();\n const name = primaryMeasurementName(widget);\n const sample = pickSample(data.latest, name);\n const { thresholds, unit, precision, range, normalize } = input;\n const raw = sample?.value ?? undefined;\n const value = normalize ? normalize(raw) : raw;\n const band = bandAt(thresholds, value);\n const bandColor = levelColor(severity, band?.level);\n return {\n name,\n sample,\n value,\n unit,\n precision,\n display: formatValue(value, precision),\n thresholds,\n band,\n levelColor: bandColor,\n colorOf: (level) => levelColor(severity, level),\n fillColor: bandColor ?? css('chart-1'),\n range,\n fill: range?.ok ? fillOf(value, range.range) : undefined,\n strings: levelStrings(),\n };\n}\n\n// The reason a scale widget has nothing to draw, or undefined when it can draw. The author's\n// fix (the scale) is named before the absence of data, which resolves itself.\nexport function emptyReason(r: LevelReading): string | undefined {\n if (r.range && !r.range.ok) return r.range.reason === 'missing' ? r.strings.setRange : r.strings.badRange;\n if (r.value === undefined) return r.strings.noData;\n return undefined;\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The few fixed words the level-and-indicator widgets render themselves (the reasons they give\n// instead of a value, and the on/off captions). The widget packages carry no i18n runtime, so\n// this is the one small per-language table, modelled on the SDK's freshness words: a host that\n// adds a runtime later replaces exactly this file. Option labels are translated in the\n// console's catalogs, not here.\n\nimport { viewerLocale } from '@devicechain/widget-sdk';\n\nexport interface LevelStrings {\n // No sample for the bound measurement yet.\n noData: string;\n // A scale widget with no min/max configured.\n setRange: string;\n // max is not above min.\n badRange: string;\n // signal-bars with fewer thresholds than it needs bars.\n setThresholds: string;\n aboveScale: string;\n belowScale: string;\n on: string;\n off: string;\n // The four points of the compass, in N, E, S, W order (West is \"O\" in Spanish).\n cardinals: readonly [string, string, string, string];\n}\n\nexport const LEVEL_STRINGS: Record<'en' | 'es', LevelStrings> = {\n en: {\n noData: 'No data',\n setRange: 'Set min and max',\n badRange: 'Max must be above min',\n setThresholds: 'Set at least two thresholds',\n aboveScale: 'Above scale',\n belowScale: 'Below scale',\n on: 'On',\n off: 'Off',\n cardinals: ['N', 'E', 'S', 'W'],\n },\n es: {\n noData: 'Sin datos',\n setRange: 'Defina m\u00EDn. y m\u00E1x.',\n badRange: 'El m\u00E1x. debe superar el m\u00EDn.',\n setThresholds: 'Defina al menos dos umbrales',\n aboveScale: 'Sobre la escala',\n belowScale: 'Bajo la escala',\n on: 'Encendido',\n off: 'Apagado',\n cardinals: ['N', 'E', 'S', 'O'],\n },\n};\n\nexport function levelStrings(locale: string | undefined = viewerLocale()): LevelStrings {\n return locale?.toLowerCase().split('-')[0] === 'es' ? LEVEL_STRINGS.es : LEVEL_STRINGS.en;\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// compass \u2014 a heading (wind direction, bearing) as a needle on a full turn. North is at the top\n// and the angle runs clockwise, so 90 is east. A reading outside 0..360 folds onto the dial\n// (370 is 10, -90 is 270). The dial is the registered gauge series; the degrees and the nearest\n// of the eight points are DOM text beneath it, so the readability gate can measure them.\n\nimport { useMemo } from 'react';\n\nimport {\n optNumber,\n optString,\n optThresholds,\n WidgetFrame,\n type WidgetProps,\n type WidgetScale,\n} from '@devicechain/widget-sdk';\nimport { buildCompassOption, EChart, useChartTheme } from '@devicechain/widget-sdk/echarts';\n\nimport { cardinalOf, shownHeading } from '../heading';\nimport { emptyReason, useLevelReading, type LevelReading } from '../level-reading';\nimport { LevelEmpty, LevelReadout } from '../level-readout';\n\n// Whole degrees unless the options ask for more: a bearing is rarely good to a tenth.\nconst DEFAULT_PRECISION = 0;\n// The share of the box the readout strip takes; the dial keeps the rest.\nconst READOUT_SHARE = 0.22;\n\nexport function Compass({ widget, data }: WidgetProps) {\n const thresholds = useMemo(() => optThresholds(widget.options, 'thresholds'), [widget.options]);\n const precision = optNumber(widget.options, 'precision') ?? DEFAULT_PRECISION;\n const reading = useLevelReading(widget, data, {\n thresholds,\n unit: undefined,\n precision,\n normalize: (raw) => shownHeading(raw, precision),\n });\n const title = optString(widget.options, 'title') ?? reading.name;\n return (\n <WidgetFrame title={title} sampleTime={reading.sample?.occurredTime ?? null} flush>\n {(scale) => <CompassBody reading={reading} title={title} scale={scale} />}\n </WidgetFrame>\n );\n}\n\nfunction CompassBody({ reading: r, title, scale: ws }: { reading: LevelReading; title: string | undefined; scale: WidgetScale }) {\n const theme = useChartTheme();\n const option = useMemo(\n () => buildCompassOption(r.value ?? null, theme, { cardinals: r.strings.cardinals, thresholds: r.thresholds, scale: ws.scale }, ws.size),\n [r.value, theme, r.strings, r.thresholds, ws.scale, ws.size],\n );\n const reason = emptyReason(r);\n if (reason !== undefined || r.value === undefined) return <LevelEmpty message={reason ?? r.strings.noData} />;\n const point = cardinalOf(r.value, r.strings.cardinals);\n const stripHeight = Math.max(ws.px('font-md') * 1.6, ws.size.height * READOUT_SHARE);\n return (\n <div\n role=\"img\"\n aria-label={`${title ? `${title}, ` : ''}${r.display}\u00B0 ${point}`}\n data-threshold-level={r.band?.level}\n style={{ height: '100%', display: 'flex', flexDirection: 'column' }}\n >\n <div style={{ flex: '1 1 0', minHeight: 0 }}>\n <EChart option={option} />\n </div>\n <div style={{ height: stripHeight, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>\n <LevelReadout\n text={`${r.display}\u00B0`}\n unit={point}\n color={r.levelColor}\n size={{ width: ws.size.width, height: stripHeight }}\n scale={ws.scale}\n strings={r.strings}\n />\n </div>\n </div>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The compass's pure helpers: rounding a heading before it is folded onto 0..360, and naming the\n// eight-point direction it is nearest. React-free, so the rules are asserted by value.\n\nimport { wrapHeading } from '@devicechain/widget-sdk/echarts';\n\nimport type { LevelStrings } from './level-strings';\n\n// The heading a compass shows: rounded to `precision` places FIRST, then folded onto [0, 360).\n// In that order so 359.6 at whole degrees is 0, not a display of 360. A value that is not a\n// finite number has no heading (undefined).\nexport function shownHeading(raw: number | undefined, precision: number): number | undefined {\n if (raw === undefined || !Number.isFinite(raw)) return undefined;\n const places = Math.min(100, Math.max(0, Math.trunc(precision)));\n return wrapHeading(Number(raw.toFixed(places)));\n}\n\nconst EIGHT_POINT = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'] as const;\nconst LETTER_INDEX: Record<string, 0 | 1 | 2 | 3> = { N: 0, E: 1, S: 2, W: 3 };\n\n// The nearest of the eight points (N, NE, E, ...), written with the locale's letters.\nexport function cardinalOf(heading: number, letters: LevelStrings['cardinals']): string {\n const point = EIGHT_POINT[Math.round(heading / 45) % 8];\n return [...point].map((c) => letters[LETTER_INDEX[c]]).join('');\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// level-gauge \u2014 a tank: the current value of one measurement as how full a vessel is, between a\n// configured min (empty) and max (full). The liquid takes the colour of the threshold band the\n// value is in and keeps the widget's neutral accent in a `normal` band; the readout floats over\n// it, as the value or as a percent of the scale. All DOM, so the readability gate sees its text.\n\nimport { useMemo } from 'react';\n\nimport {\n css,\n formatValue,\n optNumber,\n optString,\n optThresholds,\n WidgetFrame,\n type WidgetProps,\n type WidgetScale,\n} from '@devicechain/widget-sdk';\n\nimport { emptyReason, useLevelReading, type LevelReading } from '../level-reading';\nimport { LevelEmpty, LevelReadout } from '../level-readout';\nimport { bandSpans, readRange } from '../value-scale';\n\n// The strength of a band the level is not in: the linear gauge's track strength.\nconst MUTED_BAND_OPACITY = 0.35;\n\nexport function LevelGauge({ widget, data }: WidgetProps) {\n const thresholds = useMemo(() => optThresholds(widget.options, 'thresholds'), [widget.options]);\n const reading = useLevelReading(widget, data, {\n thresholds,\n unit: optString(widget.options, 'unit'),\n precision: optNumber(widget.options, 'precision'),\n range: readRange(optNumber(widget.options, 'min'), optNumber(widget.options, 'max')),\n });\n const title = optString(widget.options, 'title') ?? reading.name;\n const percent = optString(widget.options, 'readout') === 'percent';\n return (\n <WidgetFrame title={title} sampleTime={reading.sample?.occurredTime ?? null}>\n {(scale) => <TankBody reading={reading} percent={percent} scale={scale} />}\n </WidgetFrame>\n );\n}\n\nfunction TankBody({ reading: r, percent, scale: ws }: { reading: LevelReading; percent: boolean; scale: WidgetScale }) {\n const reason = emptyReason(r);\n if (reason !== undefined || !r.range?.ok || !r.fill) return <LevelEmpty message={reason ?? r.strings.noData} />;\n const range = r.range.range;\n const fill = r.fill;\n const wall = 2;\n const stripe = ws.px('space-1');\n // The percent is of the scale and is NOT clamped: 130 % of a tank is the truth the marker flags.\n const text = percent ? `${formatValue(fill.ratio * 100, r.precision ?? 0)}` : r.display;\n const unit = percent ? '%' : r.unit;\n // A band is a SCALE MARKER until the level is in it: drawn muted, as the linear gauge draws its\n // track, so a full tank's low-fuel band does not read as a warning at a glance. The band the\n // level is in is drawn at full strength, agreeing with the liquid's colour.\n const bands = bandSpans(r.thresholds, range).flatMap((b) => {\n const color = r.colorOf(b.level);\n const active = fill.fraction >= b.from && (fill.fraction < b.to || (b.to >= 1 && fill.fraction >= 1));\n return color === undefined ? [] : [{ from: b.from, to: b.to, color, active }];\n });\n const inner = { width: Math.max(0, ws.size.width - wall * 2 - stripe), height: Math.max(0, ws.size.height - wall * 2) };\n return (\n <div\n data-threshold-level={r.band?.level}\n data-out-of-range={fill.position === 'within' ? undefined : fill.position}\n data-fill={fill.fraction}\n style={{ height: '100%', boxSizing: 'border-box', display: 'flex', gap: ws.px('space-1') }}\n >\n <div\n role=\"meter\"\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n aria-valuenow={range.min + fill.fraction * (range.max - range.min)}\n aria-valuetext={`${r.display}${r.unit ? ` ${r.unit}` : ''}`}\n style={{\n position: 'relative',\n flex: '1 1 0',\n minWidth: 0,\n overflow: 'hidden',\n boxSizing: 'border-box',\n border: `${wall}px solid ${css('border')}`,\n borderRadius: ws.px('space-2'),\n background: css('muted'),\n }}\n >\n <div\n data-liquid=\"\"\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n height: `${fill.fraction * 100}%`,\n background: r.fillColor,\n opacity: 0.55,\n borderTop: fill.fraction > 0 && fill.fraction < 1 ? `2px solid ${r.fillColor}` : undefined,\n }}\n />\n <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <LevelReadout\n text={text}\n unit={unit}\n color={r.levelColor}\n position={fill.position}\n size={inner}\n scale={ws.scale}\n strings={r.strings}\n />\n </div>\n </div>\n {/* The bands as a strip beside the tank, so the thresholds read against the level. */}\n <div style={{ position: 'relative', width: stripe, flexShrink: 0, borderRadius: stripe / 2, background: css('muted'), overflow: 'hidden' }}>\n {bands.map((b, i) => (\n <div\n key={i}\n data-band=\"\"\n data-band-active={b.active ? '' : undefined}\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: `${b.from * 100}%`,\n height: `${(b.to - b.from) * 100}%`,\n background: b.color,\n opacity: b.active ? 1 : MUTED_BAND_OPACITY,\n }}\n />\n ))}\n </div>\n </div>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// linear-gauge \u2014 the current value of one measurement on a straight scale: a horizontal or\n// vertical bar, or a thermometer (a vertical tube with a bulb). Threshold bands sit on the\n// track; the fill and the readout take the colour of the band the value is in, and keep the\n// widget's own neutral in a `normal` band. All DOM, so the readability gate measures its text.\n\nimport { useMemo } from 'react';\n\nimport {\n css,\n fontVar,\n formatValue,\n optNumber,\n optString,\n optThresholds,\n WidgetFrame,\n type WidgetProps,\n type WidgetScale,\n} from '@devicechain/widget-sdk';\n\nimport { emptyReason, useLevelReading, type LevelReading } from '../level-reading';\nimport { LevelEmpty, LevelReadout } from '../level-readout';\nimport { bandSpans, readRange } from '../value-scale';\n\nexport function LinearGauge({ widget, data }: WidgetProps) {\n const thresholds = useMemo(() => optThresholds(widget.options, 'thresholds'), [widget.options]);\n const reading = useLevelReading(widget, data, {\n thresholds,\n unit: optString(widget.options, 'unit'),\n precision: optNumber(widget.options, 'precision'),\n range: readRange(optNumber(widget.options, 'min'), optNumber(widget.options, 'max')),\n });\n const title = optString(widget.options, 'title') ?? reading.name;\n const thermometer = optString(widget.options, 'style') === 'thermometer';\n // A thermometer is always vertical; `orientation` applies to the bar.\n const vertical = thermometer || optString(widget.options, 'orientation') === 'vertical';\n return (\n <WidgetFrame title={title} sampleTime={reading.sample?.occurredTime ?? null}>\n {(scale) => <LinearBody reading={reading} thermometer={thermometer} vertical={vertical} scale={scale} />}\n </WidgetFrame>\n );\n}\n\ninterface BodyProps {\n reading: LevelReading;\n thermometer: boolean;\n vertical: boolean;\n scale: WidgetScale;\n}\n\nfunction LinearBody({ reading: r, thermometer, vertical, scale: ws }: BodyProps) {\n const reason = emptyReason(r);\n if (reason !== undefined || !r.range?.ok || !r.fill) return <LevelEmpty message={reason ?? r.strings.noData} />;\n const range = r.range.range;\n const fill = r.fill;\n const { size, scale } = ws;\n const thickness = ws.px('space-3');\n const gap = ws.px('space-2');\n const labelPx = ws.px('font-xs');\n const minText = formatValue(range.min, r.precision);\n const maxText = formatValue(range.max, r.precision);\n const bulb = thermometer ? thickness * 2 : 0;\n\n // Only coloured levels draw a band: `normal`, and the stretch below the lowest threshold,\n // stay the track's own neutral.\n const bands = bandSpans(r.thresholds, range).flatMap((b) => {\n const color = r.colorOf(b.level);\n return color === undefined ? [] : [{ from: b.from, to: b.to, color }];\n });\n const track = (\n <Track\n vertical={vertical}\n thickness={thickness}\n fraction={fill.fraction}\n color={r.fillColor}\n bands={bands}\n bulb={bulb}\n aria={{\n min: range.min,\n max: range.max,\n now: range.min + fill.fraction * (range.max - range.min),\n text: `${r.display}${r.unit ? ` ${r.unit}` : ''}`,\n }}\n />\n );\n const readout = (room: { width: number; height: number }) => (\n <LevelReadout\n text={r.display}\n unit={r.unit}\n color={r.levelColor}\n position={fill.position}\n size={room}\n scale={scale}\n strings={r.strings}\n />\n );\n const labelStyle = { fontSize: fontVar('xs'), color: css('muted-foreground'), lineHeight: 1.1 } as const;\n const root = {\n height: '100%',\n boxSizing: 'border-box',\n overflow: 'hidden',\n display: 'flex',\n gap,\n } as const;\n const marks = {\n 'data-threshold-level': r.band?.level,\n 'data-out-of-range': fill.position === 'within' ? undefined : fill.position,\n 'data-fill': fill.fraction,\n };\n\n if (!vertical) {\n // The readout on top, fitted to what the track and its end labels leave; the track under it.\n const trackRoom = thickness + labelPx * 1.4 + gap * 2;\n return (\n <div {...marks} style={{ ...root, flexDirection: 'column', justifyContent: 'safe center' }}>\n <div style={{ flex: '1 1 0', minHeight: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n {readout({ width: size.width, height: Math.max(0, size.height - trackRoom) })}\n </div>\n {track}\n <div style={{ display: 'flex', justifyContent: 'space-between', gap, ...labelStyle }}>\n <span>{minText}</span>\n <span>{maxText}</span>\n </div>\n </div>\n );\n }\n\n // Vertical: the end labels beside the tube (max on top), the readout in the room that is left.\n const labelRoom = Math.ceil(Math.max(minText.length, maxText.length) * labelPx * 0.62);\n const sideRoom = Math.max(thickness, bulb) + labelRoom + gap * 2;\n return (\n <div {...marks} style={{ ...root, flexDirection: 'row', alignItems: 'stretch' }}>\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n alignItems: 'flex-end',\n paddingBottom: bulb,\n ...labelStyle,\n }}\n >\n <span>{maxText}</span>\n <span>{minText}</span>\n </div>\n {track}\n <div style={{ flex: '1 1 0', minWidth: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n {readout({ width: Math.max(0, size.width - sideRoom), height: size.height })}\n </div>\n </div>\n );\n}\n\ninterface TrackProps {\n vertical: boolean;\n thickness: number;\n fraction: number;\n color: string;\n bands: { from: number; to: number; color: string }[];\n bulb: number;\n aria: { min: number; max: number; now: number; text: string };\n}\n\nfunction Track({ vertical, thickness, fraction, color, bands, bulb, aria }: TrackProps) {\n const pct = (f: number) => `${f * 100}%`;\n const radius = thickness / 2;\n const tube = (\n <div\n role=\"meter\"\n aria-valuemin={aria.min}\n aria-valuemax={aria.max}\n aria-valuenow={aria.now}\n aria-valuetext={aria.text}\n style={{\n position: 'relative',\n overflow: 'hidden',\n background: css('muted'),\n borderRadius: radius,\n flexShrink: 0,\n ...(vertical ? { width: thickness, flex: '1 1 0', minHeight: 0 } : { width: '100%', height: thickness }),\n }}\n >\n {bands.map((b, i) => (\n <div\n key={i}\n data-band=\"\"\n style={{\n position: 'absolute',\n background: b.color,\n opacity: 0.35,\n ...(vertical\n ? { left: 0, right: 0, bottom: pct(b.from), height: pct(b.to - b.from) }\n : { top: 0, bottom: 0, left: pct(b.from), width: pct(b.to - b.from) }),\n }}\n />\n ))}\n <div\n data-fill-bar=\"\"\n style={{\n position: 'absolute',\n background: color,\n ...(vertical\n ? { left: 0, right: 0, bottom: 0, height: pct(fraction) }\n : { top: 0, bottom: 0, left: 0, width: pct(fraction) }),\n }}\n />\n <div\n data-marker=\"\"\n style={{\n position: 'absolute',\n background: css('foreground'),\n ...(vertical\n ? { left: 0, right: 0, height: 2, bottom: `calc(${pct(fraction)} - 1px)` }\n : { top: 0, bottom: 0, width: 2, left: `calc(${pct(fraction)} - 1px)` }),\n }}\n />\n </div>\n );\n if (!vertical) return tube;\n // A vertical tube sits in a column of its own so a thermometer's bulb (wider than the tube)\n // can hang under it, overlapping its foot so the two read as one glass.\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', minHeight: 0, flex: '0 0 auto', width: Math.max(thickness, bulb) }}>\n {tube}\n {bulb > 0 ? (\n <div\n data-bulb=\"\"\n style={{ width: bulb, height: bulb, borderRadius: '50%', background: color, marginTop: -radius, flexShrink: 0 }}\n />\n ) : null}\n </div>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// progress-ring \u2014 how far one measurement has come between a configured min and max, as a ring\n// that fills clockwise from the top. The readout in the middle is the percent of the scale (or\n// the value itself, by option). The arc takes the colour of the threshold band the value is in\n// and keeps the neutral accent in a `normal` band. A value off the scale pins the ring to its\n// end and carries a marker beside the true reading. SVG and DOM, so the gate sees the text.\n\nimport { useMemo } from 'react';\n\nimport {\n css,\n formatValue,\n optNumber,\n optString,\n optThresholds,\n WidgetFrame,\n type WidgetProps,\n type WidgetScale,\n} from '@devicechain/widget-sdk';\n\nimport { emptyReason, useLevelReading, type LevelReading } from '../level-reading';\nimport { LevelEmpty, LevelReadout } from '../level-readout';\nimport { readRange } from '../value-scale';\n\n// The ring's geometry in its 100 x 100 viewBox.\nconst RING_RADIUS = 42;\nconst RING_STROKE = 10;\nexport const RING_CIRCUMFERENCE = 2 * Math.PI * RING_RADIUS;\n// The readout's room inside the ring, as a share of the side.\nconst INNER = { width: 0.62, height: 0.34 };\n\nexport function ProgressRing({ widget, data }: WidgetProps) {\n const thresholds = useMemo(() => optThresholds(widget.options, 'thresholds'), [widget.options]);\n const reading = useLevelReading(widget, data, {\n thresholds,\n unit: optString(widget.options, 'unit'),\n precision: optNumber(widget.options, 'precision'),\n range: readRange(optNumber(widget.options, 'min'), optNumber(widget.options, 'max')),\n });\n const title = optString(widget.options, 'title') ?? reading.name;\n const percent = optString(widget.options, 'readout') !== 'value';\n return (\n <WidgetFrame title={title} sampleTime={reading.sample?.occurredTime ?? null}>\n {(scale) => <RingBody reading={reading} percent={percent} scale={scale} />}\n </WidgetFrame>\n );\n}\n\nfunction RingBody({ reading: r, percent, scale: ws }: { reading: LevelReading; percent: boolean; scale: WidgetScale }) {\n const reason = emptyReason(r);\n if (reason !== undefined || !r.range?.ok || !r.fill) return <LevelEmpty message={reason ?? r.strings.noData} />;\n const range = r.range.range;\n const fill = r.fill;\n // The percent is of the scale and is NOT clamped: 150 % is the truth the marker flags.\n const text = percent ? formatValue(fill.ratio * 100, r.precision ?? 0) : r.display;\n const unit = percent ? '%' : r.unit;\n const side = Math.max(0, Math.min(ws.size.width, ws.size.height));\n return (\n <div\n role=\"meter\"\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n aria-valuenow={range.min + fill.fraction * (range.max - range.min)}\n aria-valuetext={`${r.display}${r.unit ? ` ${r.unit}` : ''}`}\n data-threshold-level={r.band?.level}\n data-out-of-range={fill.position === 'within' ? undefined : fill.position}\n data-fill={fill.fraction}\n style={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}\n >\n <div style={{ position: 'relative', width: side || '100%', height: side || '100%', aspectRatio: '1' }}>\n <svg viewBox=\"0 0 100 100\" width=\"100%\" height=\"100%\" aria-hidden=\"true\" style={{ display: 'block' }}>\n <circle cx=\"50\" cy=\"50\" r={RING_RADIUS} fill=\"none\" strokeWidth={RING_STROKE} style={{ stroke: css('muted') }} />\n <circle\n data-ring-fill=\"\"\n cx=\"50\"\n cy=\"50\"\n r={RING_RADIUS}\n fill=\"none\"\n strokeWidth={RING_STROKE}\n strokeDasharray={`${fill.fraction * RING_CIRCUMFERENCE} ${RING_CIRCUMFERENCE}`}\n transform=\"rotate(-90 50 50)\"\n style={{ stroke: r.fillColor }}\n />\n </svg>\n <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <LevelReadout\n text={text}\n unit={unit}\n color={r.levelColor}\n position={fill.position}\n size={{ width: side * INNER.width, height: side * INNER.height }}\n scale={ws.scale}\n strings={r.strings}\n />\n </div>\n </div>\n </div>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// signal-bars \u2014 a signal-strength glyph. The author's thresholds ARE the bars: one bar per\n// threshold, lit for each the value has reached, in the colour of the band the value is in\n// (neutral accent in a `normal` band). Nothing is assumed about the unit or the scale, so a dBm\n// board and a 0-31 CSQ board configure their own steps; with fewer than two thresholds there is\n// nothing to draw and the widget says so.\n\nimport { useMemo } from 'react';\n\nimport {\n css,\n optNumber,\n optString,\n optThresholds,\n WidgetFrame,\n type WidgetProps,\n type WidgetScale,\n} from '@devicechain/widget-sdk';\n\nimport { useLevelReading, type LevelReading } from '../level-reading';\nimport { LevelEmpty, LevelReadout } from '../level-readout';\nimport { litBars } from '../value-scale';\n\nexport const SIGNAL_MIN_BARS = 2;\n\nconst VIEW = { w: 100, h: 60 };\n\nexport function SignalBars({ widget, data }: WidgetProps) {\n const thresholds = useMemo(() => optThresholds(widget.options, 'thresholds'), [widget.options]);\n const reading = useLevelReading(widget, data, {\n thresholds,\n unit: optString(widget.options, 'unit'),\n precision: optNumber(widget.options, 'precision'),\n });\n const title = optString(widget.options, 'title') ?? reading.name;\n return (\n <WidgetFrame title={title} sampleTime={reading.sample?.occurredTime ?? null}>\n {(scale) => <BarsBody reading={reading} scale={scale} />}\n </WidgetFrame>\n );\n}\n\nfunction BarsBody({ reading: r, scale: ws }: { reading: LevelReading; scale: WidgetScale }) {\n if (r.thresholds.length < SIGNAL_MIN_BARS) return <LevelEmpty message={r.strings.setThresholds} />;\n const bars = litBars(r.thresholds, r.value);\n if (!bars) return <LevelEmpty message={r.strings.noData} />;\n const n = bars.total;\n // n bars and n-1 gaps of a third of a bar's width across the viewBox.\n const barW = VIEW.w / (n + (n - 1) / 3);\n const gapW = barW / 3;\n const readoutHeight = Math.max(ws.px('font-md') * 1.6, ws.size.height * 0.34);\n return (\n <div\n data-threshold-level={r.band?.level}\n data-bars-lit={bars.lit}\n data-bars-total={bars.total}\n style={{ height: '100%', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', gap: ws.px('space-1') }}\n >\n <div style={{ flex: '1 1 0', minHeight: 0 }}>\n <svg\n role=\"meter\"\n aria-valuemin={0}\n aria-valuemax={bars.total}\n aria-valuenow={bars.lit}\n aria-valuetext={`${bars.lit}/${bars.total}`}\n viewBox={`0 0 ${VIEW.w} ${VIEW.h}`}\n preserveAspectRatio=\"xMidYMax meet\"\n style={{ width: '100%', height: '100%', display: 'block' }}\n >\n {Array.from({ length: n }, (_, i) => {\n const h = (VIEW.h * (i + 1)) / n;\n const lit = i < bars.lit;\n return (\n <rect\n key={i}\n data-bar={lit ? 'lit' : 'unlit'}\n x={i * (barW + gapW)}\n y={VIEW.h - h}\n width={barW}\n height={h}\n rx={Math.min(3, barW / 3)}\n style={{ fill: lit ? r.fillColor : css('muted') }}\n />\n );\n })}\n </svg>\n </div>\n <div style={{ flex: '0 0 auto', height: readoutHeight, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <LevelReadout\n text={r.display}\n unit={r.unit}\n color={r.levelColor}\n size={{ width: ws.size.width, height: readoutHeight }}\n scale={ws.scale}\n strings={r.strings}\n />\n </div>\n </div>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// status-light \u2014 an indicator lamp for one measurement. Without `onAt` the lamp is lit while a\n// value is present and takes the colour of the threshold band the value is in (neutral accent\n// in a `normal` band), captioned with the band's label or the formatted value. With `onAt` it\n// reads a 0/1-style signal: lit at or above `onAt`, dark below, captioned On/Off. No data is a\n// hollow lamp captioned as such, never \"off\", which would be a claim about the device.\n\nimport { useMemo } from 'react';\n\nimport {\n css,\n fontVar,\n optNumber,\n optString,\n optThresholds,\n WidgetFrame,\n type WidgetProps,\n type WidgetScale,\n} from '@devicechain/widget-sdk';\n\nimport { useLevelReading, type LevelReading } from '../level-reading';\n\nexport function StatusLight({ widget, data }: WidgetProps) {\n const thresholds = useMemo(() => optThresholds(widget.options, 'thresholds'), [widget.options]);\n const reading = useLevelReading(widget, data, {\n thresholds,\n unit: optString(widget.options, 'unit'),\n precision: optNumber(widget.options, 'precision'),\n });\n const title = optString(widget.options, 'title') ?? reading.name;\n const onAt = optNumber(widget.options, 'onAt');\n return (\n <WidgetFrame title={title} sampleTime={reading.sample?.occurredTime ?? null}>\n {(scale) => <LampBody reading={reading} onAt={onAt} scale={scale} />}\n </WidgetFrame>\n );\n}\n\n// What the lamp shows, decided once so the drawing and the tests agree.\nexport function lampState(r: LevelReading, onAt: number | undefined): { lit: boolean | undefined; caption: string } {\n if (r.value === undefined) return { lit: undefined, caption: r.strings.noData };\n const lit = onAt === undefined ? true : r.value >= onAt;\n const fallback = onAt === undefined ? `${r.display}${r.unit ? ` ${r.unit}` : ''}` : lit ? r.strings.on : r.strings.off;\n return { lit, caption: r.band?.label ?? fallback };\n}\n\nfunction LampBody({ reading: r, onAt, scale: ws }: { reading: LevelReading; onAt: number | undefined; scale: WidgetScale }) {\n const { lit, caption } = lampState(r, onAt);\n const captionRoom = ws.px('font-md') * 2.8;\n const smallest = ws.px('space-4');\n const measured = ws.size.width > 0 && ws.size.height > 0;\n // The caption goes UNDER the lamp while there is room for a lamp twice its smallest size and a\n // caption; below that (the 2x2 minimum with a subject line and a freshness footer, at the\n // smallest cell) it goes BESIDE it, on one line, so the minimum the descriptor declares holds\n // its whole content rather than pushing the caption out of the box.\n const beside = measured && ws.size.height - captionRoom < smallest * 2;\n const diameter = !measured\n ? smallest * 3\n : beside\n ? Math.max(Math.min(smallest, ws.size.height), Math.floor(Math.min(ws.size.height, ws.size.width * 0.4) * 0.8))\n : Math.max(smallest, Math.floor(Math.min(ws.size.width, ws.size.height - captionRoom) * 0.8));\n const color = r.fillColor;\n return (\n <div\n data-threshold-level={lit ? r.band?.level : undefined}\n data-lit={lit === undefined ? undefined : String(lit)}\n data-lamp-layout={beside ? 'beside' : 'under'}\n style={{\n height: '100%',\n boxSizing: 'border-box',\n overflow: 'hidden',\n display: 'flex',\n flexDirection: beside ? 'row' : 'column',\n alignItems: 'center',\n justifyContent: 'safe center',\n gap: ws.px('space-2'),\n textAlign: 'center',\n }}\n >\n <div\n data-lamp=\"\"\n style={{\n width: diameter,\n height: diameter,\n flexShrink: 0,\n borderRadius: '50%',\n boxSizing: 'border-box',\n background: lit ? color : 'transparent',\n border: `2px solid ${lit ? color : css('muted-foreground')}`,\n boxShadow: lit ? `0 0 ${Math.round(diameter / 4)}px ${color}` : 'none',\n }}\n />\n <div\n data-lamp-caption=\"\"\n style={{\n fontSize: fontVar('md'),\n fontWeight: 600,\n lineHeight: 1.2,\n color: lit === undefined ? css('muted-foreground') : css('foreground'),\n overflowWrap: 'anywhere',\n maxWidth: '100%',\n minWidth: 0,\n }}\n >\n {caption}\n </div>\n </div>\n );\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["css", "css", "useMemo", "optNumber", "optString", "optThresholds", "WidgetFrame", "jsx", "jsxs", "useMemo", "optThresholds", "optNumber", "optString", "WidgetFrame", "useMemo", "css", "formatValue", "optNumber", "optString", "optThresholds", "WidgetFrame", "jsx", "jsxs", "useMemo", "optThresholds", "optString", "optNumber", "WidgetFrame", "formatValue", "css", "useMemo", "css", "formatValue", "optNumber", "optString", "optThresholds", "WidgetFrame", "jsx", "jsxs", "useMemo", "optThresholds", "optString", "optNumber", "WidgetFrame", "formatValue", "css", "useMemo", "css", "formatValue", "optNumber", "optString", "optThresholds", "WidgetFrame", "jsx", "jsxs", "useMemo", "optThresholds", "optString", "optNumber", "WidgetFrame", "formatValue", "css", "useMemo", "css", "optNumber", "optString", "optThresholds", "WidgetFrame", "jsx", "jsxs", "VIEW", "useMemo", "optThresholds", "optString", "optNumber", "WidgetFrame", "css", "useMemo", "css", "fontVar", "optNumber", "optString", "optThresholds", "WidgetFrame", "jsx", "jsxs", "useMemo", "optThresholds", "optString", "optNumber", "WidgetFrame", "css", "fontVar"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/widgets/device-status.tsx", "../../src/presence-model.ts", "../../src/presence-strings.ts", "../../src/widgets/online-doughnut.tsx", "../../src/presence-feed.tsx"],
|
|
4
|
-
"sourcesContent": ["// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// device-status -- one device's connectivity: Online or Offline in words, and when it was last seen.\n// It reads device-state through the presence feed (presence-feed.tsx), not the device's readings.\n//\n// - ISA-101: the normal state is neutral. Online keeps the foreground; only Offline takes a colour,\n// and the word says which, so colour is never the only signal;\n// - a device with no state row has never sent anything: it reads \"No status yet\", muted, and is not\n// painted as an outage;\n// - \"last seen\" is the device's last activity. The frame's age readout is the age of the STATUS\n// (when device-state was last read), with a stale badge past `staleAfterSeconds` -- never the\n// device's silence, which would grey out the very Offline it explains (presence-feed.tsx);\n// - the card shows ONE device: a group reaching it is refused in words, with where the group can be shown.\n//\n// DOM text, so the readability gate sees it.\n\nimport {\n css,\n FIT_MIN_FONT_PX,\n fontVar,\n levelColor,\n optString,\n spaceVar,\n useSeverityColors,\n viewerLocale,\n WidgetFrame,\n type WidgetProps,\n} from '@devicechain/widget-sdk';\n\nimport { fleetStrings } from '../fleet-strings';\nimport { LevelEmpty, LevelReadout } from '../level-readout';\nimport { lastActivityMs, presenceKind } from '../presence-model';\nimport { presenceStrings } from '../presence-strings';\n\n// The level an offline device is drawn at: attention, short of the alarm a rule would raise.\nexport const OFFLINE_LEVEL = 'major' as const;\n\n// The room the caption line needs, before the density scale.\nconst CAPTION_ROOM_PX = 22;\n\n// \"Oct 21, 2026, 10:32 AM\" in the viewer's language; an unparseable <html lang> falls back to the runtime's.\nexport function formatLastSeen(at: number, locale: string | undefined = viewerLocale()): string {\n try {\n return new Intl.DateTimeFormat(locale, { dateStyle: 'medium', timeStyle: 'short' }).format(at);\n } catch {\n return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(at);\n }\n}\n\nexport function DeviceStatus({ widget, data }: WidgetProps) {\n const strings = presenceStrings();\n const fleet = fleetStrings();\n const severity = useSeverityColors();\n const feed = data.members;\n const title = optString(widget.options, 'title');\n\n const empty = (message: string) => (\n <WidgetFrame title={title}>\n <LevelEmpty message={message} />\n </WidgetFrame>\n );\n if (!feed || feed.status === 'loading') return empty(fleet.loading);\n if (feed.status === 'unbound') return empty(strings.unbound);\n if (feed.status === 'forbidden') return empty(fleet.forbidden);\n if (feed.status === 'unsupported') return empty(strings.unsupported);\n if (feed.members.length === 0) return empty(fleet.noMembers);\n if (feed.members.length > 1 || feed.total > 1) return empty(`${strings.oneDevice} ${strings.useDoughnut}`);\n\n const presence = feed.members[0].presence;\n const kind = presenceKind(presence);\n if (kind === 'pending') return empty(fleet.loading);\n if (kind === 'failed') return empty(strings.failed);\n\n const figure = kind === 'online' ? strings.online : kind === 'offline' ? strings.offline : strings.unknown;\n const color = kind === 'offline' ? levelColor(severity, OFFLINE_LEVEL) : kind === 'unknown' ? css('muted-foreground') : undefined;\n const seen = lastActivityMs(presence);\n const caption = seen !== undefined ? strings.lastSeen(formatLastSeen(seen)) : strings.neverSeen;\n\n return (\n <WidgetFrame title={title}>\n {({ size, scale }) => {\n const room = Math.round(CAPTION_ROOM_PX * scale);\n const fit = { width: size.width, height: Math.max(Math.round(FIT_MIN_FONT_PX * scale), size.height - room) };\n return (\n <div\n data-device-status={kind}\n style={{ display: 'flex', flexDirection: 'column', justifyContent: 'safe center', height: '100%', overflow: 'hidden' }}\n >\n <div style={{ flex: '1 1 0', minHeight: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <LevelReadout text={figure} color={color} size={fit} scale={scale} />\n </div>\n <div\n data-device-status-caption=\"\"\n style={{\n flex: '0 0 auto',\n marginTop: spaceVar(1),\n textAlign: 'center',\n fontSize: fontVar('sm'),\n color: css('muted-foreground'),\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {caption}\n </div>\n </div>\n );\n }}\n </WidgetFrame>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// What the device status card and the online doughnut say, decided apart from the drawing. Pure, so\n// each rule is a test.\n//\n// - a device is ONLINE when device-state considers it connected, and OFFLINE when it does not.\n// Which of the two it is comes from the platform (an inferred device goes offline after its\n// inactivity timeout; an asserted one follows its transport's connect and disconnect), never\n// from this widget's idea of how long is too long;\n// - a device with NO state row has never sent anything: it is neither online nor offline, and is\n// counted apart (\"no status yet\"), never folded into the offline figure -- a device that was never\n// commissioned is not an outage;\n// - a member whose read is still pending, or failed, is counted apart again. While any is pending\n// there is no tally: a share over the members read so far would be an answer that looks final;\n// - \"last seen\" is the device's last activity (device-state's lastActivityTime), the time of its\n// newest event, not the time it was last marked connected.\n\nimport type { FleetMember, MemberPresence } from '@devicechain/dashboards';\n\nexport type PresenceKind = 'online' | 'offline' | 'unknown' | 'pending' | 'failed';\n\nexport function presenceKind(presence: MemberPresence | undefined): PresenceKind {\n if (!presence) return 'pending';\n if (presence.status === 'ready') return presence.active ? 'online' : 'offline';\n return presence.status;\n}\n\n// The device's last activity (epoch ms), or undefined when it has none or it does not parse.\nexport function lastActivityMs(presence: MemberPresence | undefined): number | undefined {\n if (presence?.status !== 'ready' || !presence.lastActivityTime) return undefined;\n const at = Date.parse(presence.lastActivityTime);\n return Number.isNaN(at) ? undefined : at;\n}\n\nexport interface PresenceTally {\n online: number;\n offline: number;\n // No state row: the device has never sent anything.\n unknown: number;\n pending: number;\n failed: number;\n // The newest last-activity time among the members (epoch ms), when any has one.\n newest: number | undefined;\n}\n\nexport function tallyPresence(members: readonly FleetMember[]): PresenceTally {\n const tally: PresenceTally = { online: 0, offline: 0, unknown: 0, pending: 0, failed: 0, newest: undefined };\n for (const m of members) {\n tally[presenceKind(m.presence)]++;\n const at = lastActivityMs(m.presence);\n if (at !== undefined && (tally.newest === undefined || at > tally.newest)) tally.newest = at;\n }\n return tally;\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The fixed words the device status card and the online doughnut render themselves. The widget\n// packages carry no i18n runtime, so this is the one small per-language table (modelled on\n// fleet-strings.ts); option labels are translated in the console's catalogs, not here.\n\nimport { viewerLocale } from '@devicechain/widget-sdk';\n\nexport interface PresenceStrings {\n online: string;\n offline: string;\n // The device has never sent anything, so device-state holds no row for it.\n unknown: string;\n neverSeen: string;\n lastSeen: (when: string) => string;\n failed: string;\n unsupported: string;\n // The card is bound to a slot with nothing chosen in it yet.\n unbound: string;\n // The card is bound to a group: it shows one device.\n oneDevice: string;\n useDoughnut: string;\n // The doughnut's figure and its caption.\n ofTotal: (total: number) => string;\n onlineCaption: string;\n notRead: (n: number) => string;\n noStatusYet: (n: number) => string;\n chartLabel: (online: number, offline: number, unknown: number) => string;\n}\n\nexport const PRESENCE_STRINGS: Record<'en' | 'es', PresenceStrings> = {\n en: {\n online: 'Online',\n offline: 'Offline',\n unknown: 'No status yet',\n neverSeen: 'Never seen',\n lastSeen: (when) => `Last seen ${when}`,\n failed: 'Status could not be read',\n unsupported: 'This data source cannot read device status',\n unbound: 'Choose a device for this widget',\n oneDevice: 'This card shows one device, and it is bound to a group.',\n useDoughnut: 'Bind it to one device, or show the group in an online / offline doughnut.',\n ofTotal: (total) => `of ${total}`,\n onlineCaption: 'online',\n notRead: (n) => `${n} could not be read`,\n noStatusYet: (n) => `${n} with no status yet`,\n chartLabel: (online, offline, unknown) => `${online} online, ${offline} offline, ${unknown} with no status yet`,\n },\n es: {\n online: 'En l\u00EDnea',\n offline: 'Sin conexi\u00F3n',\n unknown: 'Sin estado todav\u00EDa',\n neverSeen: 'Nunca visto',\n lastSeen: (when) => `Visto por \u00FAltima vez ${when}`,\n failed: 'No se pudo leer el estado',\n unsupported: 'Esta fuente de datos no puede leer el estado de los dispositivos',\n unbound: 'Elija un dispositivo para este widget',\n oneDevice: 'Esta tarjeta muestra un solo dispositivo y est\u00E1 vinculada a un grupo.',\n useDoughnut: 'Vinc\u00FAlela a un dispositivo o muestre el grupo en un anillo de conectados / desconectados.',\n ofTotal: (total) => `de ${total}`,\n onlineCaption: 'en l\u00EDnea',\n notRead: (n) => `${n} sin leer`,\n noStatusYet: (n) => `${n} sin estado todav\u00EDa`,\n chartLabel: (online, offline, unknown) => `${online} en l\u00EDnea, ${offline} sin conexi\u00F3n, ${unknown} sin estado todav\u00EDa`,\n },\n};\n\nexport function presenceStrings(locale: string | undefined = viewerLocale()): PresenceStrings {\n return locale?.toLowerCase().split('-')[0] === 'es' ? PRESENCE_STRINGS.es : PRESENCE_STRINGS.en;\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// online-doughnut -- how many of a group's devices are online: a ring of online, offline and\n// \"no status yet\", with the online count in the middle and every figure in a legend. Reads\n// device-state through the presence feed (presence-feed.tsx).\n//\n// - ISA-101: the normal state is neutral. Online is the quiet grey that fills most of a healthy\n// ring; only the offline slice takes a colour, and the legend names every count, so colour is\n// never the only signal. A group with nothing offline draws no colour at all;\n// - a device with no state row has never sent anything: its own pale slice (\"no status yet\"), not\n// offline. A device whose read failed is noted apart and left out of the ring;\n// - while any member's read is pending there is no ring: a share over the members read so far would\n// be an answer that looks final;\n// - a group larger than the feed reads says so (\"Showing 500 of 812 devices\") instead of presenting\n// the subset as the fleet.\n//\n// Drawn as SVG strokes with the figures as DOM text (the readability gate sees it).\n\nimport {\n css,\n FIT_MIN_FONT_PX,\n fontVar,\n levelColor,\n optString,\n spaceVar,\n useSeverityColors,\n WidgetFrame,\n type WidgetProps,\n} from '@devicechain/widget-sdk';\n\nimport { arcPath } from '../category-geometry';\nimport { fleetStrings } from '../fleet-strings';\nimport { LevelEmpty } from '../level-readout';\nimport { tallyPresence } from '../presence-model';\nimport { presenceStrings } from '../presence-strings';\nimport { OFFLINE_LEVEL } from './device-status';\n\n// The ring, in a 100-unit box.\nconst RADIUS = 38;\nconst THICKNESS = 14;\n// How much of the online grey the no-status slice keeps.\nconst UNKNOWN_OPACITY = 0.3;\n// The room one legend line needs below the ring, before the density scale.\nconst LEGEND_LINE_PX = 18;\n\nexport function OnlineDoughnut({ widget, data }: WidgetProps) {\n const strings = presenceStrings();\n const fleet = fleetStrings();\n const severity = useSeverityColors();\n const feed = data.members;\n const title = optString(widget.options, 'title');\n\n const empty = (message: string) => (\n <WidgetFrame title={title}>\n <LevelEmpty message={message} />\n </WidgetFrame>\n );\n if (!feed || feed.status === 'loading') return empty(fleet.loading);\n if (feed.status === 'unbound') return empty(fleet.unbound);\n if (feed.status === 'forbidden') return empty(fleet.forbidden);\n if (feed.status === 'unsupported') return empty(strings.unsupported);\n if (feed.members.length === 0) return empty(fleet.noMembers);\n const tally = tallyPresence(feed.members);\n // A share over the members read so far would be an undercount that looks like an answer.\n if (tally.pending > 0) return empty(fleet.loading);\n const counted = tally.online + tally.offline + tally.unknown;\n if (counted === 0) return empty(strings.failed);\n\n const offlineColor = levelColor(severity, OFFLINE_LEVEL) ?? css('foreground');\n const segments = [\n { kind: 'online', count: tally.online, stroke: css('muted-foreground'), opacity: 1, label: strings.online },\n { kind: 'offline', count: tally.offline, stroke: offlineColor, opacity: 1, label: strings.offline },\n // The same neutral as online, pale: a device we know nothing of is less than one that is connected.\n { kind: 'unknown', count: tally.unknown, stroke: css('muted-foreground'), opacity: UNKNOWN_OPACITY, label: strings.unknown },\n ];\n let at = 0;\n const arcs = segments.map((s) => {\n const from = at;\n at += s.count / counted;\n return { ...s, from, to: at };\n });\n // Online and offline always have a line (a zero is an answer); no-status only when some device has none.\n const legend = arcs.filter((a) => a.kind !== 'unknown' || a.count > 0);\n const notes: string[] = [];\n if (tally.failed > 0) notes.push(strings.notRead(tally.failed));\n if (feed.truncated) notes.push(fleet.truncated(feed.members.length, feed.total));\n\n return (\n <WidgetFrame title={title}>\n {({ size, scale }) => {\n const legendRoom = Math.round(LEGEND_LINE_PX * scale) * (legend.length + notes.length);\n const box = Math.max(0, Math.min(size.width, size.height - legendRoom));\n const figure = Math.max(Math.round(FIT_MIN_FONT_PX * scale), Math.round(box * 0.2));\n return (\n <div\n data-online-doughnut=\"\"\n data-online={tally.online}\n data-offline={tally.offline}\n data-no-status={tally.unknown}\n style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden', gap: spaceVar(1) }}\n >\n <div style={{ position: 'relative', flex: '1 1 0', minHeight: 0 }}>\n <svg\n data-doughnut=\"\"\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"xMidYMid meet\"\n role=\"img\"\n aria-label={strings.chartLabel(tally.online, tally.offline, tally.unknown)}\n style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block' }}\n >\n {arcs.map((a) => {\n if (a.count === 0) return null;\n const common = { fill: 'none', stroke: a.stroke, strokeWidth: THICKNESS, strokeOpacity: a.opacity } as const;\n const d = arcPath(50, 50, RADIUS, a.from, a.to);\n return d ? (\n <path key={a.kind} data-segment={a.kind} data-count={a.count} d={d} style={common} />\n ) : (\n <circle key={a.kind} data-segment={a.kind} data-count={a.count} cx={50} cy={50} r={RADIUS} style={common} />\n );\n })}\n </svg>\n <div\n data-doughnut-figure=\"\"\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n fontVariantNumeric: 'tabular-nums',\n pointerEvents: 'none',\n }}\n >\n <span style={{ fontSize: figure, fontWeight: 600, lineHeight: 1.1, color: css('foreground') }}>{tally.online}</span>\n <span style={{ fontSize: fontVar('xs'), color: css('muted-foreground') }}>{`${strings.ofTotal(counted)} ${strings.onlineCaption}`}</span>\n </div>\n </div>\n <ul\n data-doughnut-legend=\"\"\n style={{ flex: '0 0 auto', margin: 0, padding: 0, listStyle: 'none', fontSize: fontVar('xs'), color: css('muted-foreground') }}\n >\n {legend.map((a) => (\n <li key={a.kind} data-legend={a.kind} style={{ display: 'flex', alignItems: 'center', gap: spaceVar(1), whiteSpace: 'nowrap', overflow: 'hidden' }}>\n <span\n aria-hidden=\"true\"\n style={{\n flex: '0 0 auto',\n width: '0.7em',\n height: '0.7em',\n borderRadius: '50%',\n background: a.stroke,\n opacity: a.opacity,\n }}\n />\n <span style={{ flex: '1 1 auto', overflow: 'hidden', textOverflow: 'ellipsis' }}>{a.label}</span>\n <span style={{ color: a.kind === 'offline' && a.count > 0 ? offlineColor : css('foreground'), fontVariantNumeric: 'tabular-nums' }}>{a.count}</span>\n </li>\n ))}\n {notes.map((note) => (\n <li key={note} data-doughnut-note=\"\" style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>\n {note}\n </li>\n ))}\n </ul>\n </div>\n );\n }}\n </WidgetFrame>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The data feed of a presence widget (the device status card, the online doughnut): the roster of\n// the datasource, then device-state's connectivity for it on a poll. Loaded on first use\n// (connected-widget.tsx imports it dynamically), so a board with no presence widget never downloads it.\n//\n// It hands the widget the SAME `data.members` a fleet widget reads, with each member's `presence`\n// filled and no readings -- connectivity folded into the measurement channel's member feed rather than\n// a channel of its own, so the exported channel union does not move.\n//\n// - ONE subscription per widget (hub.subscribePresence), one batch read per poll however many members;\n// - a member the snapshot does not carry has no state row (it has never sent anything): `unknown`,\n// a settled answer, never `pending`;\n// - a read that fails before any snapshot has landed leaves every member `failed`; once one has, a\n// later blip keeps the last good answer (the poll heals it), as the alarm and location channels do;\n// - a paused board holds the snapshot on screen (useHeld) rather than moving under a \"Paused\" badge;\n// - the frame's freshness is the age of the STATUS -- when device-state was last read successfully --\n// not the devices' last activity. What these widgets show is the platform's verdict (online or\n// offline), and that verdict is current as long as it keeps being read: an offline device is silent\n// by definition, and an asserted device can be connected and quiet, so greying a card out for the\n// device's silence would strip the one colour an outage takes, or grey out a true \"Online\". A read\n// that keeps failing is what makes the answer old, and that is what goes stale. \"Last seen\" (the\n// device's last activity) is the widget's own caption.\n\nimport {\n type DevicePresence,\n type FleetMember,\n type FleetState,\n type MeasurementStreamState,\n type MemberRoster,\n type WidgetActions,\n type WidgetDataSource,\n type WidgetDescriptor,\n type WidgetInstance,\n} from '@devicechain/dashboards';\nimport { resolveStaleAfterSeconds, useWidgetTimeRange, WidgetFreshnessProvider } from '@devicechain/widget-sdk';\nimport { useEffect, useMemo, useState, type ComponentType } from 'react';\n\nimport { useHeld } from './use-held';\n\nexport interface PresenceFeedProps {\n hub: WidgetDataSource;\n widget: WidgetInstance;\n descriptor: WidgetDescriptor;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Component: ComponentType<any>;\n actions: WidgetActions | undefined;\n ErrorFrame: ComponentType<{ widget: WidgetInstance; error: unknown }>;\n}\n\ninterface Store {\n // The selector this store was filled for: a render carrying a new selector must not show the\n // previous one's members under it while the effect that resets the store has yet to run.\n key: string | null;\n roster: MemberRoster | null;\n states: Map<string, DevicePresence> | null;\n forbidden: boolean;\n error: unknown | null;\n // When the last snapshot landed (epoch ms): the age of the status on screen.\n readAt: number | null;\n}\n\nconst emptyStore = (key: string | null): Store => ({ key, roster: null, states: null, forbidden: false, error: null, readAt: null });\n\n// The state a presence widget renders from, built from the store. Exported for the tests.\nexport function buildPresenceFleet(store: Pick<Store, 'roster' | 'states' | 'forbidden' | 'error'>): FleetState {\n if (store.forbidden) return { status: 'forbidden', members: [], total: 0, truncated: false };\n if (!store.roster) return { status: 'loading', members: [], total: 0, truncated: false };\n if (store.roster.unbound) return { status: 'unbound', members: [], total: 0, truncated: false };\n const { states, error } = store;\n const members = store.roster.members.map((ref): FleetMember => {\n const state = states?.get(ref.token);\n return {\n token: ref.token,\n name: ref.name,\n latest: {},\n seed: 'ready',\n observed: [],\n presence: state\n ? { status: 'ready', active: state.active, lastActivityTime: state.lastActivityTime, inactivityTimeout: state.inactivityTimeout }\n : states\n ? { status: 'unknown' }\n : error\n ? { status: 'failed' }\n : { status: 'pending' },\n };\n });\n return { status: 'ready', members, total: store.roster.total, truncated: store.roster.total > members.length };\n}\n\nexport default function PresenceFeed({ hub, widget, descriptor, Component, actions }: PresenceFeedProps) {\n const range = useWidgetTimeRange();\n const ds = widget.datasource;\n const dsKey = JSON.stringify(ds ?? null);\n const supported = hub.subscribePresence !== undefined;\n const [store, setStore] = useState<Store>(() => emptyStore(dsKey));\n\n useEffect(() => {\n setStore(emptyStore(dsKey));\n if (!ds || !supported) return;\n return hub.subscribePresence!(ds, {\n roster: (roster) => setStore((s) => ({ ...s, roster })),\n next: (states) => setStore((s) => ({ ...s, states: new Map(states.map((p) => [p.deviceToken, p])), error: null, readAt: Date.now() })),\n forbidden: () => setStore((s) => ({ ...s, forbidden: true })),\n error: (error) => setStore((s) => ({ ...s, error })),\n });\n // `ds` is read through `dsKey` (value identity), not by reference.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hub, dsKey, supported]);\n\n const live = useMemo<{ fleet: FleetState; readAt: number | null }>(() => {\n if (!supported) return { fleet: { status: 'unsupported', members: [], total: 0, truncated: false }, readAt: null };\n const current = store.key === dsKey ? store : emptyStore(dsKey);\n return { fleet: buildPresenceFleet(current), readAt: current.readAt };\n }, [store, dsKey, supported]);\n // Held together, so a paused board's frame ages from the snapshot it is showing.\n const held = useHeld(live, range?.paused === true, (s) => s.fleet.status !== 'loading');\n const members = held.fleet;\n\n const freshness = useMemo(\n () =>\n descriptor.freshness === true\n ? { at: held.readAt ?? undefined, staleAfterSeconds: resolveStaleAfterSeconds(widget.options) }\n : undefined,\n [descriptor, widget.options, held.readAt],\n );\n const data: MeasurementStreamState = { latest: {}, samples: [], error: null, members };\n return (\n <WidgetFreshnessProvider freshness={freshness}>\n <Component widget={widget} data={data} actions={actions} />\n </WidgetFreshnessProvider>\n );\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["viewerLocale", "viewerLocale", "css", "FIT_MIN_FONT_PX", "fontVar", "levelColor", "optString", "spaceVar", "useSeverityColors", "WidgetFrame", "jsx", "jsxs", "useSeverityColors", "optString", "WidgetFrame", "levelColor", "css", "FIT_MIN_FONT_PX", "spaceVar", "fontVar", "jsx"]
|
|
7
|
-
}
|
|
File without changes
|
/package/dist/chunks/{event-markers-feed-GEGTIHXT.js.map → event-markers-feed-B3MVFYUT.js.map}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|