@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.
@@ -0,0 +1,2 @@
1
+ import { type HistogramProps } from "./index.js";
2
+ export declare const HistogramPlot: import("react").ForwardRefExoticComponent<HistogramProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,78 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useId, useState } from "react";
3
+ import { Inline, Surface, Text, VisuallyHidden } from "./index.js";
4
+ const defaultBoundary = new Intl.NumberFormat("en", { maximumSignificantDigits: 12 });
5
+ const defaultCount = new Intl.NumberFormat("en", { maximumFractionDigits: 0 });
6
+ export const HistogramPlot = /* @__PURE__ */ forwardRef(function HistogramPlot({ label, xLabel, showXAxisLabel = true, start, binWidth, counts, maxCount, countLabel = "Count", formatBoundary = defaultBoundary.format, formatCount = defaultCount.format, emptyLabel = "No observations", navigationLabel = "Use arrow keys to explore intervals, or Home and End to jump.", className, ...props }, ref) {
7
+ const instructions = useId();
8
+ const [cursor, setCursor] = useState(0);
9
+ const [hovered, setHovered] = useState();
10
+ const [tapped, setTapped] = useState();
11
+ const [focused, setFocused] = useState(false);
12
+ if (!Number.isFinite(start) || !Number.isFinite(binWidth) || binWidth <= 0) {
13
+ throw new RangeError("Flood Histogram requires a finite start and positive finite bin width");
14
+ }
15
+ let largest = 0;
16
+ let previous = start;
17
+ const bins = counts.map((count, i) => {
18
+ const end = start + (i + 1) * binWidth;
19
+ if (!Number.isSafeInteger(count) || count < 0 || !Number.isFinite(end) || end <= previous) {
20
+ throw new RangeError("Flood Histogram requires nonnegative integer counts and increasing finite boundaries");
21
+ }
22
+ const bin = { start: previous, end, count };
23
+ previous = end;
24
+ largest = Math.max(largest, count);
25
+ return bin;
26
+ });
27
+ const limit = maxCount ?? (largest || 1);
28
+ if (!Number.isFinite(limit) || limit <= 0 || limit < largest) {
29
+ throw new RangeError("Flood Histogram maxCount must be finite, positive and at least the largest count");
30
+ }
31
+ const last = bins.length - 1;
32
+ const active = Math.min(last, hovered ?? tapped ?? cursor);
33
+ const selected = bins[active];
34
+ const inspecting = hovered !== undefined || tapped !== undefined || focused;
35
+ const interval = selected && `${formatBoundary(selected.start)}–${formatBoundary(selected.end)}`;
36
+ const value = selected && formatCount(selected.count);
37
+ const valueText = selected && `${xLabel}: ${interval}, ${countLabel}: ${value}`;
38
+ const middle = bins[Math.floor(bins.length / 2)];
39
+ const navigate = (event) => {
40
+ let next;
41
+ switch (event.key) {
42
+ case "ArrowLeft":
43
+ case "ArrowDown":
44
+ next = active - 1;
45
+ break;
46
+ case "ArrowRight":
47
+ case "ArrowUp":
48
+ next = active + 1;
49
+ break;
50
+ case "Home":
51
+ next = 0;
52
+ break;
53
+ case "End":
54
+ next = last;
55
+ break;
56
+ case "Escape":
57
+ if (inspecting)
58
+ event.preventDefault();
59
+ setHovered(undefined);
60
+ setTapped(undefined);
61
+ setFocused(false);
62
+ return;
63
+ default: return;
64
+ }
65
+ event.preventDefault();
66
+ setHovered(undefined);
67
+ setTapped(undefined);
68
+ setFocused(true);
69
+ setCursor(Math.max(0, Math.min(last, next)));
70
+ };
71
+ return _jsx("div", { ...props, ref: ref, className: ["flood-histogram", className].filter(Boolean).join(" "), role: "group", "aria-label": label, children: selected ? _jsxs(_Fragment, { children: [last > 0 && _jsx(VisuallyHidden, { id: instructions, children: navigationLabel }), _jsxs("div", { className: "flood-histogram__plot", dir: "ltr", role: last > 0 ? "slider" : "img", tabIndex: last > 0 ? 0 : undefined, "aria-label": last > 0 ? label : valueText, "aria-describedby": last > 0 ? instructions : undefined, "aria-valuemin": last > 0 ? 1 : undefined, "aria-valuemax": last > 0 ? bins.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: () => setHovered(undefined), children: [_jsx("div", { className: "flood-histogram__columns", "aria-hidden": "true", children: bins.map((bin, i) => _jsx("div", { className: "flood-histogram__bin", "data-active": inspecting && i === active || undefined, onPointerEnter: event => { if (event.pointerType !== "touch")
72
+ setHovered(i); }, onPointerUp: event => { if (event.pointerType === "touch")
73
+ setTapped(current => current === i ? undefined : i); }, children: _jsx("span", { className: "flood-histogram__bar", "data-zero": bin.count === 0 || undefined, style: { "--flood-histogram-bin-height": `${bin.count / limit * 100}%` } }) }, i)) }), inspecting && _jsxs(Surface, { className: "flood-chart__tooltip flood-histogram__tooltip", padding: "2", elevation: "raised", "aria-hidden": "true", style: {
74
+ "--flood-histogram-active": `${(active + .5) / bins.length * 100}%`,
75
+ "--flood-histogram-half-bin": `${50 / bins.length}%`,
76
+ "--flood-histogram-tip-side": active >= bins.length / 2 ? -1 : 0,
77
+ }, children: [_jsx(Text, { size: "helper", children: interval }), _jsxs(Inline, { gap: "2", align: "baseline", className: "flood-histogram__tooltip-count", children: [_jsx(Text, { size: "helper", tone: "subtle", children: countLabel }), _jsx(Text, { size: "helper", children: value })] })] })] }), _jsxs("div", { className: "flood-histogram__axis", dir: "ltr", "aria-hidden": "true", children: [_jsx(Text, { size: "helper", tone: "subtle", children: formatBoundary(start) }), last > 0 && _jsx(Text, { className: "flood-histogram__mid-label", size: "helper", tone: "subtle", style: { left: `${Math.floor(bins.length / 2) / bins.length * 100}%` }, children: formatBoundary(middle.start) }), _jsx(Text, { size: "helper", tone: "subtle", children: formatBoundary(previous) })] }), showXAxisLabel && _jsx(Text, { className: "flood-histogram__axis-label", size: "helper", tone: "subtle", dir: "auto", "aria-hidden": "true", children: xLabel })] }) : _jsx(Text, { className: "flood-histogram__empty", size: "compact", tone: "subtle", children: emptyLabel }) });
78
+ });
package/dist/index.d.ts CHANGED
@@ -80,8 +80,12 @@ export interface CollectionToolbarProps extends Omit<FieldsetProps, "children" |
80
80
  onRemoveFilter?: (id: string) => void;
81
81
  appliedFiltersLabel?: string;
82
82
  summaryPrefix?: ReactNode;
83
+ /** Align search and filters as a group to the end of a shared control row. */
84
+ align?: "stretch" | "end";
83
85
  /** At most two task-important quick filters; move additional properties into filterContent. */
84
86
  quickFilters?: ReactNode;
87
+ /** Additional commands beside Filters in the same tool row. */
88
+ actions?: ReactNode;
85
89
  filterContent?: ReactNode;
86
90
  filtersLabel?: string;
87
91
  filterTitle?: string;
@@ -277,10 +281,21 @@ export declare const ImagePreview: import("react").ForwardRefExoticComponent<Ima
277
281
  export interface DataTableColumn {
278
282
  id: string;
279
283
  label: string;
284
+ /** Short unit shown alongside the label, such as USD or kg. */
285
+ unit?: string;
280
286
  sortable?: boolean;
281
287
  numeric?: boolean;
282
288
  align?: "start" | "end";
283
289
  width?: CSSProperties["width"];
290
+ /** Keep this column visible when the host or Columns menu hides other columns. */
291
+ hideable?: boolean;
292
+ /** Opt into pointer and keyboard width adjustments for this column. */
293
+ resizable?: boolean;
294
+ /** Interactive width bounds in CSS pixels. */
295
+ minWidth?: number;
296
+ maxWidth?: number;
297
+ /** Keep the column at a logical edge when the table scrolls horizontally. */
298
+ pinned?: "start" | "end";
284
299
  }
285
300
  export interface DataTableRow {
286
301
  id: string;
@@ -288,6 +303,8 @@ export interface DataTableRow {
288
303
  cells: Readonly<Record<string, ReactNode>>;
289
304
  sortValues?: Readonly<Record<string, string | number | null>>;
290
305
  selectionDisabled?: boolean;
306
+ /** Related detail rendered in a separate full-width row on disclosure. */
307
+ expandedContent?: ReactNode;
291
308
  /** One named record-opening action. Other controls in the row remain independent. */
292
309
  primaryAction?: {
293
310
  column: string;
@@ -312,6 +329,13 @@ export interface DataTableLabels {
312
329
  results?: (from: number, to: number, total: number) => string;
313
330
  selection?: (selected: number, total: number) => string;
314
331
  sort?: (label: string) => string;
332
+ columns?: string;
333
+ resetColumns?: string;
334
+ sortedColumn?: (label: string) => string;
335
+ resizeColumn?: (label: string) => string;
336
+ expandRow?: (label: string) => string;
337
+ collapseRow?: (label: string) => string;
338
+ rowDetails?: string;
315
339
  pagination?: string;
316
340
  previousPage?: string;
317
341
  nextPage?: string;
@@ -319,17 +343,33 @@ export interface DataTableLabels {
319
343
  }
320
344
  export interface DataTableProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
321
345
  /** Host-owned heading, search and filters aligned with the outer table cells. */
322
- toolbar?: ReactNode;
346
+ toolbar?: ReactNode | ((controls: {
347
+ columns: ReactNode;
348
+ }) => ReactNode);
323
349
  inset?: "standard" | "roomy";
324
350
  /** Ready with no rows only. Compose EmptyState/actions here; loading and error keep their owners. */
325
351
  emptyContent?: ReactNode;
326
352
  caption: string;
327
353
  hideCaption?: boolean;
328
354
  columns: readonly DataTableColumn[];
355
+ showColumnVisibility?: boolean;
356
+ hiddenColumnIds?: readonly string[];
357
+ /** Initial hidden columns and the layout restored by Reset columns. */
358
+ defaultHiddenColumnIds?: readonly string[];
359
+ onHiddenColumnIdsChange?: (ids: string[]) => void;
360
+ columnWidths?: Readonly<Record<string, number>>;
361
+ defaultColumnWidths?: Readonly<Record<string, number>>;
362
+ onColumnWidthsChange?: (widths: Record<string, number>) => void;
329
363
  rows: readonly DataTableRow[];
364
+ expandedIds?: readonly string[];
365
+ defaultExpandedIds?: readonly string[];
366
+ onExpandedChange?: (ids: string[]) => void;
330
367
  density?: "compact" | "comfortable";
331
368
  striped?: boolean;
332
369
  minWidth?: CSSProperties["minWidth"];
370
+ /** Maximum height of the scroll viewport, including the header. */
371
+ maxViewportHeight?: CSSProperties["maxBlockSize"];
372
+ stickyHeader?: boolean;
333
373
  sort?: DataTableSort | null;
334
374
  defaultSort?: DataTableSort | null;
335
375
  onSortChange?: (sort: DataTableSort | null) => void;
@@ -344,6 +384,8 @@ export interface DataTableProps extends Omit<HTMLAttributes<HTMLDivElement>, "ch
344
384
  onPageChange?: (page: number) => void;
345
385
  /** Hide the result range while preserving selection and pagination controls. */
346
386
  showResults?: boolean;
387
+ /** Hide the visible selection count while retaining its accessible status. */
388
+ showSelection?: boolean;
347
389
  /** Server mode renders rows as the supplied page, without local sorting/slicing. */
348
390
  paginationMode?: "client" | "server";
349
391
  totalRows?: number;
@@ -355,6 +397,267 @@ export interface DataTableProps extends Omit<HTMLAttributes<HTMLDivElement>, "ch
355
397
  }
356
398
  /** A client-side table composed from native table, checkbox and pagination. @since 0.2.8 */
357
399
  export declare const DataTable: import("react").ForwardRefExoticComponent<DataTableProps & import("react").RefAttributes<HTMLDivElement>>;
400
+ export interface SparklineProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label" | "aria-labelledby"> {
401
+ /** Equally spaced observations in order. Missing or nonfinite values break the line. */
402
+ values: readonly (number | null)[];
403
+ /** Localized text conveying the trend or the absence of data. */
404
+ label: string;
405
+ showLabel?: boolean;
406
+ /** Shared lower and upper bounds for comparisons. Values outside the bounds are clipped. */
407
+ domain?: readonly [number, number];
408
+ size?: "sm" | "md";
409
+ tone?: "neutral" | "accent" | "success" | "warning" | "error";
410
+ variant?: "line" | "area";
411
+ }
412
+ /** @since 0.2.11 */
413
+ export declare const Sparkline: import("react").ForwardRefExoticComponent<SparklineProps & import("react").RefAttributes<HTMLDivElement>>;
414
+ export interface LineChartSeries {
415
+ id: string;
416
+ label: string;
417
+ /** One observation per category. Missing and nonfinite values break the line. */
418
+ values: readonly (number | null)[];
419
+ }
420
+ export type ChartSeries = LineChartSeries;
421
+ export interface LineChartProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
422
+ label: string;
423
+ /** Equally spaced categories in the order supplied. */
424
+ categories: readonly string[];
425
+ /** One to four comparable series sharing a scale. An empty array is also supported. */
426
+ series: readonly LineChartSeries[];
427
+ /** Shared finite bounds containing every observation. */
428
+ domain?: readonly [number, number];
429
+ variant?: "line" | "area";
430
+ /** Shape-preserving interpolation between observations. */
431
+ curve?: "linear" | "smooth";
432
+ /** Show the numeric scale and horizontal reference lines. */
433
+ showYAxis?: boolean;
434
+ /** Show the series key below the plot. Defaults to false. */
435
+ showLegend?: boolean;
436
+ formatValue?: (value: number) => string;
437
+ emptyLabel?: string;
438
+ missingLabel?: string;
439
+ navigationLabel?: string;
440
+ }
441
+ export declare const LineChart: import("react").ForwardRefExoticComponent<LineChartProps & import("react").RefAttributes<HTMLDivElement>>;
442
+ export interface BarChartProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
443
+ label: string;
444
+ categories: readonly string[];
445
+ /** Compare series side by side, by cumulative magnitude, or by share of each total. Defaults to grouped. */
446
+ layout?: "grouped" | "stacked" | "percent";
447
+ /** One to four grouped series. Use null for a missing value. */
448
+ series: readonly ChartSeries[];
449
+ /** Finite bounds containing zero and each observation or signed stack extent. Percent uses a fixed scale. */
450
+ domain?: readonly [number, number];
451
+ /** Show the series key below the plot. Defaults to false. */
452
+ showLegend?: boolean;
453
+ formatValue?: (value: number) => string;
454
+ /** Format a fraction from 0 to 1 in percent layout. */
455
+ formatShare?: (share: number) => string;
456
+ emptyLabel?: string;
457
+ missingLabel?: string;
458
+ navigationLabel?: string;
459
+ }
460
+ export declare const BarChart: import("react").ForwardRefExoticComponent<BarChartProps & import("react").RefAttributes<HTMLDivElement>>;
461
+ export interface DonutChartItem {
462
+ id: string;
463
+ label: string;
464
+ /** A finite nonnegative part of the whole. */
465
+ value: number;
466
+ }
467
+ export interface DonutChartProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
468
+ label: string;
469
+ /** Up to six categories in display order. */
470
+ items: readonly DonutChartItem[];
471
+ totalLabel?: string;
472
+ emptyLabel?: string;
473
+ navigationLabel?: string;
474
+ showLegend?: boolean;
475
+ formatValue?: (value: number) => string;
476
+ /** Receives the share as a fraction from 0 to 1. */
477
+ formatShare?: (share: number) => string;
478
+ }
479
+ export declare const DonutChart: import("react").ForwardRefExoticComponent<DonutChartProps & import("react").RefAttributes<HTMLDivElement>>;
480
+ export interface HeatmapProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
481
+ label: string;
482
+ columns: readonly string[];
483
+ rows: readonly {
484
+ id: string;
485
+ label: string;
486
+ values: readonly (number | null)[];
487
+ }[];
488
+ /** Shared zero-based scale. Defaults to the largest observed value. */
489
+ max?: number;
490
+ formatValue?: (value: number) => string;
491
+ missingLabel?: string;
492
+ emptyLabel?: string;
493
+ }
494
+ export declare const Heatmap: import("react").ForwardRefExoticComponent<HeatmapProps & import("react").RefAttributes<HTMLDivElement>>;
495
+ export interface ScatterChartPoint {
496
+ id: string;
497
+ label?: string;
498
+ x: number;
499
+ y: number;
500
+ }
501
+ export interface ScatterChartProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
502
+ label: string;
503
+ xLabel: string;
504
+ yLabel: string;
505
+ /** Observations in keyboard navigation order, with stable, unique IDs. */
506
+ points: readonly ScatterChartPoint[];
507
+ /** Finite, increasing bounds that contain all x observations. */
508
+ xDomain?: readonly [number, number];
509
+ /** Finite, increasing bounds that contain all y observations. */
510
+ yDomain?: readonly [number, number];
511
+ formatX?: (value: number) => string;
512
+ formatY?: (value: number) => string;
513
+ emptyLabel?: string;
514
+ navigationLabel?: string;
515
+ }
516
+ export declare const ScatterChart: import("react").ForwardRefExoticComponent<ScatterChartProps & import("react").RefAttributes<HTMLDivElement>>;
517
+ export interface RangeChartItem {
518
+ id: string;
519
+ label: string;
520
+ /** A missing bound leaves an empty category. */
521
+ low: number | null;
522
+ high: number | null;
523
+ /** Optional observed value within the interval, such as a median. */
524
+ midpoint?: number;
525
+ }
526
+ export interface RangeChartProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
527
+ label: string;
528
+ items: readonly RangeChartItem[];
529
+ /** Finite increasing bounds containing all complete intervals. */
530
+ domain?: readonly [number, number];
531
+ formatValue?: (value: number) => string;
532
+ lowLabel?: string;
533
+ highLabel?: string;
534
+ midpointLabel?: string;
535
+ emptyLabel?: string;
536
+ missingLabel?: string;
537
+ navigationLabel?: string;
538
+ }
539
+ export declare const RangeChart: import("react").ForwardRefExoticComponent<RangeChartProps & import("react").RefAttributes<HTMLDivElement>>;
540
+ export interface DumbbellChartItem {
541
+ id: string;
542
+ label: string;
543
+ before: number | null;
544
+ after: number | null;
545
+ }
546
+ export interface DumbbellChartProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
547
+ label: string;
548
+ items: readonly DumbbellChartItem[];
549
+ /** Finite, increasing bounds containing all observed endpoints. */
550
+ domain?: readonly [number, number];
551
+ beforeLabel?: string;
552
+ afterLabel?: string;
553
+ missingLabel?: string;
554
+ emptyLabel?: string;
555
+ formatValue?: (value: number) => string;
556
+ navigationLabel?: string;
557
+ }
558
+ export declare const DumbbellChart: import("react").ForwardRefExoticComponent<DumbbellChartProps & import("react").RefAttributes<HTMLDivElement>>;
559
+ export interface BoxPlotSummary {
560
+ low: number;
561
+ q1: number;
562
+ median: number;
563
+ q3: number;
564
+ high: number;
565
+ }
566
+ export interface BoxPlotItem {
567
+ id: string;
568
+ label: string;
569
+ /** Ordered whiskers, quartiles and median. Null preserves an empty row. */
570
+ summary: BoxPlotSummary | null;
571
+ /** Optional observations beyond the supplied whiskers. */
572
+ outliers?: readonly number[];
573
+ }
574
+ export interface BoxPlotProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
575
+ label: string;
576
+ items: readonly BoxPlotItem[];
577
+ /** Finite increasing bounds containing every observation. */
578
+ domain?: readonly [number, number];
579
+ formatValue?: (value: number) => string;
580
+ /** Format axis ticks independently of exact values. Defaults to formatValue. */
581
+ formatAxisValue?: (value: number) => string;
582
+ emptyLabel?: string;
583
+ missingLabel?: string;
584
+ navigationLabel?: string;
585
+ statisticLabels?: Partial<Record<keyof BoxPlotSummary | "outliers" | "whiskers", string>>;
586
+ }
587
+ export declare const BoxPlot: import("react").ForwardRefExoticComponent<BoxPlotProps & import("react").RefAttributes<HTMLDivElement>>;
588
+ export interface BulletChartItem {
589
+ id: string;
590
+ label: string;
591
+ value: number;
592
+ target: number;
593
+ }
594
+ export interface BulletChartProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
595
+ label: string;
596
+ items: readonly BulletChartItem[];
597
+ /** Shared scale maximum. Defaults to the largest actual or target. */
598
+ max?: number;
599
+ formatValue?: (value: number) => string;
600
+ valueLabel?: string;
601
+ targetLabel?: string;
602
+ emptyLabel?: string;
603
+ }
604
+ export declare const BulletChart: import("react").ForwardRefExoticComponent<BulletChartProps & import("react").RefAttributes<HTMLDivElement>>;
605
+ export interface WaterfallChartStep {
606
+ id: string;
607
+ label: string;
608
+ value: number;
609
+ /** A change adjusts the running total. A total is an absolute checkpoint. */
610
+ kind?: "change" | "total";
611
+ }
612
+ export interface WaterfallChartProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
613
+ label: string;
614
+ steps: readonly WaterfallChartStep[];
615
+ /** Finite increasing bounds containing zero and every running total. */
616
+ domain?: readonly [number, number];
617
+ formatValue?: (value: number) => string;
618
+ changeLabel?: string;
619
+ totalLabel?: string;
620
+ emptyLabel?: string;
621
+ navigationLabel?: string;
622
+ }
623
+ export declare const WaterfallChart: import("react").ForwardRefExoticComponent<WaterfallChartProps & import("react").RefAttributes<HTMLDivElement>>;
624
+ export interface HistogramProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
625
+ label: string;
626
+ /** Name and unit for the numeric axis. */
627
+ xLabel: string;
628
+ /** Show the axis title below the numeric ticks. Defaults to true. */
629
+ showXAxisLabel?: boolean;
630
+ /** Inclusive lower boundary of the first bin. */
631
+ start: number;
632
+ /** Positive width shared by all bins. */
633
+ binWidth: number;
634
+ /** Counts in ascending bin order. Zero is a measured empty bin. */
635
+ counts: readonly number[];
636
+ /** Common count scale for comparing histograms. Defaults to the largest count or one. */
637
+ maxCount?: number;
638
+ countLabel?: string;
639
+ formatBoundary?: (value: number) => string;
640
+ formatCount?: (count: number) => string;
641
+ emptyLabel?: string;
642
+ navigationLabel?: string;
643
+ }
644
+ export declare const Histogram: import("react").ForwardRefExoticComponent<HistogramProps & import("react").RefAttributes<HTMLDivElement>>;
645
+ export interface BarListItem {
646
+ id: string;
647
+ label: string;
648
+ value: number;
649
+ valueText?: string;
650
+ }
651
+ export interface BarListProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "aria-label"> {
652
+ label: string;
653
+ /** Nonnegative values in display order. */
654
+ items: readonly BarListItem[];
655
+ /** Shared positive upper bound. Defaults to the largest value, or 1 when all are zero. */
656
+ max?: number;
657
+ tone?: SemanticTone;
658
+ emptyLabel?: string;
659
+ }
660
+ export declare const BarList: import("react").ForwardRefExoticComponent<BarListProps & import("react").RefAttributes<HTMLDivElement>>;
358
661
  export interface DataListProps extends Omit<HTMLAttributes<HTMLUListElement>, "role"> {
359
662
  density?: "compact" | "comfortable";
360
663
  dividers?: boolean;
@@ -898,6 +1201,12 @@ export interface EditableProps extends Omit<HTMLAttributes<HTMLDivElement>, "def
898
1201
  onEditingChange?: (editing: boolean) => void;
899
1202
  onCommit?: (value: string) => void;
900
1203
  onCancel?: () => void;
1204
+ /** Return a message to keep the draft open and prevent a commit. */
1205
+ validate?: (value: string) => string | undefined;
1206
+ inputMode?: InputHTMLAttributes<HTMLInputElement>["inputMode"];
1207
+ previewVariant?: "subtle" | "ghost";
1208
+ /** Render the editor over its trigger at this preferred width. */
1209
+ editorOverlayWidth?: CSSProperties["inlineSize"];
901
1210
  blurAction?: "commit" | "cancel" | "none";
902
1211
  readOnly?: boolean;
903
1212
  disabled?: boolean;
@@ -970,6 +1279,9 @@ export interface TableProps extends Omit<TableHTMLAttributes<HTMLTableElement>,
970
1279
  density?: DataDensity;
971
1280
  striped?: boolean;
972
1281
  scrollLabel?: string;
1282
+ /** Maximum height of the scroll viewport, including the header and caption. */
1283
+ maxViewportHeight?: CSSProperties["maxBlockSize"];
1284
+ stickyHeader?: boolean;
973
1285
  /** Shared cell alignment. Middle keeps mixed record/action rows coherent; top is an explicit prose-table choice. */
974
1286
  cellVerticalAlign?: "top" | "middle" | "bottom";
975
1287
  }
@@ -1134,6 +1446,8 @@ export interface MenuProps extends Omit<HTMLAttributes<HTMLDivElement>, "childre
1134
1446
  open?: boolean;
1135
1447
  defaultOpen?: boolean;
1136
1448
  onOpenChange?: (open: boolean) => void;
1449
+ /** Resolve a fallback after close if the opener can no longer receive focus. */
1450
+ getFallbackFocus?: () => HTMLElement | null;
1137
1451
  disabled?: boolean;
1138
1452
  side?: "top" | "bottom" | "left" | "right";
1139
1453
  align?: "start" | "center" | "end";
@@ -1183,6 +1497,8 @@ export interface DialogProps extends Omit<HTMLAttributes<HTMLDialogElement>, "ch
1183
1497
  closeLabel?: string;
1184
1498
  closeOnOutsideClick?: boolean;
1185
1499
  initialFocusRef?: RefObject<HTMLElement | null>;
1500
+ /** Resolve a fallback after close if the opener can no longer receive focus. */
1501
+ getFallbackFocus?: () => HTMLElement | null;
1186
1502
  }
1187
1503
  export declare const Dialog: import("react").ForwardRefExoticComponent<DialogProps & import("react").RefAttributes<HTMLDialogElement>>;
1188
1504
  export interface CommandPaletteProps extends Omit<DialogProps, "children" | "description" | "initialFocusRef"> {
@@ -1206,6 +1522,9 @@ export interface DrawerProps extends DialogProps {
1206
1522
  footer?: ReactNode;
1207
1523
  }
1208
1524
  export declare const Drawer: import("react").ForwardRefExoticComponent<DrawerProps & import("react").RefAttributes<HTMLDialogElement>>;
1525
+ export type SheetProps = Omit<DrawerProps, "side">;
1526
+ /** A modal bottom sheet for a short task or a list of choices. @since 0.2.12 */
1527
+ export declare const Sheet: import("react").ForwardRefExoticComponent<SheetProps & import("react").RefAttributes<HTMLDialogElement>>;
1209
1528
  export interface AlertDialogProps extends Omit<DialogProps, "children" | "role" | "description" | "closeLabel" | "closeOnOutsideClick" | "initialFocusRef"> {
1210
1529
  description: string;
1211
1530
  confirmLabel?: string;
@@ -1504,7 +1823,7 @@ export interface TextProps extends HTMLAttributes<HTMLElement> {
1504
1823
  export declare const Text: import("react").ForwardRefExoticComponent<TextProps & import("react").RefAttributes<HTMLElement>>;
1505
1824
  export interface HeadingProps extends HTMLAttributes<HTMLHeadingElement> {
1506
1825
  level?: 1 | 2 | 3 | 4 | 5 | 6;
1507
- size?: "display" | "large" | "page" | "section";
1826
+ size?: "display" | "large" | "page" | "section" | "group";
1508
1827
  }
1509
1828
  export declare const Heading: import("react").ForwardRefExoticComponent<HeadingProps & import("react").RefAttributes<HTMLHeadingElement>>;
1510
1829
  export type Space = "0" | "1" | "2" | "3" | "4" | "6" | "8" | "12";
@@ -1597,6 +1916,8 @@ export declare const Divider: import("react").ForwardRefExoticComponent<HTMLAttr
1597
1916
  export interface CodeSnippetProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
1598
1917
  code: string;
1599
1918
  codeDirection?: "ltr" | "rtl" | "auto";
1919
+ /** A decorative prompt placed beside the code, outside the selectable text. @since 0.2.13 */
1920
+ prompt?: string;
1600
1921
  action?: ReactNode;
1601
1922
  }
1602
1923
  /** Selectable code with an optional host-owned action; no clipboard side effects. */
@@ -1609,6 +1930,8 @@ export interface ScrollAreaProps extends HTMLAttributes<HTMLDivElement> {
1609
1930
  export declare const ScrollArea: import("react").ForwardRefExoticComponent<ScrollAreaProps & import("react").RefAttributes<HTMLDivElement>>;
1610
1931
  export interface CopyButtonProps extends Omit<ButtonProps, "children" | "value" | "type" | "onClick" | "loading"> {
1611
1932
  value: string;
1933
+ /** Use a named square icon action with the same clipboard feedback. @since 0.2.13 */
1934
+ iconOnly?: boolean;
1612
1935
  copyLabel?: string;
1613
1936
  copiedLabel?: string;
1614
1937
  errorLabel?: string;
@@ -1748,7 +2071,7 @@ export interface SectionProps extends Omit<HTMLAttributes<HTMLElement>, "title">
1748
2071
  description?: ReactNode;
1749
2072
  actions?: ReactNode;
1750
2073
  headingLevel?: 2 | 3 | 4 | 5 | 6;
1751
- headingSize?: "display" | "large" | "page" | "section";
2074
+ headingSize?: HeadingProps["size"];
1752
2075
  }
1753
2076
  export declare const Section: import("react").ForwardRefExoticComponent<SectionProps & import("react").RefAttributes<HTMLElement>>;
1754
2077
  export interface PageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, "title" | "children"> {
@@ -1792,6 +2115,8 @@ export interface AppShellProps extends HTMLAttributes<HTMLDivElement> {
1792
2115
  mainRef?: Ref<HTMLElement>;
1793
2116
  scrollLabel?: string;
1794
2117
  scrollOrientation?: ScrollAreaProps["orientation"];
2118
+ /** Keep the content width stable with "none" when the layout already clears the overlay rails. */
2119
+ scrollContentInset?: ScrollAreaProps["contentInset"];
1795
2120
  skipLabel?: string;
1796
2121
  }
1797
2122
  /** Composes application navigation and a main landmark with optional bounded scrolling. @since 0.2.11 */
package/dist/index.js CHANGED
@@ -51,6 +51,15 @@ import { ClockTimePicker } from "./time-picker.js";
51
51
  import { CivilDateTimeRangePicker } from "./date-time-range-picker.js";
52
52
  import { FileRecord, UploadRecord, ModalImagePreview, FileMetadata } from "./file-records.js";
53
53
  import { ManagedDataTable } from "./data-table.js";
54
+ import { TrendPlot } from "./sparkline.js";
55
+ import { SeriesPlot, GroupedBars, RankedBars, ShareRing, HeatmapGrid } from "./charts.js";
56
+ import { ScatterPlot } from "./scatter-chart.js";
57
+ import { RangePlot } from "./range-chart.js";
58
+ import { DumbbellPlot } from "./dumbbell-chart.js";
59
+ import { DistributionBoxes } from "./box-plot.js";
60
+ import { BulletPlot } from "./bullet-chart.js";
61
+ import { HistogramPlot } from "./histogram.js";
62
+ import { WaterfallPlot } from "./waterfall-chart.js";
54
63
  import { CheckableCard, ExclusiveCard } from "./collection-cards.js";
55
64
  import { ColorPreview, ColorEditor } from "./color-controls.js";
56
65
  import { HoverPreview } from "./hover-card.js";
@@ -96,6 +105,46 @@ export const UploadList = /* @__PURE__ */ forwardRef(function UploadList(props,
96
105
  export const ImagePreview = /* @__PURE__ */ forwardRef(function ImagePreview(props, ref) { return _jsx(ModalImagePreview, { ...props, ref: ref }); });
97
106
  /** A client-side table composed from native table, checkbox and pagination. @since 0.2.8 */
98
107
  export const DataTable = /* @__PURE__ */ forwardRef(function DataTable(props, ref) { return _jsx(ManagedDataTable, { ...props, ref: ref }); });
108
+ /** @since 0.2.11 */
109
+ export const Sparkline = /* @__PURE__ */ forwardRef(function Sparkline({ showLabel = false, size = "md", tone = "accent", variant = "area", ...props }, ref) {
110
+ return _jsx(TrendPlot, { ...props, showLabel: showLabel, size: size, tone: tone, variant: variant, ref: ref });
111
+ });
112
+ export const LineChart = /* @__PURE__ */ forwardRef(function LineChart({ variant = "area", curve = "smooth", showYAxis = false, emptyLabel = "No data", missingLabel = "No value", navigationLabel = "Use the arrow keys to explore values, or Home and End to jump.", ...props }, ref) {
113
+ return _jsx(SeriesPlot, { ...props, variant: variant, curve: curve, showYAxis: showYAxis, emptyLabel: emptyLabel, missingLabel: missingLabel, navigationLabel: navigationLabel, ref: ref });
114
+ });
115
+ export const BarChart = /* @__PURE__ */ forwardRef(function BarChart({ emptyLabel = "No data", missingLabel = "No value", navigationLabel = "Use the arrow keys to explore categories, or Home and End to jump.", ...props }, ref) {
116
+ return _jsx(GroupedBars, { ...props, emptyLabel: emptyLabel, missingLabel: missingLabel, navigationLabel: navigationLabel, ref: ref });
117
+ });
118
+ export const DonutChart = /* @__PURE__ */ forwardRef(function DonutChart({ totalLabel = "Total", emptyLabel = "No data", navigationLabel = "Use the arrow keys to explore segments, or Home and End to jump.", ...props }, ref) {
119
+ return _jsx(ShareRing, { ...props, totalLabel: totalLabel, emptyLabel: emptyLabel, navigationLabel: navigationLabel, ref: ref });
120
+ });
121
+ export const Heatmap = /* @__PURE__ */ forwardRef(function Heatmap({ missingLabel = "No data", emptyLabel = "No observations", ...props }, ref) {
122
+ return _jsx(HeatmapGrid, { ...props, missingLabel: missingLabel, emptyLabel: emptyLabel, ref: ref });
123
+ });
124
+ export const ScatterChart = /* @__PURE__ */ forwardRef(function ScatterChart(props, ref) {
125
+ return _jsx(ScatterPlot, { ...props, ref: ref });
126
+ });
127
+ export const RangeChart = /* @__PURE__ */ forwardRef(function RangeChart(props, ref) {
128
+ return _jsx(RangePlot, { ...props, ref: ref });
129
+ });
130
+ export const DumbbellChart = /* @__PURE__ */ forwardRef(function DumbbellChart(props, ref) {
131
+ return _jsx(DumbbellPlot, { ...props, ref: ref });
132
+ });
133
+ export const BoxPlot = /* @__PURE__ */ forwardRef(function BoxPlot(props, ref) {
134
+ return _jsx(DistributionBoxes, { ...props, ref: ref });
135
+ });
136
+ export const BulletChart = /* @__PURE__ */ forwardRef(function BulletChart(props, ref) {
137
+ return _jsx(BulletPlot, { ...props, ref: ref });
138
+ });
139
+ export const WaterfallChart = /* @__PURE__ */ forwardRef(function WaterfallChart(props, ref) {
140
+ return _jsx(WaterfallPlot, { ...props, ref: ref });
141
+ });
142
+ export const Histogram = /* @__PURE__ */ forwardRef(function Histogram(props, ref) {
143
+ return _jsx(HistogramPlot, { ...props, ref: ref });
144
+ });
145
+ export const BarList = /* @__PURE__ */ forwardRef(function BarList({ tone = "accent", emptyLabel = "No data", ...props }, ref) {
146
+ return _jsx(RankedBars, { ...props, tone: tone, emptyLabel: emptyLabel, ref: ref });
147
+ });
99
148
  /** A native list; links and actions stay independent. @since 0.2.8 */
100
149
  export const DataList = /* @__PURE__ */ forwardRef(function DataList({ density = "comfortable", dividers = true, className, ...props }, ref) {
101
150
  return _jsx("ul", { ...props, ref: ref, role: "list", "data-density": density, "data-dividers": dividers, className: classes("flood-data-list", className) });
@@ -184,8 +233,8 @@ export const DescriptionList = /* @__PURE__ */ forwardRef(function DescriptionLi
184
233
  return _jsx(DescribedData, { ...props, ref: ref, items: items, layout: layout, density: density, dividers: dividers });
185
234
  });
186
235
  /** @since 0.2.4 */
187
- export const Table = /* @__PURE__ */ forwardRef(function Table({ caption, children, hideCaption = false, density = "comfortable", striped = false, scrollLabel, cellVerticalAlign = "middle", ...props }, ref) {
188
- return _jsx(TabularData, { ...props, ref: ref, caption: caption, hideCaption: hideCaption, density: density, striped: striped, scrollLabel: scrollLabel, cellVerticalAlign: cellVerticalAlign, children: children });
236
+ export const Table = /* @__PURE__ */ forwardRef(function Table({ caption, children, hideCaption = false, density = "comfortable", striped = false, scrollLabel, cellVerticalAlign = "middle", stickyHeader = false, ...props }, ref) {
237
+ return _jsx(TabularData, { ...props, ref: ref, caption: caption, hideCaption: hideCaption, density: density, striped: striped, scrollLabel: scrollLabel, cellVerticalAlign: cellVerticalAlign, stickyHeader: stickyHeader, children: children });
189
238
  });
190
239
  /** @since 0.2.4 */
191
240
  export const Badge = /* @__PURE__ */ forwardRef(function Badge({ size = "md", tone = "neutral", variant = "subtle", className, ...props }, ref) {
@@ -242,6 +291,10 @@ export const CommandPalette = /* @__PURE__ */ forwardRef(function CommandPalette
242
291
  export const Drawer = /* @__PURE__ */ forwardRef(function Drawer({ side = "end", size = "md", defaultOpen = false, closeLabel = "Close", closeOnOutsideClick = true, className, footer, ...props }, ref) {
243
292
  return _jsx(ModalOverlay, { ...props, ref: ref, defaultOpen: defaultOpen, closeLabel: closeLabel, closeOnOutsideClick: closeOnOutsideClick, className: classes("flood-drawer", className), "data-side": side, "data-size": size, scrollBody: true, footer: footer });
244
293
  });
294
+ /** A modal bottom sheet for a short task or a list of choices. @since 0.2.12 */
295
+ export const Sheet = /* @__PURE__ */ forwardRef(function Sheet({ className, size = "md", ...props }, ref) {
296
+ return _jsx(ModalOverlay, { ...props, ref: ref, "data-side": "bottom", "data-size": size, className: classes("flood-drawer", "flood-sheet", className), scrollBody: true, bodyContentInset: "none" });
297
+ });
245
298
  export const AlertDialog = /* @__PURE__ */ forwardRef(function AlertDialog({ defaultOpen = false, confirmLabel = "Continue", cancelLabel = "Cancel", confirmDisabled = false, ...props }, ref) {
246
299
  return _jsx(ConfirmationDialog, { ...props, ref: ref, defaultOpen: defaultOpen, confirmLabel: confirmLabel, cancelLabel: cancelLabel, confirmDisabled: confirmDisabled });
247
300
  });
@@ -531,8 +584,8 @@ export const Divider = /* @__PURE__ */ forwardRef(function Divider({ className,
531
584
  return _jsx("hr", { ...props, ref: ref, className: classes("flood-divider", className) });
532
585
  });
533
586
  /** Selectable code with an optional host-owned action; no clipboard side effects. */
534
- export const CodeSnippet = /* @__PURE__ */ forwardRef(function CodeSnippet({ code, codeDirection = "ltr", action, className, ...props }, ref) {
535
- return (_jsxs("div", { ...props, ref: ref, className: classes("flood-code-snippet", className), children: [_jsx("code", { dir: codeDirection, className: "flood-code-snippet__code", children: code }), action != null && _jsx("div", { className: "flood-code-snippet__action", children: action })] }));
587
+ export const CodeSnippet = /* @__PURE__ */ forwardRef(function CodeSnippet({ code, codeDirection = "ltr", prompt, action, className, ...props }, ref) {
588
+ return (_jsxs("div", { ...props, ref: ref, className: classes("flood-code-snippet", className), children: [_jsxs("div", { dir: codeDirection === "rtl" ? "rtl" : "ltr", className: "flood-code-snippet__line", children: [prompt && _jsx("span", { "aria-hidden": "true", className: "flood-code-snippet__prompt", children: prompt }), _jsx("code", { dir: codeDirection, className: "flood-code-snippet__code", children: code })] }), action != null && _jsx("div", { className: "flood-code-snippet__action", children: action })] }));
536
589
  });
537
590
  /** Native scrolling with inset overlay tracks; the ref targets the scrollable viewport. */
538
591
  export const ScrollArea = /* @__PURE__ */ forwardRef(function ScrollArea({ orientation = "vertical", contentInset = "scrollbar", ...props }, ref) {
package/dist/menu.d.ts CHANGED
@@ -15,6 +15,7 @@ interface MenuLayerProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"
15
15
  rootAnchor: () => HTMLElement | null;
16
16
  rootPanel?: () => HTMLDivElement | null;
17
17
  onAction?: (id: string) => void;
18
+ getFallbackFocus?: MenuProps["getFallbackFocus"];
18
19
  edge?: () => Edge;
19
20
  nested?: boolean;
20
21
  position?: (panel: HTMLDivElement) => void;