"use client" /** * KeyMetricsProvider — host-app injection point for the design-system * `KeyMetrics` component. * * `KeyMetrics` itself ships as a pure primitive: it knows how to render * a KPI strip, an insight rail, and a default insight CTA, but it does * NOT know anything about the host app's AI assistant, command palette, * or keyboard-shortcut registry. * * Consumers (e.g. `apps/web`) mount a `KeyMetricsProvider` near the root * of the app and supply two optional injection points: * * - `defaultInsightAction` — fired when the user clicks the default * "Ask Leo about these metrics" button in the card-variant header, * and the default insight CTA when an individual `MetricInsight` did * not supply its own `onAction`. When omitted, the default button is * hidden entirely so the primitive stays useful in apps without an * AI assistant. * * - `shortcutHint` — inline React node rendered inside the tooltip * alongside the action label (typically a keyboard chord such as * `⌘⌥K`). When omitted, the tooltip simply shows the * label. * * - `defaultActionLabel` — visible label + accessible name for the * default action button. Defaults to "Ask Leo" so the existing * Exxat-DS layout reads identically without any consumer changes. * * This is the SAME injection shape used by Adobe Spectrum * (`Provider`-based service injection) and Material UI (`Theme` * context). It lets the design-system package ship product patterns * without taking on a hard dependency on the host app's AI surface. */ import * as React from "react" export interface KeyMetricsContextValue { /** Click handler for the default "Ask Leo about these metrics" CTA. */ defaultInsightAction?: () => void /** Inline kbd chord (or any node) rendered next to the action label inside the tooltip. */ shortcutHint?: React.ReactNode /** Label + aria-label for the default insight action button. Defaults to "Ask Leo". */ defaultActionLabel?: string } const KeyMetricsContext = React.createContext({}) /** Read the active `KeyMetricsProvider` value. Returns an empty object if no provider is mounted. */ export function useKeyMetricsContext(): KeyMetricsContextValue { return React.useContext(KeyMetricsContext) } export function KeyMetricsProvider({ value, children, }: { value: KeyMetricsContextValue children: React.ReactNode }) { // Memoize the wrapper so consumers passing fresh object identities // (common in client components) do not invalidate every descendant // that reads the context. const memo = React.useMemo( () => ({ defaultInsightAction: value.defaultInsightAction, shortcutHint: value.shortcutHint, defaultActionLabel: value.defaultActionLabel, }), [value.defaultInsightAction, value.shortcutHint, value.defaultActionLabel], ) return ( {children} ) }