@devicechain/widgets 0.24.0 → 0.25.0-rc.2

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.
Files changed (67) hide show
  1. package/README.md +11 -1
  2. package/dist/absolute-range-picker.d.ts +22 -0
  3. package/dist/binding-policy.d.ts +1 -0
  4. package/dist/builtin-descriptors.d.ts +69 -0
  5. package/dist/builtin-registry.d.ts +68 -0
  6. package/dist/chunks/absolute-range-picker-E57G2TPX.js +139 -0
  7. package/dist/chunks/absolute-range-picker-E57G2TPX.js.map +7 -0
  8. package/dist/chunks/{aggregate-feed-4FSBQYJL.js → aggregate-feed-XX36GNY6.js} +2 -2
  9. package/dist/chunks/{aggregate-widgets-2ZQBW3YF.js → aggregate-widgets-72HMPMBU.js} +99 -57
  10. package/dist/chunks/aggregate-widgets-72HMPMBU.js.map +7 -0
  11. package/dist/chunks/{chunk-USRYKW2J.js → chunk-7BUCJQFP.js} +10 -2
  12. package/dist/chunks/chunk-7BUCJQFP.js.map +7 -0
  13. package/dist/chunks/chunk-AF4M5OXQ.js +23 -0
  14. package/dist/chunks/chunk-AF4M5OXQ.js.map +7 -0
  15. package/dist/chunks/{chunk-XQQQNTBX.js → chunk-EQOWBDS7.js} +1 -1
  16. package/dist/chunks/{chunk-XQQQNTBX.js.map → chunk-EQOWBDS7.js.map} +1 -1
  17. package/dist/chunks/chunk-JVC6JYUR.js +48 -0
  18. package/dist/chunks/chunk-JVC6JYUR.js.map +7 -0
  19. package/dist/chunks/{chunk-JFH4QMLA.js → chunk-NYHNQ5VR.js} +5 -1
  20. package/dist/chunks/{chunk-JFH4QMLA.js.map → chunk-NYHNQ5VR.js.map} +2 -2
  21. package/dist/chunks/chunk-VTGKDO44.js +87 -0
  22. package/dist/chunks/chunk-VTGKDO44.js.map +7 -0
  23. package/dist/chunks/chunk-XJ7UF2CP.js +90 -0
  24. package/dist/chunks/chunk-XJ7UF2CP.js.map +7 -0
  25. package/dist/chunks/{compare-feed-AY3CVKUZ.js → compare-feed-5OLZHFRL.js} +48 -23
  26. package/dist/chunks/compare-feed-5OLZHFRL.js.map +7 -0
  27. package/dist/chunks/{event-markers-feed-GEGTIHXT.js → event-markers-feed-B3MVFYUT.js} +4 -4
  28. package/dist/chunks/export-rows-OEWIBIUY.js +11 -0
  29. package/dist/chunks/{fleet-feed-2SKDR6ZQ.js → fleet-feed-D4T3LC25.js} +10 -10
  30. package/dist/chunks/history-widgets-NSNXDKEC.js +336 -0
  31. package/dist/chunks/history-widgets-NSNXDKEC.js.map +7 -0
  32. package/dist/chunks/{level-widgets-MJB7TOLU.js → level-widgets-HE6EDSWC.js} +13 -9
  33. package/dist/chunks/level-widgets-HE6EDSWC.js.map +7 -0
  34. package/dist/chunks/no-reading-B4MPXAS2.js +22 -0
  35. package/dist/chunks/no-reading-B4MPXAS2.js.map +7 -0
  36. package/dist/chunks/{presence-widgets-2LIUKN4Y.js → presence-widgets-M5VGG3OO.js} +12 -8
  37. package/dist/chunks/presence-widgets-M5VGG3OO.js.map +7 -0
  38. package/dist/chunks/table-CEVB3JZS.js +8 -0
  39. package/dist/chunks/table-CEVB3JZS.js.map +7 -0
  40. package/dist/compare-model.d.ts +1 -1
  41. package/dist/documented-descriptors.d.ts +206 -0
  42. package/dist/export-rows.d.ts +24 -0
  43. package/dist/history-feed.d.ts +10 -0
  44. package/dist/history-model.d.ts +45 -0
  45. package/dist/history-strings.d.ts +20 -0
  46. package/dist/index.d.ts +1 -1
  47. package/dist/index.js +544 -189
  48. package/dist/index.js.map +4 -4
  49. package/dist/level-reading.d.ts +1 -0
  50. package/dist/no-reading-core.d.ts +25 -0
  51. package/dist/no-reading.d.ts +10 -0
  52. package/dist/time-range-bar.d.ts +26 -2
  53. package/dist/widgets/history-lazy.d.ts +70 -0
  54. package/dist/widgets/history-table.d.ts +7 -0
  55. package/dist/widgets/history-widgets.d.ts +2 -0
  56. package/dist/widgets/no-reading-lazy.d.ts +7 -0
  57. package/package.json +8 -8
  58. package/dist/chunks/aggregate-widgets-2ZQBW3YF.js.map +0 -7
  59. package/dist/chunks/chunk-USRYKW2J.js.map +0 -7
  60. package/dist/chunks/compare-feed-AY3CVKUZ.js.map +0 -7
  61. package/dist/chunks/level-widgets-MJB7TOLU.js.map +0 -7
  62. package/dist/chunks/presence-widgets-2LIUKN4Y.js.map +0 -7
  63. package/dist/chunks/table-6EVV7QZH.js +0 -7
  64. /package/dist/chunks/{aggregate-feed-4FSBQYJL.js.map → aggregate-feed-XX36GNY6.js.map} +0 -0
  65. /package/dist/chunks/{event-markers-feed-GEGTIHXT.js.map → event-markers-feed-B3MVFYUT.js.map} +0 -0
  66. /package/dist/chunks/{table-6EVV7QZH.js.map → export-rows-OEWIBIUY.js.map} +0 -0
  67. /package/dist/chunks/{fleet-feed-2SKDR6ZQ.js.map → fleet-feed-D4T3LC25.js.map} +0 -0
@@ -0,0 +1,7 @@
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 { LevelReadout } from '../level-readout';\nimport { LevelEmptyFor } from '../no-reading';\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 <LevelEmptyFor reading={r} reason={reason} />;\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 // The widget's slot has no device bound: an empty reading then means \"choose one\".\n unbound: boolean;\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 unbound: widget.datasource?.kind === 'unbound',\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 CONFIGURATION reason a scale widget has nothing to draw, or undefined when its setup is fine.\n// The author's fix (the scale) is named before the absence of data, which resolves itself and is\n// explained apart (LevelEmptyFor).\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 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 { LevelReadout } from '../level-readout';\nimport { LevelEmptyFor } from '../no-reading';\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 <LevelEmptyFor reading={r} reason={reason} />;\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 { LevelReadout } from '../level-readout';\nimport { LevelEmptyFor } from '../no-reading';\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 <LevelEmptyFor reading={r} reason={reason} />;\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 { LevelReadout } from '../level-readout';\nimport { LevelEmptyFor } from '../no-reading';\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 <LevelEmptyFor reading={r} reason={reason} />;\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 { LevelReadout } from '../level-readout';\nimport { LevelEmptyFor } from '../no-reading';\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 <LevelEmptyFor reading={r} reason={reason} />;\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 { LevelEmptyFor } from '../no-reading';\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 <LevelEmptyFor reading={r} reason={undefined} />;\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": ";;;;;;;;;;;;;;;;AAQA,SAAS,eAAe;AAExB;AAAA,EACE,OAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;;;ACXP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;;;ACTP,SAAS,oBAAoB;AAmBtB,IAAM,gBAAmD;AAAA,EAC9D,IAAI;AAAA,IACF,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,UAAU;AAAA,IACV,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,IAAI;AAAA,IACJ,KAAK;AAAA,IACL,WAAW,CAAC,KAAK,KAAK,KAAK,GAAG;AAAA,EAChC;AAAA,EACA,IAAI;AAAA,IACF,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,UAAU;AAAA,IACV,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,IAAI;AAAA,IACJ,KAAK;AAAA,IACL,WAAW,CAAC,KAAK,KAAK,KAAK,GAAG;AAAA,EAChC;AACF;AAEO,SAAS,aAAa,SAA6B,aAAa,GAAiB;AACtF,SAAO,QAAQ,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC,MAAM,OAAO,cAAc,KAAK,cAAc;AACzF;;;ADMO,SAAS,gBAAgB,QAAwB,MAA8B,OAAiC;AACrH,QAAM,WAAW,kBAAkB;AACnC,QAAM,OAAO,uBAAuB,MAAM;AAC1C,QAAM,SAAS,WAAW,KAAK,QAAQ,IAAI;AAC3C,QAAM,EAAE,YAAY,MAAM,WAAW,OAAO,UAAU,IAAI;AAC1D,QAAM,MAAM,QAAQ,SAAS;AAC7B,QAAM,QAAQ,YAAY,UAAU,GAAG,IAAI;AAC3C,QAAM,OAAO,OAAO,YAAY,KAAK;AACrC,QAAM,YAAY,WAAW,UAAU,MAAM,KAAK;AAClD,SAAO;AAAA,IACL;AAAA,IACA,SAAS,OAAO,YAAY,SAAS;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,YAAY,OAAO,SAAS;AAAA,IACrC;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,SAAS,CAAC,UAAU,WAAW,UAAU,KAAK;AAAA,IAC9C,WAAW,aAAa,IAAI,SAAS;AAAA,IACrC;AAAA,IACA,MAAM,OAAO,KAAK,OAAO,OAAO,MAAM,KAAK,IAAI;AAAA,IAC/C,SAAS,aAAa;AAAA,EACxB;AACF;AAKO,SAAS,YAAY,GAAqC;AAC/D,MAAI,EAAE,SAAS,CAAC,EAAE,MAAM,GAAI,QAAO,EAAE,MAAM,WAAW,YAAY,EAAE,QAAQ,WAAW,EAAE,QAAQ;AACjG,SAAO;AACT;;;ADhDkB,cAoBV,YApBU;AArBX,IAAM,wBAAwB,EAAE,KAAK,GAAG,KAAK,IAAI;AAIxD,IAAM,OAAO,EAAE,GAAG,KAAK,GAAG,GAAG;AAC7B,IAAM,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,EAAE;AAC/C,IAAM,MAAM,EAAE,GAAG,KAAK,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,EAAE;AAC/C,IAAM,QAAQ;AACP,IAAM,qBAAqB,KAAK,IAAI,QAAQ;AAE5C,SAAS,QAAQ,EAAE,QAAQ,KAAK,GAAgB;AACrD,QAAM,aAAa,QAAQ,MAAM,cAAc,OAAO,SAAS,YAAY,GAAG,CAAC,OAAO,OAAO,CAAC;AAC9F,QAAM,UAAU,gBAAgB,QAAQ,MAAM;AAAA,IAC5C;AAAA,IACA,MAAM,UAAU,OAAO,SAAS,MAAM;AAAA,IACtC,WAAW,UAAU,OAAO,SAAS,WAAW;AAAA,IAChD,OAAO,UAAU,UAAU,OAAO,SAAS,KAAK,GAAG,UAAU,OAAO,SAAS,KAAK,GAAG,qBAAqB;AAAA,EAC5G,CAAC;AACD,QAAM,QAAQ,UAAU,OAAO,SAAS,OAAO,KAAK,QAAQ;AAC5D,SACE,oBAAC,eAAY,OAAc,YAAY,QAAQ,QAAQ,gBAAgB,MACpE,WAAC,UAAU,oBAAC,eAAY,SAAkB,OAAc,GAC3D;AAEJ;AAEA,SAAS,YAAY,EAAE,SAAS,GAAG,OAAO,GAAG,GAAkD;AAC7F,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,WAAW,UAAa,CAAC,EAAE,OAAO,MAAM,CAAC,EAAE,KAAM,QAAO,oBAAC,iBAAc,SAAS,GAAG,QAAgB;AACvG,QAAM,QAAQ,EAAE,MAAM;AACtB,QAAM,OAAO,EAAE;AAEf,QAAM,gBAAgB,KAAK,IAAI,GAAG,GAAG,SAAS,IAAI,KAAK,GAAG,KAAK,SAAS,GAAG;AAC3E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,wBAAsB,EAAE,MAAM;AAAA,MAC9B,qBAAmB,KAAK,aAAa,WAAW,SAAY,KAAK;AAAA,MACjE,aAAW,KAAK;AAAA,MAChB,OAAO,EAAE,QAAQ,QAAQ,WAAW,cAAc,SAAS,QAAQ,eAAe,UAAU,KAAK,GAAG,GAAG,SAAS,EAAE;AAAA,MAElH;AAAA,4BAAC,SAAI,OAAO,EAAE,MAAM,SAAS,WAAW,EAAE,GACxC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe,MAAM;AAAA,YACrB,iBAAe,MAAM;AAAA,YACrB,iBAAe,MAAM,MAAM,KAAK,YAAY,MAAM,MAAM,MAAM;AAAA,YAC9D,kBAAgB,GAAG,EAAE,OAAO,GAAG,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK,EAAE;AAAA,YACzD,SAAS,OAAO,KAAK,CAAC,IAAI,KAAK,CAAC;AAAA,YAChC,qBAAoB;AAAA,YACpB,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,SAAS,QAAQ;AAAA,YAEzD;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,GAAG,KAAK;AAAA,kBACR,GAAG,KAAK;AAAA,kBACR,OAAO,KAAK;AAAA,kBACZ,QAAQ,KAAK;AAAA,kBACb,IAAI,KAAK;AAAA,kBACT,OAAO,EAAE,MAAM,QAAQ,QAAQC,KAAI,kBAAkB,GAAG,aAAa,EAAE;AAAA;AAAA,cACzE;AAAA,cACA,oBAAC,UAAK,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,OAAO,IAAI,GAAG,QAAQ,IAAI,GAAG,IAAI,IAAI,GAAG,OAAO,EAAE,MAAMA,KAAI,kBAAkB,EAAE,GAAG;AAAA,cAC3G,KAAK,WAAW,IACf;AAAA,gBAAC;AAAA;AAAA,kBACC,iBAAc;AAAA,kBACd,GAAG,KAAK,IAAI;AAAA,kBACZ,GAAG,KAAK,IAAI;AAAA,kBACZ,OAAO,qBAAqB,KAAK;AAAA,kBACjC,QAAQ,KAAK,IAAI,QAAQ;AAAA,kBACzB,IAAI;AAAA,kBACJ,OAAO,EAAE,MAAM,EAAE,UAAU;AAAA;AAAA,cAC7B,IACE;AAAA;AAAA;AAAA,QACN,GACF;AAAA,QACA,oBAAC,SAAI,OAAO,EAAE,MAAM,YAAY,QAAQ,eAAe,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GACrH;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,OAAO,EAAE;AAAA,YACT,UAAU,KAAK;AAAA,YACf,MAAM,EAAE,OAAO,GAAG,KAAK,OAAO,QAAQ,cAAc;AAAA,YACpD,OAAO,GAAG;AAAA,YACV,SAAS,EAAE;AAAA;AAAA,QACb,GACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;AGxGA,SAAS,WAAAC,gBAAe;AAExB;AAAA,EACE,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,eAAAC;AAAA,OAGK;AACP,SAAS,oBAAoB,QAAQ,qBAAqB;;;ACZ1D,SAAS,mBAAmB;AAOrB,SAAS,aAAa,KAAyB,WAAuC;AAC3F,MAAI,QAAQ,UAAa,CAAC,OAAO,SAAS,GAAG,EAAG,QAAO;AACvD,QAAM,SAAS,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,CAAC,CAAC;AAC/D,SAAO,YAAY,OAAO,IAAI,QAAQ,MAAM,CAAC,CAAC;AAChD;AAEA,IAAM,cAAc,CAAC,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,IAAI;AAC/D,IAAM,eAA8C,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAGtE,SAAS,WAAW,SAAiB,SAA4C;AACtF,QAAM,QAAQ,YAAY,KAAK,MAAM,UAAU,EAAE,IAAI,CAAC;AACtD,SAAO,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,MAAM,QAAQ,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE;AAChE;;;ADgBkB,gBAAAC,MAgBd,QAAAC,aAhBc;AAhBlB,IAAM,oBAAoB;AAE1B,IAAM,gBAAgB;AAEf,SAAS,QAAQ,EAAE,QAAQ,KAAK,GAAgB;AACrD,QAAM,aAAaC,SAAQ,MAAMC,eAAc,OAAO,SAAS,YAAY,GAAG,CAAC,OAAO,OAAO,CAAC;AAC9F,QAAM,YAAYC,WAAU,OAAO,SAAS,WAAW,KAAK;AAC5D,QAAM,UAAU,gBAAgB,QAAQ,MAAM;AAAA,IAC5C;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA,WAAW,CAAC,QAAQ,aAAa,KAAK,SAAS;AAAA,EACjD,CAAC;AACD,QAAM,QAAQC,WAAU,OAAO,SAAS,OAAO,KAAK,QAAQ;AAC5D,SACE,gBAAAL,KAACM,cAAA,EAAY,OAAc,YAAY,QAAQ,QAAQ,gBAAgB,MAAM,OAAK,MAC/E,WAAC,UAAU,gBAAAN,KAAC,eAAY,SAAkB,OAAc,OAAc,GACzE;AAEJ;AAEA,SAAS,YAAY,EAAE,SAAS,GAAG,OAAO,OAAO,GAAG,GAA6E;AAC/H,QAAM,QAAQ,cAAc;AAC5B,QAAM,SAASE;AAAA,IACb,MAAM,mBAAmB,EAAE,SAAS,MAAM,OAAO,EAAE,WAAW,EAAE,QAAQ,WAAW,YAAY,EAAE,YAAY,OAAO,GAAG,MAAM,GAAG,GAAG,IAAI;AAAA,IACvI,CAAC,EAAE,OAAO,OAAO,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,GAAG,IAAI;AAAA,EAC7D;AACA,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,WAAW,UAAa,EAAE,UAAU,OAAW,QAAO,gBAAAF,KAAC,iBAAc,SAAS,GAAG,QAAgB;AACrG,QAAM,QAAQ,WAAW,EAAE,OAAO,EAAE,QAAQ,SAAS;AACrD,QAAM,cAAc,KAAK,IAAI,GAAG,GAAG,SAAS,IAAI,KAAK,GAAG,KAAK,SAAS,aAAa;AACnF,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY,GAAG,QAAQ,GAAG,KAAK,OAAO,EAAE,GAAG,EAAE,OAAO,QAAK,KAAK;AAAA,MAC9D,wBAAsB,EAAE,MAAM;AAAA,MAC9B,OAAO,EAAE,QAAQ,QAAQ,SAAS,QAAQ,eAAe,SAAS;AAAA,MAElE;AAAA,wBAAAD,KAAC,SAAI,OAAO,EAAE,MAAM,SAAS,WAAW,EAAE,GACxC,0BAAAA,KAAC,UAAO,QAAgB,GAC1B;AAAA,QACA,gBAAAA,KAAC,SAAI,OAAO,EAAE,QAAQ,aAAa,SAAS,QAAQ,YAAY,UAAU,gBAAgB,UAAU,YAAY,EAAE,GAChH,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,GAAG,EAAE,OAAO;AAAA,YAClB,MAAM;AAAA,YACN,OAAO,EAAE;AAAA,YACT,MAAM,EAAE,OAAO,GAAG,KAAK,OAAO,QAAQ,YAAY;AAAA,YAClD,OAAO,GAAG;AAAA,YACV,SAAS,EAAE;AAAA;AAAA,QACb,GACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;AEvEA,SAAS,WAAAO,gBAAe;AAExB;AAAA,EACE,OAAAC;AAAA,EACA,eAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,eAAAC;AAAA,OAGK;AAsBW,gBAAAC,MA+BZ,QAAAC,aA/BY;AAdlB,IAAM,qBAAqB;AAEpB,SAAS,WAAW,EAAE,QAAQ,KAAK,GAAgB;AACxD,QAAM,aAAaC,SAAQ,MAAMC,eAAc,OAAO,SAAS,YAAY,GAAG,CAAC,OAAO,OAAO,CAAC;AAC9F,QAAM,UAAU,gBAAgB,QAAQ,MAAM;AAAA,IAC5C;AAAA,IACA,MAAMC,WAAU,OAAO,SAAS,MAAM;AAAA,IACtC,WAAWC,WAAU,OAAO,SAAS,WAAW;AAAA,IAChD,OAAO,UAAUA,WAAU,OAAO,SAAS,KAAK,GAAGA,WAAU,OAAO,SAAS,KAAK,CAAC;AAAA,EACrF,CAAC;AACD,QAAM,QAAQD,WAAU,OAAO,SAAS,OAAO,KAAK,QAAQ;AAC5D,QAAM,UAAUA,WAAU,OAAO,SAAS,SAAS,MAAM;AACzD,SACE,gBAAAJ,KAACM,cAAA,EAAY,OAAc,YAAY,QAAQ,QAAQ,gBAAgB,MACpE,WAAC,UAAU,gBAAAN,KAAC,YAAS,SAAkB,SAAkB,OAAc,GAC1E;AAEJ;AAEA,SAAS,SAAS,EAAE,SAAS,GAAG,SAAS,OAAO,GAAG,GAAoE;AACrH,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,WAAW,UAAa,CAAC,EAAE,OAAO,MAAM,CAAC,EAAE,KAAM,QAAO,gBAAAA,KAAC,iBAAc,SAAS,GAAG,QAAgB;AACvG,QAAM,QAAQ,EAAE,MAAM;AACtB,QAAM,OAAO,EAAE;AACf,QAAM,OAAO;AACb,QAAM,SAAS,GAAG,GAAG,SAAS;AAE9B,QAAM,OAAO,UAAU,GAAGO,aAAY,KAAK,QAAQ,KAAK,EAAE,aAAa,CAAC,CAAC,KAAK,EAAE;AAChF,QAAM,OAAO,UAAU,MAAM,EAAE;AAI/B,QAAM,QAAQ,UAAU,EAAE,YAAY,KAAK,EAAE,QAAQ,CAAC,MAAM;AAC1D,UAAM,QAAQ,EAAE,QAAQ,EAAE,KAAK;AAC/B,UAAM,SAAS,KAAK,YAAY,EAAE,SAAS,KAAK,WAAW,EAAE,MAAO,EAAE,MAAM,KAAK,KAAK,YAAY;AAClG,WAAO,UAAU,SAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,IAAI,OAAO,OAAO,CAAC;AAAA,EAC9E,CAAC;AACD,QAAM,QAAQ,EAAE,OAAO,KAAK,IAAI,GAAG,GAAG,KAAK,QAAQ,OAAO,IAAI,MAAM,GAAG,QAAQ,KAAK,IAAI,GAAG,GAAG,KAAK,SAAS,OAAO,CAAC,EAAE;AACtH,SACE,gBAAAN;AAAA,IAAC;AAAA;AAAA,MACC,wBAAsB,EAAE,MAAM;AAAA,MAC9B,qBAAmB,KAAK,aAAa,WAAW,SAAY,KAAK;AAAA,MACjE,aAAW,KAAK;AAAA,MAChB,OAAO,EAAE,QAAQ,QAAQ,WAAW,cAAc,SAAS,QAAQ,KAAK,GAAG,GAAG,SAAS,EAAE;AAAA,MAEzF;AAAA,wBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe,MAAM;AAAA,YACrB,iBAAe,MAAM;AAAA,YACrB,iBAAe,MAAM,MAAM,KAAK,YAAY,MAAM,MAAM,MAAM;AAAA,YAC9D,kBAAgB,GAAG,EAAE,OAAO,GAAG,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK,EAAE;AAAA,YACzD,OAAO;AAAA,cACL,UAAU;AAAA,cACV,MAAM;AAAA,cACN,UAAU;AAAA,cACV,UAAU;AAAA,cACV,WAAW;AAAA,cACX,QAAQ,GAAG,IAAI,YAAYO,KAAI,QAAQ,CAAC;AAAA,cACxC,cAAc,GAAG,GAAG,SAAS;AAAA,cAC7B,YAAYA,KAAI,OAAO;AAAA,YACzB;AAAA,YAEA;AAAA,8BAAAR;AAAA,gBAAC;AAAA;AAAA,kBACC,eAAY;AAAA,kBACZ,OAAO;AAAA,oBACL,UAAU;AAAA,oBACV,MAAM;AAAA,oBACN,OAAO;AAAA,oBACP,QAAQ;AAAA,oBACR,QAAQ,GAAG,KAAK,WAAW,GAAG;AAAA,oBAC9B,YAAY,EAAE;AAAA,oBACd,SAAS;AAAA,oBACT,WAAW,KAAK,WAAW,KAAK,KAAK,WAAW,IAAI,aAAa,EAAE,SAAS,KAAK;AAAA,kBACnF;AAAA;AAAA,cACF;AAAA,cACA,gBAAAA,KAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,GAAG,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GAC5G,0BAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC;AAAA,kBACA;AAAA,kBACA,OAAO,EAAE;AAAA,kBACT,UAAU,KAAK;AAAA,kBACf,MAAM;AAAA,kBACN,OAAO,GAAG;AAAA,kBACV,SAAS,EAAE;AAAA;AAAA,cACb,GACF;AAAA;AAAA;AAAA,QACF;AAAA,QAEA,gBAAAA,KAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,YAAY,GAAG,cAAc,SAAS,GAAG,YAAYQ,KAAI,OAAO,GAAG,UAAU,SAAS,GACtI,gBAAM,IAAI,CAAC,GAAG,MACb,gBAAAR;AAAA,UAAC;AAAA;AAAA,YAEC,aAAU;AAAA,YACV,oBAAkB,EAAE,SAAS,KAAK;AAAA,YAClC,OAAO;AAAA,cACL,UAAU;AAAA,cACV,MAAM;AAAA,cACN,OAAO;AAAA,cACP,QAAQ,GAAG,EAAE,OAAO,GAAG;AAAA,cACvB,QAAQ,IAAI,EAAE,KAAK,EAAE,QAAQ,GAAG;AAAA,cAChC,YAAY,EAAE;AAAA,cACd,SAAS,EAAE,SAAS,IAAI;AAAA,YAC1B;AAAA;AAAA,UAXK;AAAA,QAYP,CACD,GACH;AAAA;AAAA;AAAA,EACF;AAEJ;;;AC/HA,SAAS,WAAAS,gBAAe;AAExB;AAAA,EACE,OAAAC;AAAA,EACA;AAAA,EACA,eAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,eAAAC;AAAA,OAGK;AAqBW,gBAAAC,MAiFV,QAAAC,aAjFU;AAdX,SAAS,YAAY,EAAE,QAAQ,KAAK,GAAgB;AACzD,QAAM,aAAaC,SAAQ,MAAMC,eAAc,OAAO,SAAS,YAAY,GAAG,CAAC,OAAO,OAAO,CAAC;AAC9F,QAAM,UAAU,gBAAgB,QAAQ,MAAM;AAAA,IAC5C;AAAA,IACA,MAAMC,WAAU,OAAO,SAAS,MAAM;AAAA,IACtC,WAAWC,WAAU,OAAO,SAAS,WAAW;AAAA,IAChD,OAAO,UAAUA,WAAU,OAAO,SAAS,KAAK,GAAGA,WAAU,OAAO,SAAS,KAAK,CAAC;AAAA,EACrF,CAAC;AACD,QAAM,QAAQD,WAAU,OAAO,SAAS,OAAO,KAAK,QAAQ;AAC5D,QAAM,cAAcA,WAAU,OAAO,SAAS,OAAO,MAAM;AAE3D,QAAM,WAAW,eAAeA,WAAU,OAAO,SAAS,aAAa,MAAM;AAC7E,SACE,gBAAAJ,KAACM,cAAA,EAAY,OAAc,YAAY,QAAQ,QAAQ,gBAAgB,MACpE,WAAC,UAAU,gBAAAN,KAAC,cAAW,SAAkB,aAA0B,UAAoB,OAAc,GACxG;AAEJ;AASA,SAAS,WAAW,EAAE,SAAS,GAAG,aAAa,UAAU,OAAO,GAAG,GAAc;AAC/E,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,WAAW,UAAa,CAAC,EAAE,OAAO,MAAM,CAAC,EAAE,KAAM,QAAO,gBAAAA,KAAC,iBAAc,SAAS,GAAG,QAAgB;AACvG,QAAM,QAAQ,EAAE,MAAM;AACtB,QAAM,OAAO,EAAE;AACf,QAAM,EAAE,MAAM,MAAM,IAAI;AACxB,QAAM,YAAY,GAAG,GAAG,SAAS;AACjC,QAAM,MAAM,GAAG,GAAG,SAAS;AAC3B,QAAM,UAAU,GAAG,GAAG,SAAS;AAC/B,QAAM,UAAUO,aAAY,MAAM,KAAK,EAAE,SAAS;AAClD,QAAM,UAAUA,aAAY,MAAM,KAAK,EAAE,SAAS;AAClD,QAAM,OAAO,cAAc,YAAY,IAAI;AAI3C,QAAM,QAAQ,UAAU,EAAE,YAAY,KAAK,EAAE,QAAQ,CAAC,MAAM;AAC1D,UAAM,QAAQ,EAAE,QAAQ,EAAE,KAAK;AAC/B,WAAO,UAAU,SAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC;AAAA,EACtE,CAAC;AACD,QAAM,QACJ,gBAAAP;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,UAAU,KAAK;AAAA,MACf,OAAO,EAAE;AAAA,MACT;AAAA,MACA;AAAA,MACA,MAAM;AAAA,QACJ,KAAK,MAAM;AAAA,QACX,KAAK,MAAM;AAAA,QACX,KAAK,MAAM,MAAM,KAAK,YAAY,MAAM,MAAM,MAAM;AAAA,QACpD,MAAM,GAAG,EAAE,OAAO,GAAG,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK,EAAE;AAAA,MACjD;AAAA;AAAA,EACF;AAEF,QAAM,UAAU,CAAC,SACf,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,EAAE;AAAA,MACR,MAAM,EAAE;AAAA,MACR,OAAO,EAAE;AAAA,MACT,UAAU,KAAK;AAAA,MACf,MAAM;AAAA,MACN;AAAA,MACA,SAAS,EAAE;AAAA;AAAA,EACb;AAEF,QAAM,aAAa,EAAE,UAAU,QAAQ,IAAI,GAAG,OAAOQ,KAAI,kBAAkB,GAAG,YAAY,IAAI;AAC9F,QAAM,OAAO;AAAA,IACX,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,UAAU;AAAA,IACV,SAAS;AAAA,IACT;AAAA,EACF;AACA,QAAM,QAAQ;AAAA,IACZ,wBAAwB,EAAE,MAAM;AAAA,IAChC,qBAAqB,KAAK,aAAa,WAAW,SAAY,KAAK;AAAA,IACnE,aAAa,KAAK;AAAA,EACpB;AAEA,MAAI,CAAC,UAAU;AAEb,UAAM,YAAY,YAAY,UAAU,MAAM,MAAM;AACpD,WACE,gBAAAP,MAAC,SAAK,GAAG,OAAO,OAAO,EAAE,GAAG,MAAM,eAAe,UAAU,gBAAgB,cAAc,GACvF;AAAA,sBAAAD,KAAC,SAAI,OAAO,EAAE,MAAM,SAAS,WAAW,GAAG,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GACxG,kBAAQ,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,IAAI,GAAG,KAAK,SAAS,SAAS,EAAE,CAAC,GAC9E;AAAA,MACC;AAAA,MACD,gBAAAC,MAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,gBAAgB,iBAAiB,KAAK,GAAG,WAAW,GACjF;AAAA,wBAAAD,KAAC,UAAM,mBAAQ;AAAA,QACf,gBAAAA,KAAC,UAAM,mBAAQ;AAAA,SACjB;AAAA,OACF;AAAA,EAEJ;AAGA,QAAM,YAAY,KAAK,KAAK,KAAK,IAAI,QAAQ,QAAQ,QAAQ,MAAM,IAAI,UAAU,IAAI;AACrF,QAAM,WAAW,KAAK,IAAI,WAAW,IAAI,IAAI,YAAY,MAAM;AAC/D,SACE,gBAAAC,MAAC,SAAK,GAAG,OAAO,OAAO,EAAE,GAAG,MAAM,eAAe,OAAO,YAAY,UAAU,GAC5E;AAAA,oBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,eAAe;AAAA,UACf,gBAAgB;AAAA,UAChB,YAAY;AAAA,UACZ,eAAe;AAAA,UACf,GAAG;AAAA,QACL;AAAA,QAEA;AAAA,0BAAAD,KAAC,UAAM,mBAAQ;AAAA,UACf,gBAAAA,KAAC,UAAM,mBAAQ;AAAA;AAAA;AAAA,IACjB;AAAA,IACC;AAAA,IACD,gBAAAA,KAAC,SAAI,OAAO,EAAE,MAAM,SAAS,UAAU,GAAG,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GACvG,kBAAQ,EAAE,OAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,GAAG,QAAQ,KAAK,OAAO,CAAC,GAC7E;AAAA,KACF;AAEJ;AAYA,SAAS,MAAM,EAAE,UAAU,WAAW,UAAU,OAAO,OAAO,MAAM,KAAK,GAAe;AACtF,QAAM,MAAM,CAAC,MAAc,GAAG,IAAI,GAAG;AACrC,QAAM,SAAS,YAAY;AAC3B,QAAM,OACJ,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,iBAAe,KAAK;AAAA,MACpB,iBAAe,KAAK;AAAA,MACpB,iBAAe,KAAK;AAAA,MACpB,kBAAgB,KAAK;AAAA,MACrB,OAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAYO,KAAI,OAAO;AAAA,QACvB,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,GAAI,WAAW,EAAE,OAAO,WAAW,MAAM,SAAS,WAAW,EAAE,IAAI,EAAE,OAAO,QAAQ,QAAQ,UAAU;AAAA,MACxG;AAAA,MAEC;AAAA,cAAM,IAAI,CAAC,GAAG,MACb,gBAAAR;AAAA,UAAC;AAAA;AAAA,YAEC,aAAU;AAAA,YACV,OAAO;AAAA,cACL,UAAU;AAAA,cACV,YAAY,EAAE;AAAA,cACd,SAAS;AAAA,cACT,GAAI,WACA,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,IAAI,EAAE,IAAI,GAAG,QAAQ,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IACrE,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,IAAI,EAAE,IAAI,GAAG,OAAO,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;AAAA,YACxE;AAAA;AAAA,UATK;AAAA,QAUP,CACD;AAAA,QACD,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,iBAAc;AAAA,YACd,OAAO;AAAA,cACL,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,GAAI,WACA,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,IAAI,QAAQ,EAAE,IACtD,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,IAAI,QAAQ,EAAE;AAAA,YACzD;AAAA;AAAA,QACF;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,eAAY;AAAA,YACZ,OAAO;AAAA,cACL,UAAU;AAAA,cACV,YAAYQ,KAAI,YAAY;AAAA,cAC5B,GAAI,WACA,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,QAAQ,IAAI,QAAQ,CAAC,UAAU,IACvE,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,QAAQ,IAAI,QAAQ,CAAC,UAAU;AAAA,YAC1E;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEF,MAAI,CAAC,SAAU,QAAO;AAGtB,SACE,gBAAAP,MAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,YAAY,UAAU,WAAW,GAAG,MAAM,YAAY,OAAO,KAAK,IAAI,WAAW,IAAI,EAAE,GAC5I;AAAA;AAAA,IACA,OAAO,IACN,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,aAAU;AAAA,QACV,OAAO,EAAE,OAAO,MAAM,QAAQ,MAAM,cAAc,OAAO,YAAY,OAAO,WAAW,CAAC,QAAQ,YAAY,EAAE;AAAA;AAAA,IAChH,IACE;AAAA,KACN;AAEJ;;;AClOA,SAAS,WAAAS,gBAAe;AAExB;AAAA,EACE,OAAAC;AAAA,EACA,eAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,eAAAC;AAAA,OAGK;AA0BW,gBAAAC,MA2BV,QAAAC,aA3BU;AAlBlB,IAAM,cAAc;AACpB,IAAM,cAAc;AACb,IAAM,qBAAqB,IAAI,KAAK,KAAK;AAEhD,IAAM,QAAQ,EAAE,OAAO,MAAM,QAAQ,KAAK;AAEnC,SAAS,aAAa,EAAE,QAAQ,KAAK,GAAgB;AAC1D,QAAM,aAAaC,SAAQ,MAAMC,eAAc,OAAO,SAAS,YAAY,GAAG,CAAC,OAAO,OAAO,CAAC;AAC9F,QAAM,UAAU,gBAAgB,QAAQ,MAAM;AAAA,IAC5C;AAAA,IACA,MAAMC,WAAU,OAAO,SAAS,MAAM;AAAA,IACtC,WAAWC,WAAU,OAAO,SAAS,WAAW;AAAA,IAChD,OAAO,UAAUA,WAAU,OAAO,SAAS,KAAK,GAAGA,WAAU,OAAO,SAAS,KAAK,CAAC;AAAA,EACrF,CAAC;AACD,QAAM,QAAQD,WAAU,OAAO,SAAS,OAAO,KAAK,QAAQ;AAC5D,QAAM,UAAUA,WAAU,OAAO,SAAS,SAAS,MAAM;AACzD,SACE,gBAAAJ,KAACM,cAAA,EAAY,OAAc,YAAY,QAAQ,QAAQ,gBAAgB,MACpE,WAAC,UAAU,gBAAAN,KAAC,YAAS,SAAkB,SAAkB,OAAc,GAC1E;AAEJ;AAEA,SAAS,SAAS,EAAE,SAAS,GAAG,SAAS,OAAO,GAAG,GAAoE;AACrH,QAAM,SAAS,YAAY,CAAC;AAC5B,MAAI,WAAW,UAAa,CAAC,EAAE,OAAO,MAAM,CAAC,EAAE,KAAM,QAAO,gBAAAA,KAAC,iBAAc,SAAS,GAAG,QAAgB;AACvG,QAAM,QAAQ,EAAE,MAAM;AACtB,QAAM,OAAO,EAAE;AAEf,QAAM,OAAO,UAAUO,aAAY,KAAK,QAAQ,KAAK,EAAE,aAAa,CAAC,IAAI,EAAE;AAC3E,QAAM,OAAO,UAAU,MAAM,EAAE;AAC/B,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO,GAAG,KAAK,MAAM,CAAC;AAChE,SACE,gBAAAP;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,iBAAe,MAAM;AAAA,MACrB,iBAAe,MAAM;AAAA,MACrB,iBAAe,MAAM,MAAM,KAAK,YAAY,MAAM,MAAM,MAAM;AAAA,MAC9D,kBAAgB,GAAG,EAAE,OAAO,GAAG,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK,EAAE;AAAA,MACzD,wBAAsB,EAAE,MAAM;AAAA,MAC9B,qBAAmB,KAAK,aAAa,WAAW,SAAY,KAAK;AAAA,MACjE,aAAW,KAAK;AAAA,MAChB,OAAO,EAAE,QAAQ,QAAQ,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS;AAAA,MAEzF,0BAAAC,MAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,aAAa,IAAI,GAClG;AAAA,wBAAAA,MAAC,SAAI,SAAQ,eAAc,OAAM,QAAO,QAAO,QAAO,eAAY,QAAO,OAAO,EAAE,SAAS,QAAQ,GACjG;AAAA,0BAAAD,KAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAG,aAAa,MAAK,QAAO,aAAa,aAAa,OAAO,EAAE,QAAQQ,KAAI,OAAO,EAAE,GAAG;AAAA,UAC/G,gBAAAR;AAAA,YAAC;AAAA;AAAA,cACC,kBAAe;AAAA,cACf,IAAG;AAAA,cACH,IAAG;AAAA,cACH,GAAG;AAAA,cACH,MAAK;AAAA,cACL,aAAa;AAAA,cACb,iBAAiB,GAAG,KAAK,WAAW,kBAAkB,IAAI,kBAAkB;AAAA,cAC5E,WAAU;AAAA,cACV,OAAO,EAAE,QAAQ,EAAE,UAAU;AAAA;AAAA,UAC/B;AAAA,WACF;AAAA,QACA,gBAAAA,KAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,GAAG,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GAC5G,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA,OAAO,EAAE;AAAA,YACT,UAAU,KAAK;AAAA,YACf,MAAM,EAAE,OAAO,OAAO,MAAM,OAAO,QAAQ,OAAO,MAAM,OAAO;AAAA,YAC/D,OAAO,GAAG;AAAA,YACV,SAAS,EAAE;AAAA;AAAA,QACb,GACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;;;AC5FA,SAAS,WAAAS,gBAAe;AAExB;AAAA,EACE,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,eAAAC;AAAA,OAGK;AAqBW,gBAAAC,MAed,QAAAC,aAfc;AAdX,IAAM,kBAAkB;AAE/B,IAAMC,QAAO,EAAE,GAAG,KAAK,GAAG,GAAG;AAEtB,SAAS,WAAW,EAAE,QAAQ,KAAK,GAAgB;AACxD,QAAM,aAAaC,SAAQ,MAAMC,eAAc,OAAO,SAAS,YAAY,GAAG,CAAC,OAAO,OAAO,CAAC;AAC9F,QAAM,UAAU,gBAAgB,QAAQ,MAAM;AAAA,IAC5C;AAAA,IACA,MAAMC,WAAU,OAAO,SAAS,MAAM;AAAA,IACtC,WAAWC,WAAU,OAAO,SAAS,WAAW;AAAA,EAClD,CAAC;AACD,QAAM,QAAQD,WAAU,OAAO,SAAS,OAAO,KAAK,QAAQ;AAC5D,SACE,gBAAAL,KAACO,cAAA,EAAY,OAAc,YAAY,QAAQ,QAAQ,gBAAgB,MACpE,WAAC,UAAU,gBAAAP,KAAC,YAAS,SAAkB,OAAc,GACxD;AAEJ;AAEA,SAAS,SAAS,EAAE,SAAS,GAAG,OAAO,GAAG,GAAkD;AAC1F,MAAI,EAAE,WAAW,SAAS,gBAAiB,QAAO,gBAAAA,KAAC,cAAW,SAAS,EAAE,QAAQ,eAAe;AAChG,QAAM,OAAO,QAAQ,EAAE,YAAY,EAAE,KAAK;AAC1C,MAAI,CAAC,KAAM,QAAO,gBAAAA,KAAC,iBAAc,SAAS,GAAG,QAAQ,QAAW;AAChE,QAAM,IAAI,KAAK;AAEf,QAAM,OAAOE,MAAK,KAAK,KAAK,IAAI,KAAK;AACrC,QAAM,OAAO,OAAO;AACpB,QAAM,gBAAgB,KAAK,IAAI,GAAG,GAAG,SAAS,IAAI,KAAK,GAAG,KAAK,SAAS,IAAI;AAC5E,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,wBAAsB,EAAE,MAAM;AAAA,MAC9B,iBAAe,KAAK;AAAA,MACpB,mBAAiB,KAAK;AAAA,MACtB,OAAO,EAAE,QAAQ,QAAQ,WAAW,cAAc,SAAS,QAAQ,eAAe,UAAU,KAAK,GAAG,GAAG,SAAS,EAAE;AAAA,MAElH;AAAA,wBAAAD,KAAC,SAAI,OAAO,EAAE,MAAM,SAAS,WAAW,EAAE,GACxC,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,iBAAe,KAAK;AAAA,YACpB,iBAAe,KAAK;AAAA,YACpB,kBAAgB,GAAG,KAAK,GAAG,IAAI,KAAK,KAAK;AAAA,YACzC,SAAS,OAAOE,MAAK,CAAC,IAAIA,MAAK,CAAC;AAAA,YAChC,qBAAoB;AAAA,YACpB,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,SAAS,QAAQ;AAAA,YAExD,gBAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,MAAM;AACnC,oBAAM,IAAKA,MAAK,KAAK,IAAI,KAAM;AAC/B,oBAAM,MAAM,IAAI,KAAK;AACrB,qBACE,gBAAAF;AAAA,gBAAC;AAAA;AAAA,kBAEC,YAAU,MAAM,QAAQ;AAAA,kBACxB,GAAG,KAAK,OAAO;AAAA,kBACf,GAAGE,MAAK,IAAI;AAAA,kBACZ,OAAO;AAAA,kBACP,QAAQ;AAAA,kBACR,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC;AAAA,kBACxB,OAAO,EAAE,MAAM,MAAM,EAAE,YAAYM,KAAI,OAAO,EAAE;AAAA;AAAA,gBAP3C;AAAA,cAQP;AAAA,YAEJ,CAAC;AAAA;AAAA,QACH,GACF;AAAA,QACA,gBAAAR,KAAC,SAAI,OAAO,EAAE,MAAM,YAAY,QAAQ,eAAe,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GACrH,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,OAAO,EAAE;AAAA,YACT,MAAM,EAAE,OAAO,GAAG,KAAK,OAAO,QAAQ,cAAc;AAAA,YACpD,OAAO,GAAG;AAAA,YACV,SAAS,EAAE;AAAA;AAAA,QACb,GACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;AC7FA,SAAS,WAAAS,gBAAe;AAExB;AAAA,EACE,OAAAC;AAAA,EACA,WAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,eAAAC;AAAA,OAGK;AAeW,gBAAAC,MA8Bd,QAAAC,aA9Bc;AAXX,SAAS,YAAY,EAAE,QAAQ,KAAK,GAAgB;AACzD,QAAM,aAAaC,SAAQ,MAAMC,eAAc,OAAO,SAAS,YAAY,GAAG,CAAC,OAAO,OAAO,CAAC;AAC9F,QAAM,UAAU,gBAAgB,QAAQ,MAAM;AAAA,IAC5C;AAAA,IACA,MAAMC,WAAU,OAAO,SAAS,MAAM;AAAA,IACtC,WAAWC,WAAU,OAAO,SAAS,WAAW;AAAA,EAClD,CAAC;AACD,QAAM,QAAQD,WAAU,OAAO,SAAS,OAAO,KAAK,QAAQ;AAC5D,QAAM,OAAOC,WAAU,OAAO,SAAS,MAAM;AAC7C,SACE,gBAAAL,KAACM,cAAA,EAAY,OAAc,YAAY,QAAQ,QAAQ,gBAAgB,MACpE,WAAC,UAAU,gBAAAN,KAAC,YAAS,SAAkB,MAAY,OAAc,GACpE;AAEJ;AAGO,SAAS,UAAU,GAAiB,MAAyE;AAClH,MAAI,EAAE,UAAU,OAAW,QAAO,EAAE,KAAK,QAAW,SAAS,EAAE,QAAQ,OAAO;AAC9E,QAAM,MAAM,SAAS,SAAY,OAAO,EAAE,SAAS;AACnD,QAAM,WAAW,SAAS,SAAY,GAAG,EAAE,OAAO,GAAG,EAAE,OAAO,IAAI,EAAE,IAAI,KAAK,EAAE,KAAK,MAAM,EAAE,QAAQ,KAAK,EAAE,QAAQ;AACnH,SAAO,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,SAAS;AACnD;AAEA,SAAS,SAAS,EAAE,SAAS,GAAG,MAAM,OAAO,GAAG,GAA4E;AAC1H,QAAM,EAAE,KAAK,QAAQ,IAAI,UAAU,GAAG,IAAI;AAC1C,QAAM,cAAc,GAAG,GAAG,SAAS,IAAI;AACvC,QAAM,WAAW,GAAG,GAAG,SAAS;AAChC,QAAM,WAAW,GAAG,KAAK,QAAQ,KAAK,GAAG,KAAK,SAAS;AAKvD,QAAM,SAAS,YAAY,GAAG,KAAK,SAAS,cAAc,WAAW;AACrE,QAAM,WAAW,CAAC,WACd,WAAW,IACX,SACE,KAAK,IAAI,KAAK,IAAI,UAAU,GAAG,KAAK,MAAM,GAAG,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,QAAQ,GAAG,KAAK,QAAQ,GAAG,IAAI,GAAG,CAAC,IAC5G,KAAK,IAAI,UAAU,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,OAAO,GAAG,KAAK,SAAS,WAAW,IAAI,GAAG,CAAC;AAChG,QAAM,QAAQ,EAAE;AAChB,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,wBAAsB,MAAM,EAAE,MAAM,QAAQ;AAAA,MAC5C,YAAU,QAAQ,SAAY,SAAY,OAAO,GAAG;AAAA,MACpD,oBAAkB,SAAS,WAAW;AAAA,MACtC,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,UAAU;AAAA,QACV,SAAS;AAAA,QACT,eAAe,SAAS,QAAQ;AAAA,QAChC,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,KAAK,GAAG,GAAG,SAAS;AAAA,QACpB,WAAW;AAAA,MACb;AAAA,MAEA;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,aAAU;AAAA,YACV,OAAO;AAAA,cACL,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,YAAY;AAAA,cACZ,cAAc;AAAA,cACd,WAAW;AAAA,cACX,YAAY,MAAM,QAAQ;AAAA,cAC1B,QAAQ,aAAa,MAAM,QAAQO,KAAI,kBAAkB,CAAC;AAAA,cAC1D,WAAW,MAAM,OAAO,KAAK,MAAM,WAAW,CAAC,CAAC,MAAM,KAAK,KAAK;AAAA,YAClE;AAAA;AAAA,QACF;AAAA,QACA,gBAAAP;AAAA,UAAC;AAAA;AAAA,YACC,qBAAkB;AAAA,YAClB,OAAO;AAAA,cACL,UAAUQ,SAAQ,IAAI;AAAA,cACtB,YAAY;AAAA,cACZ,YAAY;AAAA,cACZ,OAAO,QAAQ,SAAYD,KAAI,kBAAkB,IAAIA,KAAI,YAAY;AAAA,cACrE,cAAc;AAAA,cACd,UAAU;AAAA,cACV,UAAU;AAAA,YACZ;AAAA,YAEC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;",
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
+ }
@@ -0,0 +1,22 @@
1
+ import {
2
+ Explained,
3
+ LevelEmptyFor
4
+ } from "./chunk-AF4M5OXQ.js";
5
+ import {
6
+ ASK_DELAY_MS,
7
+ NoReading,
8
+ SETTLE_MS,
9
+ emptyKindFor,
10
+ lastReadingHint
11
+ } from "./chunk-JVC6JYUR.js";
12
+ import "./chunk-EQOWBDS7.js";
13
+ export {
14
+ ASK_DELAY_MS,
15
+ Explained,
16
+ LevelEmptyFor,
17
+ NoReading,
18
+ SETTLE_MS,
19
+ emptyKindFor,
20
+ lastReadingHint
21
+ };
22
+ //# sourceMappingURL=no-reading-B4MPXAS2.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -7,11 +7,15 @@ import {
7
7
  import {
8
8
  fleetStrings
9
9
  } from "./chunk-QMGKB6J3.js";
10
+ import {
11
+ Explained
12
+ } from "./chunk-AF4M5OXQ.js";
13
+ import "./chunk-JVC6JYUR.js";
10
14
  import "./chunk-BRH66T5F.js";
11
15
  import {
12
16
  LevelEmpty,
13
17
  LevelReadout
14
- } from "./chunk-XQQQNTBX.js";
18
+ } from "./chunk-EQOWBDS7.js";
15
19
 
16
20
  // src/widgets/device-status.tsx
17
21
  import {
@@ -106,10 +110,10 @@ function DeviceStatus({ widget, data }) {
106
110
  const severity = useSeverityColors();
107
111
  const feed = data.members;
108
112
  const title = optString(widget.options, "title");
109
- const empty = (message) => /* @__PURE__ */ jsx(WidgetFrame, { title, children: /* @__PURE__ */ jsx(LevelEmpty, { message }) });
113
+ const empty = (message, kind2) => /* @__PURE__ */ jsx(WidgetFrame, { title, children: kind2 ? /* @__PURE__ */ jsx(Explained, { kind: kind2, message }) : /* @__PURE__ */ jsx(LevelEmpty, { message }) });
110
114
  if (!feed || feed.status === "loading") return empty(fleet.loading);
111
- if (feed.status === "unbound") return empty(strings.unbound);
112
- if (feed.status === "forbidden") return empty(fleet.forbidden);
115
+ if (feed.status === "unbound") return empty(strings.unbound, "unbound");
116
+ if (feed.status === "forbidden") return empty(fleet.forbidden, "forbidden");
113
117
  if (feed.status === "unsupported") return empty(strings.unsupported);
114
118
  if (feed.members.length === 0) return empty(fleet.noMembers);
115
119
  if (feed.members.length > 1 || feed.total > 1) return empty(`${strings.oneDevice} ${strings.useDoughnut}`);
@@ -176,10 +180,10 @@ function OnlineDoughnut({ widget, data }) {
176
180
  const severity = useSeverityColors2();
177
181
  const feed = data.members;
178
182
  const title = optString2(widget.options, "title");
179
- const empty = (message) => /* @__PURE__ */ jsx2(WidgetFrame2, { title, children: /* @__PURE__ */ jsx2(LevelEmpty, { message }) });
183
+ const empty = (message, kind) => /* @__PURE__ */ jsx2(WidgetFrame2, { title, children: kind ? /* @__PURE__ */ jsx2(Explained, { kind, message }) : /* @__PURE__ */ jsx2(LevelEmpty, { message }) });
180
184
  if (!feed || feed.status === "loading") return empty(fleet.loading);
181
- if (feed.status === "unbound") return empty(fleet.unbound);
182
- if (feed.status === "forbidden") return empty(fleet.forbidden);
185
+ if (feed.status === "unbound") return empty(fleet.unbound, "unbound");
186
+ if (feed.status === "forbidden") return empty(fleet.forbidden, "forbidden");
183
187
  if (feed.status === "unsupported") return empty(strings.unsupported);
184
188
  if (feed.members.length === 0) return empty(fleet.noMembers);
185
189
  const tally = tallyPresence(feed.members);
@@ -347,4 +351,4 @@ export {
347
351
  OnlineDoughnut,
348
352
  PresenceFeed
349
353
  };
350
- //# sourceMappingURL=presence-widgets-2LIUKN4Y.js.map
354
+ //# sourceMappingURL=presence-widgets-M5VGG3OO.js.map
@@ -0,0 +1,7 @@
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 { Explained } from '../no-reading';\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, kind?: 'unbound' | 'forbidden') => (\n <WidgetFrame title={title}>\n {kind ? <Explained kind={kind} message={message} /> : <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, 'unbound');\n if (feed.status === 'forbidden') return empty(fleet.forbidden, '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 { Explained } from '../no-reading';\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, kind?: 'unbound' | 'forbidden') => (\n <WidgetFrame title={title}>\n {kind ? <Explained kind={kind} message={message} /> : <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, 'unbound');\n if (feed.status === 'forbidden') return empty(fleet.forbidden, '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", "kind", "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
+ }
@@ -0,0 +1,8 @@
1
+ import {
2
+ Table
3
+ } from "./chunk-7BUCJQFP.js";
4
+ import "./chunk-JVC6JYUR.js";
5
+ export {
6
+ Table
7
+ };
8
+ //# sourceMappingURL=table-CEVB3JZS.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -15,7 +15,7 @@ export declare function capMembers(roster: {
15
15
  total: number;
16
16
  }, limit: number): CappedMembers;
17
17
  export declare function memberLabels(members: readonly MemberRef[]): Map<string, string>;
18
- export declare function bucketSamples(token: string, measurement: string, buckets: readonly MeasurementBucket[]): MeasurementSample[];
18
+ export declare function bucketSamples(token: string, measurement: string, buckets: readonly MeasurementBucket[], bucketSeconds?: number): MeasurementSample[];
19
19
  export interface MemberHistory {
20
20
  samples: MeasurementSample[];
21
21
  end: number;
@@ -1616,6 +1616,75 @@ export declare const builtinWidgetDescriptors: {
1616
1616
  readonly helpId: 'widgetHintStaleAfter';
1617
1617
  };
1618
1618
  }>>;
1619
+ readonly 'history-table': WidgetDescriptor<"measurement", import("./builtin-descriptors").DocumentedSpecs<{
1620
+ readonly title: {
1621
+ readonly kind: 'string';
1622
+ readonly labelId: 'widgetLabelTitle';
1623
+ };
1624
+ readonly columns: {
1625
+ readonly kind: 'list';
1626
+ readonly maxItems: 24;
1627
+ readonly labelId: 'widgetLabelColumns';
1628
+ readonly helpId: 'widgetHintColumns';
1629
+ readonly item: {
1630
+ readonly measurement: {
1631
+ readonly kind: 'string';
1632
+ readonly required: true;
1633
+ readonly labelId: 'widgetLabelMeasurement';
1634
+ };
1635
+ readonly label: {
1636
+ readonly kind: 'string';
1637
+ readonly labelId: 'widgetLabelColumnHeading';
1638
+ };
1639
+ readonly unit: {
1640
+ readonly kind: 'string';
1641
+ readonly labelId: 'widgetLabelUnit';
1642
+ };
1643
+ readonly precision: {
1644
+ readonly kind: 'number';
1645
+ readonly integer: true;
1646
+ readonly min: 0;
1647
+ readonly max: 100;
1648
+ readonly labelId: 'widgetLabelPrecision';
1649
+ readonly helpId: 'widgetHintPrecision';
1650
+ };
1651
+ };
1652
+ };
1653
+ readonly precision: {
1654
+ readonly kind: 'number';
1655
+ readonly integer: true;
1656
+ readonly min: 0;
1657
+ readonly max: 100;
1658
+ readonly labelId: 'widgetLabelPrecision';
1659
+ readonly helpId: 'widgetHintPrecision';
1660
+ };
1661
+ readonly oldestFirst: {
1662
+ readonly kind: "boolean";
1663
+ readonly labelId: "widgetLabelOldestFirst";
1664
+ };
1665
+ readonly pageSize: {
1666
+ readonly kind: "number";
1667
+ readonly integer: true;
1668
+ readonly min: 5;
1669
+ readonly max: 100;
1670
+ readonly labelId: "widgetLabelRowsPerPage";
1671
+ };
1672
+ readonly staleAfterSeconds: {
1673
+ readonly kind: 'number';
1674
+ readonly integer: true;
1675
+ readonly min: 1;
1676
+ readonly labelId: 'widgetLabelStaleAfter';
1677
+ readonly helpId: 'widgetHintStaleAfter';
1678
+ };
1679
+ readonly windowSeconds: {
1680
+ readonly kind: 'number';
1681
+ readonly integer: true;
1682
+ readonly min: 60;
1683
+ readonly max: 604800;
1684
+ readonly labelId: 'widgetLabelWindowSeconds';
1685
+ readonly helpId: 'widgetHintWindowSeconds';
1686
+ };
1687
+ }>>;
1619
1688
  };
1620
1689
  export declare const builtinWidgetCatalog: import("@devicechain/dashboards").WidgetCatalog;
1621
1690
  export declare const builtinWidgetDefinitions: readonly [import("@devicechain/widget-sdk").WidgetDefinition<"measurement", import("./builtin-descriptors").DocumentedSpecs<{
@@ -3205,6 +3274,74 @@ export declare const builtinWidgetDefinitions: readonly [import("@devicechain/wi
3205
3274
  readonly labelId: 'widgetLabelStaleAfter';
3206
3275
  readonly helpId: 'widgetHintStaleAfter';
3207
3276
  };
3277
+ }>>, import("@devicechain/widget-sdk").WidgetDefinition<"measurement", import("./builtin-descriptors").DocumentedSpecs<{
3278
+ readonly title: {
3279
+ readonly kind: 'string';
3280
+ readonly labelId: 'widgetLabelTitle';
3281
+ };
3282
+ readonly columns: {
3283
+ readonly kind: 'list';
3284
+ readonly maxItems: 24;
3285
+ readonly labelId: 'widgetLabelColumns';
3286
+ readonly helpId: 'widgetHintColumns';
3287
+ readonly item: {
3288
+ readonly measurement: {
3289
+ readonly kind: 'string';
3290
+ readonly required: true;
3291
+ readonly labelId: 'widgetLabelMeasurement';
3292
+ };
3293
+ readonly label: {
3294
+ readonly kind: 'string';
3295
+ readonly labelId: 'widgetLabelColumnHeading';
3296
+ };
3297
+ readonly unit: {
3298
+ readonly kind: 'string';
3299
+ readonly labelId: 'widgetLabelUnit';
3300
+ };
3301
+ readonly precision: {
3302
+ readonly kind: 'number';
3303
+ readonly integer: true;
3304
+ readonly min: 0;
3305
+ readonly max: 100;
3306
+ readonly labelId: 'widgetLabelPrecision';
3307
+ readonly helpId: 'widgetHintPrecision';
3308
+ };
3309
+ };
3310
+ };
3311
+ readonly precision: {
3312
+ readonly kind: 'number';
3313
+ readonly integer: true;
3314
+ readonly min: 0;
3315
+ readonly max: 100;
3316
+ readonly labelId: 'widgetLabelPrecision';
3317
+ readonly helpId: 'widgetHintPrecision';
3318
+ };
3319
+ readonly oldestFirst: {
3320
+ readonly kind: "boolean";
3321
+ readonly labelId: "widgetLabelOldestFirst";
3322
+ };
3323
+ readonly pageSize: {
3324
+ readonly kind: "number";
3325
+ readonly integer: true;
3326
+ readonly min: 5;
3327
+ readonly max: 100;
3328
+ readonly labelId: "widgetLabelRowsPerPage";
3329
+ };
3330
+ readonly staleAfterSeconds: {
3331
+ readonly kind: 'number';
3332
+ readonly integer: true;
3333
+ readonly min: 1;
3334
+ readonly labelId: 'widgetLabelStaleAfter';
3335
+ readonly helpId: 'widgetHintStaleAfter';
3336
+ };
3337
+ readonly windowSeconds: {
3338
+ readonly kind: 'number';
3339
+ readonly integer: true;
3340
+ readonly min: 60;
3341
+ readonly max: 604800;
3342
+ readonly labelId: 'widgetLabelWindowSeconds';
3343
+ readonly helpId: 'widgetHintWindowSeconds';
3344
+ };
3208
3345
  }>>];
3209
3346
  export declare function createBuiltinWidgetRegistry(): WidgetRegistry;
3210
3347
  export declare const WIDGET_OPTIONS: {
@@ -4823,4 +4960,73 @@ export declare const WIDGET_OPTIONS: {
4823
4960
  readonly helpId: 'widgetHintStaleAfter';
4824
4961
  };
4825
4962
  }>;
4963
+ readonly 'history-table': import("./builtin-descriptors").DocumentedSpecs<{
4964
+ readonly title: {
4965
+ readonly kind: 'string';
4966
+ readonly labelId: 'widgetLabelTitle';
4967
+ };
4968
+ readonly columns: {
4969
+ readonly kind: 'list';
4970
+ readonly maxItems: 24;
4971
+ readonly labelId: 'widgetLabelColumns';
4972
+ readonly helpId: 'widgetHintColumns';
4973
+ readonly item: {
4974
+ readonly measurement: {
4975
+ readonly kind: 'string';
4976
+ readonly required: true;
4977
+ readonly labelId: 'widgetLabelMeasurement';
4978
+ };
4979
+ readonly label: {
4980
+ readonly kind: 'string';
4981
+ readonly labelId: 'widgetLabelColumnHeading';
4982
+ };
4983
+ readonly unit: {
4984
+ readonly kind: 'string';
4985
+ readonly labelId: 'widgetLabelUnit';
4986
+ };
4987
+ readonly precision: {
4988
+ readonly kind: 'number';
4989
+ readonly integer: true;
4990
+ readonly min: 0;
4991
+ readonly max: 100;
4992
+ readonly labelId: 'widgetLabelPrecision';
4993
+ readonly helpId: 'widgetHintPrecision';
4994
+ };
4995
+ };
4996
+ };
4997
+ readonly precision: {
4998
+ readonly kind: 'number';
4999
+ readonly integer: true;
5000
+ readonly min: 0;
5001
+ readonly max: 100;
5002
+ readonly labelId: 'widgetLabelPrecision';
5003
+ readonly helpId: 'widgetHintPrecision';
5004
+ };
5005
+ readonly oldestFirst: {
5006
+ readonly kind: "boolean";
5007
+ readonly labelId: "widgetLabelOldestFirst";
5008
+ };
5009
+ readonly pageSize: {
5010
+ readonly kind: "number";
5011
+ readonly integer: true;
5012
+ readonly min: 5;
5013
+ readonly max: 100;
5014
+ readonly labelId: "widgetLabelRowsPerPage";
5015
+ };
5016
+ readonly staleAfterSeconds: {
5017
+ readonly kind: 'number';
5018
+ readonly integer: true;
5019
+ readonly min: 1;
5020
+ readonly labelId: 'widgetLabelStaleAfter';
5021
+ readonly helpId: 'widgetHintStaleAfter';
5022
+ };
5023
+ readonly windowSeconds: {
5024
+ readonly kind: 'number';
5025
+ readonly integer: true;
5026
+ readonly min: 60;
5027
+ readonly max: 604800;
5028
+ readonly labelId: 'widgetLabelWindowSeconds';
5029
+ readonly helpId: 'widgetHintWindowSeconds';
5030
+ };
5031
+ }>;
4826
5032
  };
@@ -0,0 +1,24 @@
1
+ import { type FleetMember, type MeasurementSample } from '@devicechain/dashboards';
2
+ import { type WidgetExportTable } from '@devicechain/widget-sdk';
3
+ import { type SortKey } from './fleet-model';
4
+ export interface SamplesExportInputs {
5
+ subject: string;
6
+ samples: readonly MeasurementSample[];
7
+ unit?: string;
8
+ precision?: number;
9
+ seriesIs: 'measurement' | 'device';
10
+ spanSeconds?: number;
11
+ }
12
+ export declare function samplesExport(i: SamplesExportInputs): WidgetExportTable;
13
+ export interface FleetExportInputs {
14
+ subject: string;
15
+ members: readonly FleetMember[];
16
+ total: number;
17
+ columns: ReadonlyArray<{
18
+ name: string;
19
+ heading: string;
20
+ precision?: number;
21
+ }>;
22
+ sort: SortKey;
23
+ }
24
+ export declare function fleetExport(i: FleetExportInputs): WidgetExportTable;