semiotic 3.6.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +190 -227
- package/README.md +44 -14
- package/ai/cli.js +41 -0
- package/ai/componentMetadata.cjs +11 -2
- package/ai/dist/mcp-server.js +209 -6
- package/ai/examples.md +98 -0
- package/ai/schema.json +581 -1
- package/ai/system-prompt.md +5 -2
- package/dist/components/AccessibleNavTree.d.ts +25 -0
- package/dist/components/Annotation.d.ts +40 -14
- package/dist/components/ChartContainer.d.ts +32 -2
- package/dist/components/ai/annotationProvenance.d.ts +349 -0
- package/dist/components/ai/audienceProfile.d.ts +60 -3
- package/dist/components/ai/chartCapabilityTypes.d.ts +60 -2
- package/dist/components/ai/chartRoles.d.ts +27 -0
- package/dist/components/ai/conversationArc.d.ts +379 -0
- package/dist/components/ai/dataScaleProfile.d.ts +320 -0
- package/dist/components/ai/describeChart.d.ts +114 -0
- package/dist/components/ai/navigationTree.d.ts +45 -0
- package/dist/components/ai/readerGrounding.d.ts +70 -0
- package/dist/components/ai/suggestCharts.d.ts +34 -1
- package/dist/components/ai/useConversationArc.d.ts +89 -0
- package/dist/components/ai/useNavigationSync.d.ts +61 -0
- package/dist/components/ai/variantDiscovery.d.ts +168 -0
- package/dist/components/charts/realtime/RealtimeHeatmap.d.ts +3 -0
- package/dist/components/charts/realtime/RealtimeHistogram.d.ts +3 -0
- package/dist/components/charts/realtime/RealtimeLineChart.d.ts +3 -0
- package/dist/components/charts/realtime/RealtimeSwarmChart.d.ts +3 -0
- package/dist/components/charts/realtime/RealtimeWaterfallChart.d.ts +3 -0
- package/dist/components/charts/shared/annotationHierarchy.d.ts +42 -0
- package/dist/components/charts/shared/annotationResolvers.d.ts +3 -2
- package/dist/components/charts/shared/annotationRules.d.ts +16 -0
- package/dist/components/charts/shared/annotationTypes.d.ts +14 -0
- package/dist/components/charts/shared/auditAccessibility.d.ts +90 -0
- package/dist/components/charts/shared/chartSpecs.d.ts +2 -3
- package/dist/components/charts/shared/diagnoseConfig.d.ts +4 -6
- package/dist/components/charts/shared/selectionUtils.d.ts +5 -2
- package/dist/components/charts/shared/streamPropsHelpers.d.ts +2 -0
- package/dist/components/charts/shared/types.d.ts +5 -1
- package/dist/components/charts/value/BigNumber.capability.d.ts +13 -0
- package/dist/components/charts/value/BigNumber.d.ts +14 -0
- package/dist/components/charts/value/formatting.d.ts +40 -0
- package/dist/components/charts/value/thresholdSparkline.d.ts +40 -0
- package/dist/components/charts/value/types.d.ts +292 -0
- package/dist/components/realtime/lifecycleBands.d.ts +44 -0
- package/dist/components/realtime/types.d.ts +23 -8
- package/dist/components/recipes/annotationDensity.d.ts +69 -0
- package/dist/components/recipes/annotationLayout.d.ts +93 -0
- package/dist/components/semiotic-ai.d.ts +38 -15
- package/dist/components/semiotic-realtime.d.ts +2 -0
- package/dist/components/semiotic-recipes.d.ts +4 -0
- package/dist/components/semiotic-utils.d.ts +8 -0
- package/dist/components/semiotic-value.d.ts +55 -0
- package/dist/components/semiotic.d.ts +7 -0
- package/dist/components/server/staticAnnotations.d.ts +2 -0
- package/dist/components/stream/AccessibleDataTable.d.ts +10 -1
- package/dist/components/stream/NetworkSVGOverlay.d.ts +11 -5
- package/dist/components/stream/OrdinalSVGOverlay.d.ts +2 -0
- package/dist/components/stream/SVGOverlay.d.ts +2 -0
- package/dist/components/stream/geoTypes.d.ts +3 -0
- package/dist/components/stream/networkTypes.d.ts +2 -0
- package/dist/components/stream/ordinalTypes.d.ts +2 -0
- package/dist/components/stream/types.d.ts +2 -0
- package/dist/geo.min.js +1 -1
- package/dist/geo.module.min.js +1 -1
- package/dist/network.min.js +1 -1
- package/dist/network.module.min.js +1 -1
- package/dist/ordinal.min.js +1 -1
- package/dist/ordinal.module.min.js +1 -1
- package/dist/realtime.min.js +1 -1
- package/dist/realtime.module.min.js +1 -1
- package/dist/semiotic-ai.d.ts +38 -15
- package/dist/semiotic-ai.min.js +1 -1
- package/dist/semiotic-ai.module.min.js +1 -1
- package/dist/semiotic-realtime.d.ts +2 -0
- package/dist/semiotic-recipes.d.ts +4 -0
- package/dist/semiotic-recipes.min.js +1 -1
- package/dist/semiotic-recipes.module.min.js +1 -1
- package/dist/semiotic-themes.min.js +1 -1
- package/dist/semiotic-themes.module.min.js +1 -1
- package/dist/semiotic-utils.d.ts +8 -0
- package/dist/semiotic-utils.min.js +1 -1
- package/dist/semiotic-utils.module.min.js +1 -1
- package/dist/semiotic-value.d.ts +55 -0
- package/dist/semiotic-value.min.js +2 -0
- package/dist/semiotic-value.module.min.js +2 -0
- package/dist/semiotic.d.ts +7 -0
- package/dist/semiotic.min.js +1 -1
- package/dist/semiotic.module.min.js +1 -1
- package/dist/server.min.js +1 -1
- package/dist/server.module.min.js +1 -1
- package/dist/xy.min.js +1 -1
- package/dist/xy.module.min.js +1 -1
- package/package.json +18 -4
|
@@ -5,6 +5,7 @@ import type { HoverData } from "../../realtime/types";
|
|
|
5
5
|
import type { HoverHighlightMode, LinkedHoverProp, SelectionConfig } from "./types";
|
|
6
6
|
import type { OnObservationCallback } from "../../store/ObservationStore";
|
|
7
7
|
import type { AnimateProp } from "../../stream/pipelineTransitionUtils";
|
|
8
|
+
import type { AutoPlaceAnnotations } from "../../recipes/annotationLayout";
|
|
8
9
|
/**
|
|
9
10
|
* The frames accept `tooltipContent: (d: HoverData) => ReactNode`,
|
|
10
11
|
* which is a slightly wider parameter than the `TooltipContentFn`
|
|
@@ -48,6 +49,7 @@ export interface BaseMetadataProps {
|
|
|
48
49
|
* this to the frame. Bundling it here avoids a parallel helper
|
|
49
50
|
* + 22 separate adoption edits. */
|
|
50
51
|
axisExtent?: import("./axisExtent").AxisExtentMode;
|
|
52
|
+
autoPlaceAnnotations?: AutoPlaceAnnotations;
|
|
51
53
|
}
|
|
52
54
|
export declare function buildBaseMetadataProps(input: BaseMetadataProps): BaseMetadataProps;
|
|
53
55
|
/**
|
|
@@ -3,6 +3,7 @@ import type { PartialMargin } from "../../types/marginType";
|
|
|
3
3
|
import type { OnObservationCallback } from "../../store/ObservationStore";
|
|
4
4
|
import type { AnimateProp } from "../../stream/pipelineTransitionUtils";
|
|
5
5
|
import type { Datum } from "./datumTypes";
|
|
6
|
+
import type { AutoPlaceAnnotations } from "../../recipes/annotationLayout";
|
|
6
7
|
/**
|
|
7
8
|
* Selection consumption config — makes this chart react to a named selection
|
|
8
9
|
*/
|
|
@@ -25,8 +26,9 @@ export interface SelectionConfig {
|
|
|
25
26
|
export type LinkedHoverProp = boolean | string | {
|
|
26
27
|
name?: string;
|
|
27
28
|
fields?: string[];
|
|
28
|
-
mode?: "field" | "x-position";
|
|
29
|
+
mode?: "field" | "x-position" | "series";
|
|
29
30
|
xField?: string;
|
|
31
|
+
seriesField?: string;
|
|
30
32
|
};
|
|
31
33
|
/**
|
|
32
34
|
* Linked brush config
|
|
@@ -128,6 +130,8 @@ export interface BaseChartProps {
|
|
|
128
130
|
dataIdAccessor?: string | ((d: Datum) => string);
|
|
129
131
|
/** Visual emphasis level for dashboard hierarchy. "primary" spans two columns in ChartGrid. */
|
|
130
132
|
emphasis?: "primary" | "secondary";
|
|
133
|
+
/** Opt into annotation placement assistance. Preserves authored dx/dy by default. */
|
|
134
|
+
autoPlaceAnnotations?: AutoPlaceAnnotations;
|
|
131
135
|
/** Enable declarative bounded animation (enter/exit/update transitions + intro).
|
|
132
136
|
* `true` uses defaults (300ms ease-out, intro enabled). Object form allows customization.
|
|
133
137
|
* Set `{ intro: false }` to disable the animated intro on first render. */
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ChartCapability } from "../../ai/chartCapabilityTypes";
|
|
2
|
+
/**
|
|
3
|
+
* BigNumber capability descriptor.
|
|
4
|
+
*
|
|
5
|
+
* `fits()` accepts datasets that resolve to a single focal value:
|
|
6
|
+
* - exactly one row with a numeric field, or
|
|
7
|
+
* - any dataset where a `total` / `value` aggregation makes sense
|
|
8
|
+
* and the suggestion engine has already declared the scale `tiny`.
|
|
9
|
+
*
|
|
10
|
+
* At tiny scale BigNumber is the catalog's "honest" answer: when you
|
|
11
|
+
* have one number, a chart is the wrong abstraction — show the number.
|
|
12
|
+
*/
|
|
13
|
+
export declare const BigNumberCapability: ChartCapability;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BigNumber — the focal-value HOC behind `semiotic/value`.
|
|
3
|
+
*
|
|
4
|
+
* A plain React component (no Stream Frame underneath). This ships as a forward-looking React
|
|
5
|
+
* component that already honours the contracts a `SingleValueFrame`
|
|
6
|
+
* would inherit (format cascade, threshold zones via semantic theme
|
|
7
|
+
* roles, comparison anchoring, sentence-form ARIA, push API + staleness).
|
|
8
|
+
*/
|
|
9
|
+
import * as React from "react";
|
|
10
|
+
import type { BigNumberHandle, BigNumberProps } from "./types";
|
|
11
|
+
export declare const BigNumber: (props: BigNumberProps & {
|
|
12
|
+
ref?: React.ForwardedRef<BigNumberHandle>;
|
|
13
|
+
}) => React.ReactElement | null;
|
|
14
|
+
export default BigNumber;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Number-format cascade for BigNumber.
|
|
3
|
+
*
|
|
4
|
+
* Resolves a `BigNumberFormat` shortcut (or custom fn) against the
|
|
5
|
+
* card's locale + currency + precision props and returns a memoizable
|
|
6
|
+
* formatter. All built-ins use `Intl.NumberFormat` so locale + grouping
|
|
7
|
+
* behave correctly without bundling a separate number-format library.
|
|
8
|
+
*/
|
|
9
|
+
import type { BigNumberFormat } from "./types";
|
|
10
|
+
export interface FormatContext {
|
|
11
|
+
locale?: string;
|
|
12
|
+
currency?: string;
|
|
13
|
+
precision?: number;
|
|
14
|
+
notation?: Intl.NumberFormatOptions["notation"];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build a `(value) => string` formatter from a shortcut + context.
|
|
18
|
+
* Custom-function shortcuts are returned as-is.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildFormatter(format: BigNumberFormat | undefined, ctx?: FormatContext): (value: number) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Format a millisecond duration as a short human string:
|
|
23
|
+
* `2h 14m`, `45s`, `12ms`. Useful for latency-style KPIs.
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatDuration(ms: number): string;
|
|
26
|
+
/**
|
|
27
|
+
* Decorate a formatted number with prefix/suffix. Empty strings are
|
|
28
|
+
* skipped without padding.
|
|
29
|
+
*/
|
|
30
|
+
export declare function decorate(formatted: string, prefix: string | undefined, suffix: string | undefined): string;
|
|
31
|
+
/**
|
|
32
|
+
* Format a signed delta — always carry an explicit + on positive values
|
|
33
|
+
* so the sign-as-information stays legible. Zero renders as `"0"`
|
|
34
|
+
* unformatted-by-sign (no `+0`).
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatSignedDelta(delta: number, formatter: (value: number) => string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Format a percent change. `from` of 0 yields `null` (undefined ratio).
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatDeltaPercent(from: number, to: number, locale?: string, precision?: number): string | null;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threshold zone resolution + inline sparkline path builder for
|
|
3
|
+
* BigNumber. Lifted out so the component file stays focused on layout.
|
|
4
|
+
*/
|
|
5
|
+
import type { BigNumberLevel, BigNumberThreshold } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a numeric value against an ordered threshold list. Zones are
|
|
8
|
+
* tested by "highest `at` whose bound is ≤ value." `-Infinity` works
|
|
9
|
+
* as a "catch-all" lower zone.
|
|
10
|
+
*
|
|
11
|
+
* Returns `null` when no threshold fits (caller falls back to neutral).
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveThreshold(value: number, thresholds: ReadonlyArray<BigNumberThreshold> | undefined): BigNumberThreshold | null;
|
|
14
|
+
/**
|
|
15
|
+
* Map a level + explicit-color override to a CSS color string. The
|
|
16
|
+
* neutral level falls through to `--semiotic-text` so the value reads
|
|
17
|
+
* as the regular text colour when no thresholds fire.
|
|
18
|
+
*/
|
|
19
|
+
export declare function colorForLevel(level: BigNumberLevel, explicit?: string): string;
|
|
20
|
+
export interface SparklinePoint {
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build the SVG path string for a polyline sparkline. Maps values into
|
|
26
|
+
* a [0..width] × [0..height] box; auto-fits the y-domain by default.
|
|
27
|
+
*
|
|
28
|
+
* Empty / single-point input returns an empty string.
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildSparklinePath(values: ReadonlyArray<number>, opts: {
|
|
31
|
+
width: number;
|
|
32
|
+
height: number;
|
|
33
|
+
padding?: number;
|
|
34
|
+
yMin?: number;
|
|
35
|
+
yMax?: number;
|
|
36
|
+
}): {
|
|
37
|
+
line: string;
|
|
38
|
+
area: string;
|
|
39
|
+
points: SparklinePoint[];
|
|
40
|
+
};
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BigNumber and (forward-looking) SingleValueFrame types.
|
|
3
|
+
*
|
|
4
|
+
* BigNumber ships today as a plain React component under
|
|
5
|
+
* `semiotic/value`. The type vocabulary here is intentionally a bit
|
|
6
|
+
* broader than the v1 component uses — it sketches the contract a
|
|
7
|
+
* future `SingleValueFrame` would own,
|
|
8
|
+
* so adopters can write against types that survive the migration.
|
|
9
|
+
*/
|
|
10
|
+
import type * as React from "react";
|
|
11
|
+
import type { Datum } from "../shared/datumTypes";
|
|
12
|
+
/**
|
|
13
|
+
* Layout mode — chrome envelope around the focal value.
|
|
14
|
+
*
|
|
15
|
+
* - `tile` — dashboard cell. Label + value + comparison/target row + optional sparkline.
|
|
16
|
+
* - `presentation` — large centered value for a slide or hero card.
|
|
17
|
+
* - `inline` — value + optional delta indicator, no card chrome; flows in prose.
|
|
18
|
+
* - `thumbnail` — value only, no chrome, fixed-height. For embedding in dense grids.
|
|
19
|
+
*/
|
|
20
|
+
export type BigNumberMode = "tile" | "presentation" | "inline" | "thumbnail";
|
|
21
|
+
/**
|
|
22
|
+
* Status level mapped to a semantic CSS variable
|
|
23
|
+
* (`--semiotic-success`, `--semiotic-warning`, `--semiotic-danger`,
|
|
24
|
+
* `--semiotic-info`, falls through to `--semiotic-text` for `neutral`).
|
|
25
|
+
*/
|
|
26
|
+
export type BigNumberLevel = "success" | "warning" | "danger" | "info" | "neutral";
|
|
27
|
+
/**
|
|
28
|
+
* Whether a higher value is "better" semantically. Drives the
|
|
29
|
+
* sentiment of a delta — a `+5` delta is positive sentiment under
|
|
30
|
+
* "higher-is-better", negative under "lower-is-better", neutral when
|
|
31
|
+
* the direction isn't loaded.
|
|
32
|
+
*/
|
|
33
|
+
export type BigNumberDirection = "higher-is-better" | "lower-is-better" | "neutral";
|
|
34
|
+
/**
|
|
35
|
+
* Resolved sentiment for a delta or value-vs-target. Controls whether
|
|
36
|
+
* a delta renders in success-coloured or danger-coloured ink.
|
|
37
|
+
* `"auto"` lets the component infer from `direction` + the sign of the delta.
|
|
38
|
+
*/
|
|
39
|
+
export type BigNumberSentiment = "auto" | "positive" | "negative" | "neutral";
|
|
40
|
+
/**
|
|
41
|
+
* Number-format shortcut. `(value) => string` lets you plug in d3-format,
|
|
42
|
+
* Intl.NumberFormat, or any custom formatter.
|
|
43
|
+
*
|
|
44
|
+
* Built-in shortcuts read locale + currency + precision off the props:
|
|
45
|
+
*
|
|
46
|
+
* - `"number"` — Intl.NumberFormat with grouping.
|
|
47
|
+
* - `"currency"` — currency style; needs `currency` prop (default USD).
|
|
48
|
+
* - `"percent"` — multiplies × 100, suffixes "%".
|
|
49
|
+
* - `"compact"` — Intl compact notation: 1.2M, 3.4K.
|
|
50
|
+
* - `"duration"` — formats a millisecond duration as `1h 23m 4s`.
|
|
51
|
+
*/
|
|
52
|
+
export type BigNumberFormat = "number" | "currency" | "percent" | "compact" | "duration" | ((value: number) => string);
|
|
53
|
+
/**
|
|
54
|
+
* Threshold zone — a lower bound + status level. Zones must be sorted
|
|
55
|
+
* ascending by `at` and resolved by "highest `at` ≤ value".
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* thresholds={[
|
|
60
|
+
* { at: -Infinity, level: "danger" },
|
|
61
|
+
* { at: 50, level: "warning" },
|
|
62
|
+
* { at: 80, level: "success" },
|
|
63
|
+
* ]}
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export interface BigNumberThreshold {
|
|
67
|
+
/** Lower bound (inclusive) for this zone. `-Infinity` covers everything below. */
|
|
68
|
+
at: number;
|
|
69
|
+
/** Status level. Maps to a semantic CSS variable on the value text. */
|
|
70
|
+
level: BigNumberLevel;
|
|
71
|
+
/** Explicit colour override; otherwise `var(--semiotic-{level})`. */
|
|
72
|
+
color?: string;
|
|
73
|
+
/** Optional label surfaced in tooltips, the ARIA sentence, and capability output. */
|
|
74
|
+
label?: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Comparison value (vs. prior period, vs. last quarter, etc.). The
|
|
78
|
+
* delta is derived as `value - comparison.value` unless `delta` is set
|
|
79
|
+
* explicitly on the parent.
|
|
80
|
+
*/
|
|
81
|
+
export interface BigNumberComparison {
|
|
82
|
+
/** Prior-period value used to compute the delta. */
|
|
83
|
+
value: number;
|
|
84
|
+
/** Descriptor — e.g. `"vs last quarter"`. */
|
|
85
|
+
label?: string;
|
|
86
|
+
/** Inherit `format`/`locale`/`currency` if omitted. */
|
|
87
|
+
format?: BigNumberFormat;
|
|
88
|
+
/** Whether higher is better. Defaults to the top-level `direction`. */
|
|
89
|
+
direction?: BigNumberDirection;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Target / goal value. Renders as `… of {target.value}` with optional
|
|
93
|
+
* progress framing (the value's distance to target).
|
|
94
|
+
*/
|
|
95
|
+
export interface BigNumberTarget {
|
|
96
|
+
/** Goal value. */
|
|
97
|
+
value: number;
|
|
98
|
+
/** Descriptor — e.g. `"of Q3 target"`. */
|
|
99
|
+
label?: string;
|
|
100
|
+
/** Inherit `format`/`locale`/`currency` if omitted. */
|
|
101
|
+
format?: BigNumberFormat;
|
|
102
|
+
/** Whether higher is better. Defaults to the top-level `direction`. */
|
|
103
|
+
direction?: BigNumberDirection;
|
|
104
|
+
}
|
|
105
|
+
/** Imperative ref handle for streaming/push usage. */
|
|
106
|
+
export interface BigNumberHandle {
|
|
107
|
+
/** Append a new datapoint; updates the focal value + extends the trend. */
|
|
108
|
+
push(input: number | BigNumberPushInput): void;
|
|
109
|
+
/** Append many in one pass. */
|
|
110
|
+
pushMany(inputs: ReadonlyArray<number | BigNumberPushInput>): void;
|
|
111
|
+
/** Reset trend buffer and focal value. */
|
|
112
|
+
clear(): void;
|
|
113
|
+
/** Current focal value. Returns the most-recently-pushed value when the
|
|
114
|
+
* push API has been used; otherwise falls back to the `value` prop. Returns
|
|
115
|
+
* `null` only when no push has landed AND the prop value is not finite. */
|
|
116
|
+
getValue(): number | null;
|
|
117
|
+
/** Trend buffer snapshot (most-recent-last). */
|
|
118
|
+
getData(): ReadonlyArray<BigNumberPushInput>;
|
|
119
|
+
}
|
|
120
|
+
export interface BigNumberPushInput {
|
|
121
|
+
value: number;
|
|
122
|
+
time?: number | Date;
|
|
123
|
+
/** Override the comparison value at this tick. */
|
|
124
|
+
comparison?: number;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Render slots — drop-ins for any slot in the layout. ReactNode form
|
|
128
|
+
* is rendered as-is; the function form receives the resolved context
|
|
129
|
+
* so the slot can read formatted strings without re-deriving them.
|
|
130
|
+
*/
|
|
131
|
+
export interface BigNumberSlotContext {
|
|
132
|
+
value: number | null;
|
|
133
|
+
formattedValue: string;
|
|
134
|
+
level: BigNumberLevel;
|
|
135
|
+
/** Resolved colour for the focal value, ready to drop into a `color` /
|
|
136
|
+
* `stroke` / `fill` prop on an embedded Semiotic chart so its marks
|
|
137
|
+
* match the BigNumber's threshold level. Either a hex / rgb string
|
|
138
|
+
* or a `var(--semiotic-{level})` reference. */
|
|
139
|
+
color: string;
|
|
140
|
+
delta: number | null;
|
|
141
|
+
deltaFormatted: string | null;
|
|
142
|
+
/** Formatted percent change string (e.g. `"+20%"`), or null when undefined. */
|
|
143
|
+
deltaPercent: string | null;
|
|
144
|
+
sentiment: "positive" | "negative" | "neutral";
|
|
145
|
+
isStale: boolean;
|
|
146
|
+
/** Live push-API buffer (most-recent-last). Useful when a slot chart
|
|
147
|
+
* should redraw on every ingest — read from this in the function
|
|
148
|
+
* form so the chart re-renders alongside the focal value. */
|
|
149
|
+
pushBuffer: ReadonlyArray<BigNumberPushInput>;
|
|
150
|
+
}
|
|
151
|
+
export type BigNumberSlot = React.ReactNode | ((ctx: BigNumberSlotContext) => React.ReactNode);
|
|
152
|
+
/**
|
|
153
|
+
* The full prop surface. Intentionally broad — every block here maps
|
|
154
|
+
* to a documented `SingleValueFrame` capability so users targeting
|
|
155
|
+
* the v1 component can roll forward unchanged when (if) the frame ships.
|
|
156
|
+
*
|
|
157
|
+
* Does NOT extend `BaseChartProps` because most of those (axisExtent,
|
|
158
|
+
* pointIdAccessor, linkedHover, linkedBrush, hoverHighlight, ...) are
|
|
159
|
+
* irrelevant for a single value. The contract is documented per-prop.
|
|
160
|
+
*/
|
|
161
|
+
export interface BigNumberProps<_TDatum extends Datum = Datum> {
|
|
162
|
+
/** The number this card exists to display. `null` / `undefined` / `NaN`
|
|
163
|
+
* routes the card into its empty state (see `emptyContent`); this lets
|
|
164
|
+
* consumers pass `data?.revenue` style optional values without a
|
|
165
|
+
* conditional. */
|
|
166
|
+
value: number | null | undefined;
|
|
167
|
+
/** Top-line descriptor — e.g. `"Q3 Revenue"`. Rendered above the value. */
|
|
168
|
+
label?: string;
|
|
169
|
+
/** Secondary descriptor, smaller, below the label. */
|
|
170
|
+
caption?: string;
|
|
171
|
+
/** Format the focal value. Default `"number"`. */
|
|
172
|
+
format?: BigNumberFormat;
|
|
173
|
+
/** BCP-47 locale tag for built-in formats. Default `"en-US"`. */
|
|
174
|
+
locale?: string;
|
|
175
|
+
/** ISO 4217 code; required for `format: "currency"`. Default `"USD"`. */
|
|
176
|
+
currency?: string;
|
|
177
|
+
/** `Intl.NumberFormat` `maximumFractionDigits`. Default 0 for compact, 2 for currency, 0 elsewhere. */
|
|
178
|
+
precision?: number;
|
|
179
|
+
/** Prepend to the formatted value. */
|
|
180
|
+
prefix?: string;
|
|
181
|
+
/** Append to the formatted value. */
|
|
182
|
+
suffix?: string;
|
|
183
|
+
/** Unit label rendered after the value as small text — e.g. `"USD"`, `"req/s"`. */
|
|
184
|
+
unit?: string;
|
|
185
|
+
/** Comparison value (vs prior period). Drives delta if `delta` is not explicit. */
|
|
186
|
+
comparison?: BigNumberComparison;
|
|
187
|
+
/** Goal value; renders alongside the comparison row. */
|
|
188
|
+
target?: BigNumberTarget;
|
|
189
|
+
/** Explicit delta override; bypasses comparison.value subtraction. */
|
|
190
|
+
delta?: number;
|
|
191
|
+
/** Format the delta; defaults to `format` (inherits currency/locale). */
|
|
192
|
+
deltaFormat?: BigNumberFormat;
|
|
193
|
+
/** Also render the percent change next to the absolute delta. Default true when a comparison is present. */
|
|
194
|
+
showDeltaPercent?: boolean;
|
|
195
|
+
/** Default direction for sentiment inference. Per-comparison/target wins. */
|
|
196
|
+
direction?: BigNumberDirection;
|
|
197
|
+
/** Force sentiment classification. `"auto"` infers from `direction` + sign. Default `"auto"`. */
|
|
198
|
+
sentiment?: BigNumberSentiment;
|
|
199
|
+
/** Threshold zones — ordered ascending by `at`. Defines the level
|
|
200
|
+
* applied to the value text via a semantic CSS variable. */
|
|
201
|
+
thresholds?: ReadonlyArray<BigNumberThreshold>;
|
|
202
|
+
/** Cap the push buffer surfaced via `getData()` / `slotCtx.pushBuffer`. Default 60. */
|
|
203
|
+
windowSize?: number;
|
|
204
|
+
/** Layout mode. Default `"tile"`. */
|
|
205
|
+
mode?: BigNumberMode;
|
|
206
|
+
/** Horizontal alignment within the card. Default `"start"` for tile,
|
|
207
|
+
* `"center"` for presentation / thumbnail, `"inherit"` for inline. */
|
|
208
|
+
align?: "start" | "center" | "end";
|
|
209
|
+
/** Reserve width. Default 280 (tile), 540 (presentation), unset (inline/thumbnail). */
|
|
210
|
+
width?: number | string;
|
|
211
|
+
/** Reserve height. Default 184 (tile), 320 (presentation), unset (inline/thumbnail). */
|
|
212
|
+
height?: number | string;
|
|
213
|
+
/** Inner padding; number or `{top, right, bottom, left}`. */
|
|
214
|
+
padding?: number | {
|
|
215
|
+
top?: number;
|
|
216
|
+
right?: number;
|
|
217
|
+
bottom?: number;
|
|
218
|
+
left?: number;
|
|
219
|
+
};
|
|
220
|
+
/** Visual emphasis hint — dashboards can use this to span columns. */
|
|
221
|
+
emphasis?: "primary" | "secondary";
|
|
222
|
+
/** Override the value text colour. CSS variables work. */
|
|
223
|
+
color?: string;
|
|
224
|
+
/** Card background. CSS variables work; transparent by default in inline/thumbnail. */
|
|
225
|
+
background?: string;
|
|
226
|
+
/** Border colour. Defaults to `--semiotic-border`. */
|
|
227
|
+
borderColor?: string;
|
|
228
|
+
/** Border radius (px or any CSS length). Defaults to theme `--semiotic-border-radius`. */
|
|
229
|
+
borderRadius?: number | string;
|
|
230
|
+
/** Optional class for the outer container. */
|
|
231
|
+
className?: string;
|
|
232
|
+
/** Optional inline style — composed with the layout defaults. */
|
|
233
|
+
style?: React.CSSProperties;
|
|
234
|
+
/** Tween between value changes. `true` = 300ms ease-out + intro. */
|
|
235
|
+
animate?: boolean | {
|
|
236
|
+
duration?: number;
|
|
237
|
+
easing?: "linear" | "ease-out";
|
|
238
|
+
intro?: boolean;
|
|
239
|
+
};
|
|
240
|
+
/** Mark the card stale (dimmed) when no push occurs for this many ms. */
|
|
241
|
+
stalenessThreshold?: number;
|
|
242
|
+
/** Custom stale label appended to the ARIA sentence. Default `"stale"`. */
|
|
243
|
+
staleLabel?: string;
|
|
244
|
+
/** Replace the entire header (label + caption) slot. */
|
|
245
|
+
headerSlot?: BigNumberSlot;
|
|
246
|
+
/** Replace the focal value slot. */
|
|
247
|
+
valueSlot?: BigNumberSlot;
|
|
248
|
+
/** Replace the delta / comparison / target row. */
|
|
249
|
+
deltaSlot?: BigNumberSlot;
|
|
250
|
+
/** **Wide / rectangular** chart embedded beneath the value — e.g. a
|
|
251
|
+
* `LineChart` / `AreaChart` in `mode="sparkline"`. The card stays
|
|
252
|
+
* full-width and stacks the chart at full card width under the delta
|
|
253
|
+
* row. */
|
|
254
|
+
trendSlot?: BigNumberSlot;
|
|
255
|
+
/** **Square** chart embedded beside the value — e.g. a `DonutChart` /
|
|
256
|
+
* `PieChart` / `Scatterplot` / `Treemap`. When set, the card splits
|
|
257
|
+
* into a left column (header + value + delta) and a right column
|
|
258
|
+
* (the square chart). Compose with `trendSlot` to get both
|
|
259
|
+
* (square chart on the right, wide trend along the bottom). */
|
|
260
|
+
chartSlot?: BigNumberSlot;
|
|
261
|
+
/** Reserved pixel size (square) for `chartSlot`. Defaults are
|
|
262
|
+
* mode-keyed for sparkline scale — 44 px for `tile`, 80 px for
|
|
263
|
+
* `presentation` — so the embedded chart reads as a corner
|
|
264
|
+
* decoration. Pass a larger value for a hero-style anchor. */
|
|
265
|
+
chartSize?: number;
|
|
266
|
+
/** Free-form footer below the trend. */
|
|
267
|
+
footerSlot?: BigNumberSlot;
|
|
268
|
+
/** Card click. */
|
|
269
|
+
onClick?: (datum: {
|
|
270
|
+
value: number;
|
|
271
|
+
level: BigNumberLevel;
|
|
272
|
+
delta: number | null;
|
|
273
|
+
}, event: {
|
|
274
|
+
x: number;
|
|
275
|
+
y: number;
|
|
276
|
+
}) => void;
|
|
277
|
+
/** Generic observation hook — fires on click today; future SingleValueFrame work
|
|
278
|
+
* may extend this to value-update / hover events. */
|
|
279
|
+
onObservation?: import("../../store/ObservationStore").OnObservationCallback;
|
|
280
|
+
/** Identifier surfaced on every observation event. */
|
|
281
|
+
chartId?: string;
|
|
282
|
+
/** Override the auto-generated aria-label sentence. */
|
|
283
|
+
description?: string;
|
|
284
|
+
/** Sr-only supplement appended below the auto sentence. */
|
|
285
|
+
summary?: string;
|
|
286
|
+
/** Loading skeleton overlay. */
|
|
287
|
+
loading?: boolean;
|
|
288
|
+
/** Replace the default skeleton; `false` suppresses it entirely. */
|
|
289
|
+
loadingContent?: React.ReactNode | false;
|
|
290
|
+
/** Empty-state placeholder rendered when `value` is `null`/`undefined`/`NaN`. */
|
|
291
|
+
emptyContent?: React.ReactNode | false;
|
|
292
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named lifecycle bands. Shared by the annotation freshness surface
|
|
3
|
+
* today and available to other temporal-lifecycle policies that opt
|
|
4
|
+
* into banded classification.
|
|
5
|
+
*/
|
|
6
|
+
export type LifecycleBand = "fresh" | "aging" | "stale" | "expired";
|
|
7
|
+
/**
|
|
8
|
+
* Multipliers of `ttlMs` that mark the upper edge of each band. The
|
|
9
|
+
* default schedule:
|
|
10
|
+
*
|
|
11
|
+
* • `fresh` — `age < 1.0 × ttl`
|
|
12
|
+
* • `aging` — `age < 1.5 × ttl`
|
|
13
|
+
* • `stale` — `age < 3.0 × ttl`
|
|
14
|
+
* • `expired` — `age ≥ 3.0 × ttl`
|
|
15
|
+
*
|
|
16
|
+
* Override individual thresholds; missing entries fall back to the
|
|
17
|
+
* defaults. Setting a smaller value than the previous band's
|
|
18
|
+
* threshold is allowed but produces an unreachable band.
|
|
19
|
+
*/
|
|
20
|
+
export interface LifecycleBandThresholds {
|
|
21
|
+
/** Upper edge of the `fresh` band, as a multiple of `ttlMs`. Default `1.0`. */
|
|
22
|
+
fresh?: number;
|
|
23
|
+
/** Upper edge of the `aging` band, as a multiple of `ttlMs`. Default `1.5`. */
|
|
24
|
+
aging?: number;
|
|
25
|
+
/** Upper edge of the `stale` band, as a multiple of `ttlMs`. Default `3.0`. */
|
|
26
|
+
stale?: number;
|
|
27
|
+
}
|
|
28
|
+
export declare const DEFAULT_LIFECYCLE_THRESHOLDS: Required<LifecycleBandThresholds>;
|
|
29
|
+
/**
|
|
30
|
+
* Classify an age into a named band given a TTL.
|
|
31
|
+
*
|
|
32
|
+
* Pure function. Edge cases:
|
|
33
|
+
*
|
|
34
|
+
* - **Negative age** (future-dated items): classifies as `fresh`.
|
|
35
|
+
* - **`NaN` age** (parse failure or `now - undefined`): classifies as
|
|
36
|
+
* `fresh` — the safer default, since `expired` is filtered by the
|
|
37
|
+
* visual treatment.
|
|
38
|
+
* - **`+Infinity` age**: classifies as `expired`. Monotonic in age —
|
|
39
|
+
* "older than any finite TTL multiple" should be the oldest band.
|
|
40
|
+
* - **Non-finite / non-positive TTL**: classifies as `fresh`, since
|
|
41
|
+
* there's no meaningful interval to age against. Callers that need
|
|
42
|
+
* stricter handling should gate `ttlMs` before calling.
|
|
43
|
+
*/
|
|
44
|
+
export declare function bandFromAge(ageMs: number, ttlMs: number, thresholds?: LifecycleBandThresholds): LifecycleBand;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type { ScaleBand, ScaleLinear } from "d3-scale";
|
|
3
3
|
import type { Datum } from "../charts/shared/datumTypes";
|
|
4
|
+
import type { AutoPlaceAnnotations } from "../recipes/annotationLayout";
|
|
4
5
|
export type ArrowOfTime = "up" | "down" | "left" | "right";
|
|
5
6
|
export type WindowMode = "sliding" | "growing";
|
|
6
7
|
export type ThresholdType = "greater" | "lesser";
|
|
@@ -11,15 +12,28 @@ export interface LineStyle {
|
|
|
11
12
|
opacity?: number;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* - `"
|
|
20
|
-
*
|
|
15
|
+
* How an annotation's anchor is resolved across renders. Shared between
|
|
16
|
+
* the streaming runtime (which implements the resolution) and the
|
|
17
|
+
* `semiotic/ai` annotation lifecycle surface (which exposes the choice
|
|
18
|
+
* to authors via `lifecycle.anchor`).
|
|
19
|
+
*
|
|
20
|
+
* - `"fixed"` (default): anchored to specific datum coordinates;
|
|
21
|
+
* disappears when out of view.
|
|
22
|
+
* - `"latest"`: annotation re-pins to the most recent datum each frame.
|
|
23
|
+
* - `"sticky"`: annotation stays at its last known pixel position
|
|
24
|
+
* after the target datum scrolls off; uses `stickyPositionCache`
|
|
25
|
+
* on `AnnotationContext`.
|
|
26
|
+
* - `"semantic"`: re-resolves via `provenance.stableId` when new data
|
|
27
|
+
* arrives, falling back to the recorded coordinate if the anchor
|
|
28
|
+
* can no longer be located.
|
|
21
29
|
*/
|
|
22
|
-
export type
|
|
30
|
+
export type AnnotationAnchor = "fixed" | "latest" | "sticky" | "semantic";
|
|
31
|
+
/**
|
|
32
|
+
* @deprecated Use {@link AnnotationAnchor}. Kept as a back-compat alias
|
|
33
|
+
* because earlier 3.x releases shipped this name from the streaming
|
|
34
|
+
* surface; the `Mode` suffix added nothing semantically.
|
|
35
|
+
*/
|
|
36
|
+
export type AnnotationAnchorMode = AnnotationAnchor;
|
|
23
37
|
export interface AnnotationContext {
|
|
24
38
|
scales?: {
|
|
25
39
|
x?: ScaleLinear<number, number>;
|
|
@@ -154,6 +168,7 @@ export interface RealtimeFrameProps {
|
|
|
154
168
|
className?: string;
|
|
155
169
|
lineStyle?: LineStyle;
|
|
156
170
|
annotations?: Datum[];
|
|
171
|
+
autoPlaceAnnotations?: AutoPlaceAnnotations;
|
|
157
172
|
svgAnnotationRules?: (annotation: Datum, index: number, context: AnnotationContext) => ReactNode;
|
|
158
173
|
hoverAnnotation?: boolean | HoverAnnotationConfig;
|
|
159
174
|
tooltipContent?: (d: HoverData) => ReactNode;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Datum } from "../charts/shared/datumTypes";
|
|
2
|
+
/**
|
|
3
|
+
* M3 — Amount & density management (Rahman et al.'s sixth consideration:
|
|
4
|
+
* "balance explanatory support against clutter").
|
|
5
|
+
*
|
|
6
|
+
* A pure, geometry-light pass that decides *which* note-like annotations should
|
|
7
|
+
* stay on screen when there are more than the plot area can carry without
|
|
8
|
+
* clutter. It does not move anything (that is M2's `annotationLayout`); it
|
|
9
|
+
* partitions notes into a persistent set and a deferred set by importance and
|
|
10
|
+
* freshness, with the lowest-priority notes shed first.
|
|
11
|
+
*
|
|
12
|
+
* Priority signals, reusing what M0/M1 already attach:
|
|
13
|
+
* • `emphasis` (M1) — `"primary"` is the floor (never shed); `"secondary"`
|
|
14
|
+
* ranks below an un-emphasised note.
|
|
15
|
+
* • `provenance.confidence` (M0) — a small nudge so a higher-confidence note
|
|
16
|
+
* outranks a lower-confidence one at the same emphasis.
|
|
17
|
+
* • `lifecycle.freshness` (M0) — `fresh > aging > stale`; `expired` is shed
|
|
18
|
+
* first.
|
|
19
|
+
*
|
|
20
|
+
* Only note types compete for the budget; reference lines, bands, enclosures
|
|
21
|
+
* and statistical overlays pass through untouched (they are not "clutter notes"
|
|
22
|
+
* in the paper's sense and a density cap shedding a threshold line would be
|
|
23
|
+
* surprising).
|
|
24
|
+
*
|
|
25
|
+
* The persistent set is the floor and is never empty when any note exists — the
|
|
26
|
+
* paper's "keep the core message persistent; hover is not guaranteed."
|
|
27
|
+
*/
|
|
28
|
+
/** Plot area (px²) allotted per note before the budget tightens. */
|
|
29
|
+
export declare const DEFAULT_AREA_PER_ANNOTATION = 20000;
|
|
30
|
+
export interface AnnotationDensityConfig {
|
|
31
|
+
/**
|
|
32
|
+
* Hard cap on simultaneously-persistent notes. When set, overrides the
|
|
33
|
+
* `width`×`height`-derived budget.
|
|
34
|
+
*/
|
|
35
|
+
maxAnnotations?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Plot area (px²) allotted per note when deriving the budget from the chart
|
|
38
|
+
* dimensions. Larger ⇒ fewer notes. Default {@link DEFAULT_AREA_PER_ANNOTATION}.
|
|
39
|
+
*/
|
|
40
|
+
areaPerAnnotation?: number;
|
|
41
|
+
/** Minimum notes kept regardless of budget. Default 1. */
|
|
42
|
+
minVisible?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface AnnotationDensityOptions extends AnnotationDensityConfig {
|
|
45
|
+
annotations: ReadonlyArray<Datum>;
|
|
46
|
+
/** Plot width in px (used to derive the budget when `maxAnnotations` is unset). */
|
|
47
|
+
width: number;
|
|
48
|
+
/** Plot height in px. */
|
|
49
|
+
height: number;
|
|
50
|
+
}
|
|
51
|
+
export interface AnnotationDensityResult {
|
|
52
|
+
/** Notes kept on screen plus every non-note annotation, in author order. */
|
|
53
|
+
visible: Datum[];
|
|
54
|
+
/** Notes shed by the budget, in author order. Empty when nothing is shed. */
|
|
55
|
+
deferred: Datum[];
|
|
56
|
+
/** The note budget that produced this partition. */
|
|
57
|
+
budget: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Derive the note budget for a plot. Exported so the clutter diagnostic
|
|
61
|
+
* (`diagnoseConfig`) and the runtime pass agree on the same threshold.
|
|
62
|
+
*/
|
|
63
|
+
export declare function annotationBudget(width: number, height: number, config?: AnnotationDensityConfig): number;
|
|
64
|
+
/**
|
|
65
|
+
* Partition annotations into a persistent (visible) set and a deferred set
|
|
66
|
+
* given a note budget. Pure and deterministic; preserves author order within
|
|
67
|
+
* each returned array.
|
|
68
|
+
*/
|
|
69
|
+
export declare function annotationDensity(options: AnnotationDensityOptions): AnnotationDensityResult;
|