@flood-md/react 0.2.11 → 0.2.13

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/README.md CHANGED
@@ -6,11 +6,22 @@ HTML semantics and refs, no third-party component library or Tailwind dependency
6
6
  Named imports support tree shaking in optimizing ES-module bundlers. Import the
7
7
  shared stylesheet explicitly; styles are not split by component.
8
8
 
9
+ Sheet is a bottom-aligned Drawer for short tasks, navigation and touch-friendly
10
+ choices. It fits short content, caps long content to the viewport, and keeps
11
+ Drawer dismissal, focus restoration, body scrolling and the optional footer.
12
+
9
13
  SegmentedControl options can display a `count` alongside the label, for example
10
14
  `{value: "pending", label: "Pending", count: 2}`. Use this for a small, mutually
11
15
  exclusive choice that updates one collection. The count is read with the visible
12
16
  label and does not change the submitted value.
13
17
 
18
+ Version 0.2.12 adds opt-in DataTable column visibility. Set
19
+ `showColumnVisibility` for the Columns menu, and supply `hiddenColumnIds` and
20
+ `onHiddenColumnIdsChange` when the host saves preferences. The active sort and
21
+ record-opening columns stay visible. See [DataTable](../../docs/components/data-table.md).
22
+ Pass the Columns control from `toolbar={({ columns }) => …}` into
23
+ `CollectionToolbar.actions` to keep it alongside search and filters.
24
+
14
25
  The 0.2.11 candidate adds optional DataTable row `primaryAction` for opening an
15
26
  in-place detail panel, plus `toolbar` and `inset="roomy"` for a shared table edge.
16
27
  The title is a native button and the rest of the row also responds to pointer
@@ -46,7 +57,7 @@ the interactive size. It defaults to size; shrinking a supporting glyph must
46
57
  not shrink its target or bypass IconSlot with a custom SVG width. Existing glyph
47
58
  roles at a 16px root are 2xs=14px, xs/sm=16px and md/lg=20px.
48
59
 
49
- This package documents the **0.2.11** source API. Keep Flood package versions aligned and follow the guide matching
60
+ This package documents the **0.2.13** source API. Keep Flood package versions aligned and follow the guide matching
50
61
  your installed declarations; source changes do not modify an existing npm release.
51
62
 
52
63
  NavigationItem (0.2.11 candidate) is the shared small row for destinations,
@@ -431,6 +442,10 @@ edge-to-edge content when the host already provides safe padding. The default
431
442
  padding can wrap text and change content height. Native
432
443
  fallback scrollbars retain their platform behavior.
433
444
 
445
+ AppShell content mode uses the same ScrollArea. For a workspace whose layout
446
+ already provides clearance, `scrollContentInset="none"` keeps the content
447
+ width stable when rails appear. The default protects edge-to-edge content.
448
+
434
449
  ```tsx
435
450
  <ScrollArea aria-label="Activity" style={{ maxHeight: "12rem" }}>
436
451
  <Stack gap="4">{/* Long activity content */}</Stack>
@@ -604,8 +619,9 @@ Available in 0.2.3. Import Flood CSS and use FloodRoot for dark foundations.
604
619
 
605
620
  Disclosure corner geometry: Accordion headers have square internal seams. Only
606
621
  the first header has upper shell corners, and only a closed last header has lower
607
- shell corners. An open Collapsible header has square lower corners where its
608
- panel begins. Hover backgrounds follow that same shape without clipping focus.
622
+ shell corners. A standalone Collapsible has an inset, rounded trigger and a
623
+ separate gap before the revealed content. The trigger label and panel share
624
+ an inline edge.
609
625
 
610
626
 
611
627
  ## Tooltip, Popover and Dialog
@@ -804,7 +820,12 @@ assertive uses role=alert. Choose urgency deliberately for dynamically inserted
804
820
  content. Announcements depend on actual assistive technology; initial static
805
821
  markup is not guaranteed to be read aloud. No focus movement, auto-dismiss,
806
822
  timeout or built-in close/action button is supplied. Compose named host actions
807
- inside children when needed. Alert is separate from Dialog and future Toast.
823
+ inside children when needed. A titleless Alert centers its glyph alongside a
824
+ single Inline row. Subtle and ghost actions inherit the feedback tint on
825
+ interactive states. Use a floating ToastRegion for brief operation results.
826
+ ToastRegion defaults to `placement="bottom-end"`. Choose `bottom-start`,
827
+ `top-end` or `top-start` for a different logical corner, or `inline` to
828
+ embed it in a layout. New floating cards enter from their placement edge.
808
829
 
809
830
  See the [WAI Meter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/meter/),
810
831
  [Alert pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alert/) and
@@ -953,6 +974,9 @@ visually while retaining their full text/title. A hidden counter frees its slot.
953
974
  The host owns accepted changes, captured IDs, confirmation and focus after the
954
975
  bar disappears. Positioning is host-owned: use a stable bounded width for a
955
976
  floating rail, plus viewport safe-area spacing and measured scroll clearance.
977
+ For table selection, place the rail at the viewport's bottom center. Set
978
+ `showSelection={false}` on DataTable to keep its count available to assistive
979
+ technology while BulkActionBar displays the visible count.
956
980
 
957
981
  OverflowActions also accepts leading/trailing slots and maxVisibleActions. Slot
958
982
  width is reserved before measuring commands; use action owners in those slots
@@ -963,6 +987,9 @@ under one named action panel. After hydration it uses one Tab entry, directional
963
987
  arrows, Home/End and optional looping. Disabled/hidden actions are skipped. Arrows
964
988
  move focus, not activation. Horizontal order follows writing direction. In vertical
965
989
  toolbars open Menu with Enter/Space; horizontal menus retain Up/Down opening.
990
+ A vertical pill centers its actions on a single axis. Use same-size icon controls
991
+ with accessible names for a compact rail. Use a rounded toolbar for a vertical
992
+ group of labeled actions.
966
993
  Keep text inputs and independent selection widgets outside this action-only API.
967
994
  Native child handlers and refs remain attached; Toolbar owns their tabIndex while
968
995
  mounted and restores original attributes on cleanup. Without JavaScript, native
@@ -1109,6 +1136,7 @@ relative path, without reading their contents. Single mode replaces its selectio
1109
1136
 
1110
1137
  AlertDialog (0.2.5) is a concise confirmation, composed from Flood's
1111
1138
  native modal layer and Button. Supply title, description, trigger and onConfirm.
1139
+ Line breaks in the description separate distinct thoughts while allowing each line to wrap.
1112
1140
  Cancel receives initial focus; Escape cancels; outside clicks do not dismiss.
1113
1141
  Tab containment, background inertness, scroll lock and return focus reuse Dialog.
1114
1142
  Translate confirmLabel/cancelLabel. onConfirm runs before requesting close, while
@@ -1145,7 +1173,8 @@ The CSS build assembles the original component styles into the shared stylesheet
1145
1173
 
1146
1174
 
1147
1175
  Section headingLevel controls native h2–h6 semantics. Its independent headingSize
1148
- uses the existing Heading roles (section/page/large/display), defaulting to section.
1176
+ uses the Heading roles (group/section/page/large/display), defaulting to section.
1177
+ Choose group for a compact section inside a Drawer or another constrained panel.
1149
1178
  Keep document hierarchy meaningful when changing visual emphasis.
1150
1179
 
1151
1180
  ## Editable and TagInput · 0.2.7
@@ -1192,8 +1221,11 @@ when a query changes; ready rows must match pageSize/totalRows. Selection defaul
1192
1221
  to the supplied page in server mode and the full collection in client mode.
1193
1222
  Server selectionScope="dataset" requires controlled selectedIds/onSelectionChange;
1194
1223
  the host validates IDs outside the page. Checkboxes only select the current page.
1195
- This API does not fetch, cancel requests, select an entire remote query, virtualize
1196
- or manage column visibility/resizing/pinning.
1224
+ The host owns request execution and cancellation, remote query selection and
1225
+ virtualization. DataTable supports optional column visibility, width preferences,
1226
+ logical edge pinning and expandable record details. Use Sparkline for a compact
1227
+ trend cell. See [DataTable](../../docs/components/data-table.md) and
1228
+ [Sparkline](../../docs/components/sparkline.md).
1197
1229
 
1198
1230
  DatePicker and DateRangePicker pass viewLabels to their calendars. Calendar panels
1199
1231
  use minimal Popover chrome, with Escape/selection/trigger dismissal; there is no
package/dist/app-shell.js CHANGED
@@ -5,7 +5,7 @@ const useBrowserLayoutEffect = typeof window === "undefined" ? useEffect : useLa
5
5
  export const ApplicationTopBar = /* @__PURE__ */ forwardRef(function ApplicationTopBar({ start, end, bordered, className, ...props }, ref) {
6
6
  return _jsxs("header", { ...props, ref: ref, className: ["flood-app-top-bar", className].filter(Boolean).join(" "), "data-bordered": bordered || undefined, children: [start != null && _jsx(Inline, { align: "center", gap: "2", className: "flood-app-top-bar__start", children: start }), end != null && _jsx(Inline, { align: "center", gap: "2", className: "flood-app-top-bar__end", children: end })] });
7
7
  });
8
- export const ApplicationShell = /* @__PURE__ */ forwardRef(function ApplicationShell({ navigation, navigationSide, navigationDrawer, topBar, footer, scroll, mainId, mainAs: Main = "main", mainLabel, mainRef, scrollLabel, scrollOrientation = "both", skipLabel, children, className, ...props }, ref) {
8
+ export const ApplicationShell = /* @__PURE__ */ forwardRef(function ApplicationShell({ navigation, navigationSide, navigationDrawer, topBar, footer, scroll, mainId, mainAs: Main = "main", mainLabel, mainRef, scrollLabel, scrollOrientation = "both", scrollContentInset = "scrollbar", skipLabel, children, className, ...props }, ref) {
9
9
  const generatedId = useId();
10
10
  const contentId = mainId ?? `flood-app-${generatedId}`;
11
11
  const root = useRef(null);
@@ -61,6 +61,6 @@ export const ApplicationShell = /* @__PURE__ */ forwardRef(function ApplicationS
61
61
  ? topBar(navigationTrigger)
62
62
  : _jsxs(_Fragment, { children: [navigationTrigger && _jsx(AppTopBar, { start: navigationTrigger }), topBar] });
63
63
  return _jsxs("div", { ...props, ref: root, className: ["flood-app-shell", className].filter(Boolean).join(" "), "data-scroll": scroll, children: [_jsx(SkipLink, { href: `#${contentId}`, children: skipLabel }), navigationSide === "start" && navigationSlot, _jsxs("div", { className: "flood-app-shell__workspace", children: [chrome, _jsx(Main, { ref: mainRef, id: contentId, "aria-label": mainLabel, tabIndex: -1, className: "flood-app-shell__main", children: scroll === "content"
64
- ? _jsx(ScrollArea, { orientation: scrollOrientation, "aria-label": scrollLabel, className: "flood-app-shell__scroll", children: children })
64
+ ? _jsx(ScrollArea, { orientation: scrollOrientation, contentInset: scrollContentInset, "aria-label": scrollLabel, className: "flood-app-shell__scroll", children: children })
65
65
  : children }), footer] }), navigationSide === "end" && navigationSlot] });
66
66
  });
@@ -0,0 +1,2 @@
1
+ import { type BoxPlotProps } from "./index.js";
2
+ export declare const DistributionBoxes: import("react").ForwardRefExoticComponent<BoxPlotProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,148 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
3
+ import { Surface, Text, VisuallyHidden } from "./index.js";
4
+ import { placeOverlay } from "./overlay-runtime.js";
5
+ const number = new Intl.NumberFormat("en", { maximumSignificantDigits: 21 });
6
+ const useChartLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
7
+ const stats = ["low", "q1", "median", "q3", "high"];
8
+ const defaults = {
9
+ low: "Lower whisker", q1: "Q1", median: "Median", q3: "Q3", high: "Upper whisker", outliers: "Outliers",
10
+ };
11
+ const tooltipRows = [[2], [1, 3], [0, 4], [5]];
12
+ export const DistributionBoxes = /* @__PURE__ */ forwardRef(function DistributionBoxes({ label, items, domain, formatValue = number.format, formatAxisValue = formatValue, statisticLabels, emptyLabel = "No observations", missingLabel = "No data", navigationLabel = "Use the arrow keys to explore groups, or Home and End to jump.", className, ...props }, ref) {
13
+ const instructions = useId();
14
+ const plot = useRef(null);
15
+ const tooltip = useRef(null);
16
+ const [cursor, setCursor] = useState(0);
17
+ const [hover, setHover] = useState();
18
+ const [touch, setTouch] = useState();
19
+ const [focused, setFocused] = useState(false);
20
+ const ids = new Set();
21
+ let min = Infinity;
22
+ let max = -Infinity;
23
+ for (const { id, label: name, summary, outliers = [] } of items) {
24
+ if (!id.trim() || ids.has(id) || !name.trim())
25
+ throw new Error("Flood BoxPlot needs unique IDs and nonempty labels");
26
+ ids.add(id);
27
+ if (!summary) {
28
+ if (outliers.length)
29
+ throw new RangeError("Flood BoxPlot outliers require a summary");
30
+ continue;
31
+ }
32
+ const values = stats.map(key => summary[key]);
33
+ if (values.some((value, i) => !Number.isFinite(value) || (i > 0 && value < values[i - 1]))) {
34
+ throw new RangeError("Flood BoxPlot statistics must be finite and ordered from low to high");
35
+ }
36
+ min = Math.min(min, summary.low);
37
+ max = Math.max(max, summary.high);
38
+ for (const value of outliers) {
39
+ if (!Number.isFinite(value) || (value >= summary.low && value <= summary.high)) {
40
+ throw new RangeError("Flood BoxPlot outliers must be finite and outside the whiskers");
41
+ }
42
+ min = Math.min(min, value);
43
+ max = Math.max(max, value);
44
+ }
45
+ }
46
+ if (domain && (!Number.isFinite(domain[0]) || !Number.isFinite(domain[1]) ||
47
+ domain[0] >= domain[1] || domain[0] > min || domain[1] < max)) {
48
+ throw new RangeError("Flood BoxPlot domain must have finite increasing bounds containing every observation");
49
+ }
50
+ const hasData = min <= max;
51
+ const [floor, ceiling] = domain ?? [min, max];
52
+ const span = ceiling - floor;
53
+ const position = (value) => {
54
+ if (span === 0)
55
+ return 50;
56
+ return 100 * (Number.isFinite(span) ? (value - floor) / span : (value / 2 - floor / 2) / (ceiling / 2 - floor / 2));
57
+ };
58
+ const last = items.length - 1;
59
+ const active = Math.min(hover ?? touch ?? cursor, last);
60
+ const item = items[active];
61
+ const summary = item?.summary;
62
+ const inspecting = hover !== undefined || touch !== undefined || focused;
63
+ const readouts = summary ? stats.map(key => ({
64
+ label: statisticLabels?.[key] ?? defaults[key], value: formatValue(summary[key]),
65
+ })) : [];
66
+ if (item?.outliers?.length) {
67
+ readouts.push({ label: statisticLabels?.outliers ?? defaults.outliers, value: number.format(item.outliers.length) });
68
+ }
69
+ const valueText = [item?.label, ...(summary ? readouts.map(entry => `${entry.label}: ${entry.value}`) : [missingLabel])].join(", ");
70
+ useChartLayoutEffect(() => {
71
+ const panel = tooltip.current;
72
+ const frame = plot.current;
73
+ if (!panel || !frame)
74
+ return;
75
+ const mark = frame.querySelector("[data-active] .flood-box-plot__median, [data-active] .flood-box-plot__missing");
76
+ if (!mark)
77
+ return;
78
+ const positionTooltip = () => {
79
+ const bounds = frame.getBoundingClientRect();
80
+ if (!bounds.width || !frame.offsetWidth)
81
+ return;
82
+ const marker = mark.getBoundingClientRect();
83
+ const scale = bounds.width / frame.offsetWidth;
84
+ const gap = parseFloat(getComputedStyle(panel).columnGap) * scale;
85
+ const size = panel.getBoundingClientRect();
86
+ const x = (marker.left + marker.right) / 2;
87
+ const y = (marker.top + marker.bottom) / 2;
88
+ const anchor = { left: x, right: x, top: y, bottom: y, width: 0, height: 0 };
89
+ const horizontalRoom = size.width + 2 * gap;
90
+ const side = bounds.right - x >= horizontalRoom ? "right"
91
+ : x - bounds.left >= horizontalRoom ? "left"
92
+ : y - bounds.top < bounds.bottom - y ? "bottom" : "top";
93
+ const { left, top } = placeOverlay(anchor, size, bounds, side, "center", gap);
94
+ panel.style.left = `${(left - bounds.left) / scale}px`;
95
+ panel.style.top = `${(top - bounds.top) / scale}px`;
96
+ panel.dataset.positioned = "";
97
+ };
98
+ positionTooltip();
99
+ if (typeof ResizeObserver === "undefined")
100
+ return;
101
+ const observer = new ResizeObserver(positionTooltip);
102
+ observer.observe(frame);
103
+ observer.observe(panel);
104
+ return () => observer.disconnect();
105
+ }, [active, inspecting, item, formatValue, floor, ceiling]);
106
+ const navigate = (event) => {
107
+ let next;
108
+ switch (event.key) {
109
+ case "ArrowRight":
110
+ case "ArrowUp":
111
+ next = active + 1;
112
+ break;
113
+ case "ArrowLeft":
114
+ case "ArrowDown":
115
+ next = active - 1;
116
+ break;
117
+ case "Home":
118
+ next = 0;
119
+ break;
120
+ case "End":
121
+ next = last;
122
+ break;
123
+ case "Escape":
124
+ if (inspecting)
125
+ event.preventDefault();
126
+ setHover(undefined);
127
+ setTouch(undefined);
128
+ setFocused(false);
129
+ return;
130
+ default: return;
131
+ }
132
+ event.preventDefault();
133
+ setHover(undefined);
134
+ setTouch(undefined);
135
+ setFocused(true);
136
+ setCursor(Math.max(0, Math.min(last, next)));
137
+ };
138
+ return _jsx("div", { ...props, ref: ref, className: ["flood-box-plot", className].filter(Boolean).join(" "), role: "group", "aria-label": label, children: hasData ? _jsxs(_Fragment, { children: [last > 0 && _jsx(VisuallyHidden, { id: instructions, children: navigationLabel }), _jsxs("div", { ref: plot, className: "flood-box-plot__plot", dir: "ltr", role: last > 0 ? "slider" : "img", tabIndex: last > 0 ? 0 : undefined, "aria-label": last > 0 ? label : `${label}. ${valueText}`, "aria-describedby": last > 0 ? instructions : undefined, "aria-valuemin": last > 0 ? 1 : undefined, "aria-valuemax": last > 0 ? items.length : undefined, "aria-valuenow": last > 0 ? active + 1 : undefined, "aria-valuetext": last > 0 ? valueText : undefined, onFocus: event => setFocused(event.currentTarget.matches(":focus-visible")), onBlur: () => setFocused(false), onKeyDown: navigate, onPointerLeave: () => setHover(undefined), children: [_jsx("div", { className: "flood-box-plot__rows", "aria-hidden": "true", children: items.map(({ id, label: name, summary: values, outliers }, index) => _jsxs("div", { className: "flood-box-plot__row", "data-active": inspecting && index === active || undefined, onPointerEnter: event => { if (event.pointerType !== "touch")
139
+ setHover(index); }, onPointerUp: event => { if (event.pointerType === "touch")
140
+ setTouch(previous => previous === index ? undefined : index); }, children: [_jsx(Text, { className: "flood-box-plot__category", size: "helper", tone: "subtle", dir: "auto", title: name, children: name }), _jsxs("div", { className: "flood-box-plot__track", children: [values && _jsxs(_Fragment, { children: [_jsx("span", { className: "flood-box-plot__whisker", "data-side": "start", style: { left: `${position(values.low)}%`, right: `${100 - position(values.q1)}%` } }), _jsx("span", { className: "flood-box-plot__whisker", "data-side": "end", style: { left: `${position(values.q3)}%`, right: `${100 - position(values.high)}%` } }), _jsx("span", { className: "flood-box-plot__box", style: { left: `${position(values.q1)}%`, right: `${100 - position(values.q3)}%` } }), _jsx("span", { className: "flood-box-plot__median", style: { left: `${position(values.median)}%` } }), outliers?.map((value, i) => _jsx("span", { className: "flood-box-plot__outlier", style: { left: `${position(value)}%` } }, i))] }), !values && _jsx("span", { className: "flood-box-plot__missing" })] })] }, id)) }), _jsxs("div", { className: "flood-box-plot__axis", "aria-hidden": "true", children: [_jsx(Text, { size: "helper", tone: "subtle", children: formatAxisValue(floor) }), floor !== ceiling && _jsxs(_Fragment, { children: [_jsx(Text, { size: "helper", tone: "subtle", children: formatAxisValue(floor / 2 + ceiling / 2) }), _jsx(Text, { size: "helper", tone: "subtle", children: formatAxisValue(ceiling) })] })] }), inspecting && item && _jsxs(Surface, { ref: tooltip, className: "flood-chart__tooltip flood-box-plot__tooltip", "aria-hidden": "true", padding: "2", elevation: "raised", children: [_jsx(Text, { size: "helper", dir: "auto", children: item.label }), summary ? tooltipRows.map(([start, end]) => {
141
+ const first = readouts[start];
142
+ if (!first)
143
+ return null;
144
+ const last = end === undefined ? undefined : readouts[end];
145
+ return _jsxs("div", { className: "flood-box-plot__reading", children: [_jsx(Text, { size: "helper", tone: "subtle", dir: "auto", children: start === 0 ? statisticLabels?.whiskers ?? "Whiskers" :
146
+ last ? `${first.label}–${last.label}` : first.label }), _jsx(Text, { size: "helper", tone: start === 2 ? "default" : "subtle", children: last ? _jsxs(_Fragment, { children: [_jsxs("span", { children: [first.value, "\u2013"] }), _jsx("wbr", {}), _jsx("span", { children: last.value })] }) : first.value })] }, start);
147
+ }) : _jsx(Text, { size: "helper", tone: "subtle", children: missingLabel })] })] })] }) : _jsx(Text, { className: "flood-box-plot__empty", size: "compact", tone: "subtle", children: emptyLabel }) });
148
+ });
@@ -0,0 +1,2 @@
1
+ import { type BulletChartProps } from "./index.js";
2
+ export declare const BulletPlot: import("react").ForwardRefExoticComponent<BulletChartProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { Inline, Meter, Stack, Text } from "./index.js";
4
+ const defaultNumber = new Intl.NumberFormat("en", { maximumSignificantDigits: 21 });
5
+ export const BulletPlot = /* @__PURE__ */ forwardRef(function BulletPlot({ label, items, max, formatValue = defaultNumber.format, valueLabel = "Actual", targetLabel = "Target", emptyLabel = "No data", className, ...props }, ref) {
6
+ const ids = new Set();
7
+ let largest = 0;
8
+ for (const { id, label: itemLabel, value, target } of items) {
9
+ if (!id.trim() || ids.has(id) || !itemLabel.trim()) {
10
+ throw new Error("Flood BulletChart needs unique IDs and nonempty row labels");
11
+ }
12
+ if (!Number.isFinite(value) || value < 0 || !Number.isFinite(target) || target < 0) {
13
+ throw new RangeError("Flood BulletChart actual and target values must be finite and nonnegative");
14
+ }
15
+ ids.add(id);
16
+ largest = Math.max(largest, value, target);
17
+ }
18
+ const limit = max ?? (largest || 1);
19
+ if (!Number.isFinite(limit) || limit <= 0 || limit < largest) {
20
+ throw new RangeError("Flood BulletChart max must be finite, positive and at least the largest actual or target");
21
+ }
22
+ return _jsx("div", { ...props, ref: ref, className: ["flood-bullet-chart", className].filter(Boolean).join(" "), role: "group", "aria-label": label, children: items.length ? _jsx("ul", { className: "flood-bullet-chart__items", role: "list", children: items.map(item => {
23
+ const actual = formatValue(item.value);
24
+ const target = formatValue(item.target);
25
+ return _jsx("li", { children: _jsxs(Stack, { gap: "2", children: [_jsxs(Inline, { gap: "2", align: "baseline", className: "flood-bullet-chart__caption", "aria-hidden": "true", children: [_jsx(Text, { size: "compact", children: item.label }), _jsxs(Inline, { gap: "2", align: "baseline", className: "flood-bullet-chart__numbers", children: [_jsx(Text, { size: "compact", className: "flood-bullet-chart__actual", children: actual }), _jsxs(Text, { size: "helper", tone: "subtle", children: [targetLabel, " ", target] })] })] }), _jsxs("div", { className: "flood-bullet-chart__plot", "data-zero": item.value === 0 || undefined, children: [_jsx(Meter, { label: item.label, value: item.value, max: limit, tone: "accent", hideLabel: true, valueText: `${valueLabel}: ${actual}, ${targetLabel}: ${target}` }), _jsx("span", { "aria-hidden": "true", className: "flood-bullet-chart__target", style: { "--flood-bullet-target": `${item.target / limit * 100}%` } })] })] }) }, item.id);
26
+ }) }) : _jsx(Text, { size: "compact", tone: "subtle", children: emptyLabel }) });
27
+ });
@@ -0,0 +1,6 @@
1
+ import { type BarChartProps, type BarListProps, type DonutChartProps, type HeatmapProps, type LineChartProps } from "./index.js";
2
+ export declare const SeriesPlot: import("react").ForwardRefExoticComponent<LineChartProps & Required<Pick<LineChartProps, "curve" | "emptyLabel" | "missingLabel" | "navigationLabel" | "variant">> & import("react").RefAttributes<HTMLDivElement>>;
3
+ export declare const GroupedBars: import("react").ForwardRefExoticComponent<BarChartProps & Required<Pick<BarChartProps, "emptyLabel" | "missingLabel" | "navigationLabel">> & import("react").RefAttributes<HTMLDivElement>>;
4
+ export declare const ShareRing: import("react").ForwardRefExoticComponent<DonutChartProps & Required<Pick<DonutChartProps, "emptyLabel" | "navigationLabel" | "totalLabel">> & import("react").RefAttributes<HTMLDivElement>>;
5
+ export declare const HeatmapGrid: import("react").ForwardRefExoticComponent<HeatmapProps & Required<Pick<HeatmapProps, "emptyLabel" | "missingLabel">> & import("react").RefAttributes<HTMLDivElement>>;
6
+ export declare const RankedBars: import("react").ForwardRefExoticComponent<BarListProps & import("react").RefAttributes<HTMLDivElement>>;