Skip to content

Commit f0e31d9

Browse files
committed
Add BigNumber value chart and docs
Introduce a new value-family chart (BigNumber) and the `semiotic/value` entrypoint. Adds the BigNumber component, tests, capability metadata, AI schema, examples, and docs, plus bundle-size updates and component registry changes so BigNumber is indexed under a new "value" category (push-capable but not renderable via the MCP SSR path). Highlights: - New value chart API: BigNumber with push API (ref.current.push / pushMany / clear / getValue / getData), two slot positions (trendSlot, chartSlot), thresholds/targets/comparisons, staleness, formatting helpers and ARIA semantics. - AI surface updates: ai/schema.json, ai/capabilities.json and ai/componentMetadata.cjs (and compiled mcp-server) register BigNumber and the new category. - Documentation and examples: README, docs, examples and capability docs updated to list `semiotic/value`, usage examples, and aggregate counts. Added files include BigNumber component, tests, capability entry, example docs and a new docs page; miscellaneous scripts and metadata updated to reflect the new entrypoint and bundle sizes.
1 parent 9eaca64 commit f0e31d9

40 files changed

Lines changed: 4371 additions & 200 deletions

.clinerules

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
- Install: `npm install semiotic`
55
<!-- semiotic-bundle-sizes:start -->
66
<!-- Auto-generated by scripts/sync-bundle-sizes.mjs — do not edit by hand. -->
7-
- **Use sub-path imports** — `semiotic/xy` (86KB gz), `semiotic/ordinal` (70KB gz), `semiotic/network` (64KB gz), `semiotic/geo` (52KB gz), `semiotic/realtime` (91KB gz), `semiotic/server` (122KB gz), `semiotic/utils` (22KB gz), `semiotic/recipes` (5KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/ai` (215KB gz). Full `semiotic` is 190KB gz.
7+
- **Use sub-path imports** — `semiotic/xy` (86KB gz), `semiotic/ordinal` (70KB gz), `semiotic/network` (64KB gz), `semiotic/geo` (52KB gz), `semiotic/realtime` (91KB gz), `semiotic/server` (122KB gz), `semiotic/utils` (22KB gz), `semiotic/recipes` (5KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/value` (7KB gz), `semiotic/ai` (218KB gz). Full `semiotic` is 191KB gz.
88
<!-- semiotic-bundle-sizes:end -->
99
- CLI: `npx semiotic-ai [--schema|--compact|--examples|--doctor]` · MCP: `npx semiotic-mcp`
1010

@@ -76,6 +76,26 @@ Import from `semiotic/geo` only — avoids d3-geo in non-geo bundles.
7676

7777
All geo: `fitPadding`, `zoomable`, `zoomExtent`, `onZoom`, `dragRotate`, `graticule`, `tileURL`, `tileAttribution`. Helpers: `resolveReferenceGeography("world-110m"|"world-50m")`, `mergeData(features, data, {featureKey, dataKey})`.
7878

79+
## Value Charts (`semiotic/value`)
80+
81+
Single-focal-value displays — when one number is the answer, a chart is the wrong abstraction. Plain React (no Stream Frame); SSR-clean; ~7KB gz. **Ships no chart-family dependency** — embed your own Semiotic chart via two slots picked by aspect ratio.
82+
83+
**BigNumber** — `value` (required), `label`, `caption`, `format` ("number"|"currency"|"percent"|"compact"|"duration"|fn), `locale`, `currency`, `precision`, `prefix`/`suffix`/`unit`, `comparison` ({value, label?, format?, direction?}), `target` ({value, label?, format?, direction?}), `delta` (explicit override), `deltaFormat`, `showDeltaPercent` (true), `direction` ("higher-is-better" default | "lower-is-better" | "neutral"), `sentiment` ("auto" default | "positive" | "negative" | "neutral"), `thresholds` ([{at, level: "success"|"warning"|"danger"|"info"|"neutral", color?, label?}] — resolved by highest `at` ≤ value, painted via `--semiotic-{level}`), `windowSize` (60 — caps push buffer surfaced via `getData()` / `slotCtx.pushBuffer`), `mode` ("tile" default | "presentation" | "inline" | "thumbnail"), `align`, `padding`, `emphasis`, `color`/`background`/`borderColor`/`borderRadius`, `animate` (boolean | {duration?, easing?, intro?} — tweens between value changes), `stalenessThreshold` (ms; dims after no-push interval), `staleLabel`, slot overrides (`headerSlot`/`valueSlot`/`deltaSlot`/`footerSlot`/`trendSlot`/`chartSlot` — ReactNode or `(ctx) => ReactNode`), `chartSize` (px reserved for `chartSlot`; defaults to inner card height).
84+
85+
**Two chart slot positions, picked by chart aspect:**
86+
- **`trendSlot`** — wide / rectangular charts beneath the value (LineChart, AreaChart, DifferenceChart in `mode="sparkline"`). Renders at full card width.
87+
- **`chartSlot`** — square charts beside the value (DonutChart, PieChart, Scatterplot, Treemap, CirclePack). Splits the card horizontally: text-on-left, chart-on-right.
88+
- Pair both: square chart anchors top-right, wide trend stretches across the bottom.
89+
- Slot context `(ctx) => ReactNode` exposes `{ value, formattedValue, level, color, delta, deltaFormatted, deltaPercent, sentiment, isStale, pushBuffer }` — embedded charts read `ctx.color` to theme-link to the resolved threshold.
90+
91+
Push API via `forwardRef`: `ref.current.push(value | {value, time?, comparison?})`, `pushMany`, `clear`, `getValue()`, `getData()`. Stable across renders (refs back the imperative handle).
92+
93+
ARIA: auto sentence-form label combining `{label}: {formatted} {unit}, {up|down} {delta} ({percent}) from {comparison.label}, {target%} of {target.label}[, stale]`. Override via `description`; supplement via `summary` (sr-only).
94+
95+
Semantic classes: `semiotic-bignumber` root + `--mode-{...}` / `--level-{...}` / `--sentiment-{...}` / `--stale` modifiers; `__text-region`, `__value`, `__delta`, `__delta-row--{up|down|flat}`, `__arrow--{up|down|flat}`, `__trend` (wide slot wrapper), `__chart` (square slot wrapper), etc.
96+
97+
Helpers exported: `buildFormatter`, `formatSignedDelta`, `formatDeltaPercent`, `formatDuration`, `resolveThreshold`, `colorForLevel`, `buildSparklinePath` (for custom-slot rendering).
98+
7999
## Realtime Charts (`semiotic/realtime`)
80100

81101
Push API: `ref.current.push({time, value})`. All pushed data must include a time field.

.cursorrules

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
- Install: `npm install semiotic`
55
<!-- semiotic-bundle-sizes:start -->
66
<!-- Auto-generated by scripts/sync-bundle-sizes.mjs — do not edit by hand. -->
7-
- **Use sub-path imports** — `semiotic/xy` (86KB gz), `semiotic/ordinal` (70KB gz), `semiotic/network` (64KB gz), `semiotic/geo` (52KB gz), `semiotic/realtime` (91KB gz), `semiotic/server` (122KB gz), `semiotic/utils` (22KB gz), `semiotic/recipes` (5KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/ai` (215KB gz). Full `semiotic` is 190KB gz.
7+
- **Use sub-path imports** — `semiotic/xy` (86KB gz), `semiotic/ordinal` (70KB gz), `semiotic/network` (64KB gz), `semiotic/geo` (52KB gz), `semiotic/realtime` (91KB gz), `semiotic/server` (122KB gz), `semiotic/utils` (22KB gz), `semiotic/recipes` (5KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/value` (7KB gz), `semiotic/ai` (218KB gz). Full `semiotic` is 191KB gz.
88
<!-- semiotic-bundle-sizes:end -->
99
- CLI: `npx semiotic-ai [--schema|--compact|--examples|--doctor]` · MCP: `npx semiotic-mcp`
1010

@@ -76,6 +76,26 @@ Import from `semiotic/geo` only — avoids d3-geo in non-geo bundles.
7676

7777
All geo: `fitPadding`, `zoomable`, `zoomExtent`, `onZoom`, `dragRotate`, `graticule`, `tileURL`, `tileAttribution`. Helpers: `resolveReferenceGeography("world-110m"|"world-50m")`, `mergeData(features, data, {featureKey, dataKey})`.
7878

79+
## Value Charts (`semiotic/value`)
80+
81+
Single-focal-value displays — when one number is the answer, a chart is the wrong abstraction. Plain React (no Stream Frame); SSR-clean; ~7KB gz. **Ships no chart-family dependency** — embed your own Semiotic chart via two slots picked by aspect ratio.
82+
83+
**BigNumber** — `value` (required), `label`, `caption`, `format` ("number"|"currency"|"percent"|"compact"|"duration"|fn), `locale`, `currency`, `precision`, `prefix`/`suffix`/`unit`, `comparison` ({value, label?, format?, direction?}), `target` ({value, label?, format?, direction?}), `delta` (explicit override), `deltaFormat`, `showDeltaPercent` (true), `direction` ("higher-is-better" default | "lower-is-better" | "neutral"), `sentiment` ("auto" default | "positive" | "negative" | "neutral"), `thresholds` ([{at, level: "success"|"warning"|"danger"|"info"|"neutral", color?, label?}] — resolved by highest `at` ≤ value, painted via `--semiotic-{level}`), `windowSize` (60 — caps push buffer surfaced via `getData()` / `slotCtx.pushBuffer`), `mode` ("tile" default | "presentation" | "inline" | "thumbnail"), `align`, `padding`, `emphasis`, `color`/`background`/`borderColor`/`borderRadius`, `animate` (boolean | {duration?, easing?, intro?} — tweens between value changes), `stalenessThreshold` (ms; dims after no-push interval), `staleLabel`, slot overrides (`headerSlot`/`valueSlot`/`deltaSlot`/`footerSlot`/`trendSlot`/`chartSlot` — ReactNode or `(ctx) => ReactNode`), `chartSize` (px reserved for `chartSlot`; defaults to inner card height).
84+
85+
**Two chart slot positions, picked by chart aspect:**
86+
- **`trendSlot`** — wide / rectangular charts beneath the value (LineChart, AreaChart, DifferenceChart in `mode="sparkline"`). Renders at full card width.
87+
- **`chartSlot`** — square charts beside the value (DonutChart, PieChart, Scatterplot, Treemap, CirclePack). Splits the card horizontally: text-on-left, chart-on-right.
88+
- Pair both: square chart anchors top-right, wide trend stretches across the bottom.
89+
- Slot context `(ctx) => ReactNode` exposes `{ value, formattedValue, level, color, delta, deltaFormatted, deltaPercent, sentiment, isStale, pushBuffer }` — embedded charts read `ctx.color` to theme-link to the resolved threshold.
90+
91+
Push API via `forwardRef`: `ref.current.push(value | {value, time?, comparison?})`, `pushMany`, `clear`, `getValue()`, `getData()`. Stable across renders (refs back the imperative handle).
92+
93+
ARIA: auto sentence-form label combining `{label}: {formatted} {unit}, {up|down} {delta} ({percent}) from {comparison.label}, {target%} of {target.label}[, stale]`. Override via `description`; supplement via `summary` (sr-only).
94+
95+
Semantic classes: `semiotic-bignumber` root + `--mode-{...}` / `--level-{...}` / `--sentiment-{...}` / `--stale` modifiers; `__text-region`, `__value`, `__delta`, `__delta-row--{up|down|flat}`, `__arrow--{up|down|flat}`, `__trend` (wide slot wrapper), `__chart` (square slot wrapper), etc.
96+
97+
Helpers exported: `buildFormatter`, `formatSignedDelta`, `formatDeltaPercent`, `formatDuration`, `resolveThreshold`, `colorForLevel`, `buildSparklinePath` (for custom-slot rendering).
98+
7999
## Realtime Charts (`semiotic/realtime`)
80100

81101
Push API: `ref.current.push({time, value})`. All pushed data must include a time field.

.github/copilot-instructions.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
- Install: `npm install semiotic`
55
<!-- semiotic-bundle-sizes:start -->
66
<!-- Auto-generated by scripts/sync-bundle-sizes.mjs — do not edit by hand. -->
7-
- **Use sub-path imports**`semiotic/xy` (86KB gz), `semiotic/ordinal` (70KB gz), `semiotic/network` (64KB gz), `semiotic/geo` (52KB gz), `semiotic/realtime` (91KB gz), `semiotic/server` (122KB gz), `semiotic/utils` (22KB gz), `semiotic/recipes` (5KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/ai` (215KB gz). Full `semiotic` is 190KB gz.
7+
- **Use sub-path imports**`semiotic/xy` (86KB gz), `semiotic/ordinal` (70KB gz), `semiotic/network` (64KB gz), `semiotic/geo` (52KB gz), `semiotic/realtime` (91KB gz), `semiotic/server` (122KB gz), `semiotic/utils` (22KB gz), `semiotic/recipes` (5KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/value` (7KB gz), `semiotic/ai` (218KB gz). Full `semiotic` is 191KB gz.
88
<!-- semiotic-bundle-sizes:end -->
99
- CLI: `npx semiotic-ai [--schema|--compact|--examples|--doctor]` · MCP: `npx semiotic-mcp`
1010

@@ -76,6 +76,26 @@ Import from `semiotic/geo` only — avoids d3-geo in non-geo bundles.
7676

7777
All geo: `fitPadding`, `zoomable`, `zoomExtent`, `onZoom`, `dragRotate`, `graticule`, `tileURL`, `tileAttribution`. Helpers: `resolveReferenceGeography("world-110m"|"world-50m")`, `mergeData(features, data, {featureKey, dataKey})`.
7878

79+
## Value Charts (`semiotic/value`)
80+
81+
Single-focal-value displays — when one number is the answer, a chart is the wrong abstraction. Plain React (no Stream Frame); SSR-clean; ~7KB gz. **Ships no chart-family dependency** — embed your own Semiotic chart via two slots picked by aspect ratio.
82+
83+
**BigNumber** — `value` (required), `label`, `caption`, `format` ("number"|"currency"|"percent"|"compact"|"duration"|fn), `locale`, `currency`, `precision`, `prefix`/`suffix`/`unit`, `comparison` ({value, label?, format?, direction?}), `target` ({value, label?, format?, direction?}), `delta` (explicit override), `deltaFormat`, `showDeltaPercent` (true), `direction` ("higher-is-better" default | "lower-is-better" | "neutral"), `sentiment` ("auto" default | "positive" | "negative" | "neutral"), `thresholds` ([{at, level: "success"|"warning"|"danger"|"info"|"neutral", color?, label?}] — resolved by highest `at` ≤ value, painted via `--semiotic-{level}`), `windowSize` (60 — caps push buffer surfaced via `getData()` / `slotCtx.pushBuffer`), `mode` ("tile" default | "presentation" | "inline" | "thumbnail"), `align`, `padding`, `emphasis`, `color`/`background`/`borderColor`/`borderRadius`, `animate` (boolean | {duration?, easing?, intro?} — tweens between value changes), `stalenessThreshold` (ms; dims after no-push interval), `staleLabel`, slot overrides (`headerSlot`/`valueSlot`/`deltaSlot`/`footerSlot`/`trendSlot`/`chartSlot` — ReactNode or `(ctx) => ReactNode`), `chartSize` (px reserved for `chartSlot`; defaults to inner card height).
84+
85+
**Two chart slot positions, picked by chart aspect:**
86+
- **`trendSlot`** — wide / rectangular charts beneath the value (LineChart, AreaChart, DifferenceChart in `mode="sparkline"`). Renders at full card width.
87+
- **`chartSlot`** — square charts beside the value (DonutChart, PieChart, Scatterplot, Treemap, CirclePack). Splits the card horizontally: text-on-left, chart-on-right.
88+
- Pair both: square chart anchors top-right, wide trend stretches across the bottom.
89+
- Slot context `(ctx) => ReactNode` exposes `{ value, formattedValue, level, color, delta, deltaFormatted, deltaPercent, sentiment, isStale, pushBuffer }` — embedded charts read `ctx.color` to theme-link to the resolved threshold.
90+
91+
Push API via `forwardRef`: `ref.current.push(value | {value, time?, comparison?})`, `pushMany`, `clear`, `getValue()`, `getData()`. Stable across renders (refs back the imperative handle).
92+
93+
ARIA: auto sentence-form label combining `{label}: {formatted} {unit}, {up|down} {delta} ({percent}) from {comparison.label}, {target%} of {target.label}[, stale]`. Override via `description`; supplement via `summary` (sr-only).
94+
95+
Semantic classes: `semiotic-bignumber` root + `--mode-{...}` / `--level-{...}` / `--sentiment-{...}` / `--stale` modifiers; `__text-region`, `__value`, `__delta`, `__delta-row--{up|down|flat}`, `__arrow--{up|down|flat}`, `__trend` (wide slot wrapper), `__chart` (square slot wrapper), etc.
96+
97+
Helpers exported: `buildFormatter`, `formatSignedDelta`, `formatDeltaPercent`, `formatDuration`, `resolveThreshold`, `colorForLevel`, `buildSparklinePath` (for custom-slot rendering).
98+
7999
## Realtime Charts (`semiotic/realtime`)
80100

81101
Push API: `ref.current.push({time, value})`. All pushed data must include a time field.

.windsurfrules

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
- Install: `npm install semiotic`
55
<!-- semiotic-bundle-sizes:start -->
66
<!-- Auto-generated by scripts/sync-bundle-sizes.mjs — do not edit by hand. -->
7-
- **Use sub-path imports** — `semiotic/xy` (86KB gz), `semiotic/ordinal` (70KB gz), `semiotic/network` (64KB gz), `semiotic/geo` (52KB gz), `semiotic/realtime` (91KB gz), `semiotic/server` (122KB gz), `semiotic/utils` (22KB gz), `semiotic/recipes` (5KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/ai` (215KB gz). Full `semiotic` is 190KB gz.
7+
- **Use sub-path imports** — `semiotic/xy` (86KB gz), `semiotic/ordinal` (70KB gz), `semiotic/network` (64KB gz), `semiotic/geo` (52KB gz), `semiotic/realtime` (91KB gz), `semiotic/server` (122KB gz), `semiotic/utils` (22KB gz), `semiotic/recipes` (5KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/value` (7KB gz), `semiotic/ai` (218KB gz). Full `semiotic` is 191KB gz.
88
<!-- semiotic-bundle-sizes:end -->
99
- CLI: `npx semiotic-ai [--schema|--compact|--examples|--doctor]` · MCP: `npx semiotic-mcp`
1010

@@ -76,6 +76,26 @@ Import from `semiotic/geo` only — avoids d3-geo in non-geo bundles.
7676

7777
All geo: `fitPadding`, `zoomable`, `zoomExtent`, `onZoom`, `dragRotate`, `graticule`, `tileURL`, `tileAttribution`. Helpers: `resolveReferenceGeography("world-110m"|"world-50m")`, `mergeData(features, data, {featureKey, dataKey})`.
7878

79+
## Value Charts (`semiotic/value`)
80+
81+
Single-focal-value displays — when one number is the answer, a chart is the wrong abstraction. Plain React (no Stream Frame); SSR-clean; ~7KB gz. **Ships no chart-family dependency** — embed your own Semiotic chart via two slots picked by aspect ratio.
82+
83+
**BigNumber** — `value` (required), `label`, `caption`, `format` ("number"|"currency"|"percent"|"compact"|"duration"|fn), `locale`, `currency`, `precision`, `prefix`/`suffix`/`unit`, `comparison` ({value, label?, format?, direction?}), `target` ({value, label?, format?, direction?}), `delta` (explicit override), `deltaFormat`, `showDeltaPercent` (true), `direction` ("higher-is-better" default | "lower-is-better" | "neutral"), `sentiment` ("auto" default | "positive" | "negative" | "neutral"), `thresholds` ([{at, level: "success"|"warning"|"danger"|"info"|"neutral", color?, label?}] — resolved by highest `at` ≤ value, painted via `--semiotic-{level}`), `windowSize` (60 — caps push buffer surfaced via `getData()` / `slotCtx.pushBuffer`), `mode` ("tile" default | "presentation" | "inline" | "thumbnail"), `align`, `padding`, `emphasis`, `color`/`background`/`borderColor`/`borderRadius`, `animate` (boolean | {duration?, easing?, intro?} — tweens between value changes), `stalenessThreshold` (ms; dims after no-push interval), `staleLabel`, slot overrides (`headerSlot`/`valueSlot`/`deltaSlot`/`footerSlot`/`trendSlot`/`chartSlot` — ReactNode or `(ctx) => ReactNode`), `chartSize` (px reserved for `chartSlot`; defaults to inner card height).
84+
85+
**Two chart slot positions, picked by chart aspect:**
86+
- **`trendSlot`** — wide / rectangular charts beneath the value (LineChart, AreaChart, DifferenceChart in `mode="sparkline"`). Renders at full card width.
87+
- **`chartSlot`** — square charts beside the value (DonutChart, PieChart, Scatterplot, Treemap, CirclePack). Splits the card horizontally: text-on-left, chart-on-right.
88+
- Pair both: square chart anchors top-right, wide trend stretches across the bottom.
89+
- Slot context `(ctx) => ReactNode` exposes `{ value, formattedValue, level, color, delta, deltaFormatted, deltaPercent, sentiment, isStale, pushBuffer }` — embedded charts read `ctx.color` to theme-link to the resolved threshold.
90+
91+
Push API via `forwardRef`: `ref.current.push(value | {value, time?, comparison?})`, `pushMany`, `clear`, `getValue()`, `getData()`. Stable across renders (refs back the imperative handle).
92+
93+
ARIA: auto sentence-form label combining `{label}: {formatted} {unit}, {up|down} {delta} ({percent}) from {comparison.label}, {target%} of {target.label}[, stale]`. Override via `description`; supplement via `summary` (sr-only).
94+
95+
Semantic classes: `semiotic-bignumber` root + `--mode-{...}` / `--level-{...}` / `--sentiment-{...}` / `--stale` modifiers; `__text-region`, `__value`, `__delta`, `__delta-row--{up|down|flat}`, `__arrow--{up|down|flat}`, `__trend` (wide slot wrapper), `__chart` (square slot wrapper), etc.
96+
97+
Helpers exported: `buildFormatter`, `formatSignedDelta`, `formatDeltaPercent`, `formatDuration`, `resolveThreshold`, `colorForLevel`, `buildSparklinePath` (for custom-slot rendering).
98+
7999
## Realtime Charts (`semiotic/realtime`)
80100

81101
Push API: `ref.current.push({time, value})`. All pushed data must include a time field.

0 commit comments

Comments
 (0)