@alert-whatif/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/WhatIfPage/index.tsx","../src/util/animations.ts","../src/components/ComputeTracePanel.tsx","../src/util/reduce-animation-timing.ts","../src/styles.ts","../src/storage/grafana-history-store.ts","../src/util/format.ts","../src/components/DatasetPicker.tsx","../src/components/EvalErrorPanel.tsx","../src/components/LiveScrubControls.tsx","../src/calc/state.ts","../src/components/LiveStatusStrip.tsx","../src/chart/MetricChart.tsx","../src/util/event-colors.ts","../src/chart/constants.ts","../src/chart/geometry.ts","../src/chart/ticks.ts","../src/calc/crossings.ts","../src/chart/transitions.ts","../src/chart/format.ts","../src/chart/styles.ts","../src/chart/ChartTitle.tsx","../src/chart/ChartOverlay.tsx","../src/components/OverviewStrip.tsx","../src/components/SeriesPicker.tsx","../src/components/ModeToggle.tsx","../src/components/PageLayout.tsx","../src/components/ParamControls.tsx","../src/components/ReplayButtons.tsx","../src/components/ReplaySliderBar.tsx","../src/components/RulePicker.tsx","../src/data/parse-rule.ts","../src/live/use-live-mode.ts","../src/live/live-poller.ts","../src/storage/dataset-io.ts","../src/WhatIfPage/constants.ts","../src/WhatIfPage/helpers.ts","../src/components/ThemeToggle.tsx","../src/util/use-theme.ts","../src/util/describe-error.ts"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n computeEffectiveStepMs,\n deriveEvalGridOffsetMs,\n downsampleToStep,\n evaluate,\n planFetch,\n parseGrafanaAlertRule,\n scheduleTickTimes,\n type AlertConfig,\n type EvalEvent,\n type Sample,\n type Tick,\n} from '@alert-whatif/core';\nimport { animationScope } from '../util/animations';\nimport { ComputeTracePanel } from '../components/ComputeTracePanel';\nimport {\n loadGrafanaHistory,\n saveGrafanaHistory,\n type GrafanaHistoryEntry,\n} from '../storage/grafana-history-store';\nimport { DatasetPicker } from '../components/DatasetPicker';\nimport { EvalErrorPanel } from '../components/EvalErrorPanel';\nimport { LiveScrubControls } from '../components/LiveScrubControls';\nimport { LiveStatusStrip } from '../components/LiveStatusStrip';\nimport { MetricChart } from '../chart/MetricChart';\nimport { OverviewStrip } from '../components/OverviewStrip';\nimport { SeriesPicker } from '../components/SeriesPicker';\nimport type { ThresholdCrossing } from '../calc/crossings';\nimport { ModeToggle } from '../components/ModeToggle';\nimport { PageLayout } from '../components/PageLayout';\nimport { ParamControls } from '../components/ParamControls';\nimport { ReplayButtons, type Speed } from '../components/ReplayButtons';\nimport { ReplaySliderBar } from '../components/ReplaySliderBar';\nimport { RulePicker } from '../components/RulePicker';\nimport { extractRuleMetadata, extractRuleQuery } from '../data/parse-rule';\nimport { formatAlertExpression } from '../util/format';\nimport { reduceAnimationDurationMs } from '../util/reduce-animation-timing';\nimport { useLiveMode } from '../live/use-live-mode';\nimport {\n downloadDataset,\n loadCapturedDatasets,\n parseDataset,\n saveCapturedDatasets,\n} from '../storage/dataset-io';\nimport type {\n Dataset,\n GrafanaRuleObservation,\n RuleSummary,\n WhatIfDataSource,\n} from '../data/data-source';\nimport type { ReactNode } from 'react';\nimport type { ConfigOverrides, LiveContext, Props, WhatIfPreset } from './types';\nimport {\n AUTO_REPLAY_SPEEDUP,\n LIVE_INTERVAL_SEC,\n LIVE_LOOKBACK_SEC,\n LIVE_SCRUB_MAX_MS,\n MIN_AUTOPLAY_WAIT_MS,\n OVERVIEW_DEFAULT_LOOKBACK_SEC,\n OVERVIEW_RANGE_OPTIONS,\n PLACEHOLDER_CONFIG,\n} from './constants';\nimport {\n applyConfigOverrides,\n changedParamLabels,\n mockRightAnchorT,\n} from './helpers';\nimport {\n currentStateForTick,\n mockPlayheadGrafanaState,\n} from '../calc/state';\n\nexport type { ConfigOverrides, WhatIfPreset, LiveContext } from './types';\n\nexport function WhatIfPage({\n adapter,\n themeToggleSlot,\n liveContext,\n initialRuleUid,\n initialPreset,\n initialLookbackSec,\n initialDrill,\n initialPlay,\n titleLogo,\n}: Props) {\n const fixtures = useMemo<ReadonlyArray<Dataset>>(\n () => (adapter.capabilities.fixtures ? adapter.listFixtures!() : []),\n [adapter],\n );\n\n const hasContentSource =\n fixtures.length > 0 ||\n liveContext !== undefined ||\n adapter.capabilities.fetchRuleList;\n\n if (!hasContentSource) {\n return (\n <PageLayout\n headerLeft={renderTitle(titleLogo)}\n themeToggle={themeToggleSlot}\n main={<EmptyMessage text=\"No fixtures and no rule source available.\" />}\n bottomLeft={null}\n bottomRight={null}\n />\n );\n }\n\n return (\n <PageShell\n adapter={adapter}\n fixtures={fixtures}\n themeToggleSlot={themeToggleSlot}\n {...(liveContext !== undefined ? { liveContext } : {})}\n {...(initialRuleUid !== undefined ? { initialRuleUid } : {})}\n {...(initialPreset !== undefined ? { initialPreset } : {})}\n {...(initialLookbackSec !== undefined ? { initialLookbackSec } : {})}\n {...(initialDrill !== undefined ? { initialDrill } : {})}\n {...(initialPlay !== undefined ? { initialPlay } : {})}\n {...(titleLogo !== undefined ? { titleLogo } : {})}\n />\n );\n}\n\nfunction renderTitle(logo: ReactNode | undefined): ReactNode {\n return (\n <h1 style={titleStyle}>\n {logo !== undefined && <span style={titleLogoStyle}>{logo}</span>}\n alert-whatif\n </h1>\n );\n}\n\n// Split from the top-level export so the fixture-availability check above\n// can early-return without violating React's rules-of-hooks.\nfunction PageShell({\n adapter,\n fixtures,\n themeToggleSlot,\n liveContext: propLiveContext,\n initialRuleUid,\n initialPreset,\n initialLookbackSec,\n initialDrill,\n initialPlay,\n titleLogo,\n}: {\n readonly adapter: WhatIfDataSource;\n readonly fixtures: ReadonlyArray<Dataset>;\n readonly themeToggleSlot?: ReactNode;\n readonly liveContext?: LiveContext;\n readonly initialRuleUid?: string;\n readonly initialPreset?: WhatIfPreset;\n readonly initialLookbackSec?: number;\n readonly initialDrill?: 'first' | 'last';\n readonly initialPlay?: boolean;\n readonly titleLogo?: ReactNode;\n}) {\n const ruleListEnabled =\n adapter.capabilities.fetchRuleList && propLiveContext === undefined;\n const [rules, setRules] = useState<ReadonlyArray<RuleSummary>>([]);\n const [rulesLoading, setRulesLoading] = useState<boolean>(ruleListEnabled);\n const [rulesError, setRulesError] = useState<string | null>(null);\n const [rulesReloadTick, setRulesReloadTick] = useState<number>(0);\n const [selectedRuleUid, setSelectedRuleUid] = useState<string | null>(\n initialRuleUid ?? null,\n );\n const [internalLiveContext, setInternalLiveContext] = useState<LiveContext | null>(null);\n // Fixed sample window for a selected rule, rendered in mock mode. In-memory\n // only — every rule pick refreshes.\n const [internalRuleDataset, setInternalRuleDataset] = useState<Dataset | null>(null);\n const [internalRuleError, setInternalRuleError] = useState<string | null>(null);\n // Alert state just before the detail-chart window's left edge — feeds\n // evalHints to remove the leading-Pending phantom from the state bar.\n const [detailInitialState, setDetailInitialState] = useState<\n 'Normal' | 'Firing' | 'NoData' | null\n >(null);\n\n // On first successful load with no rule pre-selected, auto-pick the first\n // rule so the user lands on the chart with zero clicks.\n useEffect(() => {\n if (!ruleListEnabled) return;\n let cancelled = false;\n setRulesLoading(true);\n setRulesError(null);\n void (async () => {\n const result = await adapter.listRules!();\n if (cancelled) return;\n if (result.kind === 'Ok') {\n setRules(result.value);\n if (result.value.length > 0) {\n setSelectedRuleUid((prev) => prev ?? result.value[0]!.uid);\n }\n } else {\n setRulesError(result.errors.join(' · '));\n }\n setRulesLoading(false);\n })();\n return () => {\n cancelled = true;\n };\n }, [ruleListEnabled, adapter, rulesReloadTick]);\n\n // On rule selection, parse the rule and populate internalLiveContext so a\n // later Mock → Live toggle works without an extra fetch.\n useEffect(() => {\n if (!ruleListEnabled) return;\n if (selectedRuleUid === null) {\n setInternalLiveContext(null);\n setInternalRuleDataset(null);\n setInternalRuleError(null);\n return;\n }\n let cancelled = false;\n setInternalRuleError(null);\n void (async () => {\n const rule = await adapter.fetchRuleByUid!(selectedRuleUid);\n if (cancelled) return;\n if (rule === null) {\n setInternalRuleError(`Could not fetch rule \"${selectedRuleUid}\".`);\n setInternalLiveContext(null);\n setInternalRuleDataset(null);\n return;\n }\n const parseResult = parseGrafanaAlertRule(rule);\n if (parseResult.kind === 'Err') {\n setInternalRuleError(parseResult.errors.join(' · '));\n setInternalLiveContext(null);\n setInternalRuleDataset(null);\n return;\n }\n const query = extractRuleQuery(rule);\n const metadata = extractRuleMetadata(rule);\n if (query === null) {\n setInternalRuleError(\n 'Rule has no query node (datasourceUID + expr) we can poll.',\n );\n setInternalLiveContext(null);\n setInternalRuleDataset(null);\n return;\n }\n\n const title = metadata?.title ?? selectedRuleUid;\n setInternalLiveContext({\n datasourceUid: query.datasourceUid,\n query: query.expr,\n ruleTitle: title,\n defaultConfig: parseResult.value,\n ...(metadata !== null ? { ruleMetadata: metadata } : {}),\n });\n\n setInternalRuleDataset(null);\n })();\n return () => {\n cancelled = true;\n };\n }, [ruleListEnabled, selectedRuleUid, adapter]);\n\n // Prop wins over internal selection.\n const liveContext = propLiveContext ?? internalLiveContext ?? undefined;\n // `liveAvailable`: a Live context exists now. `liveAccessible`: the user\n // CAN enter Live even if no context yet (RulePicker fetches one on select).\n const liveAvailable = liveContext !== undefined;\n const liveAccessible =\n adapter.capabilities.live &&\n (propLiveContext !== undefined || adapter.capabilities.fetchRuleList);\n\n // Captured / imported datasets — user-owned, persisted to localStorage.\n const [capturedDatasets, setCapturedDatasets] = useState<ReadonlyArray<Dataset>>(\n () => loadCapturedDatasets(),\n );\n useEffect(() => {\n saveCapturedDatasets(capturedDatasets);\n }, [capturedDatasets]);\n\n // Picker order: fetched rule dataset first, then captured snapshots\n // (newest first), then bundled fixtures.\n const allDatasets = useMemo<ReadonlyArray<Dataset>>(() => {\n const items: Dataset[] = [];\n if (internalRuleDataset !== null) items.push(internalRuleDataset);\n items.push(...[...capturedDatasets].reverse(), ...fixtures);\n return items;\n }, [internalRuleDataset, capturedDatasets, fixtures]);\n const fixturesAvailable = allDatasets.length > 0;\n\n const [mode, setMode] = useState<'mock' | 'live'>(\n ruleListEnabled\n ? 'mock'\n : fixturesAvailable || !liveAccessible\n ? 'mock'\n : 'live',\n );\n\n const [selectedDatasetId, setSelectedDatasetId] = useState<string>(() => {\n if (!fixturesAvailable) return '';\n const presetId = initialPreset?.datasetId;\n if (presetId !== undefined && allDatasets.some((d) => d.id === presetId)) {\n return presetId;\n }\n return allDatasets[0]!.id;\n });\n const dataset = fixturesAvailable\n ? (allDatasets.find((d) => d.id === selectedDatasetId) ?? allDatasets[0]!)\n : null;\n\n // `workingConfig` drives chart/evaluator/fetch, changing only on Apply.\n // `draftConfig` is what ParamControls edits; Apply copies draft → working.\n const initialConfig =\n dataset?.defaultAlertConfig ?? liveContext?.defaultConfig ?? PLACEHOLDER_CONFIG;\n // Seed both from a deep-link preset so it lands already \"Applied\" — never\n // applied to the bare placeholder.\n const seededConfig =\n initialPreset?.overrides !== undefined && (dataset !== null || liveContext !== undefined)\n ? applyConfigOverrides(initialConfig, initialPreset.overrides)\n : initialConfig;\n const [workingConfig, setWorkingConfig] = useState<AlertConfig>(seededConfig);\n const [draftConfig, setDraftConfig] = useState<AlertConfig>(seededConfig);\n\n // Re-seed both on Live rule switch — unapplied drafts are dropped.\n useEffect(() => {\n if (liveContext !== undefined) {\n setWorkingConfig(liveContext.defaultConfig);\n setDraftConfig(liveContext.defaultConfig);\n }\n }, [liveContext?.defaultConfig]);\n\n // Range rules mirror Grafana's rule-editor formula; instant rules use\n // intervalMs as-is. Reads workingConfig so refetch fires only after Apply.\n const effectiveStepMs = workingConfig.instant\n ? workingConfig.intervalMs\n : computeEffectiveStepMs({\n intervalMs: workingConfig.intervalMs,\n maxDataPoints: workingConfig.maxDataPoints,\n timeRangeMs: workingConfig.windowDuration,\n });\n\n // Separated from the fetch so tweaking intervalMs re-fetches the drill\n // view at the same moment but new step.\n const [drillTarget, setDrillTarget] = useState<{\n readonly anchorMs: number;\n readonly kind: EvalEvent['kind'];\n } | null>(null);\n\n // A new in-memory dataset forces Mock mode showing it.\n useEffect(() => {\n if (internalRuleDataset === null) return;\n setSelectedDatasetId(internalRuleDataset.id);\n setMode('mock');\n }, [internalRuleDataset]);\n\n // The actual fetch happens in the useEffect below.\n const drillToMoment = (anchorMs: number, kind: EvalEvent['kind']): void => {\n setDrillTarget({ anchorMs, kind });\n };\n\n // Keyed on drillTarget AND effectiveStepMs so the drill dataset is rebuilt\n // at the new step when Apply runs.\n useEffect(() => {\n if (drillTarget === null) return;\n if (internalLiveContext === null || selectedRuleUid === null) return;\n const { anchorMs, kind } = drillTarget;\n const centerSec = Math.floor(anchorMs / 1000);\n const plan = planFetch({\n config: workingConfig,\n range: { kind: 'centered', centerSec, radiusSec: 15 * 60 },\n stepSec: effectiveStepMs / 1000,\n warmup: true,\n });\n // 🔕 (Resolved) reads backward; everything else reads forward.\n const drillFocalSide: 'leading' | 'trailing' =\n kind === 'Resolved' ? 'trailing' : 'leading';\n let cancelled = false;\n void (async () => {\n const samplesP = adapter.fetchSamples({\n datasourceUid: internalLiveContext.datasourceUid,\n expr: internalLiveContext.query,\n startSec: plan.fetchStartSec,\n endSec: plan.fetchEndSec,\n stepSec: plan.stepSec,\n });\n // Read Grafana's lastEvaluation → evalGridOffsetMs so the tick grid\n // lands on the same sub-minute offset Grafana uses (else Pending shows\n // one tick late vs the GRAFANA bar).\n const ruleStateP =\n adapter.fetchRuleState !== undefined\n ? adapter.fetchRuleState(internalLiveContext.ruleTitle).catch(\n (): GrafanaRuleObservation => ({\n state: 'unknown',\n lastEvaluationMs: null,\n }),\n )\n : Promise.resolve(null);\n // Fetch state-transition annotations so the GRAFANA bar renders even\n // when this session never polled this rule live.\n const historyP = adapter.capabilities.alertHistoryOracle\n ? adapter\n .fetchAlertHistory!(internalLiveContext.ruleTitle, plan.startTimeMs, plan.endTimeMs)\n .catch(() => null)\n : Promise.resolve(null);\n const [result, ruleObservation, historyResult] = await Promise.all([\n samplesP,\n ruleStateP,\n historyP,\n ]);\n if (cancelled || result.kind !== 'Ok') return;\n const lastEvalMs =\n ruleObservation !== null ? ruleObservation.lastEvaluationMs : null;\n const evalGridOffsetMs = deriveEvalGridOffsetMs(\n lastEvalMs,\n internalLiveContext.defaultConfig.evaluationInterval,\n );\n const grafanaHistoryForDrill =\n historyResult !== null && historyResult.kind === 'Ok' ? historyResult.value : undefined;\n const stamp = new Date(centerSec * 1000).toISOString().slice(11, 19);\n const seriesList = result.value;\n const firstSamples = seriesList[0]?.samples ?? [];\n setInternalRuleDataset({\n id: `rule:${selectedRuleUid}:drill:${centerSec}:${effectiveStepMs}`,\n displayName: `${internalLiveContext.ruleTitle} @ ${stamp}Z`,\n description: `30 min around ${new Date(centerSec * 1000).toISOString()} (drill-down from overview)`,\n source: `Drill-down ${internalLiveContext.query}`,\n samples: firstSamples,\n seriesList,\n defaultAlertConfig: internalLiveContext.defaultConfig,\n startTimeMs: plan.startTimeMs,\n endTimeMs: plan.endTimeMs,\n drillFocalMs: anchorMs,\n drillFocalSide,\n ...(evalGridOffsetMs !== undefined ? { evalGridOffsetMs } : {}),\n ...(internalLiveContext.ruleMetadata !== undefined\n ? { ruleMetadata: internalLiveContext.ruleMetadata }\n : {}),\n ...(grafanaHistoryForDrill !== undefined && grafanaHistoryForDrill.length > 0\n ? { grafanaHistory: grafanaHistoryForDrill }\n : {}),\n });\n })();\n return () => {\n cancelled = true;\n };\n }, [drillTarget, effectiveStepMs, internalLiveContext, selectedRuleUid, adapter]);\n\n const [selectedSeriesIdx, setSelectedSeriesIdx] = useState<number>(0);\n // Previous fetch's series-label signature, so the effect below resets the\n // index only when the label set actually changes.\n const lastSeriesSignatureRef = useRef<string>('');\n\n const [overviewLookbackSec, setOverviewLookbackSec] = useState<number>(() =>\n initialLookbackSec !== undefined &&\n OVERVIEW_RANGE_OPTIONS.some((o) => o.lookbackSec === initialLookbackSec)\n ? initialLookbackSec\n : OVERVIEW_DEFAULT_LOOKBACK_SEC,\n );\n\n // Mock-mode auto-dataset: freeze a fixed 30-min window for the picked rule\n // so the mock pipeline (chart + scrubber + ParamControls) has data.\n useEffect(() => {\n if (!ruleListEnabled) return;\n if (mode !== 'mock') return;\n if (selectedRuleUid === null || internalLiveContext === null) return;\n // Deep-link auto-drill pending: skip the throwaway mock window so it\n // doesn't flash an unrelated lifecycle before the drill lands.\n if (initialDrill !== undefined && internalRuleDataset === null) return;\n // Drill datasets are kept as-is; the mock dataset encodes intervalMs in\n // its id so a tweak forces a refetch at the new Prometheus step.\n const drillPrefix = `rule:${selectedRuleUid}:drill:`;\n const mockDatasetId = `rule:${selectedRuleUid}:mock:${effectiveStepMs}`;\n if (internalRuleDataset?.id.startsWith(drillPrefix)) return;\n if (internalRuleDataset?.id === mockDatasetId) return;\n let cancelled = false;\n void (async () => {\n const plan = planFetch({\n config: internalLiveContext.defaultConfig,\n range: {\n kind: 'lookback',\n nowSec: Math.floor(Date.now() / 1000),\n lookbackSec: LIVE_LOOKBACK_SEC,\n },\n stepSec: effectiveStepMs / 1000,\n warmup: true,\n });\n const samplesP = adapter.fetchSamples({\n datasourceUid: internalLiveContext.datasourceUid,\n expr: internalLiveContext.query,\n startSec: plan.fetchStartSec,\n endSec: plan.fetchEndSec,\n stepSec: plan.stepSec,\n });\n const initialStateP = adapter.capabilities.initialStateOracle\n ? adapter.fetchInitialAlertState!(internalLiveContext.ruleTitle, plan.startTimeMs)\n : Promise.resolve(null);\n // lastEvaluation → same grid offset as Live's phase-lock, so What-If\n // and Live agree on Pending start times for the same alarm.\n const ruleStateP =\n adapter.fetchRuleState !== undefined\n ? adapter.fetchRuleState(internalLiveContext.ruleTitle).catch(\n (): GrafanaRuleObservation => ({\n state: 'unknown',\n lastEvaluationMs: null,\n }),\n )\n : Promise.resolve(null);\n // State-transition annotations so the chart's grafana bar populates\n // alongside our state bar (the side-by-side view, issue #153).\n const historyP = adapter.capabilities.alertHistoryOracle\n ? adapter\n .fetchAlertHistory!(internalLiveContext.ruleTitle, plan.startTimeMs, plan.endTimeMs)\n .catch(() => null)\n : Promise.resolve(null);\n const [result, initialResult, ruleObservation, historyResult] = await Promise.all([\n samplesP,\n initialStateP,\n ruleStateP,\n historyP,\n ]);\n if (cancelled || result.kind !== 'Ok') return;\n const lastEvalMs =\n ruleObservation !== null ? ruleObservation.lastEvaluationMs : null;\n const evalGridOffsetMs = deriveEvalGridOffsetMs(\n lastEvalMs,\n internalLiveContext.defaultConfig.evaluationInterval,\n );\n const grafanaHistoryForMock =\n historyResult !== null && historyResult.kind === 'Ok' ? historyResult.value : undefined;\n const seriesList = result.value;\n const firstSamples = seriesList[0]?.samples ?? [];\n setInternalRuleDataset({\n id: mockDatasetId,\n displayName: internalLiveContext.ruleTitle,\n description: `Last 30 min of \"${internalLiveContext.ruleTitle}\" — fetched ${new Date().toISOString().slice(11, 19)}Z`,\n source: `Mock view of Grafana rule ${selectedRuleUid}`,\n samples: firstSamples,\n seriesList,\n defaultAlertConfig: internalLiveContext.defaultConfig,\n startTimeMs: plan.startTimeMs,\n endTimeMs: plan.endTimeMs,\n ...(evalGridOffsetMs !== undefined ? { evalGridOffsetMs } : {}),\n ...(internalLiveContext.ruleMetadata !== undefined\n ? { ruleMetadata: internalLiveContext.ruleMetadata }\n : {}),\n ...(grafanaHistoryForMock !== undefined && grafanaHistoryForMock.length > 0\n ? { grafanaHistory: grafanaHistoryForMock }\n : {}),\n });\n // Set here too (not just the cross-mode effect) — saves a re-fetch\n // since samples + initialState arrive in the same Promise.all.\n setDetailInitialState(\n initialResult !== null && initialResult.kind === 'Ok'\n ? initialResult.value\n : null,\n );\n })();\n return () => {\n cancelled = true;\n };\n }, [mode, ruleListEnabled, selectedRuleUid, internalLiveContext, adapter, internalRuleDataset, effectiveStepMs, initialDrill]);\n\n // Long-range overview samples for the <OverviewStrip>. Coarse on purpose\n // — orientation only, not the precision surface where ParamControls operate.\n const [overviewSamples, setOverviewSamples] = useState<ReadonlyArray<Sample>>([]);\n const [overviewStartMs, setOverviewStartMs] = useState<number | null>(null);\n // Alert state just before the overview window's left edge, fed to the\n // evaluator as `initialState` to drop the phantom Pending at windowStart.\n // `null` while pending or unsupported; CORE then keeps its 'Normal' default.\n const [overviewInitialState, setOverviewInitialState] = useState<\n 'Normal' | 'Firing' | 'NoData' | null\n >(null);\n const [overviewLoading, setOverviewLoading] = useState<boolean>(false);\n useEffect(() => {\n if (!ruleListEnabled || internalLiveContext === null) {\n setOverviewSamples([]);\n setOverviewInitialState(null);\n return;\n }\n const opt =\n OVERVIEW_RANGE_OPTIONS.find((o) => o.lookbackSec === overviewLookbackSec) ??\n OVERVIEW_RANGE_OPTIONS[0]!;\n if (opt.lookbackSec === 0) {\n setOverviewSamples([]);\n setOverviewInitialState(null);\n setOverviewLoading(false);\n return;\n }\n let cancelled = false;\n setOverviewLoading(true);\n void (async () => {\n const nowSec = Math.floor(Date.now() / 1000);\n // Instant rules need `tick.t === sample.t` exactly, so force fetch\n // step = eval interval (else every tick falls in a gap → all NoData →\n // empty strip). Range rules tolerate the coarser strip step.\n const baseline = internalLiveContext.defaultConfig;\n const isInstant = baseline.instant;\n const stepSec = isInstant\n ? Math.max(1, Math.floor(baseline.evaluationInterval / 1000))\n : opt.stepSec;\n const plan = planFetch({\n config: baseline,\n range: { kind: 'lookback', nowSec, lookbackSec: opt.lookbackSec },\n stepSec,\n warmup: true,\n });\n const samplesP = adapter.fetchSamples({\n datasourceUid: internalLiveContext.datasourceUid,\n expr: internalLiveContext.query,\n startSec: plan.fetchStartSec,\n endSec: plan.fetchEndSec,\n stepSec: plan.stepSec,\n });\n const initialStateP = adapter.capabilities.initialStateOracle\n ? adapter.fetchInitialAlertState!(internalLiveContext.ruleTitle, plan.startTimeMs)\n : Promise.resolve(null);\n const [result, initialResult] = await Promise.all([samplesP, initialStateP]);\n if (cancelled) return;\n setOverviewStartMs(plan.startTimeMs);\n if (result.kind === 'Ok') {\n // Follow the main chart's SeriesPicker selection so bells line up.\n const list = result.value;\n const idx = Math.min(selectedSeriesIdx, Math.max(list.length - 1, 0));\n setOverviewSamples(list[idx]?.samples ?? []);\n } else {\n setOverviewSamples([]);\n }\n setOverviewInitialState(\n initialResult !== null && initialResult.kind === 'Ok'\n ? initialResult.value\n : null,\n );\n setOverviewLoading(false);\n })();\n return () => {\n cancelled = true;\n };\n }, [ruleListEnabled, internalLiveContext, adapter, overviewLookbackSec, selectedSeriesIdx]);\n\n // Collapses What-If's `Current` lookback into Live's data-source path.\n // Guarded by `liveAccessible` so the demo build (capabilities.live=false,\n // Current lookback) doesn't flip to live and render \"No rule selected\"\n // forever despite a usable Mock fixture.\n const effectiveMode: 'live' | 'mock' =\n mode === 'mock' && overviewLookbackSec === 0 && liveAccessible ? 'live' : mode;\n\n const live = useLiveMode(\n {\n active: effectiveMode === 'live' && liveAvailable,\n datasourceUid: liveContext?.datasourceUid ?? '',\n query: liveContext?.query ?? '',\n ruleTitle: liveContext?.ruleTitle ?? '',\n intervalSec: LIVE_INTERVAL_SEC,\n lookbackSec: LIVE_LOOKBACK_SEC,\n stepSec: effectiveStepMs / 1000,\n evaluationIntervalMs: workingConfig.evaluationInterval,\n },\n adapter,\n );\n\n const [liveNow, setLiveNow] = useState<number>(() => Date.now());\n const [livePaused, setLivePaused] = useState<boolean>(false);\n const [scrubOffsetMs, setScrubOffsetMs] = useState<number>(0);\n // Fresh-start the scrub on lookback/rule change so a pause from a previous\n // session doesn't leave the chart frozen.\n useEffect(() => {\n setLivePaused(false);\n setScrubOffsetMs(0);\n }, [overviewLookbackSec, selectedRuleUid]);\n\n // 1 Hz wallclock ticker, decoupled from the 15-s sample poll, so the\n // chart's right edge and the NOW readout advance smoothly. Paused freezes it.\n useEffect(() => {\n if (effectiveMode !== 'live' || livePaused) return;\n setLiveNow(Date.now());\n const interval = setInterval(() => setLiveNow(Date.now()), 1000);\n return () => clearInterval(interval);\n }, [effectiveMode, livePaused]);\n\n // Grafana state-bar history, persisted by rule title.\n const ruleTitleKey = liveContext?.ruleTitle ?? '';\n const [grafanaHistory, setGrafanaHistory] = useState<\n ReadonlyArray<GrafanaHistoryEntry>\n >(() => loadGrafanaHistory(ruleTitleKey));\n\n useEffect(() => {\n setGrafanaHistory(loadGrafanaHistory(ruleTitleKey));\n }, [ruleTitleKey]);\n\n useEffect(() => {\n saveGrafanaHistory(ruleTitleKey, grafanaHistory);\n }, [ruleTitleKey, grafanaHistory]);\n\n // Lock-once initialState per rule selection: query the oracle once for the\n // first valid window, then keep it across poll-driven window-slides so the\n // evaluator's input is identical between Mock and Live for the same rule.\n useEffect(() => {\n setDetailInitialState(null);\n }, [selectedRuleUid]);\n const detailWindowStartMs =\n effectiveMode === 'live' ? live.samples[0]?.t : dataset?.samples[0]?.t;\n useEffect(() => {\n if (detailInitialState !== null) return;\n if (detailWindowStartMs === undefined) return;\n if (!adapter.capabilities.initialStateOracle) return;\n if (internalLiveContext === null) return;\n let cancelled = false;\n void (async () => {\n const result = await adapter.fetchInitialAlertState!(\n internalLiveContext.ruleTitle,\n detailWindowStartMs,\n );\n if (cancelled) return;\n setDetailInitialState(result.kind === 'Ok' ? result.value : null);\n })();\n return () => {\n cancelled = true;\n };\n }, [detailInitialState, detailWindowStartMs, adapter, internalLiveContext]);\n\n useEffect(() => {\n if (effectiveMode !== 'live') return;\n if (live.lastPollAt === null) return;\n // Stamp with Grafana's own `lastEvaluation` so the bar tracks its real\n // transition moment, not our poll arrival.\n const entryT = live.grafanaLatestEvalMs ?? live.lastPollAt;\n setGrafanaHistory((prev) => {\n const last = prev[prev.length - 1];\n if (last !== undefined && last.state === live.grafanaState) return prev;\n return [...prev, { t: entryT, state: live.grafanaState }];\n });\n // grafanaHistory intentionally not in deps — append-only effect.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [effectiveMode, live.grafanaState, live.lastPollAt, live.grafanaLatestEvalMs]);\n\n const jumpToLive = () => {\n setLivePaused(false);\n setScrubOffsetMs(0);\n if (live.lastPollAt !== null) setLiveNow(live.lastPollAt);\n };\n\n const togglePause = () => {\n if (livePaused) jumpToLive();\n else setLivePaused(true);\n };\n\n const onScrubChange = (offsetMs: number) => {\n setScrubOffsetMs(offsetMs);\n if (offsetMs !== 0 && !livePaused) setLivePaused(true);\n if (offsetMs === 0 && livePaused) jumpToLive();\n };\n\n // Live's poll-driven samples, or the frozen Dataset's selected series\n // (falling back to the legacy single `samples` field).\n const samplesRaw: ReadonlyArray<Sample> = (() => {\n if (effectiveMode === 'live') return live.samples;\n const list = dataset?.seriesList;\n if (list !== undefined && list.length > 0) {\n const idx = Math.min(selectedSeriesIdx, list.length - 1);\n return list[idx]!.samples;\n }\n return dataset?.samples ?? [];\n })();\n // Re-sample a frozen fixture to the effective step (no-op at recording\n // resolution or for already-step-spaced live data).\n const samples: ReadonlyArray<Sample> =\n effectiveMode === 'live'\n ? samplesRaw\n : downsampleToStep(samplesRaw, effectiveStepMs, dataset?.evalGridOffsetMs ?? 0);\n\n // Reset the series index only when the label set changes; an identical\n // signature across refetches preserves the user's pick.\n useEffect(() => {\n const list = dataset?.seriesList ?? [];\n const sig = list.map((s) => JSON.stringify(s.labels)).join('|');\n if (sig !== lastSeriesSignatureRef.current) {\n lastSeriesSignatureRef.current = sig;\n setSelectedSeriesIdx(0);\n }\n }, [dataset?.seriesList]);\n\n const tickTimes =\n samplesRaw.length > 0\n ? scheduleTickTimes(samplesRaw, workingConfig.evaluationInterval)\n : [];\n const tickCount = tickTimes.length;\n\n const clampTick = (t: number): number => Math.max(0, Math.min(Math.round(t), tickCount));\n const presetTickRef = useRef<number | undefined>(initialPreset?.tick);\n const [tickIndex, setTickIndex] = useState<number>(\n initialPreset?.tick !== undefined && tickCount > 0 ? clampTick(initialPreset.tick) : tickCount,\n );\n const [playing, setPlaying] = useState<boolean>(false);\n const [speed, setSpeed] = useState<Speed>(1);\n\n useEffect(() => {\n // Land at the last tick on dataset change, unless a deep-link preset tick\n // wins on first mount (then clears).\n if (presetTickRef.current !== undefined && tickCount > 0) {\n setTickIndex(clampTick(presetTickRef.current));\n presetTickRef.current = undefined;\n } else {\n setTickIndex(tickCount);\n }\n setPlaying(false);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selectedDatasetId, mode]);\n\n useEffect(() => {\n if (effectiveMode === 'live') {\n setTickIndex(tickCount);\n } else if (tickIndex > tickCount) {\n setTickIndex(tickCount);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tickCount, mode]);\n\n useEffect(() => {\n if (!playing) return;\n if (tickIndex >= tickCount) {\n setPlaying(false);\n autoReplayingRef.current = false;\n return;\n }\n const tickT = tickIndex > 0 ? tickTimes[tickIndex - 1]! : null;\n const windowDuration = workingConfig.instant ? 0 : workingConfig.windowDuration;\n const N =\n tickT === null || workingConfig.instant\n ? 0\n : samples.filter(\n (s) =>\n Number.isFinite(s.v) &&\n s.t > tickT - windowDuration &&\n s.t <= tickT,\n ).length;\n const animMs = reduceAnimationDurationMs(N);\n const speedFactor = autoReplayingRef.current ? speed * AUTO_REPLAY_SPEEDUP : speed;\n const waitMs = Math.max(MIN_AUTOPLAY_WAIT_MS, animMs) / speedFactor;\n const id = setTimeout(\n () => setTickIndex((i) => Math.min(i + 1, tickCount)),\n waitMs,\n );\n return () => clearTimeout(id);\n }, [playing, tickIndex, tickCount, speed, samples, tickTimes, workingConfig]);\n\n const visibleSamples =\n tickIndex >= tickCount\n ? samples\n : tickIndex <= 0\n ? []\n : samples.filter((s) => s.t <= tickTimes[tickIndex - 1]!);\n\n const selectDataset = (id: string) => {\n const next = allDatasets.find((d) => d.id === id);\n if (!next) return;\n setSelectedDatasetId(id);\n setWorkingConfig(next.defaultAlertConfig);\n };\n\n const [exportToast, setExportToast] = useState<string | null>(null);\n const exportToastTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const flashExportToast = (msg: string) => {\n if (exportToastTimerRef.current) clearTimeout(exportToastTimerRef.current);\n setExportToast(msg);\n exportToastTimerRef.current = setTimeout(() => setExportToast(null), 4000);\n };\n\n // Freeze the current Live samples into a Mock-mode Dataset; the current\n // workingConfig travels with the snapshot.\n const captureLiveSnapshot = () => {\n if (liveContext === undefined) return;\n if (live.samples.length === 0) return;\n const captureTime = new Date();\n const id = `live-snapshot-${captureTime.getTime()}`;\n const evalGridOffsetMs = deriveEvalGridOffsetMs(\n live.grafanaLastEvalMs,\n workingConfig.evaluationInterval,\n );\n const captured: Dataset = {\n id,\n displayName: `📸 Snapshot @ ${captureTime.toISOString().slice(11, 19)}Z`,\n description: `Captured from Live mode at ${captureTime.toISOString()} — ${live.samples.length} samples; rule \"${liveContext.ruleTitle}\".`,\n source: `Live capture (${liveContext.query})`,\n samples: live.samples,\n defaultAlertConfig: workingConfig,\n ...(liveContext.rateInnerWindow !== undefined\n ? { rateInnerWindow: liveContext.rateInnerWindow }\n : {}),\n ...(evalGridOffsetMs !== undefined ? { evalGridOffsetMs } : {}),\n };\n setCapturedDatasets((prev) => [...prev, captured]);\n setMode('mock');\n setSelectedDatasetId(id);\n };\n\n // Export the current scenario to JSON: Live bundles live.samples +\n // workingConfig; Mock serializes the selected dataset.\n const exportCurrent = () => {\n if (mode === 'live' && liveContext !== undefined) {\n if (live.samples.length === 0) return;\n const captureTime = new Date();\n const lastSampleT = live.samples[live.samples.length - 1]!.t;\n const evalGridOffsetMs = deriveEvalGridOffsetMs(\n live.grafanaLastEvalMs,\n workingConfig.evaluationInterval,\n );\n downloadDataset({\n id: `live-export-${captureTime.getTime()}`,\n displayName: `Live export @ ${captureTime.toISOString().slice(11, 19)}Z`,\n description: `Exported from Live mode at ${captureTime.toISOString()} — ${live.samples.length} samples; rule \"${liveContext.ruleTitle}\".`,\n source: `Live export (${liveContext.query})`,\n samples: live.samples,\n defaultAlertConfig: workingConfig,\n ...(liveContext.rateInnerWindow !== undefined\n ? { rateInnerWindow: liveContext.rateInnerWindow }\n : {}),\n ...(evalGridOffsetMs !== undefined ? { evalGridOffsetMs } : {}),\n });\n flashExportToast(\n `✓ Exported ${live.samples.length} samples · cutoff ${new Date(lastSampleT).toISOString().slice(11, 19)}Z`,\n );\n } else if (dataset !== null) {\n downloadDataset(dataset);\n flashExportToast(\n `✓ Exported \"${dataset.displayName}\" · ${dataset.samples.length} samples`,\n );\n }\n };\n\n // Validate a .json file, append to capturedDatasets, and switch to it.\n // ID collisions get a unique suffix so re-import doesn't overwrite.\n const importFromFile = async (file: File): Promise<{ ok: boolean; error?: string }> => {\n try {\n const text = await file.text();\n const result = parseDataset(text);\n if (result.kind === 'err') return { ok: false, error: result.error };\n const existingIds = new Set(allDatasets.map((d) => d.id));\n let finalId = result.dataset.id;\n let suffix = 1;\n while (existingIds.has(finalId)) {\n finalId = `${result.dataset.id}-${suffix}`;\n suffix += 1;\n }\n const datasetWithUniqueId =\n finalId === result.dataset.id ? result.dataset : { ...result.dataset, id: finalId };\n setCapturedDatasets((prev) => [...prev, datasetWithUniqueId]);\n setMode('mock');\n setSelectedDatasetId(finalId);\n setWorkingConfig(datasetWithUniqueId.defaultAlertConfig);\n return { ok: true };\n } catch (e) {\n return { ok: false, error: e instanceof Error ? e.message : String(e) };\n }\n };\n\n // Derived from whichever source knows Grafana's `lastEvaluation`. Naturally\n // stable (deterministic scheduler) and follows a schedule shift without a lock.\n const sharedGridOffsetMs: number | undefined =\n deriveEvalGridOffsetMs(live.grafanaLastEvalMs, workingConfig.evaluationInterval) ??\n dataset?.evalGridOffsetMs;\n const evalHints =\n effectiveMode === 'live'\n ? {\n ...(sharedGridOffsetMs !== undefined\n ? { evalGridOffsetMs: sharedGridOffsetMs }\n : {}),\n endTime: liveNow,\n ...(detailInitialState !== null ? { initialState: detailInitialState } : {}),\n }\n : effectiveMode === 'mock' && sharedGridOffsetMs !== undefined\n ? {\n evalGridOffsetMs: sharedGridOffsetMs,\n // Drill: skip endTime so the grid stops at the last visible\n // sample and the playhead overlaps the bell instead of walking\n // off-screen. Non-drill mocks keep it for their NoData tail.\n ...(dataset?.endTimeMs !== undefined && dataset?.drillFocalMs === undefined\n ? { endTime: dataset.endTimeMs }\n : {}),\n ...(dataset?.startTimeMs !== undefined ? { startTime: dataset.startTimeMs } : {}),\n ...(detailInitialState !== null ? { initialState: detailInitialState } : {}),\n }\n : effectiveMode === 'mock' &&\n (dataset?.endTimeMs !== undefined || dataset?.startTimeMs !== undefined)\n ? {\n ...(dataset.endTimeMs !== undefined && dataset.drillFocalMs === undefined\n ? { endTime: dataset.endTimeMs }\n : {}),\n ...(dataset.startTimeMs !== undefined ? { startTime: dataset.startTimeMs } : {}),\n ...(detailInitialState !== null ? { initialState: detailInitialState } : {}),\n }\n : detailInitialState !== null\n ? { initialState: detailInitialState }\n : undefined;\n\n const result = evaluate(\n workingConfig,\n { labels: {}, samples: visibleSamples },\n evalHints,\n );\n const events: ReadonlyArray<EvalEvent> = result.kind === 'Ok' ? result.value.events : [];\n const ticks: ReadonlyArray<Tick> = result.kind === 'Ok' ? result.value.ticks : [];\n const currentTick: Tick | null = ticks.length > 0 ? ticks[ticks.length - 1]! : null;\n const ourState = currentStateForTick(currentTick, events);\n const subtitle = formatAlertExpression(workingConfig);\n\n // Crossings at the eval-interval midpoint (pending/resolved.at -\n // evalInterval/2): the most honest marker since the discrete scrape grid\n // makes sub-step precision unreachable — visibly off both tick boundaries.\n const preciseCrossings: ReadonlyArray<ThresholdCrossing> = useMemo(() => {\n if (!('value' in workingConfig.threshold) || events.length === 0) return [];\n const evalIntervalMs = workingConfig.evaluationInterval;\n const thresholdValue = workingConfig.threshold.value;\n const out: ThresholdCrossing[] = [];\n let prevKind: string | null = null;\n for (const e of events) {\n if (e.kind === 'Pending') {\n out.push({ t: e.from - evalIntervalMs / 2, v: thresholdValue, direction: 'ignition' });\n } else if (e.kind === 'Firing' && prevKind !== 'Pending') {\n out.push({ t: e.from - evalIntervalMs / 2, v: thresholdValue, direction: 'ignition' });\n } else if (e.kind === 'Resolved') {\n out.push({ t: e.at - evalIntervalMs / 2, v: thresholdValue, direction: 'resolution' });\n }\n prevKind = e.kind;\n }\n return out;\n }, [events, workingConfig.threshold, workingConfig.evaluationInterval]);\n\n // Grafana's recorded state at the playhead, scanned from grafanaHistory.\n const playheadGrafanaState = mockPlayheadGrafanaState(\n dataset?.grafanaHistory,\n currentTick?.t,\n detailInitialState,\n );\n\n // The rule's unmodified config, re-evaluated so the chart can stack\n // baseline vs what-if events. Skip when reference-equal (bands would overlap).\n const baselineConfig: AlertConfig | null =\n mode === 'mock' && dataset !== null\n ? dataset.defaultAlertConfig\n : liveContext !== undefined\n ? liveContext.defaultConfig\n : null;\n const baselineDiffers = baselineConfig !== null && baselineConfig !== workingConfig;\n const changedLabels = changedParamLabels(draftConfig, baselineConfig);\n const baselineResult = baselineDiffers\n ? evaluate(baselineConfig, { labels: {}, samples: visibleSamples }, evalHints)\n : null;\n const baselineEvents: ReadonlyArray<EvalEvent> | undefined =\n baselineResult !== null && baselineResult.kind === 'Ok'\n ? baselineResult.value.events\n : undefined;\n\n // Run the BASELINE config (not the tweaked workingConfig) over the overview\n // samples so the strip marks where this rule actually fired historically.\n const overviewEvents: ReadonlyArray<EvalEvent> = useMemo(() => {\n if (baselineConfig === null || overviewSamples.length === 0) return [];\n // Instant rules omit evalGridOffsetMs so ticks anchor to samples[0].t and\n // land on existing samples; range rules use the shared offset.\n const hints: {\n initialState?: 'Normal' | 'Firing' | 'NoData';\n evalGridOffsetMs?: number;\n startTime?: number;\n } = {\n ...(overviewInitialState !== null ? { initialState: overviewInitialState } : {}),\n ...(baselineConfig.instant || sharedGridOffsetMs === undefined\n ? {}\n : { evalGridOffsetMs: sharedGridOffsetMs }),\n // Clamp the grid to the display start so warm-up over-fetched samples\n // complete the leftmost reduce window without spawning bells.\n ...(baselineConfig.instant || overviewStartMs === null\n ? {}\n : { startTime: overviewStartMs }),\n };\n const r = evaluate(baselineConfig, { labels: {}, samples: overviewSamples }, hints);\n return r.kind === 'Ok' ? r.value.events : [];\n }, [baselineConfig, overviewSamples, overviewInitialState, sharedGridOffsetMs, overviewStartMs]);\n\n // `?drill=first|last`: anchor on the first/last Pending-or-Firing event\n // (not Firing) so it lands exactly on the bell at the episode start.\n const autoDrillDoneRef = useRef<boolean>(initialDrill === undefined);\n useEffect(() => {\n if (autoDrillDoneRef.current) return;\n const active = overviewEvents.filter(\n (e): e is Extract<EvalEvent, { kind: 'Firing' | 'Pending' }> =>\n e.kind === 'Firing' || e.kind === 'Pending',\n );\n const target = initialDrill === 'last' ? active[active.length - 1] : active[0];\n if (target) {\n autoDrillDoneRef.current = true;\n drillToMoment(target.from, 'Firing');\n }\n }, [overviewEvents]);\n\n // Auto-replay drives the real buttons via `.click()` (not setState) so it\n // takes the hand-tested path and each press flashes on camera. Triggers:\n // `?play=1` deep link and postMessage `{type:'whatif:play'}`.\n const resetBtnRef = useRef<HTMLButtonElement>(null);\n const playBtnRef = useRef<HTMLButtonElement>(null);\n const [autoFlash, setAutoFlash] = useState<'reset' | 'play' | null>(null);\n const replayTimersRef = useRef<number[]>([]);\n const autoReplayingRef = useRef<boolean>(false);\n\n const pressReplayButton = useCallback((which: 'reset' | 'play') => {\n const el = which === 'reset' ? resetBtnRef.current : playBtnRef.current;\n if (el === null || el.disabled) return;\n setAutoFlash(which);\n el.click();\n replayTimersRef.current.push(window.setTimeout(() => setAutoFlash(null), 260));\n }, []);\n\n const runAutoReplay = useCallback(\n (holdMs: number) => {\n replayTimersRef.current.forEach((t) => window.clearTimeout(t));\n replayTimersRef.current = [];\n autoReplayingRef.current = true;\n replayTimersRef.current.push(window.setTimeout(() => pressReplayButton('reset'), holdMs));\n replayTimersRef.current.push(window.setTimeout(() => pressReplayButton('play'), holdMs + 1000));\n },\n [pressReplayButton],\n );\n\n const autoPlayedRef = useRef<boolean>(initialPlay !== true);\n useEffect(() => {\n if (autoPlayedRef.current) return;\n if (samples.length === 0 || drillTarget === null) return;\n autoPlayedRef.current = true;\n runAutoReplay(1300);\n }, [samples, drillTarget, runAutoReplay]);\n\n useEffect(() => {\n const onMessage = (e: MessageEvent) => {\n if (e.data === null || typeof e.data !== 'object') return;\n if (e.data.type === 'whatif:play') {\n runAutoReplay(300);\n } else if (e.data.type === 'whatif:tweak' && e.data.overrides !== undefined) {\n // Apply an override to both configs (an instant Apply) so the chart\n // re-runs in place on the same drilled history — no reload.\n const next = applyConfigOverrides(workingConfig, e.data.overrides as ConfigOverrides);\n setDraftConfig(next);\n setWorkingConfig(next);\n }\n };\n window.addEventListener('message', onMessage);\n return () => window.removeEventListener('message', onMessage);\n }, [runAutoReplay, workingConfig]);\n\n useEffect(() => () => replayTimersRef.current.forEach((t) => window.clearTimeout(t)), []);\n\n // No context for the active mode — hide chart/params/trace so\n // PLACEHOLDER_CONFIG never reaches the user. Mode-scoped.\n const hasContext =\n effectiveMode === 'mock' ? dataset !== null : liveContext !== undefined;\n const emptyHint =\n internalRuleError !== null\n ? internalRuleError\n : rulesError !== null\n ? `Could not load rules: ${rulesError}`\n : ruleListEnabled && rulesLoading\n ? 'Loading rules…'\n : ruleListEnabled\n ? 'Pick a Grafana alert rule above to see its lifecycle.'\n : 'No rule selected.';\n\n return (\n <PageLayout\n className={animationScope}\n headerLeft={\n <>\n {renderTitle(titleLogo)}\n {!ruleListEnabled && fixturesAvailable && liveAccessible ? (\n <ModeToggle mode={mode} onChange={setMode} />\n ) : null}\n {!ruleListEnabled && mode === 'mock' && dataset !== null && allDatasets.length > 1 ? (\n <DatasetPicker\n dataset={dataset}\n datasets={allDatasets}\n onSelect={selectDataset}\n />\n ) : null}\n {ruleListEnabled ? (\n <RulePicker\n rules={rules}\n selectedUid={selectedRuleUid}\n onSelect={setSelectedRuleUid}\n loading={rulesLoading}\n error={rulesError}\n onRefresh={() => setRulesReloadTick((n) => n + 1)}\n />\n ) : null}\n </>\n }\n themeToggle={themeToggleSlot}\n summaryStrip={null}\n main={!hasContext ? (\n <EmptyMessage text={emptyHint} />\n ) : (\n <>\n {effectiveMode === 'live' && liveContext !== undefined ? (\n <LiveStatusStrip\n mode=\"live\"\n {...(adapter.capabilities.grafanaStateOracle\n ? { grafanaState: live.grafanaState }\n : {})}\n {...(dataset?.seriesList !== undefined && dataset.seriesList.length > 1\n ? {\n pillExtra: (\n <SeriesPicker\n seriesList={dataset.seriesList}\n selectedIdx={selectedSeriesIdx}\n onSelect={setSelectedSeriesIdx}\n />\n ),\n }\n : {})}\n ourState={ourState}\n lastPollAt={live.lastPollAt}\n intervalSec={LIVE_INTERVAL_SEC}\n error={live.error}\n {...(!ruleListEnabled ? { query: liveContext.query } : {})}\n {...(ruleListEnabled\n ? {}\n : {\n onSnapshot: captureLiveSnapshot,\n canSnapshot: live.samples.length > 0,\n })}\n onExport={exportCurrent}\n canExport={live.samples.length > 0}\n exportToast={exportToast}\n {...(ruleListEnabled\n ? {\n onImport: (file: File) => {\n void importFromFile(file).then((result) => {\n if (!result.ok) {\n flashExportToast(\n `Import failed: ${result.error ?? 'unknown error'}`,\n );\n }\n });\n },\n }\n : {})}\n {...(liveContext.footerSlot !== undefined\n ? { footerSlot: liveContext.footerSlot }\n : {})}\n />\n ) : effectiveMode === 'mock' && dataset !== null ? (\n <LiveStatusStrip\n mode=\"mock\"\n ourState={ourState}\n {...(playheadGrafanaState !== undefined &&\n adapter.capabilities.grafanaStateOracle\n ? { grafanaState: playheadGrafanaState }\n : {})}\n {...(dataset.seriesList !== undefined && dataset.seriesList.length > 1\n ? {\n pillExtra: (\n <SeriesPicker\n seriesList={dataset.seriesList}\n selectedIdx={selectedSeriesIdx}\n onSelect={setSelectedSeriesIdx}\n />\n ),\n }\n : {})}\n {...(!ruleListEnabled ? { query: dataset.id } : {})}\n tickIndex={tickIndex}\n tickCount={tickCount}\n onExport={exportCurrent}\n onImport={(file) => {\n void importFromFile(file).then((result) => {\n if (!result.ok) {\n flashExportToast(`Import failed: ${result.error ?? 'unknown error'}`);\n }\n });\n }}\n replayButtons={\n <ReplayButtons\n tickIndex={tickIndex}\n tickCount={tickCount}\n playing={playing}\n speed={speed}\n onReset={() => {\n setTickIndex(0);\n setPlaying(false);\n }}\n onStepBack={() => {\n setPlaying(false);\n setTickIndex((i) => Math.max(0, i - 1));\n }}\n onTogglePlay={() => setPlaying((p) => !p)}\n onStepForward={() => {\n setPlaying(false);\n setTickIndex((i) => Math.min(tickCount, i + 1));\n }}\n onJumpToEnd={() => {\n setPlaying(false);\n setTickIndex(tickCount);\n }}\n onSpeedChange={setSpeed}\n hideSpeed={ruleListEnabled}\n resetButtonRef={resetBtnRef}\n playButtonRef={playBtnRef}\n flashing={autoFlash}\n />\n }\n />\n ) : null}\n {ruleListEnabled && internalLiveContext !== null && mode === 'mock' ? (\n <OverviewStrip\n samples={overviewSamples}\n events={overviewEvents}\n loading={overviewLoading}\n onEventClick={drillToMoment}\n lookbackSec={overviewLookbackSec}\n onLookbackChange={setOverviewLookbackSec}\n rangeOptions={OVERVIEW_RANGE_OPTIONS}\n {...(overviewInitialState !== null\n ? { initialState: overviewInitialState }\n : {})}\n {...(internalLiveContext?.ruleMetadata?.updatedMs !== undefined\n ? { ruleCreatedMs: internalLiveContext.ruleMetadata.updatedMs }\n : {})}\n />\n ) : null}\n <MetricChart\n samples={samples}\n visibleSamples={visibleSamples}\n ticks={ticks}\n threshold={workingConfig.threshold}\n evaluationInterval={workingConfig.evaluationInterval}\n windowDuration={workingConfig.instant ? 0 : workingConfig.windowDuration}\n {...(preciseCrossings.length > 0 ? { crossings: preciseCrossings } : {})}\n {...(workingConfig.instant ? {} : { reducer: workingConfig.reducer })}\n events={events}\n {...(baselineEvents !== undefined &&\n !(adapter.capabilities.grafanaStateOracle && grafanaHistory.length > 0)\n ? { baselineEvents }\n : {})}\n {...(detailInitialState !== null ? { initialState: detailInitialState } : {})}\n subtitle={subtitle}\n currentState={ourState}\n {...(effectiveMode === 'mock' && dataset !== null\n ? {\n rightAnchorT: mockRightAnchorT(dataset),\n ...(dataset.drillFocalMs !== undefined\n ? { focalMs: dataset.drillFocalMs }\n : {}),\n // Drill GRAFANA bar: prefer drill-time annotations, fall\n // back to localStorage Live-polling history.\n ...(adapter.capabilities.grafanaStateOracle &&\n dataset.grafanaHistory !== undefined &&\n dataset.grafanaHistory.length > 0\n ? {\n grafanaHistory: dataset.grafanaHistory,\n grafanaHistoryEnd:\n dataset.endTimeMs ?? liveNow,\n }\n : adapter.capabilities.grafanaStateOracle &&\n grafanaHistory.length > 0\n ? {\n grafanaHistory,\n grafanaHistoryEnd: liveNow,\n }\n : {}),\n }\n : {})}\n {...(effectiveMode === 'live'\n ? {\n rightAnchorT: liveNow + scrubOffsetMs,\n yMax: 6,\n ...(live.lastPollAt !== null ? { pollSignal: live.lastPollAt } : {}),\n // GRAFANA history bar only when the oracle exists (demo);\n // plugin disables the dev-only comparison.\n ...(adapter.capabilities.grafanaStateOracle\n ? {\n grafanaHistory,\n grafanaHistoryEnd: liveNow,\n }\n : {}),\n }\n : {})}\n bottomSlot={\n // Plugin: no bottom strip — the top status bar already carries\n // the replay controls, so a slider here would duplicate them.\n ruleListEnabled ? null : effectiveMode === 'live' ? (\n <LiveScrubControls\n paused={livePaused}\n scrubOffsetMs={scrubOffsetMs}\n scrubMaxMs={LIVE_SCRUB_MAX_MS}\n onTogglePause={togglePause}\n onScrubChange={onScrubChange}\n onJumpToLive={jumpToLive}\n />\n ) : (\n <ReplaySliderBar\n tickIndex={tickIndex}\n tickCount={tickCount}\n onTickIndexChange={(next) => {\n setPlaying(false);\n setTickIndex(next);\n }}\n />\n )\n }\n />\n </>\n )}\n bottomLeft={!hasContext ? null : (\n <ParamControls\n config={draftConfig}\n onChange={setDraftConfig}\n onApply={() => setWorkingConfig(draftConfig)}\n onReset={() => {\n const defaults =\n mode === 'live' && liveContext !== undefined\n ? liveContext.defaultConfig\n : (dataset?.defaultAlertConfig ?? draftConfig);\n // Reset reloads defaults into both draft and applied.\n setDraftConfig(defaults);\n setWorkingConfig(defaults);\n }}\n changedLabels={changedLabels}\n {...(mode === 'mock' && dataset?.ruleMetadata !== undefined\n ? { ruleMetadata: dataset.ruleMetadata }\n : {})}\n />\n )}\n bottomRight={!hasContext ? null : (\n result.kind === 'Err' ? (\n <EvalErrorPanel errors={result.errors} />\n ) : (\n <ComputeTracePanel\n tickIndex={tickIndex}\n tickCount={tickCount}\n currentTick={currentTick}\n samples={samples}\n config={workingConfig}\n events={events}\n />\n )\n )}\n />\n );\n}\n\nfunction EmptyMessage({ text }: { readonly text: string }) {\n return (\n <div style={emptyStyle}>\n <p>{text}</p>\n </div>\n );\n}\n\nconst titleStyle: React.CSSProperties = {\n margin: 0,\n fontSize: '1.25rem',\n fontWeight: 600,\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.4rem',\n};\n\nconst titleLogoStyle: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n lineHeight: 1,\n};\n\nconst emptyStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flex: 1,\n color: 'var(--text-muted)',\n};\n","import { css, keyframes } from '@emotion/css';\n\nconst reduceSweep = keyframes`\n 0% { opacity: 0; transform: scale(0); }\n 30% { opacity: 1; transform: scale(2.5); }\n 100% { opacity: 1; transform: scale(1.2); }\n`;\n\nconst reduceFlash = keyframes`\n 0% { opacity: 1; transform: scale(1.2); }\n 50% { opacity: 1; transform: scale(2.5); }\n 100% { opacity: 1; transform: scale(1.2); }\n`;\n\nconst reduceFade = keyframes`\n 0% { opacity: 1; transform: scale(1.2); }\n 100% { opacity: 0; transform: scale(0); }\n`;\n\nconst reducePop = keyframes`\n 0% { opacity: 0; transform: scale(0); }\n 40% { opacity: 1; transform: scale(3.5); }\n 100% { opacity: 0.85; transform: scale(1.2); }\n`;\n\nconst reduceOutputFlash = keyframes`\n 0% { color: inherit; background: transparent; }\n 10% { color: #1a1a1a; background: var(--event-pending); }\n 60% { color: #1a1a1a; background: var(--event-pending); }\n 100% { color: inherit; background: transparent; }\n`;\n\nconst nowPollPop = keyframes`\n 0% { transform: scale(1.6); filter: brightness(1.6); }\n 60% { transform: scale(1); filter: brightness(1); }\n 100% { transform: scale(1); filter: brightness(1); }\n`;\n\nconst nowBreath = keyframes`\n 0%, 100% { transform: scale(1); opacity: 0.95; }\n 50% { transform: scale(1.12); opacity: 1; }\n`;\n\nexport const animationScope = css`\n & .reduce-sample-dot {\n position: absolute;\n width: 6px;\n height: 6px;\n margin-left: -3px;\n margin-top: -3px;\n border-radius: 50%;\n background: var(--event-pending);\n box-shadow: 0 0 4px var(--event-pending);\n opacity: 0;\n pointer-events: none;\n animation:\n ${reduceSweep} 500ms ease-out forwards,\n ${reduceFlash} 500ms ease-in-out forwards,\n ${reduceFade} 400ms ease-out forwards;\n }\n\n & .reduce-result-dot {\n position: absolute;\n width: 6px;\n height: 6px;\n margin-left: -3px;\n margin-top: -3px;\n border-radius: 50%;\n background: var(--event-pending);\n box-shadow: 0 0 8px var(--event-pending);\n opacity: 0;\n pointer-events: none;\n animation: ${reducePop} 1200ms ease-out forwards;\n }\n\n & .reduce-output-flash {\n display: inline-block;\n animation: ${reduceOutputFlash} 700ms ease-out both;\n }\n\n & .alert-whatif-now-clock-pop {\n display: inline-block;\n transform-origin: 50% 50%;\n animation: ${nowPollPop} 900ms ease-out;\n }\n\n & .alert-whatif-now-clock-breath {\n display: inline-block;\n transform-origin: 50% 50%;\n animation: ${nowBreath} 2s ease-in-out infinite;\n }\n`;\n","// Per-tick compute trace, laid out to mirror alert.json's expressions DAG\n// (A query → B reduce → C threshold → for-gate) so the user can map UI block\n// to JSON node by refId. Pure presentation; the parent supplies currentTick.\n\nimport React from 'react';\nimport type { CSSProperties } from 'react';\nimport type { AlertConfig, EvalEvent, Sample, Tick } from '@alert-whatif/core';\nimport { computeEffectiveStepMs, passes } from '@alert-whatif/core';\nimport {\n FLASH_DURATION_MS,\n FLASH_GAP_MS,\n SWEEP_PER_DOT_MS,\n SWEEP_STAGGER_MS,\n} from '../util/reduce-animation-timing';\nimport { cardStyle, mutedTextStyle } from '../styles';\n\ntype Props = {\n readonly tickIndex: number;\n readonly tickCount: number;\n readonly currentTick: Tick | null;\n readonly samples: ReadonlyArray<Sample>;\n readonly config: AlertConfig;\n readonly events: ReadonlyArray<EvalEvent>;\n};\n\nexport function ComputeTracePanel({\n tickIndex,\n tickCount,\n currentTick,\n samples,\n config,\n events,\n}: Props) {\n if (currentTick === null) {\n return (\n <section style={cardStyle}>\n <h2 style={headingStyle}>Compute trace</h2>\n <p style={mutedTextStyle}>\n No ticks evaluated yet — press <strong>▶</strong> or <strong>▶ +1</strong> to step\n forward.\n </p>\n </section>\n );\n }\n\n const tickTime = currentTick.t;\n // Range slices a window for the reducer; instant looks up the sample at\n // tick.t exactly.\n const windowEnd = tickTime;\n const windowStart = config.instant ? tickTime : tickTime - config.windowDuration;\n const slice = config.instant\n ? samples.filter((s) => s.t === tickTime)\n : samples.filter((s) => s.t > windowStart && s.t <= windowEnd);\n const finiteCount = slice.filter((s) => Number.isFinite(s.v)).length;\n const droppedCount = slice.length - finiteCount;\n\n const lifecycle = lifecycleAt(tickTime, events);\n\n const thresholdSummary = thresholdSummaryOf(config.threshold);\n\n return (\n <section style={cardStyle}>\n <header style={titleRowStyle}>\n <h2 style={headingStyle}>Compute trace</h2>\n <span style={mutedTextStyle}>\n Tick <strong>{tickIndex}</strong> / {tickCount} &middot;{' '}\n <span key={`tick-time-${tickTime}`} className=\"reduce-output-flash\">\n <code style={codeInlineStyle}>{formatTime(tickTime)}</code>\n </span>\n </span>\n </header>\n\n {/* DAG node A — query. */}\n <NodeHeader\n refId=\"A\"\n type=\"query\"\n summary={config.instant ? 'instant' : `range · ${formatMs(config.windowDuration)} → 0s`}\n />\n {config.instant ? (\n <TraceRow label=\"Sample @ tick.t\">\n {slice.length > 0 ? (\n <code style={codeInlineStyle}>\n {Number.isFinite(slice[0]!.v) ? slice[0]!.v.toFixed(3) : String(slice[0]!.v)}\n </code>\n ) : (\n <span style={mutedInlineStyle}>NoData (Prom returned no sample at this step)</span>\n )}\n </TraceRow>\n ) : (\n <>\n <TraceRow label=\"Window\">\n <span key={`window-${windowEnd}`} className=\"reduce-output-flash\">\n <code style={codeInlineStyle}>\n ({formatTime(windowStart)}, {formatTime(windowEnd)}]\n </code>\n </span>\n </TraceRow>\n <TraceRow label=\"Samples\">\n <strong>{slice.length}</strong>\n {droppedCount > 0 ? (\n <span style={mutedInlineStyle}>\n {' '}\n ({finiteCount} finite, {droppedCount} NaN/Inf — nanMode: {config.nanMode.kind})\n </span>\n ) : null}\n {slice.length > 0 ? (\n <div style={sliceListStyle}>\n {slice.map((s, i) => (\n <span\n key={`slice-${tickTime}-${s.t}`}\n className=\"reduce-output-flash\"\n style={{\n // Match the chart's reduce-sample-dot sweep stagger.\n animationDelay: `${i * SWEEP_STAGGER_MS}ms`,\n }}\n >\n <code style={sliceItemStyle}>\n {Number.isFinite(s.v) ? s.v.toFixed(3) : String(s.v)}\n </code>\n </span>\n ))}\n </div>\n ) : null}\n </TraceRow>\n </>\n )}\n\n {/* DAG node B — reduce. Range only; Output flashes in sync with the\n chart's reduce-result-dot pop. */}\n {config.instant ? null : (\n <>\n <NodeHeader refId=\"B\" type=\"reduce\" summary={config.reducer.toLowerCase()} />\n <TraceRow label=\"Output\">\n {currentTick.kind === 'Data' ? (\n <span\n key={`reduce-out-${tickTime}`}\n className=\"reduce-output-flash\"\n style={{\n animationDelay: `${reduceFlashDelayMs(slice.length)}ms`,\n }}\n >\n <code style={codeInlineStyle}>{currentTick.v.toFixed(6)}</code>\n </span>\n ) : (\n <span style={mutedInlineStyle}>NoData (empty slice or reducer NaN)</span>\n )}\n </TraceRow>\n <SampleCountBreakdown config={config} />\n </>\n )}\n\n {/* Threshold node — refId C (range, after B) or B (instant, after A). */}\n <NodeHeader\n refId={config.instant ? 'B' : 'C'}\n type=\"threshold\"\n summary={thresholdSummary}\n />\n <TraceRow label=\"Check\">\n {currentTick.kind === 'Data' ? (\n <ThresholdLine value={currentTick.v} threshold={config.threshold} />\n ) : (\n <span style={mutedInlineStyle}>n/a</span>\n )}\n </TraceRow>\n\n {/* For-gate / lifecycle — rule-level (spec.for), not an expression node. */}\n <NodeHeader label=\"For-gate\" summary={`for ${formatMs(config.forDuration)}`} />\n <TraceRow label=\"Lifecycle\">\n {lifecycle ? (\n <strong\n key={`lifecycle-${lifecycle}`}\n className=\"reduce-output-flash\"\n style={{ color: stateColor(lifecycle) }}\n >\n {lifecycle}\n </strong>\n ) : (\n <span\n key=\"lifecycle-normal\"\n className=\"reduce-output-flash\"\n style={mutedInlineStyle}\n >\n Normal (no active episode)\n </span>\n )}\n </TraceRow>\n </section>\n );\n}\n\n// Makes the otherwise-invisible fetch-layer effective-step formula auditable.\n// Range only.\nfunction SampleCountBreakdown({ config }: { readonly config: AlertConfig }) {\n if (config.instant) return null;\n const intervalMs = config.intervalMs;\n const maxDataPoints = config.maxDataPoints;\n const rangeMs = config.windowDuration;\n const resolution = maxDataPoints === 0 ? 1500 : maxDataPoints;\n const safeMs = rangeMs / resolution;\n const safeBranchTaken = safeMs < intervalMs;\n const effectiveStepMs = computeEffectiveStepMs({ intervalMs, maxDataPoints, timeRangeMs: rangeMs });\n const samplesPerWindow = Math.floor(rangeMs / effectiveStepMs);\n\n const maxValue = safeBranchTaken ? intervalMs : safeMs;\n // Suffix only when grid rounding changes the value.\n const gridSuffix =\n maxValue === effectiveStepMs ? '' : ` → grid ${effectiveStepMs}`;\n\n return (\n <div style={breakdownBoxStyle}>\n <div style={breakdownHeaderStyle}>How many samples per window</div>\n <pre style={formulaStyle}>\n {`step = max(${intervalMs}, ${rangeMs}/${resolution}) = max(${intervalMs}, ${formatNumber(safeMs)}) = `}\n <span key={`step-${maxValue}`} className=\"reduce-output-flash\">\n {formatNumber(maxValue)}{gridSuffix} ms\n </span>\n {'\\n'}\n {`samples = ${rangeMs} / ${effectiveStepMs} = `}\n <span key={`samples-${samplesPerWindow}`} className=\"reduce-output-flash\">\n {samplesPerWindow}\n </span>\n </pre>\n </div>\n );\n}\n\nfunction formatNumber(n: number): string {\n if (Number.isInteger(n)) return String(n);\n return n.toFixed(2);\n}\n\n// Mirrors MetricChart so the panel's reduce-output flash fires in sync.\nfunction reduceFlashDelayMs(n: number): number {\n if (n <= 0) return 0;\n const lastSweepEnd = (n - 1) * SWEEP_STAGGER_MS + SWEEP_PER_DOT_MS;\n return lastSweepEnd + FLASH_GAP_MS + FLASH_DURATION_MS;\n}\n\n// `refId + type` (matching alert.json), or an explicit `label` for the for-gate.\nfunction NodeHeader({\n refId,\n type,\n label,\n summary,\n}: {\n readonly refId?: string;\n readonly type?: string;\n readonly label?: string;\n readonly summary?: string;\n}) {\n const title = label ?? `${refId} · ${type}`;\n return (\n <div style={nodeHeaderStyle}>\n <span style={nodeHeaderTitleStyle}>{title}</span>\n {summary !== undefined ? <span style={nodeHeaderSummaryStyle}>{summary}</span> : null}\n </div>\n );\n}\n\nfunction thresholdSummaryOf(threshold: AlertConfig['threshold']): string {\n if ('value' in threshold) return `${threshold.op} ${threshold.value}`;\n return `${threshold.op} [${threshold.left}, ${threshold.right}]`;\n}\n\nfunction TraceRow({ label, children }: { readonly label: string; readonly children: React.ReactNode }) {\n return (\n <div style={rowStyle}>\n <div style={labelStyle}>{label}</div>\n <div style={valueStyle}>{children}</div>\n </div>\n );\n}\n\nfunction ThresholdLine({ value, threshold }: { readonly value: number; readonly threshold: AlertConfig['threshold'] }) {\n const pass = passes(value, threshold);\n const thr = 'value' in threshold ? `${threshold.op} ${threshold.value}` : `${threshold.op} [${threshold.left}, ${threshold.right}]`;\n const valueStr = value.toFixed(3);\n const verdict = pass ? 'PASS' : 'fail';\n return (\n <code style={codeInlineStyle}>\n <span key={`thr-val-${valueStr}`} className=\"reduce-output-flash\">\n {valueStr}\n </span>\n {' '}{thr}{' → '}\n <strong\n key={`thr-verdict-${verdict}`}\n className=\"reduce-output-flash\"\n style={{ color: pass ? 'var(--event-firing)' : 'var(--text-muted)' }}\n >\n {verdict}\n </strong>\n </code>\n );\n}\n\n// Which ranged event contains tickTime, half-open [from, until) to match\n// currentStateForTick + the state bar + Grafana's resolution semantics.\nfunction lifecycleAt(\n tickTime: number,\n events: ReadonlyArray<EvalEvent>,\n): 'Pending' | 'Firing' | 'NoData' | 'Recovering' | null {\n for (const e of events) {\n if (e.kind === 'Resolved') continue;\n if (tickTime >= e.from && tickTime < e.until) return e.kind;\n }\n return null;\n}\n\nfunction stateColor(state: string): string {\n switch (state) {\n case 'Firing':\n return 'var(--event-firing)';\n case 'Pending':\n return 'var(--event-pending)';\n case 'Recovering':\n return 'var(--event-recovering, var(--event-pending))';\n case 'NoData':\n return 'var(--event-nodata, var(--text-muted))';\n default:\n return 'var(--text-primary)';\n }\n}\n\n// Local timezone to match MetricChart's wallclock.\nfunction formatTime(t: number): string {\n const d = new Date(t);\n const pad = (n: number) => n.toString().padStart(2, '0');\n return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n}\n\nfunction formatMs(d: number): string {\n if (d >= 60_000 && d % 60_000 === 0) return `${d / 60_000}m`;\n if (d >= 60_000) return `${(d / 60_000).toFixed(1)}m`;\n if (d >= 1000 && d % 1000 === 0) return `${d / 1000}s`;\n if (d >= 1000) return `${(d / 1000).toFixed(1)}s`;\n return `${d}ms`;\n}\n\nconst headingStyle: CSSProperties = {\n marginTop: 0,\n marginBottom: 0,\n fontSize: '0.95rem',\n};\n\nconst titleRowStyle: CSSProperties = {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'baseline',\n gap: '0.5rem',\n marginBottom: '0.4rem',\n};\n\nconst rowStyle: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: '7.5rem 1fr',\n alignItems: 'baseline',\n gap: '0.5rem',\n marginBottom: '0.2rem',\n};\n\nconst labelStyle: CSSProperties = {\n color: 'var(--text-muted)',\n fontSize: '0.8rem',\n textTransform: 'uppercase',\n letterSpacing: '0.04em',\n};\n\nconst valueStyle: CSSProperties = {\n color: 'var(--text-primary)',\n fontSize: '0.9rem',\n fontVariantNumeric: 'tabular-nums',\n overflowWrap: 'anywhere',\n};\n\nconst codeInlineStyle: CSSProperties = {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.85rem',\n background: 'var(--bg-input, transparent)',\n padding: '1px 4px',\n borderRadius: 3,\n};\n\nconst mutedInlineStyle: CSSProperties = {\n color: 'var(--text-muted)',\n fontSize: '0.85rem',\n};\n\nconst sliceListStyle: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: '0.25rem',\n marginTop: '0.35rem',\n};\n\nconst sliceItemStyle: CSSProperties = {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.78rem',\n padding: '1px 5px',\n borderRadius: 3,\n background: 'var(--bg-input, rgba(127,127,127,0.08))',\n border: '1px solid var(--border-card)',\n};\n\nconst nodeHeaderStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'baseline',\n gap: '0.5rem',\n marginTop: '0.5rem',\n marginBottom: '0.2rem',\n paddingTop: '0.35rem',\n borderTop: '1px solid var(--border-card)',\n};\n\nconst nodeHeaderTitleStyle: CSSProperties = {\n fontSize: '0.78rem',\n fontWeight: 600,\n letterSpacing: '0.04em',\n textTransform: 'uppercase',\n color: 'var(--text-primary)',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n};\n\nconst nodeHeaderSummaryStyle: CSSProperties = {\n fontSize: '0.78rem',\n color: 'var(--text-muted)',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n};\n\nconst breakdownBoxStyle: CSSProperties = {\n marginTop: '0.8rem',\n padding: '0.6rem 0.7rem',\n border: '1px dashed var(--border-card)',\n borderRadius: 4,\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n};\n\nconst breakdownHeaderStyle: CSSProperties = {\n fontSize: '0.78rem',\n fontWeight: 600,\n letterSpacing: '0.04em',\n textTransform: 'uppercase',\n color: 'var(--text-muted)',\n marginBottom: '0.4rem',\n};\n\nconst formulaStyle: CSSProperties = {\n margin: 0,\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.78rem',\n lineHeight: 1.5,\n color: 'var(--text-primary)',\n whiteSpace: 'pre-wrap',\n fontVariantNumeric: 'tabular-nums',\n};\n","// Reduce-animation timing constants. MUST stay in sync with the CSS keyframes\n// in index.css (.reduce-sample-dot / .reduce-result-dot), else auto-play\n// pacing desyncs from the visual.\n\nexport const SWEEP_PER_DOT_MS = 500;\nexport const SWEEP_STAGGER_MS = 80;\nexport const FLASH_GAP_MS = 100;\nexport const FLASH_DURATION_MS = 500;\nexport const FADE_DURATION_MS = 400;\nexport const RESULT_POP_MS = 1200;\n\n// Total duration for `n` samples, mirroring MetricChart's delay arithmetic.\n// 0 for NoData ticks.\nexport function reduceAnimationDurationMs(n: number): number {\n if (n <= 0) return 0;\n const lastSweepEnd = (n - 1) * SWEEP_STAGGER_MS + SWEEP_PER_DOT_MS;\n const flashDelay = lastSweepEnd + FLASH_GAP_MS;\n const fadeDelay = flashDelay + FLASH_DURATION_MS;\n return fadeDelay + RESULT_POP_MS;\n}\n","// Shared inline-style objects, theme-aware via index.css CSS variables.\n\nimport type { CSSProperties } from 'react';\n\nexport const pageStyle: CSSProperties = {\n fontFamily: 'system-ui, sans-serif',\n // 100% (not 100vh) so the plugin's content area minus topbar doesn't\n // overflow into an outer scrollbar.\n height: '100%',\n padding: '1rem',\n display: 'flex',\n flexDirection: 'column',\n gap: '1rem',\n boxSizing: 'border-box',\n color: 'var(--text-primary)',\n};\n\nexport const cardStyle: CSSProperties = {\n border: '1px solid var(--border-card)',\n borderRadius: 8,\n padding: '0.6rem 0.9rem',\n background: 'var(--bg-card)',\n boxSizing: 'border-box',\n // min-height (not height) so tall content expands the card and the column's\n // overflow-y:auto kicks in.\n minHeight: '100%',\n};\n\nexport const cardHeadingStyle: CSSProperties = {\n marginTop: 0,\n marginBottom: '0.4rem',\n fontSize: '0.95rem',\n};\n\nexport const mutedTextStyle: CSSProperties = {\n color: 'var(--text-muted)',\n fontSize: '0.78rem',\n margin: '0.15rem 0 0.35rem',\n};\n\nexport const errorTextStyle: CSSProperties = { color: 'var(--text-error)' };\n\nexport const footerStyle: CSSProperties = {\n color: 'var(--text-faded)',\n fontSize: '0.8rem',\n marginTop: '2rem',\n};\n","// localStorage Grafana state-bar history, keyed by rule title; entries older\n// than 24h are pruned on load. Pure I/O, no React.\n\nimport type { GrafanaAlertState } from '../data/data-source';\n\nexport type GrafanaHistoryEntry = {\n readonly t: number;\n readonly state: GrafanaAlertState;\n};\n\nconst STORAGE_KEY_PREFIX = 'alert-whatif:grafana-history:';\nconst MAX_AGE_MS = 24 * 60 * 60 * 1000;\nconst VALID_STATES: ReadonlySet<string> = new Set([\n 'inactive',\n 'pending',\n 'firing',\n 'unknown',\n]);\n\nexport function loadGrafanaHistory(\n ruleTitle: string,\n): ReadonlyArray<GrafanaHistoryEntry> {\n if (typeof window === 'undefined' || ruleTitle === '') return [];\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY_PREFIX + ruleTitle);\n if (raw === null) return [];\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const cutoff = Date.now() - MAX_AGE_MS;\n return parsed.flatMap((e: unknown) => {\n if (typeof e !== 'object' || e === null) return [];\n const t = (e as { t?: unknown }).t;\n const state = (e as { state?: unknown }).state;\n if (typeof t !== 'number' || !Number.isFinite(t) || t < cutoff) return [];\n if (typeof state !== 'string' || !VALID_STATES.has(state)) return [];\n return [{ t, state: state as GrafanaAlertState }];\n });\n } catch {\n return [];\n }\n}\n\nexport function saveGrafanaHistory(\n ruleTitle: string,\n history: ReadonlyArray<GrafanaHistoryEntry>,\n): void {\n if (typeof window === 'undefined' || ruleTitle === '') return;\n try {\n window.localStorage.setItem(\n STORAGE_KEY_PREFIX + ruleTitle,\n JSON.stringify(history),\n );\n } catch {\n // Quota exceeded / private mode — in-memory state still works.\n }\n}\n","// Pure display helpers.\n\n// \"<ISO start> UTC (<dur> min total)\".\nexport function formatRange(fromMs: number, toMs: number): string {\n const from = new Date(fromMs).toISOString().replace('T', ' ').slice(0, 19);\n const durMin = (toMs - fromMs) / 60_000;\n return `${from} UTC (${durMin.toFixed(1)} min total)`;\n}\n\n// Compact duration: \"0\" / \"2m\" / \"30s\" / \"1.5s\" / \"500ms\".\nexport function formatDurCompact(d: number): string {\n if (d === 0) return '0';\n if (d >= 60_000 && d % 60_000 === 0) return `${d / 60_000}m`;\n if (d >= 60_000) return `${(d / 60_000).toFixed(1)}m`;\n if (d >= 1000 && d % 1000 === 0) return `${d / 1000}s`;\n if (d >= 1000) return `${(d / 1000).toFixed(1)}s`;\n return `${d}ms`;\n}\n\nimport type { AlertConfig, Threshold } from '@alert-whatif/core';\n\n// Chart subtitle, e.g. \"mean(samples) > 5 · for: 2m · eval: 1m\".\nexport function formatAlertExpression(config: AlertConfig): string {\n const cond = config.instant\n ? `instant ${formatThresholdInline(config.threshold)}`\n : `${config.reducer.toLowerCase()}(samples) ${formatThresholdInline(config.threshold)}`;\n const parts = [\n cond,\n `for: ${formatDurCompact(config.forDuration)}`,\n `eval: ${formatDurCompact(config.evaluationInterval)}`,\n ];\n if (config.keepFiringFor > 0) {\n parts.push(`keepFiring: ${formatDurCompact(config.keepFiringFor)}`);\n }\n return parts.join(' · ');\n}\n\n// \"> 0.05\" / \"∈ [0, 10]\" / \"∉ (0, 10)\".\nfunction formatThresholdInline(t: Threshold): string {\n if ('value' in t) {\n return `${OP_SYMBOL[t.op]} ${t.value}`;\n }\n const open = t.op === 'WithinRangeIncluded' || t.op === 'OutsideRangeIncluded' ? '[' : '(';\n const close = t.op === 'WithinRangeIncluded' || t.op === 'OutsideRangeIncluded' ? ']' : ')';\n const verb = t.op === 'WithinRange' || t.op === 'WithinRangeIncluded' ? '∈' : '∉';\n return `${verb} ${open}${t.left}, ${t.right}${close}`;\n}\n\nconst OP_SYMBOL: Record<string, string> = {\n Gt: '>',\n Lt: '<',\n GtEq: '≥',\n LtEq: '≤',\n Eq: '=',\n Ne: '≠',\n};\n","// Slim header dataset selector — dropdown + a one-line metadata strip.\n\nimport React from 'react';\nimport type { CSSProperties } from 'react';\nimport type { Dataset } from '../data/data-source';\nimport { formatRange } from '../util/format';\n\ntype Props = {\n readonly dataset: Dataset;\n readonly datasets: ReadonlyArray<Dataset>;\n readonly onSelect: (id: string) => void;\n};\n\nexport function DatasetPicker({ dataset, datasets, onSelect }: Props) {\n const first = dataset.samples[0];\n const last = dataset.samples[dataset.samples.length - 1];\n // Guard the empty-window case so formatRange isn't called on undefined edges.\n const range =\n first !== undefined && last !== undefined\n ? `${dataset.samples.length} samples · ${formatRange(first.t, last.t)}`\n : '(no samples in window)';\n return (\n <label style={wrapperStyle}>\n <span style={labelStyle}>Scenario:</span>\n <select value={dataset.id} onChange={(e) => onSelect(e.target.value)} style={selectStyle}>\n {datasets.map((d) => (\n <option key={d.id} value={d.id}>\n {d.displayName}\n </option>\n ))}\n </select>\n <span style={metaStyle}>{range}</span>\n </label>\n );\n}\n\nconst wrapperStyle: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.5rem',\n flexWrap: 'wrap',\n};\n\nconst labelStyle: CSSProperties = {\n fontSize: '0.875rem',\n color: 'var(--text-muted)',\n};\n\nconst selectStyle: CSSProperties = {\n padding: '0.4rem 0.55rem',\n minHeight: '2rem',\n lineHeight: 1.2,\n fontSize: '0.875rem',\n minWidth: '14rem',\n // Inline wins over Grafana's select color/height reset.\n background: 'var(--bg-input)',\n color: 'var(--text-primary)',\n border: '1px solid var(--border-input)',\n borderRadius: 4,\n};\n\nconst metaStyle: CSSProperties = {\n fontSize: '0.8rem',\n color: 'var(--text-muted)',\n};\n","// The validator's Err arm as a red list, shown when `evaluate()` rejects config.\n\nimport React from 'react';\nimport { cardHeadingStyle, cardStyle, errorTextStyle } from '../styles';\n\nexport function EvalErrorPanel({ errors }: { readonly errors: ReadonlyArray<string> }) {\n return (\n <section style={cardStyle}>\n <h2 style={{ ...cardHeadingStyle, ...errorTextStyle }}>Configuration rejected</h2>\n <p style={errorTextStyle}>Evaluator rejected the current config:</p>\n <ul style={{ color: 'var(--text-primary)', marginTop: 0 }}>\n {errors.map((e) => (\n <li key={e}>{e}</li>\n ))}\n </ul>\n </section>\n );\n}\n","// Live-mode pause + history-scrub strip below the chart. Stateless — the\n// parent owns `paused` + `scrubOffsetMs`.\n\nimport React from 'react';\nimport type { CSSProperties } from 'react';\n\ntype Props = {\n readonly paused: boolean;\n readonly scrubOffsetMs: number;\n // Max scrubback distance; slider runs -scrubMaxMs..0 (live).\n readonly scrubMaxMs: number;\n readonly onTogglePause: () => void;\n readonly onScrubChange: (offsetMs: number) => void;\n readonly onJumpToLive: () => void;\n};\n\nconst SLIDER_STEP_MS = 15_000; // 15s — matches the poll cadence\n\nexport function LiveScrubControls({\n paused,\n scrubOffsetMs,\n scrubMaxMs,\n onTogglePause,\n onScrubChange,\n onJumpToLive,\n}: Props) {\n const atLive = !paused && scrubOffsetMs === 0;\n const offsetSec = Math.round(-scrubOffsetMs / 1000);\n const offsetLabel = atLive\n ? 'live'\n : offsetSec >= 60\n ? `${Math.floor(offsetSec / 60)}m ${offsetSec % 60}s back`\n : `${offsetSec}s back`;\n\n // Filled fraction, handed to CSS so the WebKit track can paint the fill\n // (Firefox uses ::-moz-range-progress natively).\n const fillPct = scrubMaxMs === 0\n ? 100\n : Math.round(((scrubOffsetMs + scrubMaxMs) / scrubMaxMs) * 100);\n\n return (\n <div style={rowStyle}>\n {/* Left gutter — same width as the chart's, pause button right-aligned. */}\n <div style={gutterSlotStyle}>\n <button\n type=\"button\"\n onClick={onTogglePause}\n style={iconButtonStyle}\n title={paused ? 'Resume live updates' : 'Pause live updates'}\n aria-label={paused ? 'Resume live updates' : 'Pause live updates'}\n >\n {paused ? '▶' : '⏸'}\n </button>\n </div>\n\n {/* Track takes 11/12 of the post-gutter width so the thumb at max lands\n under the chart's NOW line; `⤓ now` occupies the remaining 1/12. */}\n <input\n type=\"range\"\n min={-scrubMaxMs}\n max={0}\n step={SLIDER_STEP_MS}\n value={scrubOffsetMs}\n onChange={(e) => onScrubChange(Number(e.target.value))}\n className=\"scrub-slider\"\n style={{ ...sliderStyle, ['--scrub-fill' as 'width']: `${fillPct}%` }}\n aria-label=\"Scrub through live history\"\n title={offsetLabel}\n />\n\n <button\n type=\"button\"\n onClick={onJumpToLive}\n disabled={atLive}\n style={liveButtonStyle(atLive)}\n title={`Snap back to live tip${atLive ? '' : ` · currently ${offsetLabel}`}`}\n >\n ⤓ now\n </button>\n </div>\n );\n}\n\nconst rowStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 0,\n paddingTop: '0.15rem',\n};\n\n// 5.5rem to match MetricChart's gutter so the track starts at the plot area.\nconst gutterSlotStyle: CSSProperties = {\n width: '5.5rem',\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n paddingRight: '0.5rem',\n boxSizing: 'border-box',\n};\n\nconst iconButtonStyle: CSSProperties = {\n width: 26,\n height: 26,\n padding: 0,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '0.85rem',\n lineHeight: 1,\n border: 'none',\n borderRadius: 999,\n background: 'transparent',\n color: 'var(--text-primary)',\n cursor: 'pointer',\n};\n\n// paddingLeft 10px keeps the text clear of the slider thumb's disk at max.\nconst liveButtonStyle = (atLive: boolean): CSSProperties => ({\n flex: '1 1 0',\n minWidth: 0,\n padding: '2px 4px 2px 10px',\n fontSize: '0.72rem',\n fontWeight: 600,\n letterSpacing: '0.02em',\n border: 'none',\n borderRadius: 999,\n background: 'transparent',\n color: atLive ? 'var(--text-faded)' : 'var(--event-firing, #ef4444)',\n cursor: atLive ? 'default' : 'pointer',\n opacity: atLive ? 0.55 : 1,\n whiteSpace: 'nowrap',\n textAlign: 'left',\n});\n\n// 11/12 matches the chart's NOW position; the +7px offsets the native thumb\n// halo inset so the thumb center at max lands directly under NOW.\nconst sliderStyle: CSSProperties = {\n flex: '0 1 calc((100% - 5.5rem) * 11 / 12 + 7px)',\n minWidth: 0,\n margin: 0,\n height: 18,\n padding: 0,\n // appearance:none so the .scrub-slider CSS paints the track/thumb.\n WebkitAppearance: 'none',\n appearance: 'none',\n background: 'transparent',\n border: 'none',\n};\n","import type {\n EvalEvent,\n GrafanaAlertState,\n StateTransition,\n Tick,\n} from '@alert-whatif/core';\n\nexport type OurState = 'Normal' | 'Pending' | 'Firing' | 'NoData' | 'Recovering';\n\n// Adapt EvalEvent[] into the StateTransition[] core's divergence detector\n// consumes; only Pending/Firing/Resolved are extracted.\nexport function eventsToTransitions(events: ReadonlyArray<EvalEvent>): ReadonlyArray<StateTransition> {\n const out: StateTransition[] = [];\n for (const e of events) {\n if (e.kind === 'Pending') out.push({ t: e.from, kind: 'Pending' });\n else if (e.kind === 'Firing') out.push({ t: e.from, kind: 'Firing' });\n else if (e.kind === 'Resolved') out.push({ t: e.at, kind: 'Resolved' });\n }\n return out;\n}\n\n// Each grafanaHistory entry is already a transition; map it directly,\n// skipping `unknown`.\nexport function grafanaHistoryToTransitions(\n history: ReadonlyArray<{ readonly t: number; readonly state: string }>,\n): ReadonlyArray<StateTransition> {\n const out: StateTransition[] = [];\n for (const entry of history) {\n if (entry.state === 'pending') out.push({ t: entry.t, kind: 'Pending' });\n else if (entry.state === 'firing') out.push({ t: entry.t, kind: 'Firing' });\n else if (entry.state === 'inactive') out.push({ t: entry.t, kind: 'Resolved' });\n }\n return out;\n}\n\n// One contiguous range per run of consecutive NoData ticks; each covers\n// `[tick.t, tick.t + evaluationInterval)` so adjacent ticks merge.\nexport function computeNoDataRanges(\n ticks: ReadonlyArray<Tick>,\n evaluationInterval: number,\n): ReadonlyArray<{ readonly from: number; readonly until: number }> {\n if (!Number.isFinite(evaluationInterval) || evaluationInterval <= 0) return [];\n const runs: Array<{ from: number; until: number }> = [];\n let current: { from: number; until: number } | null = null;\n for (const tick of ticks) {\n if (tick.kind !== 'NoData') {\n if (current !== null) {\n runs.push(current);\n current = null;\n }\n continue;\n }\n const tickUntil = tick.t + evaluationInterval;\n if (current === null) {\n current = { from: tick.t, until: tickUntil };\n } else {\n current.until = tickUntil;\n }\n }\n if (current !== null) runs.push(current);\n return runs;\n}\n\n// Grafana's recorded state at the playhead: the latest entry whose\n// `t <= playheadMs`, falling back to initialState when before any annotation.\nexport function mockPlayheadGrafanaState(\n history: ReadonlyArray<{ readonly t: number; readonly state: string }> | undefined,\n playheadMs: number | undefined,\n initialState: 'Normal' | 'Firing' | 'NoData' | null,\n): 'pending' | 'firing' | 'inactive' | undefined {\n if (history === undefined || history.length === 0 || playheadMs === undefined) {\n return undefined;\n }\n let latest: { t: number; state: string } | null = null;\n for (const entry of history) {\n if (entry.t <= playheadMs && (latest === null || entry.t > latest.t)) {\n latest = entry;\n }\n }\n if (latest === null) {\n if (initialState === 'Firing') return 'firing';\n if (initialState === 'NoData') return 'inactive';\n return 'inactive';\n }\n if (latest.state === 'pending' || latest.state === 'firing' || latest.state === 'inactive') {\n return latest.state;\n }\n return undefined;\n}\n\nexport function currentStateForTick(\n tick: Tick | null,\n events: ReadonlyArray<EvalEvent>,\n): OurState {\n if (tick === null) return 'Normal';\n for (const e of events) {\n if (e.kind === 'Resolved') continue;\n if (tick.t >= e.from && tick.t < e.until) return e.kind;\n }\n if (tick.kind === 'NoData') return 'NoData';\n return 'Normal';\n}\n\nexport function statesMatch(g: GrafanaAlertState, ours: OurState): boolean {\n if (g === 'firing') return ours === 'Firing';\n if (g === 'pending') return ours === 'Pending';\n if (g === 'inactive') return ours === 'Normal';\n return true;\n}\n","// Status strip above the chart in both Live and Mock modes — one component so\n// chrome, chips, and spacing stay in lockstep. Live shows both state pills + a\n// =/≠ comparison and a Snapshot/Export action; Mock shows our pill alone and\n// the replay button row in the same action slot.\n\nimport React from 'react';\nimport type { CSSProperties, ReactNode } from 'react';\nimport type { GrafanaAlertState } from '../data/data-source';\nimport type { OurState } from '../calc/state';\nimport { statesMatch } from '../calc/state';\n\ntype CommonProps = {\n readonly ourState: OurState;\n // Context label (PromQL live / dataset id mock); omitted skips the chip.\n readonly query?: string;\n // Slot after the comparison pill (e.g. SeriesPicker for multi-series).\n readonly pillExtra?: ReactNode;\n};\n\ntype LiveProps = CommonProps & {\n readonly mode: 'live';\n // Omitted (grafanaStateOracle off) degrades to the What-If pill alone.\n readonly grafanaState?: GrafanaAlertState;\n readonly lastPollAt: number | null;\n readonly intervalSec: number;\n readonly error: string | null;\n // Freeze current live samples into a Mock dataset for scrubbing.\n readonly onSnapshot?: () => void;\n readonly canSnapshot?: boolean;\n readonly onExport?: () => void;\n readonly canExport?: boolean;\n // Plugin uses Import in place of Snapshot.\n readonly onImport?: (file: File) => void;\n // Brief post-export confirmation carrying the file's cutoff timestamp.\n readonly exportToast?: string | null;\n // Extra row inside the same card (today <PushControls/>).\n readonly footerSlot?: ReactNode;\n};\n\ntype MockProps = CommonProps & {\n readonly mode: 'mock';\n // Rendered in the same action slot Snapshot uses in Live.\n readonly replayButtons: ReactNode;\n readonly tickIndex: number;\n readonly tickCount: number;\n // Grafana's state at the playhead (from grafanaHistory); omitted shows our\n // chip alone.\n readonly grafanaState?: GrafanaAlertState;\n readonly onExport?: () => void;\n readonly onImport?: (file: File) => void;\n};\n\ntype Props = LiveProps | MockProps;\n\nexport function LiveStatusStrip(props: Props) {\n return (\n <div style={rootStyle}>\n <div style={rowStyle}>\n {props.query !== undefined && props.query !== '' ? (\n <>\n <span style={queryStyle}>\n <code style={codeStyle}>{props.query}</code>\n </span>\n <span style={separatorStyle}>·</span>\n </>\n ) : null}\n\n {props.mode === 'live' ? (\n <LivePills\n {...(props.grafanaState !== undefined\n ? { grafanaState: props.grafanaState }\n : {})}\n ourState={props.ourState}\n />\n ) : (\n <LivePills\n {...(props.grafanaState !== undefined\n ? { grafanaState: props.grafanaState }\n : {})}\n ourState={props.ourState}\n />\n )}\n\n {props.pillExtra !== undefined ? (\n <span style={{ marginLeft: '0.75rem', display: 'inline-flex', alignItems: 'center' }}>\n {props.pillExtra}\n </span>\n ) : null}\n\n <div style={spacerStyle} />\n\n {props.mode === 'live' ? (\n <>\n <span style={pollMetaStyle}>\n {props.lastPollAt === null\n ? 'connecting…'\n : `polled ${formatTime(props.lastPollAt)} · every ${props.intervalSec}s`}\n </span>\n {props.onSnapshot !== undefined ? (\n <button\n type=\"button\"\n onClick={props.onSnapshot}\n disabled={!props.canSnapshot}\n style={iconButtonStyle(!!props.canSnapshot)}\n title={\n props.canSnapshot\n ? 'Freeze the current live samples into a Mock dataset and switch to it (for tick-by-tick scrubbing)'\n : 'Wait for the first poll to complete'\n }\n >\n 📸 Snapshot\n </button>\n ) : null}\n {props.onExport !== undefined ? (\n <button\n type=\"button\"\n onClick={props.onExport}\n disabled={!props.canExport}\n style={iconButtonStyle(!!props.canExport)}\n title={\n props.canExport\n ? 'Download the current scenario as a JSON file you can re-import or share.\\n\\nThe file freezes everything up to the most recent poll — no need to pause first. If you want the export to precisely match a frame you’re inspecting (e.g. mid-firing), pause Live updates first via the ⏸ button on the scrub strip.'\n : 'Wait for the first poll to complete'\n }\n >\n 📥 Export\n </button>\n ) : null}\n {props.onImport !== undefined ? (\n <label style={iconButtonStyle(true)} title=\"Import a previously-exported JSON dataset\">\n 📤 Import\n <input\n type=\"file\"\n accept=\"application/json,.json\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file !== undefined && props.onImport !== undefined) {\n props.onImport(file);\n }\n e.target.value = '';\n }}\n style={hiddenFileInputStyle}\n />\n </label>\n ) : null}\n </>\n ) : (\n <>\n <span style={pollMetaStyle}>\n tick <strong>{props.tickIndex}</strong> / {props.tickCount}\n </span>\n <span style={actionSlotStyle}>{props.replayButtons}</span>\n {props.onExport !== undefined ? (\n <button\n type=\"button\"\n onClick={props.onExport}\n style={iconButtonStyle(true)}\n title=\"Download the current dataset as a JSON file you can re-import or share\"\n >\n 📥 Export\n </button>\n ) : null}\n {props.onImport !== undefined ? (\n <label style={iconButtonStyle(true)} title=\"Import a previously-exported JSON dataset\">\n 📤 Import\n <input\n type=\"file\"\n accept=\"application/json,.json\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file !== undefined && props.onImport !== undefined) {\n props.onImport(file);\n }\n e.target.value = '';\n }}\n style={hiddenFileInputStyle}\n />\n </label>\n ) : null}\n </>\n )}\n </div>\n\n {props.mode === 'live' && props.error !== null ? (\n <div style={errorRowStyle}>\n <span style={errorLabelStyle}>poll error</span>\n <code style={errorCodeStyle}>{props.error}</code>\n </div>\n ) : null}\n\n {props.mode === 'live' && props.exportToast ? (\n <div style={toastRowStyle}>{props.exportToast}</div>\n ) : null}\n\n {props.mode === 'live' && props.footerSlot !== undefined ? (\n <div style={rowStyle}>{props.footerSlot}</div>\n ) : null}\n </div>\n );\n}\n\nfunction LivePills({\n grafanaState,\n ourState,\n}: {\n // Omitted renders only the What-If pill, no comparison symbol.\n readonly grafanaState?: GrafanaAlertState;\n readonly ourState: OurState;\n}) {\n if (grafanaState === undefined) {\n return (\n <>\n <span style={labelStyle}>What-If</span>\n <Chip kind={chipKindForOurs(ourState)}>{ourState}</Chip>\n </>\n );\n }\n const grafanaLabel = grafanaState === 'unknown' ? '—' : grafanaState;\n const matched = statesMatch(grafanaState, ourState);\n return (\n <>\n <span style={labelStyle}>Grafana</span>\n <Chip kind={chipKindForGrafana(grafanaState)}>{grafanaLabel}</Chip>\n <span\n style={matched ? matchSymbolStyle : mismatchSymbolStyle}\n aria-label={matched ? 'match' : 'diverged'}\n title={matched ? 'States agree' : 'States disagree — investigate'}\n >\n {matched ? '=' : '≠'}\n </span>\n <span style={labelStyle}>What-If</span>\n <Chip kind={chipKindForOurs(ourState)}>{ourState.toLowerCase()}</Chip>\n </>\n );\n}\n\ntype ChipKind = 'firing' | 'pending' | 'nodata' | 'inactive' | 'unknown';\n\nfunction Chip({ kind, children }: { readonly kind: ChipKind; readonly children: React.ReactNode }) {\n return <span style={chipStyle(kind)}>{children}</span>;\n}\n\nfunction chipKindForGrafana(s: GrafanaAlertState): ChipKind {\n if (s === 'firing') return 'firing';\n if (s === 'pending') return 'pending';\n if (s === 'inactive') return 'inactive';\n return 'unknown';\n}\n\nfunction chipKindForOurs(s: OurState): ChipKind {\n if (s === 'Firing') return 'firing';\n if (s === 'Pending') return 'pending';\n if (s === 'NoData') return 'nodata';\n if (s === 'Recovering') return 'pending';\n return 'inactive';\n}\n\n// Local timezone to match MetricChart + ComputeTracePanel.\nfunction formatTime(ms: number): string {\n const d = new Date(ms);\n const pad = (n: number) => n.toString().padStart(2, '0');\n return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n}\n\nconst rootStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: '0.35rem',\n padding: '0.5rem 0.75rem',\n border: '1px solid var(--border-card)',\n borderRadius: 8,\n background: 'var(--bg-card)',\n marginBottom: '0.5rem',\n};\n\nconst rowStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '0.4rem',\n fontSize: '0.85rem',\n};\n\nconst errorRowStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'baseline',\n gap: '0.4rem',\n paddingTop: '0.25rem',\n borderTop: '1px solid var(--border-card)',\n fontSize: '0.8rem',\n};\n\nconst toastRowStyle: CSSProperties = {\n paddingTop: '0.25rem',\n borderTop: '1px solid var(--border-card)',\n fontSize: '0.78rem',\n color: 'var(--text-muted)',\n fontVariantNumeric: 'tabular-nums',\n};\n\nconst labelStyle: CSSProperties = {\n color: 'var(--text-muted)',\n fontSize: '0.78rem',\n textTransform: 'uppercase',\n letterSpacing: '0.04em',\n};\n\nconst queryStyle: CSSProperties = {\n color: 'var(--text-primary)',\n fontSize: '0.85rem',\n};\n\nconst codeStyle: CSSProperties = {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.8rem',\n padding: '1px 4px',\n borderRadius: 3,\n background: 'var(--bg-input, transparent)',\n};\n\nconst pollMetaStyle: CSSProperties = {\n color: 'var(--text-muted)',\n fontSize: '0.8rem',\n fontVariantNumeric: 'tabular-nums',\n};\n\nconst matchSymbolStyle: CSSProperties = {\n color: 'var(--chart-state-normal, #22c55e)',\n fontWeight: 700,\n fontSize: '1rem',\n padding: '0 0.15rem',\n};\n\nconst mismatchSymbolStyle: CSSProperties = {\n color: 'var(--event-firing, #ef4444)',\n fontWeight: 700,\n fontSize: '1rem',\n padding: '0 0.15rem',\n};\n\nconst separatorStyle: CSSProperties = {\n color: 'var(--text-faded)',\n fontSize: '0.85rem',\n};\n\nconst spacerStyle: CSSProperties = { flex: '1 1 auto' };\n\n// Shared by the 📸/📥/📤 buttons; also styles the <label> wrapping Import's\n// hidden file input.\nconst iconButtonStyle = (enabled: boolean): CSSProperties => ({\n display: 'inline-flex',\n alignItems: 'center',\n marginLeft: '0.5rem',\n padding: '2px 8px',\n fontSize: '0.78rem',\n border: '1px solid var(--border-card)',\n borderRadius: 4,\n background: 'var(--bg-input, transparent)',\n color: enabled ? 'var(--text-primary)' : 'var(--text-faded)',\n cursor: enabled ? 'pointer' : 'not-allowed',\n opacity: enabled ? 1 : 0.5,\n whiteSpace: 'nowrap',\n});\n\n// Visually hidden but keyboard-focusable so the label can trigger it.\nconst hiddenFileInputStyle: CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n opacity: 0,\n pointerEvents: 'none',\n};\n\nconst actionSlotStyle: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.3rem',\n marginLeft: '0.5rem',\n};\n\nconst errorLabelStyle: CSSProperties = {\n color: 'var(--text-error)',\n fontSize: '0.75rem',\n textTransform: 'uppercase',\n letterSpacing: '0.04em',\n};\n\nconst errorCodeStyle: CSSProperties = {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.78rem',\n color: 'var(--text-error)',\n};\n\nconst chipStyle = (kind: ChipKind): CSSProperties => ({\n padding: '1px 8px',\n borderRadius: 999,\n fontSize: '0.78rem',\n fontWeight: 600,\n textTransform: 'lowercase',\n background: chipBackground(kind),\n color: chipColor(kind),\n border: `1px solid ${chipBorder(kind)}`,\n});\n\nfunction chipBackground(kind: ChipKind): string {\n switch (kind) {\n case 'firing':\n return 'rgba(239, 68, 68, 0.22)';\n case 'pending':\n return 'rgba(234, 179, 8, 0.22)';\n case 'nodata':\n return 'rgba(99, 102, 241, 0.22)';\n case 'inactive':\n return 'rgba(34, 197, 94, 0.22)';\n case 'unknown':\n default:\n return 'rgba(127, 127, 127, 0.22)';\n }\n}\n\nfunction chipColor(kind: ChipKind): string {\n switch (kind) {\n case 'firing':\n return 'var(--event-firing, #ef4444)';\n case 'pending':\n return 'var(--event-pending, #eab308)';\n case 'nodata':\n return 'var(--event-nodata, #6366f1)';\n case 'inactive':\n return '#22c55e';\n case 'unknown':\n default:\n return 'var(--text-muted)';\n }\n}\n\nfunction chipBorder(kind: ChipKind): string {\n return chipColor(kind);\n}\n","// Hybrid HTML + SVG: an SVG layer (preserveAspectRatio=\"none\",\n// non-scaling-stroke) holds geometry; an HTML overlay holds text + emoji so\n// they stay crisp despite the SVG stretch. Both use [0,100] percentage coords.\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport type {\n EvalEvent,\n ReducerKind,\n Sample,\n Threshold,\n Tick,\n} from '@alert-whatif/core';\nimport { detectStateBarDivergence } from '@alert-whatif/core';\nimport { EVENT_COLOR } from '../util/event-colors';\nimport {\n FLASH_DURATION_MS,\n FLASH_GAP_MS,\n SWEEP_PER_DOT_MS,\n SWEEP_STAGGER_MS,\n} from '../util/reduce-animation-timing';\nimport { mutedTextStyle } from '../styles';\nimport {\n CHART_TOP_PCT,\n CHART_BOTTOM_PCT,\n GRAFANA_BAR_TOP_PCT,\n GRAFANA_BAR_BOTTOM_PCT,\n STATE_BAR_TOP_PCT,\n STATE_BAR_BOTTOM_PCT,\n BASELINE_BAR_TOP_PCT,\n BASELINE_BAR_BOTTOM_PCT,\n COLOR_LINE,\n COLOR_THRESHOLD,\n COLOR_AXIS,\n COLOR_WINDOW,\n COLOR_WINDOW_BORDER,\n COLOR_STATE_NORMAL,\n DIVERGENCE_STROKE,\n DIVERGENCE_LABEL_PCT,\n MAX_EYES,\n TARGET_CHART_SPAN_MS,\n RIGHT_ANCHOR_PAD_MS,\n} from './constants';\nimport { thresholdYValues, padDomain, niceCeil } from './geometry';\nimport {\n computeEvalTicks,\n computeDisplayTicks,\n computeSubdivisionTicks,\n computeMinuteTicks,\n} from './ticks';\nimport {\n eventsToTransitions,\n grafanaHistoryToTransitions,\n computeNoDataRanges,\n} from '../calc/state';\nimport { findThresholdCrossings } from '../calc/crossings';\nimport type { ThresholdCrossing } from '../calc/crossings';\nimport {\n filterEvents,\n buildGappedPath,\n} from './transitions';\nimport {\n formatTime,\n formatTimeShort,\n formatSeconds,\n formatTickLabel,\n formatThresholdLabelValue,\n} from './format';\nimport {\n chartCardStyle,\n chartCanvasStyle,\n gutterStyle,\n chartAreaStyle,\n overlayStyle,\n legendStyle,\n legendItemStyle,\n legendTextStackStyle,\n legendSubLabelStyle,\n numericStyle,\n tickLabelStyle,\n secondsLabelStyle,\n barLabelStyle,\n windowLabelStyle,\n emojiStyle,\n subdivisionDotStyle,\n crossingEmojiStyle,\n stateLabelStyle,\n divergenceLabelStyle,\n divergencePopoverStyle,\n divergencePopoverTitleStyle,\n divergencePopoverRowStyle,\n divergencePopoverKeyStyle,\n divergencePopoverValStyle,\n divergencePopoverNoteStyle,\n} from './styles';\nimport { ChartTitle } from './ChartTitle';\nimport { ChartOverlay, GutterLabel } from './ChartOverlay';\n\ntype Props = {\n readonly samples: ReadonlyArray<Sample>;\n // Subset of `samples` to plot (replay prefix); X-axis stays pinned to the\n // full sample range. Defaults to `samples`.\n readonly visibleSamples?: ReadonlyArray<Sample>;\n // Per-tick reduced values — the single number the threshold compared against.\n readonly ticks?: ReadonlyArray<Tick>;\n // Live: pin the right edge here (a 1-Hz wallclock) and extend backward, so\n // \"now\" advances every second. Omit (Mock) to center the data.\n readonly rightAnchorT?: number | undefined;\n // Force the Y ceiling (Live passes a fixed cap) so a value's pixel height\n // is stable across polls; values above clip to the top.\n readonly yMax?: number | undefined;\n readonly threshold: Threshold;\n readonly evaluationInterval: number;\n readonly windowDuration: number;\n // Pre-computed crossings; falls back to internal interpolation when omitted.\n readonly crossings?: ReadonlyArray<ThresholdCrossing>;\n // Drives the legend's \"reduce (…)\" label; falls back to \"mean\".\n readonly reducer?: ReducerKind;\n readonly events?: ReadonlyArray<EvalEvent>;\n // Second event series for the what-if comparison: working config vs baseline.\n readonly baselineEvents?: ReadonlyArray<EvalEvent>;\n readonly subtitle?: string;\n // Single source of truth from the parent so the status line matches the\n // LiveStatusStrip chip exactly (avoids lag from local recomputation).\n readonly currentState?: EvalEvent['kind'] | 'Normal';\n // State just before the first sample. 'Firing'/'NoData' suppresses the\n // left-edge marker since there's no transition INTO it to mark.\n readonly initialState?: 'Normal' | 'Firing' | 'NoData';\n // Drill: extend the right edge past the last sample so a post-data Resolved\n // transition stays visible.\n readonly displayEndT?: number;\n // Mirror of displayEndT for the left edge (🔔 firing at samples[0].t).\n readonly displayStartT?: number;\n // Drill focal timestamp shown in the time-range banner.\n readonly focalMs?: number;\n // React `key` for the NOW ⏰ pop animation — bump per Live poll.\n readonly pollSignal?: number;\n // Per-poll Grafana state changes (Live/drill), rendered as a second bar so\n // divergence from ours is obvious.\n readonly grafanaHistory?: ReadonlyArray<{ readonly t: number; readonly state: string }> | undefined;\n // \"until\" for grafanaHistory's last segment (usually liveNow).\n readonly grafanaHistoryEnd?: number | undefined;\n // Docked inside the chart card below the SVG (Live scrub strip).\n readonly bottomSlot?: ReactNode;\n};\n\nexport function MetricChart({\n samples,\n visibleSamples,\n ticks,\n threshold,\n evaluationInterval,\n windowDuration,\n crossings: crossingsOverride,\n reducer,\n events = [],\n subtitle,\n rightAnchorT,\n yMax,\n bottomSlot,\n currentState,\n grafanaHistory,\n grafanaHistoryEnd,\n baselineEvents,\n initialState,\n displayEndT,\n displayStartT,\n focalMs,\n pollSignal,\n}: Props) {\n // Banner uses the visible sample range, not the wider fetch window, so it\n // matches what the user actually sees.\n const bannerStart = samples[0]?.t;\n const bannerEnd = samples[samples.length - 1]?.t;\n const spanMs =\n bannerStart !== undefined && bannerEnd !== undefined\n ? bannerEnd - bannerStart\n : undefined;\n const spanLabel =\n spanMs !== undefined && spanMs > 0\n ? ` · ${spanMs >= 3600_000 ? `${Math.round(spanMs / 3600_000)}h` : `${Math.round(spanMs / 60_000)}m visible`}`\n : '';\n const timeRange =\n bannerStart === undefined || bannerEnd === undefined\n ? undefined\n : focalMs !== undefined\n ? `${formatTime(bannerStart)} → 📍 ${formatTime(focalMs)} → ${formatTime(bannerEnd)}${spanLabel}`\n : `${formatTime(bannerStart)} → ${formatTime(bannerEnd)}${spanLabel}`;\n return (\n <section style={chartCardStyle}>\n <ChartTitle subtitle={subtitle ?? ''} timeRange={timeRange} />\n {samples.length === 0 ? (\n <p style={mutedTextStyle}>No samples to plot.</p>\n ) : (\n <ChartBody\n samples={samples}\n visibleSamples={visibleSamples ?? samples}\n ticks={ticks ?? []}\n threshold={threshold}\n evaluationInterval={evaluationInterval}\n windowDuration={windowDuration}\n {...(crossingsOverride !== undefined ? { crossingsOverride } : {})}\n reducer={reducer}\n events={events}\n rightAnchorT={rightAnchorT}\n yMaxOverride={yMax}\n bottomSlot={bottomSlot}\n currentState={currentState}\n grafanaHistory={grafanaHistory}\n grafanaHistoryEnd={grafanaHistoryEnd}\n baselineEvents={baselineEvents}\n initialState={initialState}\n displayEndT={displayEndT}\n displayStartT={displayStartT}\n pollSignal={pollSignal}\n />\n )}\n </section>\n );\n}\n\nfunction ChartBody({\n samples,\n visibleSamples,\n ticks,\n threshold,\n evaluationInterval,\n windowDuration,\n crossingsOverride,\n reducer,\n events,\n rightAnchorT,\n yMaxOverride,\n bottomSlot,\n currentState,\n grafanaHistory,\n grafanaHistoryEnd,\n baselineEvents,\n initialState,\n displayEndT,\n displayStartT,\n pollSignal,\n}: {\n readonly samples: ReadonlyArray<Sample>;\n readonly visibleSamples: ReadonlyArray<Sample>;\n readonly ticks: ReadonlyArray<Tick>;\n readonly threshold: Threshold;\n readonly evaluationInterval: number;\n readonly windowDuration: number;\n readonly crossingsOverride?: ReadonlyArray<ThresholdCrossing>;\n readonly reducer: ReducerKind | undefined;\n readonly events: ReadonlyArray<EvalEvent>;\n readonly rightAnchorT: number | undefined;\n readonly yMaxOverride: number | undefined;\n readonly bottomSlot: ReactNode | undefined;\n readonly grafanaHistory: ReadonlyArray<{ readonly t: number; readonly state: string }> | undefined;\n readonly grafanaHistoryEnd: number | undefined;\n readonly currentState: EvalEvent['kind'] | 'Normal' | undefined;\n readonly baselineEvents: ReadonlyArray<EvalEvent> | undefined;\n readonly initialState: 'Normal' | 'Firing' | 'NoData' | undefined;\n readonly displayEndT: number | undefined;\n readonly displayStartT: number | undefined;\n readonly pollSignal: number | undefined;\n}) {\n const first = samples[0]!;\n const last = samples[samples.length - 1]!;\n // Live (rightAnchorT set): pin the right edge and extend a FIXED span back\n // so the grid density stays stable as samples accumulate. Mock: center the\n // data. Both fall back to data span when data is wider than the target.\n const dataSpan = last.t - first.t;\n let chartMinT: number;\n let chartMaxT: number;\n if (rightAnchorT !== undefined) {\n chartMaxT = rightAnchorT + RIGHT_ANCHOR_PAD_MS;\n chartMinT = chartMaxT - TARGET_CHART_SPAN_MS;\n } else {\n const span = Math.max(dataSpan, TARGET_CHART_SPAN_MS);\n const center = (first.t + last.t) / 2;\n chartMinT = center - span / 2;\n chartMaxT = center + span / 2;\n }\n // Drill: extend past the last sample (keeping chartMinT at first.t) so the\n // empty tail makes a post-data Resolved/NoData transition land on-screen.\n if (displayEndT !== undefined && displayEndT > chartMaxT) {\n chartMaxT = displayEndT;\n if (chartMinT > first.t) chartMinT = first.t;\n }\n // Mirror for the left edge (🔔 click where Normal/NoData precedes data).\n if (displayStartT !== undefined && displayStartT < chartMinT) {\n chartMinT = displayStartT;\n if (chartMaxT < last.t) chartMaxT = last.t;\n }\n const tSpan = chartMaxT - chartMinT || 1;\n\n const sampleValues = samples.map((s) => s.v).filter((v) => Number.isFinite(v));\n const rawMin = sampleValues.length > 0 ? Math.min(...sampleValues) : 0;\n const rawMax = sampleValues.length > 0 ? Math.max(...sampleValues) : 1;\n // Override (Live's fixed cap) keeps pixel height stable across polls;\n // otherwise niceCeil steps in familiar buckets so the line doesn't jitter.\n const yMax = yMaxOverride ?? niceCeil(rawMax);\n const yMin = padDomain(rawMin, yMax).yMin;\n const ySpan = yMax - yMin || 1;\n\n const xPct = (t: number) => ((t - chartMinT) / tSpan) * 100;\n const yPctInChart = (v: number) => {\n if (!Number.isFinite(v)) return (CHART_TOP_PCT + CHART_BOTTOM_PCT) / 2;\n const pct = (yMax - v) / ySpan;\n const clamped = Math.max(0, Math.min(1, pct));\n return CHART_TOP_PCT + clamped * (CHART_BOTTOM_PCT - CHART_TOP_PCT);\n };\n\n const thresholdYs = thresholdYValues(threshold);\n // Eyes mark \"where Grafana evaluates\": anchor to the evaluator's grid and\n // step in evaluationInterval to fill the chart. Live clips to ≤ NOW so no\n // eye claims an eval that hasn't happened. Falls back to the sample grid\n // when evaluate() returned no ticks.\n const evalRangeEnd = rightAnchorT ?? chartMaxT;\n const evalTicks =\n ticks.length > 0 && evaluationInterval > 0\n ? computeDisplayTicks(ticks[0]!.t, evaluationInterval, chartMinT, evalRangeEnd)\n : computeEvalTicks(first.t, last.t, evaluationInterval);\n // Labels on the absolute UTC minute grid (HH:MM:00) so a :30 eval sits\n // visually between two labels, not stacked on one.\n const displayTicks = computeMinuteTicks(chartMinT, chartMaxT);\n\n // 15s grid dotted into the gaps; coincidences with shown markers filtered at\n // render time.\n const subdivisionTicks = computeSubdivisionTicks(chartMinT, chartMaxT, 15_000);\n const displayTickSet = new Set(displayTicks);\n const evalTickSet = new Set(evalTicks);\n\n // Eval ticks beyond the latest visible sample stay drawn so the playhead\n // reads as sliding over a fixed grid, not scrolling it.\n const hasVisible = visibleSamples.length > 0;\n const lastVisible = hasVisible ? visibleSamples[visibleSamples.length - 1]! : undefined;\n const visibleEvalTicks = hasVisible\n ? evalTicks.filter((t) => t <= lastVisible!.t)\n : [];\n // Most-recent Data tick. Read from `ticks` (evaluator output), NOT\n // visibleEvalTicks, so a Prometheus delivery gap near the boundary doesn't\n // freeze the playhead while the evaluator keeps reducing older samples.\n let latestDataTickT: number | null = null;\n for (let i = ticks.length - 1; i >= 0; i--) {\n if (ticks[i]!.kind === 'Data') {\n latestDataTickT = ticks[i]!.t;\n break;\n }\n }\n const latestTick = latestDataTickT !== null\n ? latestDataTickT\n : visibleEvalTicks.length > 0\n ? visibleEvalTicks[visibleEvalTicks.length - 1]!\n : (hasVisible ? lastVisible!.t : first.t);\n // Anchored to latestTick so the box's right border and the reduce-result\n // dot share one moment.\n const windowAnchor = latestTick;\n // Full windowDuration left of the playhead — no clamp to first.t, since the\n // window is a semantic span; xPct clipping handles overflow.\n const windowStart = windowAnchor - windowDuration;\n const showEyes = evalTicks.length > 0 && evalTicks.length <= MAX_EYES;\n const showWindow = hasVisible && windowDuration > 0 && evaluationInterval > 0;\n\n // Re-mount the animation on each forward latestTick. Skipped on backward\n // moves (replay scrubbing) and same-tick sample refreshes.\n const [animationKey, setAnimationKey] = useState(0);\n const prevLatestTickRef = useRef<number | null>(null);\n\n const [openDivergenceIdx, setOpenDivergenceIdx] = useState<number | null>(null);\n useEffect(() => {\n if (openDivergenceIdx === null) return;\n const onDocClick = (e: MouseEvent) => {\n const tgt = e.target as HTMLElement | null;\n if (tgt?.closest('[data-divergence-popover], [data-divergence-trigger]')) return;\n setOpenDivergenceIdx(null);\n };\n document.addEventListener('click', onDocClick);\n return () => document.removeEventListener('click', onDocClick);\n }, [openDivergenceIdx]);\n useEffect(() => {\n const prev = prevLatestTickRef.current;\n if (prev !== null && latestTick > prev) {\n setAnimationKey((k) => k + 1);\n }\n prevLatestTickRef.current = latestTick;\n }, [latestTick]);\n // Same window math as evaluate()'s slideTo.\n const animationWindowSamples = visibleSamples.filter(\n (s) =>\n s.t > latestTick - windowDuration &&\n s.t <= latestTick &&\n Number.isFinite(s.v),\n );\n // Pulled from ticks (not recomputed) to match evaluate() exactly.\n const latestTickValue =\n ticks.length > 0 && ticks[ticks.length - 1]!.t === latestTick &&\n ticks[ticks.length - 1]!.kind === 'Data'\n ? (ticks[ticks.length - 1] as Extract<Tick, { kind: 'Data' }>).v\n : null;\n // Phase timing MUST stay in sync with the CSS keyframes in index.css. Flash\n // + fade start after the last sweep dot ends. Instant rules skip the sweep —\n // only the result-pop dot, zero delay.\n const isInstant = reducer === undefined;\n const N = isInstant ? 0 : animationWindowSamples.length;\n const lastSweepEndMs = N > 0 ? (N - 1) * SWEEP_STAGGER_MS + SWEEP_PER_DOT_MS : 0;\n const flashDelayMs = lastSweepEndMs + FLASH_GAP_MS;\n const fadeDelayMs = flashDelayMs + FLASH_DURATION_MS;\n const resultDelayMs = isInstant ? 0 : fadeDelayMs;\n\n // Prefer parent-supplied crossings; fall back to local interpolation.\n // 'ignition'/'resolution' are framed by alert state, not value direction\n // (an Lt threshold ignites on a falling value).\n const crossings =\n crossingsOverride !== undefined\n ? crossingsOverride\n : findThresholdCrossings(visibleSamples, threshold);\n // Drawn on top of the event rects so an in-progress NoData lifecycle (which\n // only emits a Pending event until the for-gate fires) still shows NoData.\n const noDataRanges = computeNoDataRanges(ticks, evaluationInterval);\n // One marker per event — a live window can contain multiple cycles.\n const pendingEvents = filterEvents(events, 'Pending');\n const allFiringEvents = filterEvents(events, 'Firing');\n // Already-Firing-before-windowStart: snap the first marker to first.t so the\n // 🔔 lines up with the state bar's leftmost red pixel.\n const firingSuppressionWindow = first.t + evaluationInterval;\n const firingEvents =\n initialState === 'Firing' &&\n allFiringEvents.length > 0 &&\n allFiringEvents[0]!.from <= firingSuppressionWindow\n ? [{ ...allFiringEvents[0]!, from: first.t }, ...allFiringEvents.slice(1)]\n : allFiringEvents;\n const resolvedEvents = filterEvents(events, 'Resolved');\n const allNoDataEvents = filterEvents(events, 'NoData');\n const noDataEvents =\n initialState === 'NoData' &&\n allNoDataEvents.length > 0 &&\n allNoDataEvents[0]!.from <= firingSuppressionWindow\n ? allNoDataEvents.slice(1)\n : allNoDataEvents;\n\n // Derive the gap threshold from the observed cadence (2× step) so tweaking\n // intervalMs doesn't break the polyline at every pair. Falls back to 30s.\n const inferredSampleStepMs =\n visibleSamples.length >= 2\n ? Math.max(1, visibleSamples[1]!.t - visibleSamples[0]!.t)\n : 15_000;\n const RATE_GAP_THRESHOLD_MS = inferredSampleStepMs * 2;\n const MEAN_GAP_THRESHOLD_MS = evaluationInterval * 1.5;\n\n const ratePath = buildGappedPath(\n visibleSamples,\n (s) => s.t,\n (s) => s.v,\n xPct,\n yPctInChart,\n RATE_GAP_THRESHOLD_MS,\n );\n\n // One point per Data tick at the reducer's output; NoData ticks gap the line.\n const meanPath = buildGappedPath(\n ticks.filter((t): t is Extract<Tick, { kind: 'Data' }> => t.kind === 'Data'),\n (t) => t.t,\n (t) => t.v,\n xPct,\n yPctInChart,\n MEAN_GAP_THRESHOLD_MS,\n );\n\n // Surfaces the issue #153 timing gap: UI-built rules skip the query_offset\n // imported rules get, so their transitions lag by ~1 eval cycle.\n const divergences =\n grafanaHistory !== undefined && grafanaHistory.length > 0\n ? detectStateBarDivergence(\n eventsToTransitions(events),\n grafanaHistoryToTransitions(grafanaHistory),\n evaluationInterval,\n )\n : [];\n\n return (\n <>\n <div style={chartCanvasStyle}>\n {/* Numeric Y labels intentionally omitted — with multiple curves a bare\n axis number wouldn't say which curve it measures. */}\n <div style={gutterStyle}>\n {thresholdYs.map((v) => {\n const inRange = v >= yMin && v <= yMax;\n const lineY = inRange ? yPctInChart(v) : v < yMin ? CHART_BOTTOM_PCT : CHART_TOP_PCT;\n const arrow = inRange ? '' : v < yMin ? '↓ ' : '↑ ';\n return (\n <GutterLabel key={`thresh-lbl-${v}`} y={lineY} align=\"bottom\">\n <span style={{ ...numericStyle, color: 'var(--chart-threshold)' }}>\n thresh {arrow}\n {formatThresholdLabelValue(threshold, v)}\n </span>\n </GutterLabel>\n );\n })}\n {grafanaHistory !== undefined && grafanaHistory.length > 0 ? (\n <GutterLabel y={(GRAFANA_BAR_TOP_PCT + GRAFANA_BAR_BOTTOM_PCT) / 2} align=\"middle\">\n <span style={barLabelStyle}>grafana</span>\n </GutterLabel>\n ) : null}\n {baselineEvents !== undefined ? (\n <GutterLabel\n y={(BASELINE_BAR_TOP_PCT + BASELINE_BAR_BOTTOM_PCT) / 2}\n align=\"middle\"\n >\n <span style={barLabelStyle}>baseline</span>\n </GutterLabel>\n ) : null}\n <GutterLabel y={(STATE_BAR_TOP_PCT + STATE_BAR_BOTTOM_PCT) / 2} align=\"middle\">\n <span style={barLabelStyle}>{baselineEvents !== undefined ? 'what-if' : 'state'}</span>\n </GutterLabel>\n {/* Series legend — labels split across two lines to fit the gutter. */}\n <GutterLabel y={CHART_TOP_PCT + (CHART_BOTTOM_PCT - CHART_TOP_PCT) * 0.35} align=\"middle\">\n <div style={legendStyle}>\n <span style={legendItemStyle}>\n <svg width=\"18\" height=\"10\" aria-hidden style={{ flexShrink: 0 }}>\n <line\n x1=\"0\"\n y1=\"5\"\n x2=\"18\"\n y2=\"5\"\n stroke=\"var(--chart-line)\"\n strokeWidth=\"2\"\n />\n </svg>\n <span style={legendTextStackStyle}>\n <span>Prom</span>\n <span style={legendSubLabelStyle}>(rate)</span>\n </span>\n </span>\n {isInstant ? null : (\n <span style={legendItemStyle}>\n <svg width=\"18\" height=\"10\" aria-hidden style={{ flexShrink: 0 }}>\n <line\n x1=\"0\"\n y1=\"5\"\n x2=\"18\"\n y2=\"5\"\n stroke=\"var(--event-pending)\"\n strokeWidth=\"2\"\n strokeDasharray=\"3 2\"\n opacity=\"0.55\"\n />\n </svg>\n <span style={legendTextStackStyle}>\n <span>reduce</span>\n <span style={legendSubLabelStyle}>\n ({(reducer ?? 'Mean').toLowerCase()})\n </span>\n </span>\n </span>\n )}\n </div>\n </GutterLabel>\n </div>\n\n <div style={chartAreaStyle}>\n <svg\n role=\"img\"\n aria-label=\"Metric chart\"\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"none\"\n width=\"100%\"\n height=\"100%\"\n style={{ position: 'absolute', inset: 0, display: 'block' }}\n >\n {/* relativeTimeRange highlight — bottom half only, so it doesn't\n collide with the polyline in the top half. */}\n {!isInstant && showWindow ? (\n <rect\n x={xPct(windowStart)}\n y={(CHART_TOP_PCT + CHART_BOTTOM_PCT) / 2}\n width={Math.max(xPct(windowAnchor) - xPct(windowStart), 0.1)}\n height={(CHART_BOTTOM_PCT - CHART_TOP_PCT) / 2}\n fill={COLOR_WINDOW}\n stroke={COLOR_WINDOW_BORDER}\n strokeWidth={0.8}\n vectorEffect=\"non-scaling-stroke\"\n />\n ) : null}\n\n {/* Chart-bottom baseline — X-axis frame plus a y=0 reference. */}\n <line\n x1={0}\n x2={100}\n y1={CHART_BOTTOM_PCT}\n y2={CHART_BOTTOM_PCT}\n stroke={COLOR_AXIS}\n strokeWidth={0.5}\n vectorEffect=\"non-scaling-stroke\"\n />\n\n {/* Threshold line(s). */}\n {thresholdYs.map((v) => {\n const inRange = v >= yMin && v <= yMax;\n const lineY = inRange ? yPctInChart(v) : v < yMin ? CHART_BOTTOM_PCT : CHART_TOP_PCT;\n return (\n <line\n key={`thresh-${v}`}\n x1={0}\n x2={100}\n y1={lineY}\n y2={lineY}\n stroke={COLOR_THRESHOLD}\n strokeDasharray=\"3 2\"\n strokeWidth={0.6}\n vectorEffect=\"non-scaling-stroke\"\n />\n );\n })}\n\n {/* Sample polyline — `<path>` so data gaps break the line instead of\n drawing a fake straight segment across them. */}\n <path\n d={ratePath}\n fill=\"none\"\n stroke={COLOR_LINE}\n strokeWidth={1.25}\n vectorEffect=\"non-scaling-stroke\"\n />\n\n {/* `mean` polyline — dashed, one point per Data tick. */}\n {!isInstant && meanPath.length > 0 ? (\n <path\n d={meanPath}\n fill=\"none\"\n stroke={COLOR_LINE}\n strokeWidth={1}\n strokeDasharray=\"3 2\"\n vectorEffect=\"non-scaling-stroke\"\n opacity={0.85}\n />\n ) : null}\n\n {/* Crossing guides — dashed (vs the solid lifecycle guides) to signal\n the crossing time is interpolated, not a real eval moment. */}\n {crossings.map((c) => {\n const xp = xPct(c.t);\n if (xp < 0 || xp > 100) return null;\n return (\n <line\n key={`xguide-${c.t}-${c.direction}`}\n x1={xp}\n x2={xp}\n y1={CHART_TOP_PCT}\n y2={STATE_BAR_BOTTOM_PCT}\n stroke={COLOR_THRESHOLD}\n strokeWidth={0.8}\n strokeDasharray=\"3 2\"\n vectorEffect=\"non-scaling-stroke\"\n opacity={0.45}\n />\n );\n })}\n\n {/* NOW reference line — fixed position in Live mode; data scrolls past. */}\n {rightAnchorT !== undefined ? (\n <line\n x1={xPct(rightAnchorT)}\n x2={xPct(rightAnchorT)}\n y1={CHART_TOP_PCT}\n y2={STATE_BAR_BOTTOM_PCT}\n stroke=\"var(--text-primary)\"\n strokeWidth={0.9}\n strokeDasharray=\"2 2\"\n vectorEffect=\"non-scaling-stroke\"\n opacity={0.55}\n />\n ) : null}\n\n {/* Pending guides — one per Normal → Pending transition. */}\n {pendingEvents.map((p, i) => {\n const xp = xPct(p.from);\n if (xp < 0 || xp > 100) return null;\n return (\n <line\n key={`pending-guide-${i}-${p.from}`}\n x1={xp}\n x2={xp}\n y1={CHART_TOP_PCT}\n y2={STATE_BAR_BOTTOM_PCT}\n stroke={EVENT_COLOR.Pending}\n strokeWidth={0.8}\n vectorEffect=\"non-scaling-stroke\"\n opacity={0.45}\n />\n );\n })}\n\n {/* Firing guides — one per Firing event. */}\n {firingEvents.map((f, i) => {\n const xp = xPct(f.from);\n if (xp < 0 || xp > 100) return null;\n return (\n <line\n key={`firing-guide-${i}-${f.from}`}\n x1={xp}\n x2={xp}\n y1={CHART_TOP_PCT}\n y2={STATE_BAR_BOTTOM_PCT}\n stroke=\"var(--event-firing)\"\n strokeWidth={0.8}\n vectorEffect=\"non-scaling-stroke\"\n opacity={0.45}\n />\n );\n })}\n\n {/* Resolved guides — one per Resolved point event. */}\n {resolvedEvents.map((r, i) => {\n const xp = xPct(r.at);\n if (xp < 0 || xp > 100) return null;\n return (\n <line\n key={`resolved-guide-${i}-${r.at}`}\n x1={xp}\n x2={xp}\n y1={CHART_TOP_PCT}\n y2={STATE_BAR_BOTTOM_PCT}\n stroke={EVENT_COLOR.Resolved}\n strokeWidth={0.8}\n vectorEffect=\"non-scaling-stroke\"\n opacity={0.45}\n />\n );\n })}\n\n {/* NoData guides — one per NoData event. */}\n {noDataEvents.map((n, i) => {\n const xp = xPct(n.from);\n if (xp < 0 || xp > 100) return null;\n return (\n <line\n key={`nodata-guide-${i}-${n.from}`}\n x1={xp}\n x2={xp}\n y1={CHART_TOP_PCT}\n y2={STATE_BAR_BOTTOM_PCT}\n stroke={EVENT_COLOR.NoData}\n strokeWidth={0.8}\n vectorEffect=\"non-scaling-stroke\"\n opacity={0.45}\n />\n );\n })}\n\n {/* GRAFANA state bar. Segments clipped to the playhead (latestTick)\n so it reveals progressively in step with the what-if bar below. */}\n {grafanaHistory !== undefined && grafanaHistory.length > 0 ? (\n <>\n <rect\n x={0}\n y={GRAFANA_BAR_TOP_PCT}\n width={100}\n height={GRAFANA_BAR_BOTTOM_PCT - GRAFANA_BAR_TOP_PCT}\n fill={COLOR_STATE_NORMAL}\n />\n {grafanaHistory.map((entry, idx) => {\n const next = grafanaHistory[idx + 1];\n const rawUntil = next?.t ?? grafanaHistoryEnd ?? entry.t;\n const segUntil = Math.min(rawUntil, latestTick);\n if (entry.t >= latestTick) return null;\n const fillKind: EvalEvent['kind'] | null =\n entry.state === 'pending' ? 'Pending' :\n entry.state === 'firing' ? 'Firing' :\n null;\n if (fillKind === null) return null;\n const x1 = xPct(entry.t);\n const x2 = xPct(segUntil);\n if (x2 <= 0 || x1 >= 100) return null;\n const x = Math.max(x1, 0);\n const w = Math.min(x2, 100) - x;\n if (w <= 0) return null;\n return (\n <rect\n key={`grafana-seg-${idx}-${entry.t}`}\n x={x}\n y={GRAFANA_BAR_TOP_PCT}\n width={Math.max(w, 0.1)}\n height={GRAFANA_BAR_BOTTOM_PCT - GRAFANA_BAR_TOP_PCT}\n fill={EVENT_COLOR[fillKind]}\n />\n );\n })}\n </>\n ) : null}\n\n {/* Baseline event bar — the rule's current config vs the tweaked one. */}\n {baselineEvents !== undefined ? (\n <>\n <rect\n x={0}\n y={BASELINE_BAR_TOP_PCT}\n width={100}\n height={BASELINE_BAR_BOTTOM_PCT - BASELINE_BAR_TOP_PCT}\n fill={COLOR_STATE_NORMAL}\n />\n {baselineEvents.map((event, idx) => {\n const color = EVENT_COLOR[event.kind];\n if (event.kind === 'Resolved') {\n const x = xPct(event.at);\n return (\n <line\n key={`base-evt-${idx}`}\n x1={x}\n x2={x}\n y1={BASELINE_BAR_TOP_PCT - 0.5}\n y2={BASELINE_BAR_BOTTOM_PCT + 0.5}\n stroke={color}\n strokeWidth={1.5}\n vectorEffect=\"non-scaling-stroke\"\n />\n );\n }\n const untilCapped = Math.min(event.until, windowAnchor);\n if (untilCapped <= event.from) return null;\n const x1 = xPct(event.from);\n const x2 = xPct(untilCapped);\n return (\n <rect\n key={`base-evt-${idx}`}\n x={x1}\n y={BASELINE_BAR_TOP_PCT}\n width={Math.max(x2 - x1, 0.1)}\n height={BASELINE_BAR_BOTTOM_PCT - BASELINE_BAR_TOP_PCT}\n fill={color}\n />\n );\n })}\n </>\n ) : null}\n\n {/* State bar — Normal background + event overlays. */}\n <rect\n x={0}\n y={STATE_BAR_TOP_PCT}\n width={100}\n height={STATE_BAR_BOTTOM_PCT - STATE_BAR_TOP_PCT}\n fill={COLOR_STATE_NORMAL}\n />\n {events.map((event, idx) => {\n const color = EVENT_COLOR[event.kind];\n if (event.kind === 'Resolved') {\n const x = xPct(event.at);\n return (\n <line\n key={`evt-${idx}`}\n x1={x}\n x2={x}\n y1={STATE_BAR_TOP_PCT - 0.5}\n y2={STATE_BAR_BOTTOM_PCT + 0.5}\n stroke={color}\n strokeWidth={1.5}\n vectorEffect=\"non-scaling-stroke\"\n />\n );\n }\n // Cap at NOW: emit.ts extends an open lifecycle one eval past the\n // last tick, which would push our bar past NOW while Grafana's\n // stops at the last observation, making the two incommensurable.\n const eventUntilCapped = Math.min(event.until, windowAnchor);\n if (eventUntilCapped <= event.from) return null;\n const x1 = xPct(event.from);\n const x2 = xPct(eventUntilCapped);\n return (\n <rect\n key={`evt-${idx}`}\n x={x1}\n y={STATE_BAR_TOP_PCT}\n width={Math.max(x2 - x1, 0.1)}\n height={STATE_BAR_BOTTOM_PCT - STATE_BAR_TOP_PCT}\n fill={color}\n />\n );\n })}\n\n {/* Divergence indicators — dashed verticals through both bars per\n ≥1-eval timing gap, with a connector at the inter-bar mid-y. */}\n {divergences.map((d, i) => {\n const xs = xPct(d.stateAt);\n const xg = xPct(d.grafanaAt);\n const yTop = DIVERGENCE_LABEL_PCT;\n const yBot = STATE_BAR_BOTTOM_PCT;\n const yMid = (GRAFANA_BAR_BOTTOM_PCT + STATE_BAR_TOP_PCT) / 2;\n return (\n <g key={`divg-${i}-${d.stateAt}`} opacity={0.85}>\n <line\n x1={xs} x2={xs} y1={yTop} y2={yBot}\n stroke={DIVERGENCE_STROKE}\n strokeWidth={0.8}\n strokeDasharray=\"0.6 0.6\"\n vectorEffect=\"non-scaling-stroke\"\n />\n <line\n x1={xg} x2={xg} y1={yTop} y2={yBot}\n stroke={DIVERGENCE_STROKE}\n strokeWidth={0.8}\n strokeDasharray=\"0.6 0.6\"\n vectorEffect=\"non-scaling-stroke\"\n />\n <line\n x1={Math.min(xs, xg)} x2={Math.max(xs, xg)} y1={yMid} y2={yMid}\n stroke={DIVERGENCE_STROKE}\n strokeWidth={0.8}\n vectorEffect=\"non-scaling-stroke\"\n />\n </g>\n );\n })}\n\n {/* NoData overlay rects — drawn after events.map so NoData wins over\n the Pending rect emitted during an in-progress NoData lifecycle. */}\n {noDataRanges.map((r, i) => {\n const untilCapped = Math.min(r.until, windowAnchor);\n if (untilCapped <= r.from) return null;\n return (\n <rect\n key={`nodata-tick-${i}-${r.from}`}\n x={xPct(r.from)}\n y={STATE_BAR_TOP_PCT}\n width={Math.max(xPct(untilCapped) - xPct(r.from), 0.1)}\n height={STATE_BAR_BOTTOM_PCT - STATE_BAR_TOP_PCT}\n fill={EVENT_COLOR.NoData}\n />\n );\n })}\n\n {/* Playhead at the latest seen eval tick. */}\n {hasVisible ? (\n <line\n x1={xPct(latestTick)}\n x2={xPct(latestTick)}\n y1={CHART_TOP_PCT}\n y2={STATE_BAR_BOTTOM_PCT}\n stroke={COLOR_LINE}\n strokeWidth={0.8}\n vectorEffect=\"non-scaling-stroke\"\n opacity={0.65}\n />\n ) : null}\n </svg>\n\n {/* HTML overlay — text + emoji, pointer-events:none. */}\n <div style={overlayStyle}>\n {/* Reduce-animation dots — HTML (not SVG) so they stay round under\n the SVG's stretch. animationDelay staggers the sweep. */}\n {animationKey > 0 && latestTickValue !== null && (N > 0 || isInstant) ? (\n <div key={`reduce-${animationKey}`}>\n {/* Sweep dots — range mode only; instant skips straight to the pop. */}\n {N > 0 ? animationWindowSamples.map((s, i) => (\n <div\n key={`reduce-sample-${i}`}\n className=\"reduce-sample-dot\"\n style={{\n left: `${xPct(s.t)}%`,\n top: `${yPctInChart(s.v)}%`,\n animationDelay: `${i * SWEEP_STAGGER_MS}ms, ${flashDelayMs}ms, ${fadeDelayMs}ms`,\n }}\n />\n )) : null}\n <div\n className=\"reduce-result-dot\"\n style={{\n left: `${xPct(latestTick)}%`,\n top: `${yPctInChart(latestTickValue)}%`,\n animationDelay: `${resultDelayMs}ms`,\n }}\n />\n </div>\n ) : null}\n\n {/* Divergence labels — \"60s ⓘ\" pill; click opens the popover below. */}\n {divergences.map((d, i) => {\n const xs = xPct(d.stateAt);\n const xg = xPct(d.grafanaAt);\n const cx = (xs + xg) / 2;\n const cy = DIVERGENCE_LABEL_PCT;\n const seconds = Math.round(Math.abs(d.gapMs) / 1000);\n const label = seconds % 60 === 0 ? `${seconds / 60}m` : `${seconds}s`;\n return (\n <ChartOverlay\n key={`divg-label-${i}-${d.stateAt}`}\n x={cx}\n y={cy}\n anchor=\"center-middle\"\n >\n <span\n style={divergenceLabelStyle}\n data-divergence-trigger\n title={`Grafana detected this ${d.kind.toLowerCase()} transition ${label} after the algorithm did. Click for details.`}\n onClick={(e) => {\n e.stopPropagation();\n setOpenDivergenceIdx(openDivergenceIdx === i ? null : i);\n }}\n >\n {label} ⓘ\n </span>\n </ChartOverlay>\n );\n })}\n\n {/* Divergence popover (single open at a time). */}\n {openDivergenceIdx !== null && divergences[openDivergenceIdx] !== undefined ? (() => {\n const d = divergences[openDivergenceIdx]!;\n const xs = xPct(d.stateAt);\n const xg = xPct(d.grafanaAt);\n const cx = (xs + xg) / 2;\n // Pop up into the empty chart area above the bars.\n const cy = DIVERGENCE_LABEL_PCT - 1.5;\n const seconds = Math.round(Math.abs(d.gapMs) / 1000);\n const label = seconds % 60 === 0 ? `${seconds / 60}m` : `${seconds}s`;\n const kindLower = d.kind.toLowerCase();\n return (\n <ChartOverlay x={cx} y={cy} anchor=\"center-bottom\">\n <div style={divergencePopoverStyle} data-divergence-popover>\n <div style={divergencePopoverTitleStyle}>\n {kindLower} divergence · {label}\n </div>\n <div style={divergencePopoverRowStyle}>\n <span style={divergencePopoverKeyStyle}>Algorithm</span>\n <code style={divergencePopoverValStyle}>{formatTime(d.stateAt)}</code>\n </div>\n <div style={divergencePopoverRowStyle}>\n <span style={divergencePopoverKeyStyle}>Grafana</span>\n <code style={divergencePopoverValStyle}>{formatTime(d.grafanaAt)}</code>\n </div>\n <div style={divergencePopoverNoteStyle}>\n Grafana queried Prometheus before the latest samples were\n ingested. UI-built rules don't apply the query_offset\n that imported rules get.\n </div>\n </div>\n </ChartOverlay>\n );\n })() : null}\n\n {/* State-bar text labels — segments narrower than 5% are skipped. */}\n {events.map((event, idx) => {\n if (event.kind === 'Resolved') return null;\n const x1 = xPct(event.from);\n const x2 = xPct(event.until);\n const widthPct = x2 - x1;\n if (widthPct < 5) return null;\n const centerX = (x1 + x2) / 2;\n const centerY = (STATE_BAR_TOP_PCT + STATE_BAR_BOTTOM_PCT) / 2;\n return (\n <ChartOverlay\n key={`state-label-${idx}`}\n x={centerX}\n y={centerY}\n anchor=\"center-middle\"\n >\n <span style={stateLabelStyle}>{event.kind.toLowerCase()}</span>\n </ChartOverlay>\n );\n })}\n\n {/* \"nodata\" labels for the tick-derived NoData overlays. */}\n {noDataRanges.map((r, i) => {\n const x1 = xPct(r.from);\n const x2 = xPct(r.until);\n const widthPct = x2 - x1;\n if (widthPct < 5) return null;\n const centerX = (x1 + x2) / 2;\n const centerY = (STATE_BAR_TOP_PCT + STATE_BAR_BOTTOM_PCT) / 2;\n return (\n <ChartOverlay\n key={`nodata-tick-label-${i}-${r.from}`}\n x={centerX}\n y={centerY}\n anchor=\"center-middle\"\n >\n <span style={stateLabelStyle}>nodata</span>\n </ChartOverlay>\n );\n })}\n\n {/* Time labels (HH:MM) — edge anchors flip from center to start/end. */}\n {displayTicks.map((t) => {\n const xp = xPct(t);\n const anchor = xp < 3 ? 'start-top' : xp > 97 ? 'end-top' : 'center-top';\n return (\n <ChartOverlay key={`tick-label-${t}`} x={xp} y={2} anchor={anchor}>\n <span style={tickLabelStyle}>{formatTimeShort(t)}</span>\n </ChartOverlay>\n );\n })}\n\n {/* 15s subdivision dots between minute labels. */}\n {subdivisionTicks\n .filter((t) => !displayTickSet.has(t))\n .map((t) => (\n <ChartOverlay key={`tick-dot-${t}`} x={xPct(t)} y={3} anchor=\"center-middle\">\n <span style={subdivisionDotStyle} />\n </ChartOverlay>\n ))}\n\n {/* Eye emoji per eval tick. */}\n {showEyes &&\n evalTicks.map((t) => {\n const xp = xPct(t);\n const anchor = xp < 3 ? 'start-top' : xp > 97 ? 'end-top' : 'center-top';\n return (\n <ChartOverlay key={`eye-${t}`} x={xp} y={11} anchor={anchor}>\n <span style={emojiStyle}>{'\\u{1F441}'}</span>\n </ChartOverlay>\n );\n })}\n\n {/* 15s subdivision dots between the eyes. */}\n {showEyes &&\n subdivisionTicks\n .filter((t) => !evalTickSet.has(t))\n .map((t) => (\n <ChartOverlay key={`eye-dot-${t}`} x={xPct(t)} y={13} anchor=\"center-middle\">\n <span style={subdivisionDotStyle} />\n </ChartOverlay>\n ))}\n\n {/* `:SS` under each eye — confirms eval ticks land on Grafana's grid. */}\n {showEyes &&\n evalTicks.map((t) => {\n const xp = xPct(t);\n const anchor = xp < 3 ? 'start-top' : xp > 97 ? 'end-top' : 'center-top';\n return (\n <ChartOverlay key={`eye-sec-${t}`} x={xp} y={17} anchor={anchor}>\n <span style={secondsLabelStyle}>{formatSeconds(t)}</span>\n </ChartOverlay>\n );\n })}\n\n {/* relativeTimeRange [Nm] label. */}\n {!isInstant && showWindow ? (\n <ChartOverlay\n x={(xPct(windowStart) + xPct(windowAnchor)) / 2}\n y={(CHART_TOP_PCT + CHART_BOTTOM_PCT) / 2 + 4}\n anchor=\"center-top\"\n >\n <span style={windowLabelStyle}>\n relativeTimeRange [{formatTickLabel(windowDuration)}]\n </span>\n </ChartOverlay>\n ) : null}\n\n {/* Crossing markers — 💥 ignition, 💧 resolution. */}\n {crossings.map((c) => {\n const xp = xPct(c.t);\n if (xp < 0 || xp > 100) return null;\n return (\n <ChartOverlay\n key={`xicon-${c.t}-${c.direction}`}\n x={xp}\n y={yPctInChart(c.v)}\n anchor=\"center-middle\"\n >\n <span style={crossingEmojiStyle}>\n {c.direction === 'ignition' ? '\\u{1F4A5}' : '\\u{1F4A7}'}\n </span>\n </ChartOverlay>\n );\n })}\n\n {/* Crossing time label — inside the state bar, off the threshold line. */}\n {crossings.map((c) => {\n const xp = xPct(c.t);\n if (xp < 0 || xp > 100) return null;\n return (\n <ChartOverlay\n key={`xicon-time-${c.t}-${c.direction}`}\n x={xp}\n y={(STATE_BAR_TOP_PCT + STATE_BAR_BOTTOM_PCT) / 2}\n anchor=\"center-middle\"\n >\n <span style={secondsLabelStyle}>{formatSeconds(c.t)}</span>\n </ChartOverlay>\n );\n })}\n\n {/* NOW indicator — ⏰ at the dashed NOW line, time below. Live only. */}\n {rightAnchorT !== undefined ? (\n <>\n <ChartOverlay x={xPct(rightAnchorT)} y={50} anchor=\"center-middle\">\n <span\n key={pollSignal ?? 'no-poll'}\n className=\"alert-whatif-now-clock-pop\"\n aria-label=\"now\"\n >\n <span className=\"alert-whatif-now-clock-breath\" style={emojiStyle}>\n ⏰\n </span>\n </span>\n </ChartOverlay>\n <ChartOverlay x={xPct(rightAnchorT)} y={54} anchor=\"center-top\">\n <span style={secondsLabelStyle}>{formatSeconds(rightAnchorT)}</span>\n </ChartOverlay>\n </>\n ) : null}\n\n {/* ⚠️/🔔/🔕/🌫️ lifecycle markers — emoji only; each lands on an eval\n tick, so the eye-row timestamp below already shows the time. */}\n {pendingEvents.map((p, i) => {\n const xp = xPct(p.from);\n if (xp < 0 || xp > 100) return null;\n return (\n <ChartOverlay\n key={`pending-marker-${i}-${p.from}`}\n x={xp}\n y={11}\n anchor=\"center-top\"\n >\n <span style={emojiStyle}>{'⚠️'}</span>\n </ChartOverlay>\n );\n })}\n\n {firingEvents.map((f, i) => {\n const xp = xPct(f.from);\n if (xp < 0 || xp > 100) return null;\n return (\n <ChartOverlay\n key={`firing-marker-${i}-${f.from}`}\n x={xp}\n y={11}\n anchor=\"center-top\"\n >\n <span style={emojiStyle}>{'\\u{1F514}'}</span>\n </ChartOverlay>\n );\n })}\n\n {resolvedEvents.map((r, i) => {\n const xp = xPct(r.at);\n if (xp < 0 || xp > 100) return null;\n return (\n <ChartOverlay\n key={`resolved-marker-${i}-${r.at}`}\n x={xp}\n y={11}\n anchor=\"center-top\"\n >\n <span style={emojiStyle}>{'\\u{1F515}'}</span>\n </ChartOverlay>\n );\n })}\n\n {noDataEvents.map((n, i) => {\n const xp = xPct(n.from);\n if (xp < 0 || xp > 100) return null;\n return (\n <ChartOverlay\n key={`nodata-marker-${i}-${n.from}`}\n x={xp}\n y={11}\n anchor=\"center-top\"\n >\n <span style={emojiStyle}>{'\\u{1F32B}️'}</span>\n </ChartOverlay>\n );\n })}\n\n </div>\n </div>\n </div>\n\n {bottomSlot}\n </>\n );\n}\n","// Shared per-kind color encoding (CSS vars from index.css, theme-aware).\n\nimport type { EvalEvent } from '@alert-whatif/core';\n\nexport const EVENT_COLOR: Record<EvalEvent['kind'], string> = {\n Pending: 'var(--event-pending)',\n Firing: 'var(--event-firing)',\n Recovering: 'var(--event-recovering)',\n NoData: 'var(--event-nodata)',\n Resolved: 'var(--event-resolved)',\n};\n","// Chart-area band within the 0..100 SVG; decoration rows and bars live outside\n// it via HTML overlays.\nexport const CHART_TOP_PCT = 26;\nexport const CHART_BOTTOM_PCT = 86;\n// GRAFANA state bar — above ours, thinner (3% vs 5%) so it reads as supplementary.\nexport const GRAFANA_BAR_TOP_PCT = 88;\nexport const GRAFANA_BAR_BOTTOM_PCT = 91;\nexport const STATE_BAR_TOP_PCT = 94;\nexport const STATE_BAR_BOTTOM_PCT = 99;\n// Second event band for the baseline-vs-tweaked comparison.\nexport const BASELINE_BAR_TOP_PCT = 88;\nexport const BASELINE_BAR_BOTTOM_PCT = 93;\n\nexport const COLOR_LINE = 'var(--chart-line)';\nexport const COLOR_THRESHOLD = 'var(--chart-threshold)';\nexport const COLOR_AXIS = 'var(--chart-axis)';\nexport const COLOR_WINDOW = 'var(--chart-window-highlight)';\n// Defaults transparent so the plugin is unchanged; the demo sets it.\nexport const COLOR_WINDOW_BORDER = 'var(--chart-window-border, transparent)';\nexport const COLOR_STATE_NORMAL = 'var(--chart-state-normal)';\n// Divergence indicator (issue #153) — Grafana's warning-amber.\nexport const DIVERGENCE_STROKE = 'var(--chart-divergence, #f5a524)';\n// Sits above the GRAFANA bar (top = 88%) with breathing room.\nexport const DIVERGENCE_LABEL_PCT = 85;\nexport const MAX_EVAL_TICKS = 200;\n// Above this, the eye + seconds row is hidden — glyphs would collide.\nexport const MAX_EYES = 60;\n// Visible X span when data is narrower (data centered); 15 min fits the\n// reference rule's 2-min `for` + 4-min window with surrounding context.\nexport const TARGET_CHART_SPAN_MS = 15 * 60 * 1000;\n// Pushes Live's \"now\" inward ~1 min so the playhead doesn't sit on the edge.\nexport const RIGHT_ANCHOR_PAD_MS = 60 * 1000;\n","import type { Threshold } from '@alert-whatif/core';\n\nfunction thresholdYValues(t: Threshold): number[] {\n if ('value' in t) return [t.value];\n return [t.left, t.right];\n}\n\nfunction padDomain(min: number, max: number): { yMin: number; yMax: number } {\n if (!Number.isFinite(min) || !Number.isFinite(max)) return { yMin: 0, yMax: 1 };\n if (min === max) return { yMin: min - 0.5, yMax: max + 0.5 };\n const span = max - min;\n const yMin = min >= 0 && min < max * 0.3 ? 0 : min - span * 0.05;\n return { yMin, yMax: max + span * 0.05 };\n}\n\n// Round up to the next nice number (1, 2, 5, 10, …) to stabilise the Y ceiling.\nfunction niceCeil(x: number): number {\n if (!Number.isFinite(x) || x <= 0) return 1;\n const exp = Math.floor(Math.log10(x));\n const base = Math.pow(10, exp);\n const norm = x / base;\n const niceNorm = norm <= 1 ? 1 : norm <= 2 ? 2 : norm <= 5 ? 5 : 10;\n return niceNorm * base;\n}\n\nexport { thresholdYValues, padDomain, niceCeil };\n","import { MAX_EVAL_TICKS } from './constants';\n\nfunction computeEvalTicks(firstT: number, lastT: number, evalInterval: number): number[] {\n if (!Number.isFinite(evalInterval) || evalInterval <= 0) return [];\n const span = lastT - firstT;\n const count = Math.floor(span / evalInterval) + 1;\n if (count > MAX_EVAL_TICKS) return [];\n const ticks: number[] = [];\n for (let i = 0; i < count; i++) ticks.push(firstT + i * evalInterval);\n return ticks;\n}\n\n// Eye positions stepping in evalInterval from an on-grid anchor to fill\n// [minT, maxT]. May fall outside the sample range — those eyes mark \"Grafana\n// would evaluate here but there's no data\"; visual only, not the state bar.\nfunction computeDisplayTicks(\n anchor: number,\n evalInterval: number,\n minT: number,\n maxT: number,\n): number[] {\n if (!Number.isFinite(evalInterval) || evalInterval <= 0) return [];\n const stepsBack = Math.floor((anchor - minT) / evalInterval);\n const firstTick = anchor - stepsBack * evalInterval;\n if (firstTick > maxT) return [];\n const count = Math.floor((maxT - firstTick) / evalInterval) + 1;\n if (count > MAX_EVAL_TICKS) return [];\n const out: number[] = [];\n for (let i = 0; i < count; i++) out.push(firstTick + i * evalInterval);\n return out;\n}\n\n// Subdivision grid anchored to absolute multiples of stepMs so a 15s dot lands\n// on :15/:30/:45, not a data-relative offset.\nfunction computeSubdivisionTicks(minT: number, maxT: number, stepMs: number): number[] {\n const startMs = Math.ceil(minT / stepMs) * stepMs;\n const endMs = Math.floor(maxT / stepMs) * stepMs;\n const ticks: number[] = [];\n for (let t = startMs; t <= endMs; t += stepMs) ticks.push(t);\n return ticks;\n}\n\n// Minute-boundary times snapped to the absolute UTC minute grid (HH:MM:00), so\n// a label sits at :00 and an eye at :30 reads as between two labels. Step adapts\n// to span to keep ~10–15 labels.\nfunction computeMinuteTicks(minT: number, maxT: number): number[] {\n const spanMin = (maxT - minT) / 60_000;\n const stepMin = spanMin <= 12 ? 1 : spanMin <= 30 ? 2 : spanMin <= 75 ? 5 : 10;\n const stepMs = stepMin * 60_000;\n const startMs = Math.ceil(minT / stepMs) * stepMs;\n const endMs = Math.floor(maxT / stepMs) * stepMs;\n const ticks: number[] = [];\n for (let t = startMs; t <= endMs; t += stepMs) ticks.push(t);\n return ticks;\n}\n\nexport { computeEvalTicks, computeDisplayTicks, computeSubdivisionTicks, computeMinuteTicks };\n","import type { Sample, Threshold } from '@alert-whatif/core';\nimport { passes } from '@alert-whatif/core';\n\nexport type CrossingDirection = 'ignition' | 'resolution';\nexport type ThresholdCrossing = {\n readonly t: number;\n readonly v: number;\n readonly direction: CrossingDirection;\n};\n\n// Geometric crossings of the mean line with the threshold, tagged ignition vs\n// resolution by alert-state (an `Lt 5` threshold ignites on a falling value).\n// [] for range thresholds (no single intersection point).\nexport function findThresholdCrossings(\n samples: ReadonlyArray<Sample>,\n threshold: Threshold,\n): ReadonlyArray<ThresholdCrossing> {\n if (!('value' in threshold)) return [];\n\n const finite: Sample[] = [];\n for (const s of samples) {\n if (Number.isFinite(s.v)) finite.push(s);\n }\n if (finite.length < 2) return [];\n\n const thresholdValue = threshold.value;\n const out: ThresholdCrossing[] = [];\n for (let i = 0; i < finite.length - 1; i++) {\n const a = finite[i]!;\n const b = finite[i + 1]!;\n const aPasses = passes(a.v, threshold);\n const bPasses = passes(b.v, threshold);\n if (aPasses === bPasses) continue;\n // Intersection of segment a→b with the threshold; on samples (not ticks)\n // so the marker lands on the exact visual crossing.\n const denom = b.v - a.v;\n const t =\n denom === 0\n ? (a.t + b.t) / 2\n : a.t + ((thresholdValue - a.v) / denom) * (b.t - a.t);\n out.push({\n t,\n v: thresholdValue,\n direction: bPasses ? 'ignition' : 'resolution',\n });\n }\n return out;\n}\n","import type { EvalEvent } from '@alert-whatif/core';\n\n// Build an SVG `<path>` d-string; a gap wider than `gapThresholdMs` becomes a\n// move-to (M) instead of line-to (L) so genuine data gaps break the line.\nfunction buildGappedPath<T>(\n points: ReadonlyArray<T>,\n getT: (p: T) => number,\n getV: (p: T) => number,\n xPct: (t: number) => number,\n yPct: (v: number) => number,\n gapThresholdMs: number,\n): string {\n let d = '';\n let prevT: number | null = null;\n for (const p of points) {\n const v = getV(p);\n if (!Number.isFinite(v)) continue;\n const t = getT(p);\n const x = xPct(t).toFixed(2);\n const y = yPct(v).toFixed(2);\n const cmd = prevT === null || t - prevT > gapThresholdMs ? 'M' : 'L';\n d += `${cmd}${x},${y} `;\n prevT = t;\n }\n return d.trim();\n}\n\n// Filter events by kind, returning a type-narrowed array.\nfunction filterEvents<K extends EvalEvent['kind']>(\n events: ReadonlyArray<EvalEvent>,\n kind: K,\n): ReadonlyArray<Extract<EvalEvent, { kind: K }>> {\n return events.filter((e): e is Extract<EvalEvent, { kind: K }> => e.kind === kind);\n}\n\nexport {\n filterEvents,\n buildGappedPath,\n};\n","import type { Threshold } from '@alert-whatif/core';\n\n// Chart timestamps render in the browser's local timezone to match Grafana's\n// panel display; UTC stays canonical for ids / logs / filenames.\nconst pad2 = (n: number): string => n.toString().padStart(2, '0');\n\nfunction formatTime(t: number): string {\n const d = new Date(t);\n return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;\n}\n\nfunction formatTimeShort(t: number): string {\n const d = new Date(t);\n return `${pad2(d.getHours())}:${pad2(d.getMinutes())}`;\n}\n\n// Full HH:MM:SS so under-marker labels can't be misread as the top-row HH:MM\n// axis labels.\nfunction formatSeconds(t: number): string {\n return formatTime(t);\n}\n\n// \"Nm\" at minute boundaries, \"M:SS\" for sub-minute; handles negative deltas.\nfunction formatTickLabel(deltaMs: number): string {\n const sec = Math.round(deltaMs / 1000);\n const sign = sec < 0 ? '-' : '';\n const abs = Math.abs(sec);\n const min = Math.floor(abs / 60);\n const remSec = abs % 60;\n if (remSec === 0) return `${sign}${min}m`;\n return `${sign}${min}:${String(remSec).padStart(2, '0')}`;\n}\n\nfunction formatThresholdLabelValue(t: Threshold, v: number): string {\n if ('value' in t) return String(v);\n if (v === t.left) return `≥ ${t.left}`;\n return `≤ ${t.right}`;\n}\n\nexport {\n formatTime,\n formatTimeShort,\n formatSeconds,\n formatTickLabel,\n formatThresholdLabelValue,\n};\n","import type { CSSProperties } from 'react';\nimport { cardStyle } from '../styles';\n\nexport const chartCardStyle: CSSProperties = {\n ...cardStyle,\n // basis 0 so sibling natural heights win first; the chart absorbs the rest.\n flex: '1 1 0',\n display: 'flex',\n flexDirection: 'column',\n minHeight: 0,\n border: 'none',\n padding: '0.25rem 0.5rem',\n};\n\nexport const chartTitleWrapStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'baseline',\n gap: '0.75rem',\n paddingLeft: '5.5rem',\n paddingRight: '0.5rem',\n marginBottom: '0.25rem',\n flexShrink: 0,\n};\n\nexport const chartTitleMainStyle: CSSProperties = {\n fontSize: '0.85rem',\n fontWeight: 600,\n color: 'var(--text-primary)',\n};\n\nexport const chartTitleSubStyle: CSSProperties = {\n fontFamily: 'ui-monospace, Menlo, monospace',\n fontSize: '0.7rem',\n color: 'var(--text-muted)',\n};\n\nexport const chartTitleSpacerStyle: CSSProperties = { flex: '1 1 auto' };\n\nexport const chartTitleRangeStyle: CSSProperties = {\n fontFamily: 'ui-monospace, Menlo, monospace',\n fontSize: '0.7rem',\n color: 'var(--text-muted)',\n fontVariantNumeric: 'tabular-nums',\n};\n\n// 2-column row: left gutter for labels, right chart-area for SVG + overlays.\nexport const chartCanvasStyle: CSSProperties = {\n flex: '1 1 auto',\n display: 'flex',\n minHeight: 0,\n};\n\nexport const gutterStyle: CSSProperties = {\n width: '5.5rem',\n position: 'relative',\n flexShrink: 0,\n};\n\nexport const gutterLabelStyle: CSSProperties = {\n position: 'absolute',\n right: '0.5rem',\n whiteSpace: 'nowrap',\n};\n\nexport const chartAreaStyle: CSSProperties = {\n flex: '1 1 auto',\n position: 'relative',\n minHeight: 0,\n overflow: 'hidden',\n};\n\nexport const overlayStyle: CSSProperties = {\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n};\n\nexport const overlayItemStyle: CSSProperties = {\n position: 'absolute',\n whiteSpace: 'nowrap',\n};\n\nexport const legendStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n // Larger than the intra-item line gap so the two stacked items read as\n // distinct entries, not one block.\n gap: '0.45rem',\n fontFamily: 'ui-monospace, Menlo, monospace',\n fontSize: '0.7rem',\n color: 'var(--text-primary)',\n};\n\nexport const legendItemStyle: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.4rem',\n};\n\nexport const legendTextStackStyle: CSSProperties = {\n display: 'inline-flex',\n flexDirection: 'column',\n lineHeight: 1.1,\n};\n\nexport const legendSubLabelStyle: CSSProperties = {\n color: 'var(--text-muted)',\n};\n\nexport const numericStyle: CSSProperties = {\n fontFamily: 'ui-monospace, Menlo, monospace',\n fontSize: '0.65rem',\n color: 'var(--chart-axis-text)',\n};\n\nexport const tickLabelStyle: CSSProperties = {\n fontFamily: 'ui-monospace, Menlo, monospace',\n fontSize: '0.65rem',\n color: 'var(--chart-axis-text)',\n};\n\nexport const secondsLabelStyle: CSSProperties = {\n fontFamily: 'ui-monospace, Menlo, monospace',\n fontSize: '0.55rem',\n color: 'var(--text-faded)',\n fontVariantNumeric: 'tabular-nums',\n};\n\nexport const barLabelStyle: CSSProperties = {\n fontFamily: 'ui-monospace, Menlo, monospace',\n fontSize: '0.65rem',\n color: 'var(--text-muted)',\n};\n\nexport const windowLabelStyle: CSSProperties = {\n fontFamily: 'ui-monospace, Menlo, monospace',\n fontSize: '0.6rem',\n color: 'var(--text-muted)',\n opacity: 0.75,\n};\n\nexport const emojiStyle: CSSProperties = {\n fontSize: '0.9rem',\n lineHeight: 1,\n};\n\nexport const subdivisionDotStyle: CSSProperties = {\n display: 'inline-block',\n width: 2,\n height: 2,\n borderRadius: '50%',\n background: 'var(--text-faded)',\n opacity: 0.6,\n};\n\nexport const crossingEmojiStyle: CSSProperties = {\n fontSize: '0.95rem',\n lineHeight: 1,\n};\n\n// White-with-shadow to stay readable against any event color.\nexport const stateLabelStyle: CSSProperties = {\n fontSize: '0.6rem',\n fontWeight: 600,\n letterSpacing: '0.04em',\n color: 'rgba(255, 255, 255, 0.95)',\n textShadow: '0 0 2px rgba(0,0,0,0.5)',\n whiteSpace: 'nowrap',\n};\n\n// Divergence indicator label (issue #153).\nexport const divergenceLabelStyle: CSSProperties = {\n fontSize: '0.65rem',\n color: 'var(--chart-divergence, #f5a524)',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n background: 'var(--bg-card, rgba(20,20,30,0.85))',\n padding: '0 0.25rem',\n borderRadius: 3,\n border: '1px solid var(--chart-divergence, #f5a524)',\n whiteSpace: 'nowrap',\n cursor: 'pointer',\n pointerEvents: 'auto',\n userSelect: 'none',\n};\n\n// Overrides ChartOverlay's `whiteSpace: nowrap` so the note wraps at 18rem.\nexport const divergencePopoverStyle: CSSProperties = {\n fontSize: '0.72rem',\n background: 'var(--bg-card, rgba(20,20,30,0.97))',\n border: '1px solid var(--chart-divergence, #f5a524)',\n borderRadius: 4,\n padding: '0.5rem 0.65rem',\n width: '18rem',\n boxShadow: '0 4px 16px rgba(0,0,0,0.35)',\n pointerEvents: 'auto',\n color: 'var(--text-primary, #e0e0e0)',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n lineHeight: 1.4,\n whiteSpace: 'normal',\n overflowWrap: 'break-word',\n};\nexport const divergencePopoverTitleStyle: CSSProperties = {\n color: 'var(--chart-divergence, #f5a524)',\n fontWeight: 600,\n marginBottom: '0.3rem',\n};\nexport const divergencePopoverRowStyle: CSSProperties = {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'baseline',\n gap: '0.4rem',\n};\nexport const divergencePopoverKeyStyle: CSSProperties = {\n color: 'var(--text-muted, #999)',\n};\nexport const divergencePopoverValStyle: CSSProperties = {\n fontVariantNumeric: 'tabular-nums',\n};\nexport const divergencePopoverNoteStyle: CSSProperties = {\n marginTop: '0.35rem',\n color: 'var(--text-muted, #999)',\n fontFamily: 'inherit',\n};\n","import React from 'react';\nimport {\n chartTitleWrapStyle,\n chartTitleMainStyle,\n chartTitleSubStyle,\n chartTitleSpacerStyle,\n chartTitleRangeStyle,\n} from './styles';\n\nexport function ChartTitle({\n subtitle,\n timeRange,\n}: {\n readonly subtitle: string;\n readonly timeRange: string | undefined;\n}) {\n return (\n <div style={chartTitleWrapStyle}>\n <span style={chartTitleMainStyle}>Alert lifecycle</span>\n {subtitle.length > 0 ? <span style={chartTitleSubStyle}>{subtitle}</span> : null}\n {timeRange !== undefined ? (\n <>\n <div style={chartTitleSpacerStyle} />\n <span style={chartTitleRangeStyle}>{timeRange}</span>\n </>\n ) : null}\n </div>\n );\n}\n","import React from 'react';\nimport type { CSSProperties } from 'react';\nimport { overlayItemStyle, gutterLabelStyle } from './styles';\n\n// HTML element positioned in [0,100] canvas coords; `anchor` aligns its box\n// relative to (x, y).\nexport type ChartOverlayAnchor =\n | 'center-top'\n | 'center-middle'\n | 'center-bottom'\n | 'start-top'\n | 'end-top';\n\nexport function ChartOverlay({\n x,\n y,\n anchor,\n children,\n}: {\n readonly x: number;\n readonly y: number;\n readonly anchor: ChartOverlayAnchor;\n readonly children: React.ReactNode;\n}) {\n return (\n <div\n style={{\n ...overlayItemStyle,\n left: `${x}%`,\n top: `${y}%`,\n ...overlayAnchorStyles[anchor],\n }}\n >\n {children}\n </div>\n );\n}\n\nconst overlayAnchorStyles: Record<ChartOverlayAnchor, CSSProperties> = {\n 'center-top': { transform: 'translateX(-50%)' },\n 'center-middle': { transform: 'translate(-50%, -50%)' },\n 'center-bottom': { transform: 'translate(-50%, -100%)' },\n 'start-top': {},\n 'end-top': { transform: 'translateX(-100%)' },\n};\n\n// Gutter-column label right-aligned to the chart-area's left edge; `align`\n// sets which vertical edge sits at y.\nexport type GutterAlign = 'top' | 'middle' | 'bottom';\n\nexport function GutterLabel({\n y,\n align,\n children,\n}: {\n readonly y: number;\n readonly align: GutterAlign;\n readonly children: React.ReactNode;\n}) {\n return (\n <div\n style={{\n ...gutterLabelStyle,\n top: `${y}%`,\n transform:\n align === 'middle'\n ? 'translateY(-50%)'\n : align === 'bottom'\n ? 'translateY(-100%)'\n : undefined,\n }}\n >\n {children}\n </div>\n );\n}\n","// Thin time-axis strip marking where the rule tripped over a long lookback;\n// one marker per Pending/Firing transition.\n\nimport React, { useState } from 'react';\nimport type { CSSProperties } from 'react';\nimport type { EvalEvent, Sample } from '@alert-whatif/core';\n\nconst ICON_FOR_KIND: Record<EvalEvent['kind'], string> = {\n Pending: '⚠️',\n Firing: '\\u{1F514}',\n Resolved: '\\u{1F515}',\n NoData: '\\u{1F32B}️',\n Recovering: '\\u{1F4A7}',\n};\n\nexport type OverviewRangeOption = {\n readonly label: string;\n readonly lookbackSec: number;\n readonly stepSec: number;\n};\n\ntype Props = {\n readonly samples: ReadonlyArray<Sample>;\n readonly events: ReadonlyArray<EvalEvent>;\n readonly loading?: boolean;\n // Click-to-drill; kind lets the caller frame forward (🔔/⚠️/🌫️) or\n // backward (🔕).\n readonly onEventClick?: (t: number, kind: EvalEvent['kind']) => void;\n // Omitted renders a static label instead of the dropdown.\n readonly lookbackSec?: number;\n readonly onLookbackChange?: (sec: number) => void;\n readonly rangeOptions?: ReadonlyArray<OverviewRangeOption>;\n // 'Firing'/'NoData' suppresses the leftmost marker (no transition to mark).\n readonly initialState?: 'Normal' | 'Firing' | 'NoData';\n // Bells before this (rule didn't exist) render dimmed — Grafana has no\n // annotations to compare, so a drill shows an empty grafana bar.\n readonly ruleCreatedMs?: number;\n};\n\nconst STRIP_HEIGHT_PX = 26;\nconst ICON_FONT_SIZE_PX = 13;\n// Selected marker grows so 🔔 vs 🔕 (near-identical at 13px) is unambiguous.\nconst ICON_SELECTED_FONT_SIZE_PX = 26;\n// Firing/pending events within this fraction of strip width are one episode\n// (threshold flap), collapsing to one 🔔 + one 🔕.\nconst EPISODE_GAP_PCT = 2;\n\nexport function OverviewStrip({\n samples,\n events,\n loading,\n onEventClick,\n lookbackSec,\n onLookbackChange,\n rangeOptions,\n initialState,\n ruleCreatedMs,\n}: Props) {\n const [selectedT, setSelectedT] = useState<number | null>(null);\n const labelNode =\n rangeOptions !== undefined &&\n onLookbackChange !== undefined &&\n lookbackSec !== undefined ? (\n <select\n value={String(lookbackSec)}\n onChange={(e) => onLookbackChange(Number(e.target.value))}\n style={selectorStyle}\n >\n {rangeOptions.map((opt) => (\n <option key={opt.lookbackSec} value={String(opt.lookbackSec)}>\n {opt.label}\n </option>\n ))}\n </select>\n ) : (\n <span style={labelStyle}>{describeLookback(lookbackSec)}</span>\n );\n\n // `Current` mode — just the selector; the main chart covers the present.\n if (lookbackSec === 0) {\n return (\n <div style={currentOnlyStyle}>\n {labelNode}\n </div>\n );\n }\n if (loading && samples.length === 0) {\n return (\n <div style={containerStyle}>\n {labelNode}\n <div style={bandLoadingStyle}>Loading overview…</div>\n </div>\n );\n }\n if (samples.length === 0) {\n return (\n <div style={containerStyle}>\n {labelNode}\n <div style={bandEmptyStyle}>No samples in overview window.</div>\n </div>\n );\n }\n\n const tMin = samples[0]!.t;\n const tMax = samples[samples.length - 1]!.t;\n const tRange = Math.max(tMax - tMin, 1);\n\n const episodeGapMs = (EPISODE_GAP_PCT / 100) * tRange;\n\n type FiringSpan = { readonly from: number; readonly until: number };\n const firingSpans: FiringSpan[] = events\n .flatMap<FiringSpan>((e) => {\n if (e.kind === 'Pending' || e.kind === 'Firing') {\n return [{ from: e.from, until: e.until }];\n }\n return [];\n })\n .sort((a, b) => a.from - b.from);\n\n type Episode = { from: number; until: number };\n const episodes: Episode[] = [];\n for (const span of firingSpans) {\n const open = episodes[episodes.length - 1];\n if (open !== undefined && span.from - open.until <= episodeGapMs) {\n open.until = Math.max(open.until, span.until);\n } else {\n episodes.push({ from: span.from, until: span.until });\n }\n }\n\n const noDataMarkers = events.flatMap<{ kind: EvalEvent['kind']; t: number }>((e) =>\n e.kind === 'NoData' ? [{ kind: e.kind, t: e.from }] : [],\n );\n\n const seriesStart = samples[0]!.t;\n const seriesEnd = samples[samples.length - 1]!.t;\n // Suppress the first 🔔 when the alarm was already active before\n // windowStart — it didn't start in this window.\n const firstIsContinuation =\n (initialState === 'Firing' || initialState === 'NoData') &&\n episodes.length > 0 &&\n episodes[0]!.from <= seriesStart;\n const markers: Array<{ kind: EvalEvent['kind']; t: number }> = [];\n episodes.forEach((ep, idx) => {\n const next = episodes[idx + 1];\n const epEndsBeforeNext = next !== undefined;\n const epEndsBeforeSeriesEnd = ep.until < seriesEnd - episodeGapMs;\n if (!(idx === 0 && firstIsContinuation)) {\n markers.push({ kind: 'Firing', t: ep.from });\n }\n if (epEndsBeforeNext || epEndsBeforeSeriesEnd) {\n markers.push({ kind: 'Resolved', t: ep.until });\n }\n });\n for (const m of noDataMarkers) markers.push(m);\n markers.sort((a, b) => a.t - b.t);\n\n // Time ticks snapped to clean wallclock boundaries so they line up across\n // reloads. Hover shows the local wallclock.\n const tickIntervalMs = pickTickIntervalMs(tRange);\n const tickMarks: Array<number> = [];\n const firstTick = Math.ceil(tMin / tickIntervalMs) * tickIntervalMs;\n for (let t = firstTick; t < tMin + tRange; t += tickIntervalMs) {\n tickMarks.push(t);\n }\n\n return (\n <div style={containerStyle}>\n {labelNode}\n <div style={bandStyle}>\n <div style={baselineStyle} />\n {tickMarks.map((t) => {\n const xPct = ((t - tMin) / tRange) * 100;\n if (xPct < 0 || xPct > 100) return null;\n // Date in the tooltip — 48h views straddle midnight, so HH:MM alone\n // is ambiguous.\n const tickIsSelected = selectedT === t;\n return (\n <span\n key={`tick-${t}`}\n style={{\n ...tickMarkStyle,\n left: `${xPct}%`,\n ...(tickIsSelected\n ? { opacity: 1, background: 'var(--text-primary, #fff)' }\n : {}),\n }}\n title={new Date(t).toLocaleString(undefined, {\n month: 'short',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n })}\n onClick={() => setSelectedT(tickIsSelected ? null : t)}\n />\n );\n })}\n {markers.map((m, idx) => {\n const xPct = ((m.t - tMin) / tRange) * 100;\n if (xPct < 0 || xPct > 100) return null;\n const isSelected = selectedT === m.t;\n const isPreRule =\n ruleCreatedMs !== undefined && m.t < ruleCreatedMs;\n const title = isPreRule\n ? `${m.kind} · ${new Date(m.t).toISOString()}\\nRule didn't exist yet (created ${new Date(ruleCreatedMs!).toISOString()}). Grafana has no annotations — drill will show empty grafana bar.`\n : `${m.kind} · ${new Date(m.t).toISOString()}`;\n return (\n <span\n key={`marker-${idx}`}\n role=\"button\"\n title={title}\n style={{\n ...iconStyle,\n left: `${xPct}%`,\n cursor: onEventClick !== undefined ? 'pointer' : 'default',\n ...(isPreRule\n ? { opacity: 0.3, filter: 'grayscale(1)' }\n : {}),\n ...(isSelected\n ? {\n fontSize: ICON_SELECTED_FONT_SIZE_PX,\n zIndex: 1,\n filter: 'drop-shadow(0 0 4px var(--text-primary))',\n }\n : {}),\n }}\n onClick={() => {\n setSelectedT(m.t);\n if (onEventClick !== undefined) onEventClick(m.t, m.kind);\n }}\n >\n {ICON_FOR_KIND[m.kind]}\n </span>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction describeLookback(sec: number | undefined): string {\n if (sec === undefined) return 'overview';\n if (sec >= 24 * 3600) return `Last ${Math.round(sec / (24 * 3600))}d`;\n if (sec >= 3600) return `Last ${Math.round(sec / 3600)}h`;\n return `Last ${Math.round(sec / 60)}m`;\n}\n\n// Aims for ~6-8 ticks across the strip at any lookback.\nfunction pickTickIntervalMs(rangeMs: number): number {\n const MIN = 60_000;\n const TEN_MIN = 600_000;\n const HOUR = 3_600_000;\n const THREE_H = 3 * HOUR;\n const SIX_H = 6 * HOUR;\n if (rangeMs >= 36 * HOUR) return SIX_H; // 48h+\n if (rangeMs >= 12 * HOUR) return THREE_H; // 24h-36h\n if (rangeMs >= 3 * HOUR) return HOUR; // 6h-12h\n if (rangeMs >= 30 * MIN) return TEN_MIN; // ~30min - 3h\n return MIN; // <30min\n}\n\nconst containerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '0.5rem',\n height: STRIP_HEIGHT_PX,\n padding: '0.2rem 0.4rem',\n border: '1px solid var(--border-card)',\n borderRadius: 6,\n background: 'var(--bg-card)',\n flexShrink: 0,\n};\n\nconst currentOnlyStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n paddingBottom: '0.25rem',\n flexShrink: 0,\n};\n\nconst labelStyle: CSSProperties = {\n fontSize: '0.7rem',\n color: 'var(--text-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.04em',\n whiteSpace: 'nowrap',\n};\n\nconst selectorStyle: CSSProperties = {\n // Inline sizing/colors beat Grafana's near-zero `<select>` reset.\n padding: '0.3rem 0.5rem',\n minHeight: '1.7rem',\n lineHeight: 1.2,\n fontSize: '0.78rem',\n fontFamily: 'inherit',\n letterSpacing: '0.04em',\n background: 'var(--bg-input)',\n color: 'var(--text-primary)',\n border: '1px solid var(--border-input)',\n borderRadius: 4,\n width: 'auto',\n minWidth: '7rem',\n maxWidth: '10rem',\n cursor: 'pointer',\n flexShrink: 0,\n};\n\nconst bandStyle: CSSProperties = {\n position: 'relative',\n flex: 1,\n height: '100%',\n background: 'var(--bg-tile-empty)',\n borderRadius: 4,\n};\n\nconst baselineStyle: CSSProperties = {\n position: 'absolute',\n left: 0,\n right: 0,\n top: '50%',\n height: 1,\n background: 'var(--chart-axis)',\n transform: 'translateY(-50%)',\n};\n\nconst iconStyle: CSSProperties = {\n position: 'absolute',\n top: '50%',\n transform: 'translate(-50%, -50%)',\n fontSize: ICON_FONT_SIZE_PX,\n lineHeight: 1,\n userSelect: 'none',\n};\n\nconst tickMarkStyle: CSSProperties = {\n position: 'absolute',\n top: '50%',\n transform: 'translate(-50%, -50%)',\n width: 8,\n height: 8,\n borderRadius: '50%',\n background: 'var(--text-primary, #d0d0d0)',\n opacity: 0.85,\n border: '1px solid var(--bg-card, #1a1a1a)',\n boxSizing: 'border-box',\n cursor: 'pointer',\n pointerEvents: 'auto',\n};\n\nconst bandLoadingStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'var(--text-muted)',\n fontSize: '0.72rem',\n fontStyle: 'italic',\n};\n\nconst bandEmptyStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'var(--text-faded)',\n fontSize: '0.72rem',\n};\n","// Selects which series feeds the (single-instance) evaluator when a query\n// returned more than one. Hidden for ≤1 series.\n\nimport React from 'react';\nimport type { CSSProperties } from 'react';\nimport type { MetricSeries } from '@alert-whatif/core';\n\ntype Props = {\n readonly seriesList: ReadonlyArray<MetricSeries>;\n readonly selectedIdx: number;\n readonly onSelect: (idx: number) => void;\n};\n\nexport function SeriesPicker({ seriesList, selectedIdx, onSelect }: Props) {\n if (seriesList.length < 2) return null;\n return (\n <div style={containerStyle}>\n <span style={labelStyle}>series</span>\n <select\n value={selectedIdx}\n onChange={(e) => onSelect(Number(e.target.value))}\n style={selectStyle}\n title=\"Prometheus returned multiple series for this rule's query. Pick which one to evaluate.\"\n >\n {seriesList.map((s, i) => (\n <option key={i} value={i}>\n {formatLabels(s.labels) || `(series ${i + 1})`}\n </option>\n ))}\n </select>\n <span style={countStyle}>\n {selectedIdx + 1} / {seriesList.length}\n </span>\n </div>\n );\n}\n\nfunction formatLabels(labels: Readonly<Record<string, string>>): string {\n const entries = Object.entries(labels).filter(\n ([k]) => k !== '__name__' && k !== '',\n );\n if (entries.length === 0) return '';\n return entries.map(([k, v]) => `${k}=\"${v}\"`).join(', ');\n}\n\nconst containerStyle: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.5rem',\n fontSize: '0.75rem',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n};\n\nconst labelStyle: CSSProperties = {\n color: 'var(--text-muted, #999)',\n textTransform: 'uppercase',\n fontSize: '0.65rem',\n letterSpacing: '0.05em',\n};\n\nconst selectStyle: CSSProperties = {\n fontSize: '0.75rem',\n fontFamily: 'inherit',\n background: 'var(--bg-input, #1a1a1a)',\n color: 'var(--text-primary, #e0e0e0)',\n border: '1px solid var(--chart-axis, #555)',\n borderRadius: 3,\n padding: '0.1rem 0.3rem',\n minHeight: '1.4rem',\n maxWidth: '24rem',\n};\n\nconst countStyle: CSSProperties = {\n color: 'var(--text-muted, #999)',\n fontSize: '0.65rem',\n};\n","// What-If | Live header toggle. The internal state key is still `'mock'`; only\n// the visible label reads \"What-If\".\n\nimport React from 'react';\nimport type { CSSProperties } from 'react';\n\nexport type DemoMode = 'mock' | 'live';\n\ntype Props = {\n readonly mode: DemoMode;\n readonly onChange: (next: DemoMode) => void;\n // Disables Live with a hint (no VITE_GRAFANA_TOKEN → proxy 401).\n readonly liveDisabled?: boolean;\n};\n\nconst MOCK_ACCENT = '#6366f1';\nconst LIVE_ACCENT = '#ef4444';\n\nexport function ModeToggle({ mode, onChange, liveDisabled }: Props) {\n return (\n <div style={wrapStyle} role=\"radiogroup\" aria-label=\"Demo mode\">\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={mode === 'mock'}\n onClick={() => onChange('mock')}\n style={buttonStyle(mode === 'mock', MOCK_ACCENT)}\n >\n What-If\n </button>\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={mode === 'live'}\n onClick={() => !liveDisabled && onChange('live')}\n disabled={liveDisabled}\n style={buttonStyle(mode === 'live', LIVE_ACCENT, liveDisabled)}\n title={liveDisabled ? 'Set VITE_GRAFANA_TOKEN in .env.local to enable Live mode' : undefined}\n >\n Live\n </button>\n </div>\n );\n}\n\nconst wrapStyle: CSSProperties = {\n display: 'inline-flex',\n border: '1px solid var(--border-card)',\n borderRadius: 6,\n overflow: 'hidden',\n};\n\nconst buttonStyle = (\n active: boolean,\n accent: string,\n disabled?: boolean,\n): CSSProperties => ({\n padding: '0.25rem 0.75rem',\n fontSize: '0.85rem',\n fontWeight: active ? 600 : 400,\n border: 'none',\n background: active ? hexWithAlpha(accent, 0.22) : 'transparent',\n color: disabled ? 'var(--text-faded)' : active ? accent : 'var(--text-primary)',\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n boxShadow: active ? `inset 0 -2px 0 ${accent}` : undefined,\n});\n\nfunction hexWithAlpha(hex: string, alpha: number): string {\n const r = parseInt(hex.slice(1, 3), 16);\n const g = parseInt(hex.slice(3, 5), 16);\n const b = parseInt(hex.slice(5, 7), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","// 100vh three-row page chrome (header / main chart / bottom two-column).\n// Columns scroll internally so there's no document-level scrollbar.\n\nimport React from 'react';\nimport type { CSSProperties, ReactNode } from 'react';\nimport { pageStyle } from '../styles';\n\ntype Props = {\n readonly className?: string;\n readonly headerLeft: ReactNode;\n readonly themeToggle?: ReactNode;\n // Compact summary chips below the top header row.\n readonly summaryStrip?: ReactNode;\n readonly main: ReactNode;\n readonly bottomLeft: ReactNode;\n readonly bottomRight: ReactNode;\n};\n\nexport function PageLayout({\n className,\n headerLeft,\n themeToggle,\n summaryStrip,\n main,\n bottomLeft,\n bottomRight,\n}: Props) {\n return (\n <div style={pageStyle} className={className}>\n <header style={headerStyle}>\n <div style={headerTopRowStyle}>\n <div style={headerLeftStyle}>{headerLeft}</div>\n {themeToggle}\n </div>\n {summaryStrip ? <div style={headerSummaryStyle}>{summaryStrip}</div> : null}\n </header>\n <div style={mainSlotStyle}>{main}</div>\n <div style={bottomGridStyle}>\n <div style={bottomColStyle}>{bottomLeft}</div>\n <div style={bottomColStyle}>{bottomRight}</div>\n </div>\n </div>\n );\n}\n\nconst headerStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: '0.4rem',\n flexShrink: 0,\n};\n\nconst headerTopRowStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '1rem',\n};\n\nconst headerSummaryStyle: CSSProperties = {};\n\nconst headerLeftStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '1rem',\n flexWrap: 'wrap',\n};\n\n// Chart row absorbs spare viewport, floored at 380px; children stack so the\n// status strip takes its natural height and the chart fills the rest.\nconst mainSlotStyle: CSSProperties = {\n flex: '1 1 380px',\n minHeight: 380,\n display: 'flex',\n flexDirection: 'column',\n gap: '0.4rem',\n};\n\nconst bottomGridStyle: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n gap: '1rem',\n // Capped at 45vh so a tall Parameters card doesn't push the chart down;\n // columns scroll internally past that.\n flex: '0 1 auto',\n maxHeight: '45vh',\n minHeight: 0,\n};\n\nconst bottomColStyle: CSSProperties = {\n overflowY: 'auto',\n minHeight: 0,\n};\n","// Pure-presentation form mirroring the tree shape of Grafana's alert.json\n// (spec → expressions A/B/C). Row labels carry the full JSON path so each\n// control maps back to a field. Fields the evaluator doesn't act on yet render\n// greyed. Owns no state — the parent holds the config.\n\nimport React from 'react';\nimport type {\n AlertConfig,\n ExecErrState,\n NanMode,\n NoDataState,\n RangeAlertConfig,\n ReducerKind,\n Threshold,\n ThresholdOp,\n} from '@alert-whatif/core';\nimport { changeThresholdOp, COMPARISON_OPS, RANGE_OPS } from '@alert-whatif/core';\nimport type { CSSProperties } from 'react';\nimport type { RuleMetadata } from '../types';\nimport { cardHeadingStyle, cardStyle } from '../styles';\n\n// Threaded via context so each Row self-checks whether it was tweaked.\nconst EMPTY_LABELS: ReadonlySet<string> = new Set();\nconst ChangedLabelsContext = React.createContext<ReadonlySet<string>>(EMPTY_LABELS);\n\ntype Props = {\n readonly config: AlertConfig;\n readonly onChange: (next: AlertConfig) => void;\n // Commit the draft; edits don't propagate until the parent's onApply runs.\n readonly onApply: () => void;\n readonly onReset: () => void;\n // Falls back to placeholder text when omitted.\n readonly ruleMetadata?: RuleMetadata | undefined;\n readonly paused?: boolean | undefined;\n readonly onPausedChange?: ((paused: boolean) => void) | undefined;\n // Row labels to frame as \"changed from default\".\n readonly changedLabels?: ReadonlySet<string> | undefined;\n};\n\nconst ALL_OPS: ReadonlyArray<ThresholdOp> = [...COMPARISON_OPS, ...RANGE_OPS];\n\nconst REDUCERS: ReadonlyArray<ReducerKind> = [\n 'Last', 'Min', 'Max', 'Sum', 'Mean', 'Count', 'Median',\n];\nconst NODATA_STATES: ReadonlyArray<NoDataState> = ['Alerting', 'NoData', 'Ok', 'KeepLast'];\nconst EXECERR_STATES: ReadonlyArray<ExecErrState> = ['Alerting', 'Error', 'Ok', 'KeepLast'];\nconst NAN_KINDS: ReadonlyArray<NanMode['kind']> = ['None', 'DropNN', 'ReplaceNN'];\n\nexport function ParamControls({\n config,\n onChange,\n onApply,\n onReset,\n ruleMetadata,\n paused = false,\n onPausedChange,\n changedLabels,\n}: Props) {\n // Typed against RangeAlertConfig (the superset); range-only controls render\n // conditionally so the call is sound at runtime.\n const set = <K extends keyof RangeAlertConfig>(key: K, value: RangeAlertConfig[K]) =>\n onChange({ ...config, [key]: value } as AlertConfig);\n\n return (\n <ChangedLabelsContext.Provider value={changedLabels ?? EMPTY_LABELS}>\n <section style={cardStyle}>\n <header style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n <h2 style={cardHeadingStyle} title=\"Mirrors `spec` in Grafana's alert.json. Greyed rows are shown for completeness but not yet editable / acted on.\">\n Parameters\n </h2>\n <div style={{ display: 'flex', gap: '0.5rem' }}>\n <button type=\"button\" onClick={onReset} style={resetButtonStyle}>\n Reset to defaults\n </button>\n <button type=\"button\" onClick={onApply} style={applyButtonStyle}>\n Apply\n </button>\n </div>\n </header>\n\n <div style={fieldsetGridStyle}>\n <Fieldset title=\"Rule (spec)\">\n <Row label=\"title\" disabled>\n <ReadOnlyText value={ruleMetadata?.title ?? '(none)'} />\n </Row>\n <Row label=\"labels\" disabled>\n <LabelsDisplay labels={ruleMetadata?.labels} />\n </Row>\n <Row label=\"paused\" path=\"spec.paused — calc/ does not suppress events (#103)\" disabled>\n <input\n type=\"checkbox\"\n checked={paused}\n onChange={(e) => onPausedChange?.(e.target.checked)}\n disabled\n />\n </Row>\n <Row label=\"for\">\n <NumberInput value={config.forDuration} onChange={(v) => set('forDuration', v)} min={0} />\n </Row>\n <Row\n label=\"keepFiringFor\"\n path=\"spec.keep_firing_for — temporarily disabled\"\n disabled\n >\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: '0.4rem' }}>\n <NumberInput\n value={config.keepFiringFor}\n onChange={(v) => set('keepFiringFor', v)}\n min={0}\n disabled\n />\n <ComingSoonHint />\n </span>\n </Row>\n <Row label=\"noDataState\">\n <select\n value={config.noDataState}\n onChange={(e) => set('noDataState', e.target.value as NoDataState)}\n style={selectStyle}\n >\n {NODATA_STATES.map((s) => (\n <option key={s} value={s}>{s}</option>\n ))}\n </select>\n </Row>\n <Row\n label=\"execErrState\"\n path=\"spec.execErrState — calc/ does not apply this policy (#103)\"\n disabled\n >\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: '0.4rem' }}>\n <select\n value={config.execErrState}\n onChange={(e) => set('execErrState', e.target.value as ExecErrState)}\n style={selectStyle}\n disabled\n >\n {EXECERR_STATES.map((s) => (\n <option key={s} value={s}>{s}</option>\n ))}\n </select>\n <ComingSoonHint />\n </span>\n </Row>\n <Row label=\"trigger.interval\">\n <NumberInput\n value={config.evaluationInterval}\n onChange={(v) => set('evaluationInterval', v)}\n min={0}\n />\n </Row>\n </Fieldset>\n\n <Fieldset title=\"expressions.A — Query (Stage A · Prometheus)\">\n <Row label=\"expr\" path=\"expressions.A.model.expr\" disabled>\n <ReadOnlyCode value={ruleMetadata?.query.expr ?? '(no PromQL provided)'} />\n </Row>\n <Row label=\"mode\" path=\"expressions.A.model.range / .instant\" disabled>\n <ModeToggle mode={ruleMetadata?.query.mode ?? 'range'} />\n </Row>\n {/* Step + cap feed computeEffectiveStepMs upstream of calc/, so a tweak\n changes the Prometheus step and sample density. */}\n <Row label=\"intervalMs\" path=\"expressions.A.model.intervalMs\">\n <NumberInput\n value={config.intervalMs}\n onChange={(v) => set('intervalMs', v)}\n min={1}\n step={1000}\n />\n </Row>\n <Row label=\"maxDataPoints\" path=\"expressions.A.model.maxDataPoints\">\n <NumberInput\n value={config.maxDataPoints}\n onChange={(v) => set('maxDataPoints', v)}\n min={1}\n step={1}\n />\n </Row>\n {config.instant ? null : (\n <Row label=\"relativeTimeRange.from\" path=\"expressions.A.relativeTimeRange.from\">\n <NumberInput\n value={config.windowDuration}\n onChange={(v) => set('windowDuration', v)}\n min={0}\n />\n </Row>\n )}\n <Row label=\"relativeTimeRange.to\" path=\"expressions.A.relativeTimeRange.to\" disabled>\n <ReadOnlyText value=\"0s (fixed)\" />\n </Row>\n </Fieldset>\n\n {/* Reduce expression — range rules only; instant has no B node. */}\n {config.instant ? null : (\n <Fieldset title=\"expressions.B — Reduce\">\n <Row label=\"reducer\" path=\"expressions.B.model.reducer\">\n <select\n value={config.reducer}\n onChange={(e) => set('reducer', e.target.value as ReducerKind)}\n style={selectStyle}\n >\n {REDUCERS.map((r) => (\n <option key={r} value={r}>{r}</option>\n ))}\n </select>\n </Row>\n <Row label=\"settings.mode\" path=\"expressions.B.model.settings.mode\">\n <select\n value={config.nanMode.kind}\n onChange={(e) =>\n set('nanMode', changeNanKind(config.nanMode, e.target.value as NanMode['kind']))\n }\n style={selectStyle}\n >\n {NAN_KINDS.map((k) => (\n <option key={k} value={k}>{k}</option>\n ))}\n </select>\n </Row>\n {config.nanMode.kind === 'ReplaceNN' ? (\n <Row\n label=\"settings.replaceWithValue\"\n path=\"expressions.B.model.settings.replaceWithValue\"\n >\n <NumberInput\n value={config.nanMode.replaceWithValue}\n onChange={(v) => set('nanMode', { kind: 'ReplaceNN', replaceWithValue: v })}\n />\n </Row>\n ) : null}\n </Fieldset>\n )}\n\n <Fieldset title={config.instant ? 'expressions.B — Threshold' : 'expressions.C — Threshold'}>\n <Row\n label=\"evaluator.type\"\n path=\"expressions.C.model.conditions[0].evaluator.type\"\n >\n <select\n value={config.threshold.op}\n onChange={(e) =>\n set('threshold', changeThresholdOp(config.threshold, e.target.value as ThresholdOp))\n }\n style={selectStyle}\n >\n {ALL_OPS.map((op) => (\n <option key={op} value={op}>{op}</option>\n ))}\n </select>\n </Row>\n <ThresholdFields\n threshold={config.threshold}\n onChange={(t) => set('threshold', t)}\n />\n </Fieldset>\n </div>\n </section>\n </ChangedLabelsContext.Provider>\n );\n}\n\nfunction Fieldset({ title, children }: { readonly title: string; readonly children: React.ReactNode }) {\n return (\n <fieldset style={fieldsetStyle}>\n <legend style={legendStyle}>{title}</legend>\n <div\n style={{\n display: 'grid',\n // minmax(0, 1fr) so a long unbreakable value can shrink instead of\n // overflowing the column.\n gridTemplateColumns: 'max-content minmax(0, 1fr)',\n gap: '0.25rem 0.75rem',\n }}\n >\n {children}\n </div>\n </fieldset>\n );\n}\n\nfunction Row({\n label,\n path,\n disabled,\n children,\n}: {\n readonly label: string;\n // Full JSON path the label abbreviates, shown on hover.\n readonly path?: string;\n readonly disabled?: boolean;\n readonly children: React.ReactNode;\n}) {\n const changed = React.useContext(ChangedLabelsContext).has(label);\n return (\n <>\n <label\n style={{ ...(disabled ? disabledLabelStyle : labelStyle), ...(changed ? changedLabelStyle : null) }}\n title={path ?? label}\n >\n {changed ? '✎ ' : ''}{label}\n </label>\n <div style={{ ...(disabled ? disabledRowStyle : null), ...(changed ? changedCellStyle : null) }}>\n {children}\n </div>\n </>\n );\n}\n\nfunction NumberInput({\n value,\n onChange,\n min,\n step,\n disabled,\n}: {\n readonly value: number;\n readonly onChange: (v: number) => void;\n readonly min?: number;\n readonly step?: number;\n readonly disabled?: boolean;\n}) {\n // Track raw text locally so partial retypes don't snap back; push to the\n // parent only on a finite parse, so the form never holds NaN.\n const [raw, setRaw] = React.useState<string>(\n Number.isFinite(value) ? String(value) : '',\n );\n const lastPropValueRef = React.useRef<number>(value);\n React.useEffect(() => {\n if (value !== lastPropValueRef.current) {\n lastPropValueRef.current = value;\n setRaw(Number.isFinite(value) ? String(value) : '');\n }\n }, [value]);\n\n return (\n <input\n type=\"number\"\n value={raw}\n min={min}\n step={step ?? 'any'}\n disabled={disabled}\n onChange={(e) => {\n const next = e.target.value;\n setRaw(next);\n if (next.trim() !== '') {\n const parsed = e.target.valueAsNumber;\n if (Number.isFinite(parsed)) onChange(parsed);\n }\n }}\n onBlur={() => {\n // Snap back to the last valid value if left empty / unparseable.\n if (raw.trim() === '' || !Number.isFinite(Number(raw))) {\n setRaw(Number.isFinite(value) ? String(value) : '');\n }\n }}\n style={numberInputStyle}\n />\n );\n}\n\n// Small ⓘ that reveals \"coming soon\" when clicked.\nfunction ComingSoonHint() {\n const [open, setOpen] = React.useState(false);\n return (\n <span style={{ position: 'relative', display: 'inline-block' }}>\n <span\n role=\"button\"\n title=\"Will come soon\"\n aria-label=\"Will come soon\"\n onClick={() => setOpen((v) => !v)}\n style={{\n cursor: 'pointer',\n color: 'var(--text-muted, #888)',\n fontSize: '0.85rem',\n userSelect: 'none',\n }}\n >\n ⓘ\n </span>\n {open ? (\n <span\n style={{\n position: 'absolute',\n top: '100%',\n left: '50%',\n transform: 'translateX(-50%)',\n marginTop: '0.25rem',\n padding: '0.25rem 0.5rem',\n background: 'var(--bg-card, rgba(20,20,30,0.97))',\n border: '1px solid var(--chart-axis, #555)',\n borderRadius: 3,\n fontSize: '0.7rem',\n color: 'var(--text-primary, #d0d0d0)',\n whiteSpace: 'nowrap',\n zIndex: 5,\n boxShadow: '0 2px 8px rgba(0,0,0,0.3)',\n }}\n >\n Will come soon\n </span>\n ) : null}\n </span>\n );\n}\n\nfunction ReadOnlyText({ value }: { readonly value: string }) {\n return <span style={readOnlyTextStyle}>{value}</span>;\n}\n\nfunction ReadOnlyCode({ value }: { readonly value: string }) {\n // title carries the full value so ellipsised PromQL is visible on hover.\n return (\n <code style={readOnlyCodeStyle} title={value}>\n {value}\n </code>\n );\n}\n\nfunction LabelsDisplay({ labels }: { readonly labels: Readonly<Record<string, string>> | undefined }) {\n const entries = labels ? Object.entries(labels) : [];\n if (entries.length === 0) {\n return <ReadOnlyText value=\"(none)\" />;\n }\n return (\n <span style={readOnlyTextStyle}>\n {entries.map(([k, v]) => `${k}=${v}`).join(' · ')}\n </span>\n );\n}\n\n// Read-only range / instant indicator; switching modes happens upstream.\nfunction ModeToggle({ mode }: { readonly mode: 'range' | 'instant' }) {\n return (\n <span style={readOnlyTextStyle}>\n <label style={inlineLabelStyle}>\n <input type=\"radio\" name=\"query-mode\" checked={mode === 'range'} disabled readOnly /> range\n </label>\n <label style={inlineLabelStyle}>\n <input type=\"radio\" name=\"query-mode\" checked={mode === 'instant'} disabled readOnly /> instant\n </label>\n </span>\n );\n}\n\n\n// Extracted so the discriminated-union narrowing on `threshold` survives into\n// the inline onChange closures.\nfunction ThresholdFields({\n threshold,\n onChange,\n}: {\n readonly threshold: Threshold;\n readonly onChange: (t: Threshold) => void;\n}) {\n if ('value' in threshold) {\n return (\n <Row label=\"conditions[0].evaluator.params\">\n <NumberInput\n value={threshold.value}\n onChange={(v) => onChange({ op: threshold.op, value: v })}\n />\n </Row>\n );\n }\n return (\n <>\n <Row label=\"conditions[0].evaluator.params[0] (left)\">\n <NumberInput\n value={threshold.left}\n onChange={(v) => onChange({ op: threshold.op, left: v, right: threshold.right })}\n />\n </Row>\n <Row label=\"conditions[0].evaluator.params[1] (right)\">\n <NumberInput\n value={threshold.right}\n onChange={(v) => onChange({ op: threshold.op, left: threshold.left, right: v })}\n />\n </Row>\n </>\n );\n}\n\n// Preserves replaceWithValue across a round-trip out of and back into ReplaceNN.\nfunction changeNanKind(current: NanMode, nextKind: NanMode['kind']): NanMode {\n if (nextKind === 'ReplaceNN') {\n const prevValue = current.kind === 'ReplaceNN' ? current.replaceWithValue : 0;\n return { kind: 'ReplaceNN', replaceWithValue: prevValue };\n }\n return { kind: nextKind };\n}\n\nconst resetButtonStyle: CSSProperties = {\n fontSize: 12,\n padding: '0.25rem 0.5rem',\n cursor: 'pointer',\n border: '1px solid var(--border-input)',\n background: 'var(--bg-button)',\n color: 'var(--text-primary)',\n borderRadius: 4,\n};\n\nconst applyButtonStyle: CSSProperties = {\n ...resetButtonStyle,\n background: 'var(--accent-primary, #3b82f6)',\n color: 'var(--text-on-accent, #fff)',\n borderColor: 'transparent',\n fontWeight: 600,\n};\n\nconst fieldsetGridStyle: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)',\n gap: '0.4rem',\n marginTop: '0.25rem',\n};\n\nconst fieldsetStyle: CSSProperties = {\n marginTop: 0,\n border: '1px solid var(--border-card)',\n borderRadius: 6,\n padding: '0.3rem 0.5rem',\n};\n\nconst legendStyle: CSSProperties = {\n fontWeight: 600,\n fontSize: '0.78rem',\n padding: '0 0.25rem',\n};\n\nconst labelStyle: CSSProperties = {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.72rem',\n alignSelf: 'center',\n};\n\nconst disabledLabelStyle: CSSProperties = {\n ...labelStyle,\n color: 'var(--text-faded)',\n};\n\nconst disabledRowStyle: CSSProperties = {\n opacity: 0.6,\n};\n\n// Amber, distinct from the chart's other colors.\nconst changedLabelStyle: CSSProperties = {\n color: '#f59e0b',\n fontWeight: 700,\n};\nconst changedCellStyle: CSSProperties = {\n outline: '2px solid #f59e0b',\n outlineOffset: '2px',\n borderRadius: '4px',\n background: 'rgba(245, 158, 11, 0.12)',\n};\n\n// Inline bg/color/border so controls render inside any host stylesheet —\n// Grafana's reset uses `!important` that beats even our scoped rules, but\n// inline styles sit above the cascade entirely.\nconst numberInputStyle: CSSProperties = {\n width: 'auto',\n maxWidth: '6rem',\n padding: '0.15rem 0.35rem',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.75rem',\n background: 'var(--bg-input)',\n color: 'var(--text-primary)',\n border: '1px solid var(--border-input)',\n borderRadius: 4,\n};\n\nconst selectStyle: CSSProperties = {\n // Grafana compresses native `<select>` to near-zero height and hides the\n // font; inline minHeight + explicit color/background wins.\n width: '100%',\n maxWidth: '9rem',\n boxSizing: 'border-box',\n minHeight: '1.6rem',\n padding: '0.15rem 0.35rem',\n lineHeight: 1.2,\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.75rem',\n background: 'var(--bg-input)',\n color: 'var(--text-primary)',\n border: '1px solid var(--border-input)',\n borderRadius: 4,\n cursor: 'pointer',\n};\n\nconst readOnlyTextStyle: CSSProperties = {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.72rem',\n color: 'var(--text-muted)',\n};\n\nconst readOnlyCodeStyle: CSSProperties = {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.72rem',\n color: 'var(--text-primary)',\n background: 'var(--bg-input, transparent)',\n padding: '1px 4px',\n borderRadius: 3,\n // Block-sized so its overflow:hidden ellipsis takes effect in the cell.\n display: 'block',\n width: '100%',\n boxSizing: 'border-box',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nconst inlineLabelStyle: CSSProperties = {\n marginRight: '0.5rem',\n whiteSpace: 'nowrap',\n};\n\n","// Compact replay button row + speed selector for the Mock-mode strip's\n// action slot. The scrubber lives separately in <ReplaySliderBar>.\n\nimport React from 'react';\nimport type { CSSProperties } from 'react';\n\nexport type Speed = 1 | 2 | 4;\n\ntype Props = {\n readonly tickIndex: number;\n readonly tickCount: number;\n readonly playing: boolean;\n readonly speed: Speed;\n readonly onReset: () => void;\n readonly onStepBack: () => void;\n readonly onTogglePlay: () => void;\n readonly onStepForward: () => void;\n readonly onJumpToEnd: () => void;\n readonly onSpeedChange: (speed: Speed) => void;\n // Plugin hides the speed selector — windows are ~12 ticks.\n readonly hideSpeed?: boolean;\n // Let auto-replay drive these via real `.click()`s.\n readonly resetButtonRef?: React.Ref<HTMLButtonElement>;\n readonly playButtonRef?: React.Ref<HTMLButtonElement>;\n // Momentary highlight so an auto-driven click reads as a press.\n readonly flashing?: 'reset' | 'play' | null;\n};\n\nexport function ReplayButtons({\n tickIndex,\n tickCount,\n playing,\n speed,\n onReset,\n onStepBack,\n onTogglePlay,\n onStepForward,\n onJumpToEnd,\n onSpeedChange,\n hideSpeed,\n resetButtonRef,\n playButtonRef,\n flashing,\n}: Props) {\n const atStart = tickIndex <= 0;\n const atEnd = tickIndex >= tickCount;\n\n return (\n <span style={groupStyle}>\n <button\n ref={resetButtonRef}\n onClick={onReset}\n disabled={atStart}\n style={flashing === 'reset' ? pressedStyle : buttonStyle}\n title=\"Reset to start\"\n >\n ⏮\n </button>\n <button onClick={onStepBack} disabled={atStart} style={buttonStyle} title=\"Step back one tick\">\n ◀\n </button>\n {/* ⏯ when paused (not plain ▶) so the toggle differs from step-forward. */}\n <button\n ref={playButtonRef}\n onClick={onTogglePlay}\n disabled={atEnd && !playing}\n style={flashing === 'play' ? pressedPlayStyle : playButtonStyle}\n title={playing ? 'Pause' : 'Play'}\n >\n {playing ? '⏸' : '⏯'}\n </button>\n <button onClick={onStepForward} disabled={atEnd} style={buttonStyle} title=\"Step forward one tick\">\n ▶\n </button>\n <button onClick={onJumpToEnd} disabled={atEnd} style={buttonStyle} title=\"Jump to end\">\n ⏭\n </button>\n {hideSpeed ? null : (\n <select\n value={speed}\n onChange={(e) => onSpeedChange(Number(e.target.value) as Speed)}\n style={selectStyle}\n aria-label=\"Playback speed\"\n title=\"Playback speed\"\n >\n <option value={1}>1×</option>\n <option value={2}>2×</option>\n <option value={4}>4×</option>\n </select>\n )}\n </span>\n );\n}\n\nconst groupStyle: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.25rem',\n};\n\nconst buttonStyle: CSSProperties = {\n minWidth: 26,\n height: 24,\n padding: '0 0.35rem',\n border: '1px solid var(--border-card)',\n borderRadius: 4,\n background: 'var(--bg-input, transparent)',\n color: 'var(--text-primary)',\n cursor: 'pointer',\n fontSize: '0.78rem',\n lineHeight: 1,\n};\n\nconst playButtonStyle: CSSProperties = {\n ...buttonStyle,\n minWidth: 32,\n fontWeight: 600,\n};\n\nconst pressedStyle: CSSProperties = {\n ...buttonStyle,\n background: 'var(--text-link, #4f8cff)',\n color: '#fff',\n borderColor: 'var(--text-link, #4f8cff)',\n boxShadow: '0 0 0 3px color-mix(in srgb, var(--text-link, #4f8cff) 35%, transparent)',\n transform: 'translateY(1px)',\n};\n\nconst pressedPlayStyle: CSSProperties = {\n ...pressedStyle,\n minWidth: 32,\n fontWeight: 600,\n};\n\nconst selectStyle: CSSProperties = {\n height: 24,\n padding: '0 0.2rem',\n border: '1px solid var(--border-card)',\n borderRadius: 4,\n background: 'var(--bg-input, transparent)',\n color: 'var(--text-primary)',\n fontSize: '0.78rem',\n marginLeft: '0.25rem',\n};\n","// Mock-mode tickIndex scrubber, docked in the chart's bottomSlot to mirror\n// Live's <LiveScrubControls>. Stateless — the parent owns tickIndex/tickCount.\n\nimport React from 'react';\nimport type { CSSProperties } from 'react';\n\ntype Props = {\n readonly tickIndex: number;\n readonly tickCount: number;\n readonly onTickIndexChange: (next: number) => void;\n};\n\nexport function ReplaySliderBar({ tickIndex, tickCount, onTickIndexChange }: Props) {\n // [0, 1] when empty so the layout still reserves the same height.\n const max = Math.max(tickCount, 1);\n const fillPct = tickCount === 0 ? 0 : Math.round((tickIndex / tickCount) * 100);\n\n return (\n <div style={rowStyle}>\n {/* Gutter placeholder mirroring LiveScrubControls' pause-button gutter. */}\n <div style={gutterSlotStyle} aria-hidden />\n <input\n type=\"range\"\n min={0}\n max={max}\n step={1}\n value={tickIndex}\n onChange={(e) => onTickIndexChange(Number(e.target.value))}\n disabled={tickCount === 0}\n className=\"scrub-slider\"\n style={{ ...sliderStyle, ['--scrub-fill' as 'width']: `${fillPct}%` }}\n aria-label=\"Replay tick index\"\n title={`tick ${tickIndex} / ${tickCount}`}\n />\n </div>\n );\n}\n\nconst rowStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 0,\n paddingTop: '0.15rem',\n};\n\nconst gutterSlotStyle: CSSProperties = {\n width: '5.5rem',\n flexShrink: 0,\n};\n\n// Full post-gutter width — Mock has no `⤓ now` button to make room for.\nconst sliderStyle: CSSProperties = {\n flex: '1 1 auto',\n minWidth: 0,\n margin: 0,\n height: 18,\n padding: 0,\n WebkitAppearance: 'none',\n appearance: 'none',\n background: 'transparent',\n border: 'none',\n};\n","// Grafana alert-rule selector for the header, rendered when the adapter\n// exposes `listRules`. Grouped by folder, state-dot prefixed, with a ↻ refresh.\n\nimport React from 'react';\nimport type { CSSProperties } from 'react';\nimport type { GrafanaAlertState, RuleSummary } from '../data/data-source';\n\ntype Props = {\n readonly rules: ReadonlyArray<RuleSummary>;\n readonly selectedUid: string | null;\n readonly onSelect: (uid: string) => void;\n readonly loading: boolean;\n readonly error: string | null;\n // Omitted hides the ↻ button.\n readonly onRefresh?: () => void;\n};\n\nexport function RulePicker({\n rules,\n selectedUid,\n onSelect,\n loading,\n error,\n onRefresh,\n}: Props) {\n const disabled = loading || error !== null;\n const grouped = groupByFolder(rules);\n const counts = countByState(rules);\n\n return (\n <label style={wrapperStyle}>\n <span style={labelStyle}>Rule:</span>\n <select\n value={selectedUid ?? ''}\n onChange={(e) => onSelect(e.target.value)}\n style={selectStyle}\n disabled={disabled}\n >\n {loading && <option value=\"\">Loading rules…</option>}\n {error !== null && !loading && <option value=\"\">(error loading rules)</option>}\n {!loading && error === null && selectedUid === null && (\n <option value=\"\" disabled>\n Pick a rule…\n </option>\n )}\n {!loading &&\n error === null &&\n grouped.map(({ folder, rules: folderRules }) => {\n // No-folder rules render flat; folder-tagged ones inside an optgroup.\n if (folder === undefined) {\n return folderRules.map((r) => (\n <option key={r.uid} value={r.uid}>\n {renderOption(r)}\n </option>\n ));\n }\n return (\n <optgroup key={folder} label={folder}>\n {folderRules.map((r) => (\n <option key={r.uid} value={r.uid}>\n {renderOption(r)}\n </option>\n ))}\n </optgroup>\n );\n })}\n </select>\n {!loading && error === null && (\n <span style={metaStyle}>{describeCounts(rules.length, counts)}</span>\n )}\n {onRefresh !== undefined && (\n <button\n type=\"button\"\n onClick={onRefresh}\n disabled={loading}\n style={refreshButtonStyle}\n title=\"Reload rules list\"\n aria-label=\"Reload rules list\"\n >\n ↻\n </button>\n )}\n </label>\n );\n}\n\nconst STATE_DOT: Record<GrafanaAlertState, string> = {\n firing: '🔴',\n pending: '🟡',\n inactive: '⚪',\n unknown: '❔',\n};\n\nfunction renderOption(r: RuleSummary): string {\n const dot = r.state !== undefined ? STATE_DOT[r.state] : '';\n return dot !== '' ? `${dot} ${r.title}` : r.title;\n}\n\ntype FolderGroup = {\n readonly folder: string | undefined;\n readonly rules: ReadonlyArray<RuleSummary>;\n};\n\n// Preserves first-seen folder order so the picker doesn't re-shuffle on refresh.\nfunction groupByFolder(rules: ReadonlyArray<RuleSummary>): ReadonlyArray<FolderGroup> {\n const groups = new Map<string | undefined, RuleSummary[]>();\n for (const r of rules) {\n const existing = groups.get(r.folder);\n if (existing) existing.push(r);\n else groups.set(r.folder, [r]);\n }\n return Array.from(groups.entries()).map(([folder, folderRules]) => ({\n folder,\n rules: folderRules,\n }));\n}\n\ntype StateCounts = {\n readonly firing: number;\n readonly pending: number;\n readonly inactive: number;\n readonly unknown: number;\n};\n\nfunction countByState(rules: ReadonlyArray<RuleSummary>): StateCounts {\n const counts = { firing: 0, pending: 0, inactive: 0, unknown: 0 };\n for (const r of rules) {\n if (r.state !== undefined) counts[r.state] += 1;\n }\n return counts;\n}\n\n// \"3 rules · 1 firing · 2 inactive\" — non-zero buckets only.\nfunction describeCounts(total: number, c: StateCounts): string {\n const noun = `${total} rule${total === 1 ? '' : 's'}`;\n const parts: string[] = [];\n if (c.firing > 0) parts.push(`${c.firing} firing`);\n if (c.pending > 0) parts.push(`${c.pending} pending`);\n if (c.unknown > 0) parts.push(`${c.unknown} unknown`);\n // Skip inactive when it's the only non-zero bucket (\"3 rules · 3 inactive\").\n const nonInactiveTotal = c.firing + c.pending + c.unknown;\n if (nonInactiveTotal > 0 && c.inactive > 0) parts.push(`${c.inactive} inactive`);\n return parts.length > 0 ? `${noun} · ${parts.join(' · ')}` : noun;\n}\n\nconst wrapperStyle: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '0.5rem',\n flexWrap: 'wrap',\n};\n\nconst labelStyle: CSSProperties = {\n fontSize: '0.875rem',\n color: 'var(--text-muted)',\n};\n\nconst selectStyle: CSSProperties = {\n // Inline sizing/colors beat Grafana's select reset.\n padding: '0.4rem 0.55rem',\n minHeight: '2rem',\n lineHeight: 1.2,\n fontSize: '0.875rem',\n width: 'auto',\n minWidth: '14rem',\n maxWidth: '24rem',\n background: 'var(--bg-input)',\n color: 'var(--text-primary)',\n border: '1px solid var(--border-input)',\n borderRadius: 4,\n};\n\nconst metaStyle: CSSProperties = {\n fontSize: '0.8rem',\n color: 'var(--text-muted)',\n};\n\nconst refreshButtonStyle: CSSProperties = {\n padding: '0.15rem 0.4rem',\n fontSize: '0.9rem',\n lineHeight: 1,\n border: '1px solid var(--border-card)',\n borderRadius: 3,\n background: 'transparent',\n color: 'var(--text-muted)',\n cursor: 'pointer',\n};\n","import type { RuleMetadata } from '../types';\n\n// The (datasourceUid, PromQL expr) from the query node — info\n// parseGrafanaAlertRule discards. A query node has a real (non-`__expr__`)\n// datasourceUID, mirroring core's isQueryNode.\nexport type RuleQuery = {\n readonly datasourceUid: string;\n readonly expr: string;\n};\n\nexport function extractRuleQuery(rule: unknown): RuleQuery | null {\n if (typeof rule !== 'object' || rule === null) return null;\n const spec = (rule as { spec?: unknown }).spec;\n if (typeof spec !== 'object' || spec === null) return null;\n const expressions = (spec as { expressions?: unknown }).expressions;\n if (typeof expressions !== 'object' || expressions === null) return null;\n for (const node of Object.values(expressions as Record<string, unknown>)) {\n if (typeof node !== 'object' || node === null) continue;\n const datasourceUid = (node as { datasourceUID?: unknown }).datasourceUID;\n if (typeof datasourceUid !== 'string' || datasourceUid === '__expr__') continue;\n const model = (node as { model?: unknown }).model;\n if (typeof model !== 'object' || model === null) continue;\n const expr = (model as { expr?: unknown }).expr;\n if (typeof expr !== 'string') continue;\n return { datasourceUid, expr };\n }\n return null;\n}\n\n// UI-side metadata for ParamControls's read-only sections (math-irrelevant,\n// so parseGrafanaAlertRule discards it). null falls back to placeholders.\nexport function extractRuleMetadata(rule: unknown): RuleMetadata | null {\n if (typeof rule !== 'object' || rule === null) return null;\n const spec = (rule as { spec?: unknown }).spec;\n if (typeof spec !== 'object' || spec === null) return null;\n\n const title =\n typeof (spec as { title?: unknown }).title === 'string'\n ? ((spec as { title: string }).title)\n : '';\n\n const rawLabels = (spec as { labels?: unknown }).labels;\n const labels: Record<string, string> = {};\n if (typeof rawLabels === 'object' && rawLabels !== null) {\n for (const [k, v] of Object.entries(rawLabels as Record<string, unknown>)) {\n if (typeof v === 'string') labels[k] = v;\n }\n }\n\n const paused = (spec as { paused?: unknown }).paused === true;\n\n const query = extractRuleQuery(rule);\n // Instant query nodes carry `model.instant: true`; default range.\n let mode: 'range' | 'instant' = 'range';\n const exprs = (spec as { expressions?: unknown }).expressions;\n if (typeof exprs === 'object' && exprs !== null) {\n for (const node of Object.values(exprs as Record<string, unknown>)) {\n if (typeof node !== 'object' || node === null) continue;\n const ds = (node as { datasourceUID?: unknown }).datasourceUID;\n if (typeof ds !== 'string' || ds === '__expr__') continue;\n const model = (node as { model?: unknown }).model;\n if (typeof model === 'object' && model !== null) {\n if ((model as { instant?: unknown }).instant === true) mode = 'instant';\n }\n break;\n }\n }\n\n // `metadata.updated` (ISO-8601) → epoch-ms; OverviewStrip dims bells from\n // before this moment. Skipped when absent / malformed.\n const metaObj = (rule as { metadata?: unknown }).metadata;\n const updatedIso =\n typeof metaObj === 'object' && metaObj !== null\n ? (metaObj as { updated?: unknown }).updated\n : undefined;\n let updatedMs: number | undefined;\n if (typeof updatedIso === 'string') {\n const parsed = Date.parse(updatedIso);\n if (Number.isFinite(parsed)) updatedMs = parsed;\n }\n\n return {\n title,\n labels,\n paused,\n query: { expr: query?.expr ?? '', mode },\n ...(updatedMs !== undefined ? { updatedMs } : {}),\n };\n}\n\n","// Drives Live mode: polls the adapter for samples + Grafana's state, owns the\n// poller lifecycle and all Grafana-eval-grid phase logic (discovery, lock,\n// sample-start alignment). Cleared when `active` is false.\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { Sample } from '@alert-whatif/core';\nimport type {\n GrafanaAlertState,\n WhatIfDataSource,\n} from '../data/data-source';\nimport { createLivePoller } from './live-poller';\n\nexport type LiveModeOptions = {\n readonly active: boolean;\n readonly datasourceUid: string;\n readonly query: string;\n readonly ruleTitle: string;\n readonly intervalSec: number;\n // Trailing-window length fetched each tick; gaps stay as gaps.\n readonly lookbackSec: number;\n // `query_range` step; also phase-aligns startSec to Grafana's eval grid.\n readonly stepSec: number;\n // Aligns the sample query's start to Grafana's eval-grid phase so every\n // moment Grafana evaluates at has a sample exactly there.\n readonly evaluationIntervalMs: number;\n};\n\nexport type LiveModeState = {\n readonly samples: ReadonlyArray<Sample>;\n // Grafana's decision as of the last poll; 'unknown' until the first.\n readonly grafanaState: GrafanaAlertState;\n readonly lastPollAt: number | null;\n // Phase anchor (Grafana's lastEvaluation ms when first learned). The parent\n // passes `phase % evaluationInterval` as the evalGridOffsetMs hint. LOCKED\n // after the first poll: re-reading it would let any divergence be written\n // off as clock drift rather than a real evaluator bug.\n readonly grafanaLastEvalMs: number | null;\n // Unlocked — updates every poll. Stamps the GRAFANA bar with the moment\n // Grafana actually transitioned, not our poll time.\n readonly grafanaLatestEvalMs: number | null;\n readonly error: string | null;\n};\n\nexport function useLiveMode(\n opts: LiveModeOptions,\n adapter: WhatIfDataSource,\n): LiveModeState {\n const [samples, setSamples] = useState<ReadonlyArray<Sample>>([]);\n const [grafanaState, setGrafanaState] = useState<GrafanaAlertState>('unknown');\n const [lastPollAt, setLastPollAt] = useState<number | null>(null);\n const [grafanaLastEvalMs, setGrafanaLastEvalMs] = useState<number | null>(null);\n const [grafanaLatestEvalMs, setGrafanaLatestEvalMs] = useState<number | null>(null);\n const [error, setError] = useState<string | null>(null);\n // Mirrors grafanaLastEvalMs so the async poll closure reads the latest value\n // without re-creating the effect.\n const phaseAnchorRef = useRef<number | null>(null);\n useEffect(() => {\n phaseAnchorRef.current = grafanaLastEvalMs;\n }, [grafanaLastEvalMs]);\n\n useEffect(() => {\n // Clear phase + samples on every re-run: a new rule context has its own\n // scheduler phase, so keeping old samples through the realignment gap\n // shows phantom NoData. An honest \"loading\" pause is better.\n setGrafanaLastEvalMs(null);\n setGrafanaLatestEvalMs(null);\n phaseAnchorRef.current = null;\n setSamples([]);\n setGrafanaState('unknown');\n if (!opts.active) {\n setLastPollAt(null);\n setError(null);\n return;\n }\n\n const poller = createLivePoller({\n intervalSec: opts.intervalSec,\n // Align poll moments to Grafana's eval phase (+1s buffer) so the NOW dot\n // lands on the eval tick and transitions are seen within ~1s, not 15s\n // late. Fixed cadence until the phase is known.\n getNextDelayMs: () => {\n const phaseAnchorMs = phaseAnchorRef.current;\n if (phaseAnchorMs === null) return null;\n const phaseMs =\n ((phaseAnchorMs % opts.evaluationIntervalMs) +\n opts.evaluationIntervalMs) %\n opts.evaluationIntervalMs;\n const stepMs = opts.intervalSec * 1000;\n const BUFFER_MS = 1000;\n const now = Date.now();\n const offset = ((now - phaseMs - BUFFER_MS) % stepMs + stepMs) % stepMs;\n const delay = (stepMs - offset) % stepMs;\n // delay=0 would immediate-fire into a tight loop; push to the next slot.\n return delay === 0 ? stepMs : delay;\n },\n poll: async () => {\n const stepSec = opts.stepSec;\n\n // Discover the phase once on the first poll even when the state oracle\n // is off (plugin): without it, startSec drifts 15s per poll and the\n // eval-grid offset hops the lifecycle markers between polls.\n if (\n phaseAnchorRef.current === null &&\n adapter.fetchRuleState !== undefined\n ) {\n const rule = await adapter.fetchRuleState(opts.ruleTitle);\n if (rule.lastEvaluationMs !== null) {\n // Sync the ref so the samples fetch below aligns to the new phase.\n phaseAnchorRef.current = rule.lastEvaluationMs;\n setGrafanaLastEvalMs(rule.lastEvaluationMs);\n setGrafanaLatestEvalMs(rule.lastEvaluationMs);\n }\n if (adapter.capabilities.grafanaStateOracle) {\n setGrafanaState(rule.state);\n }\n }\n\n // Round startSec down to a stepSec mark offset by phaseSec, so samples\n // land on Grafana's phase. Falls back to rawStartSec when unknown.\n const nowSec = Math.floor(Date.now() / 1000);\n const rawStartSec = nowSec - opts.lookbackSec;\n const phaseAnchorMs = phaseAnchorRef.current;\n let startSec: number;\n if (phaseAnchorMs !== null) {\n const phaseSec = Math.floor(\n ((phaseAnchorMs % opts.evaluationIntervalMs) +\n opts.evaluationIntervalMs) %\n opts.evaluationIntervalMs /\n 1000,\n );\n startSec =\n Math.floor((rawStartSec - phaseSec) / stepSec) * stepSec + phaseSec;\n } else {\n startSec = rawStartSec;\n }\n\n // Fetch samples + rule in parallel so a slow rules API doesn't delay\n // samples; skip the rule fetch when there's no state oracle.\n const samplesP = adapter.fetchSamples({\n datasourceUid: opts.datasourceUid,\n expr: opts.query,\n startSec,\n endSec: nowSec,\n stepSec,\n });\n const ruleP = adapter.capabilities.grafanaStateOracle\n ? adapter.fetchRuleState!(opts.ruleTitle)\n : Promise.resolve(null);\n const [samplesResult, rule] = await Promise.all([samplesP, ruleP]);\n if (samplesResult.kind === 'Err') {\n // Throw so createLivePoller's onError handler runs.\n throw new Error(samplesResult.errors.join(' · '));\n }\n // Live consumes the first series only — no SeriesPicker in Live mode.\n setSamples(samplesResult.value[0]?.samples ?? []);\n if (rule !== null) {\n setGrafanaState(rule.state);\n if (rule.lastEvaluationMs !== null) {\n setGrafanaLatestEvalMs(rule.lastEvaluationMs);\n // Follow the (deterministic) schedule each poll rather than\n // locking, so a rule/container restart re-aligns the phase.\n phaseAnchorRef.current = rule.lastEvaluationMs;\n setGrafanaLastEvalMs(rule.lastEvaluationMs);\n }\n }\n setLastPollAt(Date.now());\n setError(null);\n },\n onError: (err) => {\n setError(err instanceof Error ? err.message : String(err));\n },\n });\n\n poller.start();\n return () => poller.stop();\n }, [opts.active, opts.query, opts.ruleTitle, opts.intervalSec, opts.lookbackSec, opts.stepSec, opts.evaluationIntervalMs]);\n\n return { samples, grafanaState, lastPollAt, grafanaLastEvalMs, grafanaLatestEvalMs, error };\n}\n","// Polling loop: runs `poll` every `intervalSec`, routes errors to `onError`\n// without killing the loop, fires once immediately on start, and skips\n// overlapping ticks. Pure runtime utility — use-live-mode.ts wires it up.\n\nexport type LivePollerOptions = {\n // Minimum 1; clamped silently.\n readonly intervalSec: number;\n readonly poll: () => Promise<void>;\n readonly onError?: (err: unknown) => void;\n // Per-poll delay override to align to an external grid (Grafana's eval\n // phase); `null` falls back to the fixed cadence.\n readonly getNextDelayMs?: () => number | null;\n};\n\nexport type LivePoller = {\n readonly start: () => void;\n readonly stop: () => void;\n readonly setInterval: (sec: number) => void;\n readonly isRunning: () => boolean;\n};\n\nexport function createLivePoller(opts: LivePollerOptions): LivePoller {\n let timer: ReturnType<typeof setTimeout> | null = null;\n let intervalSec = Math.max(1, opts.intervalSec);\n let inFlight = false;\n let stopped = false;\n\n const computeDelayMs = (): number => {\n if (opts.getNextDelayMs !== undefined) {\n const supplied = opts.getNextDelayMs();\n if (supplied !== null && supplied > 0) return supplied;\n }\n return intervalSec * 1000;\n };\n\n const schedule = () => {\n if (stopped) return;\n timer = setTimeout(() => {\n void tick();\n }, computeDelayMs());\n };\n\n const tick = async () => {\n if (inFlight) {\n schedule();\n return;\n }\n inFlight = true;\n try {\n await opts.poll();\n } catch (err) {\n opts.onError?.(err);\n } finally {\n inFlight = false;\n schedule();\n }\n };\n\n return {\n start() {\n if (timer || !stopped && timer) return;\n stopped = false;\n // Fire immediately so the UI doesn't wait up to one intervalSec for the\n // first alignment slot.\n void tick();\n },\n stop() {\n stopped = true;\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n },\n setInterval(sec: number) {\n intervalSec = Math.max(1, sec);\n },\n isRunning() {\n return timer !== null;\n },\n };\n}\n","// Export / import datasets as JSON (one self-contained Dataset + a version /\n// exportedAt envelope). Parse-time validation is strict so a corrupt file\n// fails loudly rather than crashing the evaluator later.\n\nimport type { AlertConfig, Sample } from '@alert-whatif/core';\nimport type { Dataset } from '../data/data-source';\nimport type { RuleMetadata } from '../types';\n\nconst CURRENT_VERSION = 1;\n\ntype ExportEnvelope = {\n readonly version: 1;\n readonly exportedAt: string;\n readonly dataset: Dataset;\n};\n\nexport type ImportResult =\n | { readonly kind: 'ok'; readonly dataset: Dataset }\n | { readonly kind: 'err'; readonly error: string };\n\nexport function downloadDataset(dataset: Dataset): void {\n const envelope: ExportEnvelope = {\n version: CURRENT_VERSION,\n exportedAt: new Date().toISOString(),\n dataset,\n };\n const json = JSON.stringify(envelope, null, 2);\n // octet-stream (not application/json) so the browser / Grafana host honors\n // the `download` attribute instead of opening the JSON inline.\n const blob = new Blob([json], { type: 'application/octet-stream' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filenameFor(dataset);\n a.rel = 'noopener';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n // Defer revoke past the tick — synchronous revoke raced the download\n // initiator in some Grafana plugin contexts.\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\nfunction filenameFor(dataset: Dataset): string {\n const safeId = dataset.id.replace(/[^a-zA-Z0-9._-]+/g, '-');\n const stamp = new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-');\n return `alert-whatif-${safeId}-${stamp}.json`;\n}\n\n// Tolerates extra fields, rejects missing/wrong-typed required ones.\nexport function parseDataset(rawJson: string): ImportResult {\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawJson);\n } catch (e) {\n return { kind: 'err', error: `Not valid JSON: ${e instanceof Error ? e.message : String(e)}` };\n }\n\n if (!isRecord(parsed)) {\n return { kind: 'err', error: 'Root is not an object' };\n }\n\n if (parsed.version !== CURRENT_VERSION) {\n return {\n kind: 'err',\n error: `Unsupported version: expected ${CURRENT_VERSION}, got ${String(parsed.version)}`,\n };\n }\n\n if (!isRecord(parsed.dataset)) {\n return { kind: 'err', error: 'Missing or invalid `dataset` field' };\n }\n\n const validation = validateDataset(parsed.dataset);\n if (validation.kind === 'err') return validation;\n return { kind: 'ok', dataset: validation.dataset };\n}\n\nfunction validateDataset(raw: Record<string, unknown>): ImportResult {\n if (typeof raw.id !== 'string' || raw.id.length === 0) {\n return { kind: 'err', error: '`dataset.id` must be a non-empty string' };\n }\n if (typeof raw.displayName !== 'string') {\n return { kind: 'err', error: '`dataset.displayName` must be a string' };\n }\n if (typeof raw.description !== 'string') {\n return { kind: 'err', error: '`dataset.description` must be a string' };\n }\n if (typeof raw.source !== 'string') {\n return { kind: 'err', error: '`dataset.source` must be a string' };\n }\n if (!Array.isArray(raw.samples)) {\n return { kind: 'err', error: '`dataset.samples` must be an array' };\n }\n const samples: Sample[] = [];\n for (let i = 0; i < raw.samples.length; i++) {\n const s: unknown = raw.samples[i];\n if (!isRecord(s) || typeof s.t !== 'number' || typeof s.v !== 'number') {\n return { kind: 'err', error: `\\`dataset.samples[${i}]\\` must be { t: number, v: number }` };\n }\n samples.push({ t: s.t, v: s.v });\n }\n if (!isRecord(raw.defaultAlertConfig)) {\n return { kind: 'err', error: '`dataset.defaultAlertConfig` must be an object' };\n }\n // No deep AlertConfig validation — evaluate() does its own.\n const defaultAlertConfig = raw.defaultAlertConfig as AlertConfig;\n\n const dataset: Dataset = {\n id: raw.id,\n displayName: raw.displayName,\n description: raw.description,\n source: raw.source,\n samples,\n defaultAlertConfig,\n ...(typeof raw.rateInnerWindow === 'number' ? { rateInnerWindow: raw.rateInnerWindow } : {}),\n // Round-trip the eval-grid phase so an import lands on the same :phase\n // boundaries as the original capture.\n ...(typeof raw.evalGridOffsetMs === 'number'\n ? { evalGridOffsetMs: raw.evalGridOffsetMs }\n : {}),\n ...(isRecord(raw.ruleMetadata)\n ? { ruleMetadata: raw.ruleMetadata as unknown as RuleMetadata }\n : {}),\n };\n return { kind: 'ok', dataset };\n}\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\n// Best-effort localStorage — failures are swallowed (never load-bearing).\nconst STORAGE_KEY = 'alert-whatif:captured-datasets';\n\nexport function loadCapturedDatasets(): ReadonlyArray<Dataset> {\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (raw === null) return [];\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const out: Dataset[] = [];\n for (const entry of parsed) {\n if (!isRecord(entry)) continue;\n const validation = validateDataset(entry);\n if (validation.kind === 'ok') out.push(validation.dataset);\n }\n return out;\n } catch {\n return [];\n }\n}\n\nexport function saveCapturedDatasets(datasets: ReadonlyArray<Dataset>): void {\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(datasets));\n } catch {\n // Quota exceeded, private mode, etc.\n }\n}\n","import type { AlertConfig } from '@alert-whatif/core';\n\nexport const MIN_AUTOPLAY_WAIT_MS = 1000;\nexport const AUTO_REPLAY_SPEEDUP = 5;\n\nexport const PLACEHOLDER_CONFIG: AlertConfig = {\n threshold: { op: 'Gt', value: 0 },\n forDuration: 0,\n keepFiringFor: 0,\n evaluationInterval: 60000,\n intervalMs: 1000,\n maxDataPoints: 1,\n noDataState: 'Ok',\n execErrState: 'Error',\n instant: true,\n};\n\nexport const LIVE_INTERVAL_SEC = 15;\nexport const OVERVIEW_RANGE_OPTIONS = [\n { label: 'Current', lookbackSec: 0, stepSec: 0 },\n { label: 'Last 1h', lookbackSec: 60 * 60, stepSec: 30 },\n { label: 'Last 6h', lookbackSec: 6 * 60 * 60, stepSec: 60 },\n { label: 'Last 24h', lookbackSec: 24 * 60 * 60, stepSec: 60 },\n { label: 'Last 48h', lookbackSec: 48 * 60 * 60, stepSec: 120 },\n] as const;\nexport const OVERVIEW_DEFAULT_LOOKBACK_SEC = 0;\nexport const LIVE_LOOKBACK_SEC = 1800;\nexport const LIVE_SCRUB_MAX_MS = LIVE_LOOKBACK_SEC * 1000 - 12 * 60 * 1000;\n// Drill focal lands at the 2nd tick from the left ('leading') or 3rd from\n// the right ('trailing'); both edges stay inside the ±15-min drill fetch.\nexport const DRILL_FOCAL_LEADING_OFFSET_MS = 12 * 60 * 1000;\nexport const DRILL_FOCAL_TRAILING_OFFSET_MS = 2 * 60 * 1000;\n","import type { AlertConfig } from '@alert-whatif/core';\nimport type { ConfigOverrides } from './types';\nimport type { Dataset } from '../data/data-source';\nimport {\n DRILL_FOCAL_LEADING_OFFSET_MS,\n DRILL_FOCAL_TRAILING_OFFSET_MS,\n} from './constants';\n\nexport function applyConfigOverrides(base: AlertConfig, overrides?: ConfigOverrides): AlertConfig {\n if (overrides === undefined) return base;\n return { ...base, ...overrides } as AlertConfig;\n}\n\nconst PARAM_LABEL_BY_KEY: Record<string, string> = {\n forDuration: 'for',\n keepFiringFor: 'keepFiringFor',\n evaluationInterval: 'trigger.interval',\n intervalMs: 'intervalMs',\n maxDataPoints: 'maxDataPoints',\n windowDuration: 'relativeTimeRange.from',\n reducer: 'reducer',\n noDataState: 'noDataState',\n execErrState: 'execErrState',\n};\n\nexport function changedParamLabels(cur: AlertConfig, base: AlertConfig | null): ReadonlySet<string> {\n const out = new Set<string>();\n if (base === null) return out;\n const c = cur as Record<string, unknown>;\n const b = base as Record<string, unknown>;\n for (const [key, label] of Object.entries(PARAM_LABEL_BY_KEY)) {\n if (c[key] !== b[key]) out.add(label);\n }\n if (JSON.stringify(c.nanMode) !== JSON.stringify(b.nanMode)) out.add('settings.mode');\n if (JSON.stringify(cur.threshold) !== JSON.stringify(base.threshold)) {\n out.add('conditions[0].evaluator.params');\n out.add('conditions[0].evaluator.params[0] (left)');\n out.add('conditions[0].evaluator.params[1] (right)');\n }\n return out;\n}\n\nexport function mockRightAnchorT(dataset: Dataset): number | undefined {\n if (dataset.drillFocalMs !== undefined) {\n const offset =\n dataset.drillFocalSide === 'trailing'\n ? DRILL_FOCAL_TRAILING_OFFSET_MS\n : DRILL_FOCAL_LEADING_OFFSET_MS;\n return dataset.drillFocalMs + offset;\n }\n const last = dataset.samples[dataset.samples.length - 1];\n return last?.t;\n}\n","// Dark/Light segmented control. Stateless — the parent owns the theme.\n\nimport React from 'react';\nimport type { CSSProperties } from 'react';\nimport type { Theme } from '../util/use-theme';\n\ntype Props = {\n readonly theme: Theme;\n readonly onChange: (next: Theme) => void;\n};\n\nexport function ThemeToggle({ theme, onChange }: Props) {\n return (\n <div role=\"group\" aria-label=\"Theme\" style={groupStyle}>\n <Button label=\"Dark\" active={theme === 'dark'} onClick={() => onChange('dark')} />\n <Button label=\"Light\" active={theme === 'light'} onClick={() => onChange('light')} />\n </div>\n );\n}\n\nfunction Button({\n label,\n active,\n onClick,\n}: {\n readonly label: string;\n readonly active: boolean;\n readonly onClick: () => void;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={active}\n style={active ? { ...buttonStyle, ...buttonActiveStyle } : buttonStyle}\n >\n {label}\n </button>\n );\n}\n\nconst groupStyle: CSSProperties = {\n display: 'inline-flex',\n border: '1px solid var(--border-card)',\n borderRadius: 6,\n overflow: 'hidden',\n};\n\n// The wrapper carries the border/radius, so individual buttons drop them.\nconst buttonStyle: CSSProperties = {\n border: 'none',\n borderRadius: 0,\n padding: '0.25rem 0.7rem',\n fontSize: '0.8rem',\n background: 'transparent',\n color: 'var(--text-muted)',\n};\n\nconst buttonActiveStyle: CSSProperties = {\n background: 'var(--bg-button-hover)',\n color: 'var(--text-primary)',\n};\n","// localStorage theme hook (defaults 'dark'); publishes to <html data-theme>.\n\nimport { useEffect, useState } from 'react';\n\nexport type Theme = 'dark' | 'light';\n\nconst STORAGE_KEY = 'alert-whatif:theme';\n\nfunction readInitialTheme(): Theme {\n if (typeof window === 'undefined') return 'dark';\n const saved = window.localStorage.getItem(STORAGE_KEY);\n return saved === 'light' ? 'light' : 'dark';\n}\n\nexport function useTheme(): readonly [Theme, (next: Theme) => void] {\n const [theme, setTheme] = useState<Theme>(readInitialTheme);\n\n useEffect(() => {\n document.documentElement.setAttribute('data-theme', theme);\n window.localStorage.setItem(STORAGE_KEY, theme);\n }, [theme]);\n\n return [theme, setTheme] as const;\n}\n","// Flattens the varied reject shapes from plugin/demo fetchers into a\n// diagnostic message (String(err) would give \"[object Object]\").\nexport function describeFetchError(err: unknown): string {\n if (err instanceof Error) return err.message;\n if (typeof err === 'string') return err;\n if (typeof err !== 'object' || err === null) return String(err);\n const e = err as Record<string, unknown>;\n const status = typeof e.status === 'number' ? e.status : null;\n const statusText = typeof e.statusText === 'string' ? e.statusText : null;\n const data = e.data as { message?: unknown; error?: unknown } | undefined;\n const dataMsg =\n data && typeof data === 'object'\n ? typeof data.message === 'string'\n ? data.message\n : typeof data.error === 'string'\n ? data.error\n : null\n : null;\n const topMsg = typeof e.message === 'string' ? e.message : null;\n const parts = [\n status !== null ? `HTTP ${status}` : null,\n statusText,\n dataMsg ?? topMsg,\n ].filter((p): p is string => p !== null && p !== '');\n if (parts.length > 0) return parts.join(' · ');\n try {\n return JSON.stringify(err);\n } catch {\n return 'Unknown error';\n }\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","computeEffectiveStepMs","jsx","jsxs","labelStyle","jsx","jsxs","jsx","jsxs","rowStyle","Fragment","jsx","jsxs","rowStyle","formatTime","iconButtonStyle","labelStyle","passes","formatTime","Fragment","jsx","jsxs","jsx","Fragment","jsx","jsxs","formatTime","useState","jsx","jsxs","labelStyle","jsx","jsxs","containerStyle","labelStyle","selectStyle","jsx","jsxs","jsx","jsxs","React","Fragment","jsx","jsxs","React","selectStyle","ModeToggle","legendStyle","labelStyle","jsx","jsxs","buttonStyle","selectStyle","jsx","jsxs","rowStyle","gutterSlotStyle","sliderStyle","jsx","jsxs","wrapperStyle","labelStyle","selectStyle","metaStyle","useEffect","useRef","useState","useState","useRef","useEffect","rule","Fragment","jsx","jsxs","useState","useEffect","result","computeEffectiveStepMs","useRef","jsx","jsxs","groupStyle","buttonStyle","useEffect","useState","STORAGE_KEY"]}