@ciridae/ui 1.0.5 → 1.0.9

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.
Files changed (147) hide show
  1. package/README.md +3 -2
  2. package/dist/chat/conversation-source.d.ts +1 -3
  3. package/dist/chat/message-text.js +6 -6
  4. package/dist/chat/use-chat-conversation.d.ts +7 -2
  5. package/dist/chat/use-chat-conversation.js +2 -1
  6. package/dist/components/activity-feed.d.ts +0 -1
  7. package/dist/components/activity-feed.js +6 -7
  8. package/dist/components/agent-work.d.ts +5 -1
  9. package/dist/components/agent-work.js +27 -13
  10. package/dist/components/app-frame.d.ts +3 -17
  11. package/dist/components/app-frame.js +11 -30
  12. package/dist/components/app-navigation.d.ts +5 -6
  13. package/dist/components/app-navigation.js +65 -40
  14. package/dist/components/badge.d.ts +0 -4
  15. package/dist/components/badge.js +17 -27
  16. package/dist/components/bulk-action-bar.js +2 -2
  17. package/dist/components/button.js +41 -50
  18. package/dist/components/calendar.js +5 -8
  19. package/dist/components/centered-page.js +4 -4
  20. package/dist/components/chart.js +3 -4
  21. package/dist/components/chat-client-source.js +55 -34
  22. package/dist/components/chat-page.js +1 -1
  23. package/dist/components/chat-sheet.d.ts +30 -20
  24. package/dist/components/chat-sheet.js +109 -51
  25. package/dist/components/chat.d.ts +27 -56
  26. package/dist/components/chat.js +151 -129
  27. package/dist/components/checkbox-item.js +4 -4
  28. package/dist/components/checkbox-list.js +6 -6
  29. package/dist/components/chip.js +2 -2
  30. package/dist/components/collapsible.js +3 -3
  31. package/dist/components/color-theme.d.ts +3 -6
  32. package/dist/components/color-theme.js +10 -11
  33. package/dist/components/column-settings.js +3 -3
  34. package/dist/components/command-menu.d.ts +1 -2
  35. package/dist/components/command-menu.js +56 -77
  36. package/dist/components/command-palette.js +5 -2
  37. package/dist/components/copyable-id.js +5 -5
  38. package/dist/components/data-display.d.ts +1 -7
  39. package/dist/components/data-display.js +32 -55
  40. package/dist/components/data-grid.d.ts +4 -7
  41. package/dist/components/data-grid.js +106 -90
  42. package/dist/components/date-range-picker.js +4 -5
  43. package/dist/components/document-viewer.js +23 -23
  44. package/dist/components/drawer.d.ts +2 -1
  45. package/dist/components/drawer.js +45 -20
  46. package/dist/components/dropzone.js +13 -13
  47. package/dist/components/editable-field.d.ts +2 -12
  48. package/dist/components/editable-field.js +13 -26
  49. package/dist/components/email-input.js +2 -3
  50. package/dist/components/environment-frame.js +7 -7
  51. package/dist/components/expandable-text.js +2 -2
  52. package/dist/components/feedback-screenshot.js +7 -7
  53. package/dist/components/feedback-sheet.js +8 -8
  54. package/dist/components/filter-bar.js +41 -27
  55. package/dist/components/form-controls.d.ts +3 -6
  56. package/dist/components/form-controls.js +15 -22
  57. package/dist/components/form-layout.d.ts +6 -6
  58. package/dist/components/form-layout.js +10 -16
  59. package/dist/components/glass-menu.d.ts +2 -0
  60. package/dist/components/glass-menu.js +14 -18
  61. package/dist/components/gradient-edge.d.ts +0 -1
  62. package/dist/components/gradient-edge.js +8 -9
  63. package/dist/components/icon.js +1 -1
  64. package/dist/components/input.js +18 -17
  65. package/dist/components/keycap.d.ts +2 -6
  66. package/dist/components/keycap.js +4 -12
  67. package/dist/components/layout.js +11 -10
  68. package/dist/components/lightbox.js +8 -8
  69. package/dist/components/link.js +1 -1
  70. package/dist/components/locale.d.ts +23 -7
  71. package/dist/components/locale.js +19 -7
  72. package/dist/components/log-entry.d.ts +2 -14
  73. package/dist/components/log-entry.js +11 -22
  74. package/dist/components/log-list.js +1 -1
  75. package/dist/components/mention-input.js +13 -14
  76. package/dist/components/menu.d.ts +7 -4
  77. package/dist/components/menu.js +23 -10
  78. package/dist/components/meter.d.ts +2 -3
  79. package/dist/components/meter.js +12 -16
  80. package/dist/components/navigation.d.ts +0 -7
  81. package/dist/components/navigation.js +3 -12
  82. package/dist/components/notification-tray.js +7 -7
  83. package/dist/components/overlays.d.ts +5 -2
  84. package/dist/components/overlays.js +24 -24
  85. package/dist/components/panel.js +3 -3
  86. package/dist/components/progress.js +2 -2
  87. package/dist/components/radio-card.d.ts +1 -1
  88. package/dist/components/radio-card.js +9 -9
  89. package/dist/components/record.d.ts +2 -4
  90. package/dist/components/record.js +19 -32
  91. package/dist/components/scroll-area.js +10 -10
  92. package/dist/components/segmented-bar.js +9 -9
  93. package/dist/components/select.d.ts +3 -5
  94. package/dist/components/select.js +26 -44
  95. package/dist/components/settings.js +1 -1
  96. package/dist/components/shell-skeleton.js +1 -1
  97. package/dist/components/shell.d.ts +1 -1
  98. package/dist/components/shell.js +69 -24
  99. package/dist/components/side-panel.js +3 -3
  100. package/dist/components/sidebar.d.ts +0 -5
  101. package/dist/components/sidebar.js +25 -33
  102. package/dist/components/single-line-text.js +3 -4
  103. package/dist/components/site-banner.js +4 -4
  104. package/dist/components/skeleton.js +19 -22
  105. package/dist/components/skeletons.d.ts +0 -3
  106. package/dist/components/skeletons.js +5 -10
  107. package/dist/components/stages.d.ts +6 -3
  108. package/dist/components/stages.js +77 -105
  109. package/dist/components/stat-card.d.ts +2 -5
  110. package/dist/components/stat-card.js +23 -31
  111. package/dist/components/status-banner.js +6 -6
  112. package/dist/components/status.js +3 -3
  113. package/dist/components/steps.js +2 -2
  114. package/dist/components/switch.js +1 -1
  115. package/dist/components/tabs.js +15 -18
  116. package/dist/components/theme-customizer.d.ts +5 -8
  117. package/dist/components/theme-customizer.js +9 -41
  118. package/dist/components/theme-toggle.d.ts +0 -1
  119. package/dist/components/theme-toggle.js +6 -11
  120. package/dist/components/toast.d.ts +1 -7
  121. package/dist/components/toast.js +19 -22
  122. package/dist/components/user-chip.js +8 -8
  123. package/dist/components/wizard.js +6 -4
  124. package/dist/preset.d.ts +1 -2
  125. package/dist/preset.js +39 -89
  126. package/dist/styled-system/css/conditions.mjs +1 -1
  127. package/dist/styled-system/css/css.mjs +1 -1
  128. package/dist/styled-system/styles.css +805 -1279
  129. package/dist/styled-system/tokens/index.mjs +74 -1926
  130. package/dist/styled-system/tokens/tokens.d.ts +18 -33
  131. package/dist/styled-system/types/conditions.d.ts +0 -74
  132. package/dist/styled-system/types/prop-type.d.ts +15 -40
  133. package/dist/styled-system/types/style-props.d.ts +705 -705
  134. package/dist/theme/color.d.ts +0 -1
  135. package/dist/theme/color.js +0 -16
  136. package/dist/theme/derive.d.ts +3 -3
  137. package/dist/theme/derive.js +9 -32
  138. package/dist/theme/index.d.ts +1 -2
  139. package/dist/theme/index.js +3 -5
  140. package/dist/theme/options.d.ts +2 -4
  141. package/dist/theme/options.js +0 -1
  142. package/dist/theme/{palettes.d.ts → palette.d.ts} +12 -23
  143. package/dist/theme/palette.js +127 -0
  144. package/dist/theme/tokens.d.ts +8 -13
  145. package/dist/theme/tokens.js +38 -92
  146. package/package.json +1 -1
  147. package/dist/theme/palettes.js +0 -254
@@ -30,7 +30,6 @@ const panelRow = css({
30
30
  borderTop: "1px solid token(colors.border.divider)",
31
31
  "&:first-of-type": { borderTop: "0" },
32
32
  });
33
- // A list row: two lines of copy over each other, then a status chip at the end.
34
33
  const listRow = css({
35
34
  display: "flex",
36
35
  alignItems: "center",
@@ -39,7 +38,6 @@ const listRow = css({
39
38
  lineHeight: "tight",
40
39
  });
41
40
  const listRowCopy = css({ display: "grid", gap: "control.iconGap", flex: "1", minWidth: "0" });
42
- // A stat tile's and a card's placeholders wear the card they stand in for.
43
41
  const statTile = css(cardSurface, {
44
42
  display: "grid",
45
43
  alignContent: "start",
@@ -73,15 +71,15 @@ const cardTakeaway = css({
73
71
  const textWidths = ["72%", "54%", "64%", "46%"];
74
72
  /** Stands in for a labelled group of sidebar rows: a section label, then icon-and-name rows. */
75
73
  export function SidebarRowsSkeleton({ rows = 3 }) {
76
- return (_jsxs("div", { className: sidebarSection, children: [_jsx("span", { className: sidebarLabel, children: _jsx(Skeleton, { shape: "text", style: { width: 64 } }) }), Array.from({ length: rows }, (_, index) => (_jsxs("div", { className: sidebarRow, children: [_jsx(Skeleton, { shape: "circle", style: { width: 16 } }), _jsx(Skeleton, { shape: "text", style: { width: textWidths[index % textWidths.length] } })] }, index)))] }));
74
+ return (_jsxs("div", { className: sidebarSection, children: [_jsx("span", { className: sidebarLabel, children: _jsx(Skeleton, { shape: "text", width: "short" }) }), Array.from({ length: rows }, (_, index) => (_jsxs("div", { className: sidebarRow, children: [_jsx(Skeleton, { shape: "circle", style: { width: 16 } }), _jsx(Skeleton, { shape: "text", style: { width: textWidths[index % textWidths.length] } })] }, index)))] }));
77
75
  }
78
76
  /** Stands in for a page header: optional avatar, title, meta line, and action buttons. */
79
77
  export function PageHeaderSkeleton({ avatar = false, actions = 0, }) {
80
- return (_jsxs(Toolbar, { render: _jsx("header", {}), gap: "16", justify: "between", stackOnPhone: true, children: [_jsxs(Cluster, { gap: "12", wrap: false, children: [avatar && _jsx(Skeleton, { shape: "circle", style: { width: 50 } }), _jsxs("div", { children: [_jsx("div", { className: pageTitle, children: _jsx(Skeleton, { shape: "text", style: { width: 220 } }) }), _jsx(Text, { render: _jsx("div", {}), size: "caption", children: _jsx(Skeleton, { shape: "text", style: { width: 160 } }) })] })] }), actions > 0 && (_jsx(Cluster, { gap: "12", wrap: false, children: Array.from({ length: actions }, (_, index) => (_jsx(Skeleton, { style: { width: 112, height: 38 } }, index))) }))] }));
78
+ return (_jsxs(Toolbar, { render: _jsx("header", {}), gap: "16", justify: "between", stackOnPhone: true, children: [_jsxs(Cluster, { gap: "12", wrap: false, children: [avatar && _jsx(Skeleton, { shape: "circle", style: { width: "var(--sizes-avatar\\.welcome)" } }), _jsxs("div", { children: [_jsx("div", { className: pageTitle, children: _jsx(Skeleton, { shape: "text", style: { width: 220 } }) }), _jsx(Text, { render: _jsx("div", {}), size: "caption", children: _jsx(Skeleton, { shape: "text", style: { width: 160 } }) })] })] }), actions > 0 && (_jsx(Cluster, { gap: "12", wrap: false, children: Array.from({ length: actions }, (_, index) => (_jsx(Skeleton, { height: "control", style: { width: 112 } }, index))) }))] }));
81
79
  }
82
80
  /** Stands in for a panel of label-value rows. */
83
81
  export function PanelSkeleton({ rows = 4 }) {
84
- return (_jsxs(Panel, { tone: "outline", children: [_jsx(PanelHeader, { level: 2, title: _jsx(Skeleton, { shape: "text", style: { width: 120 } }) }), _jsx("div", { children: Array.from({ length: rows }, (_, index) => (_jsxs(Toolbar, { justify: "between", className: panelRow, children: [_jsx(Skeleton, { shape: "text", style: { width: 80 } }), _jsx(Skeleton, { shape: "text", style: { width: 96 + (index % 3) * 24 } })] }, index))) })] }));
82
+ return (_jsxs(Panel, { tone: "outline", children: [_jsx(PanelHeader, { level: 2, title: _jsx(Skeleton, { shape: "text", width: "medium" }) }), _jsx("div", { children: Array.from({ length: rows }, (_, index) => (_jsxs(Toolbar, { justify: "between", className: panelRow, children: [_jsx(Skeleton, { shape: "text", style: { width: 80 } }), _jsx(Skeleton, { shape: "text", style: { width: 96 + (index % 3) * 24 } })] }, index))) })] }));
85
83
  }
86
84
  /* Each placeholder row varies its bars' widths, so a column of them does not read as a grid. */
87
85
  const listRowWidths = [
@@ -89,25 +87,22 @@ const listRowWidths = [
89
87
  [180, 120],
90
88
  [200, 70],
91
89
  ];
92
- /** Stands in for list rows: a line of text over a line of small print, then a status chip. */
93
90
  export function ListRowsSkeleton({ rows = 3 }) {
94
91
  return (_jsx("div", { children: Array.from({ length: rows }, (_, index) => {
95
92
  const [text, caption] = listRowWidths[index % listRowWidths.length];
96
93
  return (_jsxs("div", { className: listRow, children: [_jsxs("div", { className: listRowCopy, children: [_jsx(Skeleton, { shape: "text", height: "line", style: { maxWidth: text } }), _jsx(Skeleton, { shape: "text", height: "smallLine", style: { maxWidth: caption } })] }), _jsx(Skeleton, { shape: "pill", width: "short" })] }, index));
97
94
  }) }));
98
95
  }
99
- /** Stands in for a stat tile: its label, a small badge for the figure, and a line of small print. */
100
96
  export function StatTileSkeleton({ className }) {
101
- return (_jsxs("div", { className: cx(statTile, className), children: [_jsx(Skeleton, { shape: "text", height: "line", style: { width: 100 } }), _jsx(Skeleton, { shape: "pill", height: "badge", style: { width: 48 } }), _jsx(Skeleton, { shape: "text", height: "smallLine", style: { width: 120 } })] }));
97
+ return (_jsxs("div", { className: cx(statTile, className), children: [_jsx(Skeleton, { shape: "text", height: "line", style: { width: 100 } }), _jsx(Skeleton, { shape: "pill", height: "badge", style: { width: 48 } }), _jsx(Skeleton, { shape: "text", height: "smallLine", width: "medium" })] }));
102
98
  }
103
99
  const cardBarWidths = ["35%", "46%", "60%", "23%"];
104
- /** Stands in for a card: a title and its meta line, labelled bars, and a takeaway under a rule. */
105
100
  export function CardSkeleton({ bars = 4 }) {
106
101
  return (_jsxs("div", { className: card, children: [_jsxs("div", { className: cardHeader, children: [_jsx(Skeleton, { shape: "text", height: "line", style: { width: 170 } }), _jsx(Skeleton, { shape: "text", height: "smallLine", style: { maxWidth: 220 } })] }), _jsx("div", { className: cardBars, children: Array.from({ length: bars }, (_, index) => (_jsxs("div", { className: cardBar, children: [_jsx(Skeleton, { shape: "text", height: "smallLine", style: { width: 56 } }), _jsx(Skeleton, { height: "bar", width: cardBarWidths[index % cardBarWidths.length] })] }, index))) }), _jsx("div", { className: cardTakeaway, children: _jsx(Skeleton, { shape: "text", height: "smallLine", style: { maxWidth: 200 } }) })] }));
107
102
  }
108
103
  /** Placeholder for a row's compact edit and delete icon buttons. */
109
104
  export function RowActionsSkeleton() {
110
- return (_jsxs(Cluster, { gap: "12", render: _jsx("span", {}), children: [_jsx(Skeleton, { shape: "circle", style: { width: 24 } }), _jsx(Skeleton, { shape: "circle", style: { width: 24 } })] }));
105
+ return (_jsxs(Cluster, { gap: "12", render: _jsx("span", {}), children: [_jsx(Skeleton, { shape: "circle" }), _jsx(Skeleton, { shape: "circle" })] }));
111
106
  }
112
107
  const placeholderColumn = createTableColumns();
113
108
  /**
@@ -24,8 +24,13 @@ export type Stage = {
24
24
  /** The stage a record is at: the first neither done nor ahead, else the last done, else the first. */
25
25
  export declare function currentStageIndex(stages: readonly Pick<Stage, "status">[]): number;
26
26
  export type StageStripProps = Omit<ComponentProps<"ol">, "children" | "defaultValue"> & {
27
+ /** At least one; an empty list throws. */
27
28
  stages: readonly Stage[];
28
- /** The chosen stage's id; the current stage while neither this nor `defaultValue` is set. */
29
+ /**
30
+ * The chosen stage's id, which must name one of `stages`; the current stage while neither this
31
+ * nor `defaultValue` is set. Left to the strip, a choice whose stage leaves `stages` goes back
32
+ * to the current stage.
33
+ */
29
34
  value?: string;
30
35
  defaultValue?: string;
31
36
  onValueChange?: (id: string) => void;
@@ -44,10 +49,8 @@ export type StepAction = {
44
49
  content: ReactNode;
45
50
  };
46
51
  };
47
- /** One way forward from a stuck step. */
48
52
  export type HelpOption = {
49
53
  label: string;
50
- /** What choosing it does, in a line. */
51
54
  detail?: string;
52
55
  icon?: ReactNode;
53
56
  onSelect?: () => void;
@@ -1,12 +1,6 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /*
3
- * A record's path through its stages, and the work at the stage it is at. `StepDot` marks a
4
- * step's status wherever one is listed; `StageStrip` is the path as one row of stages joined by
5
- * connectors, each a button that chooses its stage, and `PartsRollup` stands in for it on a record
6
- * split into parts; `CurrentStep` is the attention row for the step the reader acts on, and
7
- * `StepChain` the steps that follow from it, as `StepChip`s, and `HelpMenu` its ways forward when
8
- * stuck; `Requirement` is one thing a stage needs and `StageChecklist` lists them per stage;
9
- * `ParallelChip` is someone else's work under way; `ConfirmationRow` says a move landed.
3
+ * A record's path through its stages, and the work at the stage it is at.
10
4
  */
11
5
  import { Menu as BaseMenu } from "@base-ui/react/menu";
12
6
  import { CaretDownIcon, CaretUpIcon, CheckIcon, SparkleIcon } from "@phosphor-icons/react";
@@ -14,17 +8,13 @@ import { css, cva, cx } from "#primitives/css";
14
8
  import { Button } from "./button.js";
15
9
  import { useControllableState } from "./controllable-state.js";
16
10
  import { DateTime } from "./date-time.js";
11
+ import { glassMenuSurface } from "./glass-menu.js";
17
12
  import { HotkeyLayer } from "./hotkeys.js";
18
13
  import { icon, Spinner } from "./icon.js";
19
14
  import { Cluster, MutedText } from "./layout.js";
20
15
  import { useCiridaeLocale } from "./locale.js";
21
16
  import { Menu } from "./menu.js";
22
17
  import { Popover } from "./overlays.js";
23
- /*
24
- * Step dot: 16 on the strip, 14 on rows, 12 inside chips. A ring in its status's hue, solid or
25
- * dashed, with a mark inside: a check on the green glass once done, a dot for the reader's step
26
- * and the agent's, a bar for a blocked one. Waiting, ahead and locked are the ring alone.
27
- */
28
18
  const stepDot = cva({
29
19
  base: {
30
20
  display: "inline-grid",
@@ -42,7 +32,7 @@ const stepDot = cva({
42
32
  // The green glass, its hairline drawn by the `[data-edge]` ring in place of the border.
43
33
  done: {
44
34
  borderWidth: "0!",
45
- background: "token(gradients.stepDoneGlass)",
35
+ background: "[token(gradients.stepDoneGlass)]",
46
36
  color: "fg.primary",
47
37
  "--edge": "token(gradients.border.stepDoneGlass)",
48
38
  _light: { color: "accent.green" },
@@ -87,19 +77,18 @@ const stepDot = cva({
87
77
  },
88
78
  defaultVariants: { status: "todo", size: "medium" },
89
79
  });
90
- // The marks inside, as shares of the dot so every size draws them alike: the kit's 7px centre in
91
- // a 16px dot, measured across the whole dot rather than inside its ring.
80
+ // The marks inside are shares of the dot, measured across the whole dot rather than inside its ring.
92
81
  const stepDotCenter = css({
93
- width: "calc(var(--step-dot-size) * 0.4375)",
94
- height: "calc(var(--step-dot-size) * 0.4375)",
82
+ width: "[calc(var(--step-dot-size) * 0.4375)]",
83
+ height: "[calc(var(--step-dot-size) * 0.4375)]",
95
84
  borderRadius: "round",
96
85
  background: "currentColor",
97
- "[data-status=agent] > &": { width: "25%", height: "25%" },
86
+ "[data-status=agent] > &": { width: "[25%]", height: "[25%]" },
98
87
  });
99
88
  const stepDotBar = css({
100
- width: "44%",
101
- height: "10%",
102
- minHeight: "1px",
89
+ width: "[44%]",
90
+ height: "[10%]",
91
+ minHeight: "[1px]",
103
92
  borderRadius: "round",
104
93
  background: "currentColor",
105
94
  });
@@ -108,10 +97,7 @@ export function StepDot({ status, size = "medium", className, children, ...props
108
97
  return (_jsx("span", { "aria-hidden": "true", ...props, className: cx(stepDot({ status, size }), className), "data-ciridae-ui": "", "data-edge": status === "done" ? "gradient" : undefined, "data-status": status, children: children ?? (_jsxs(_Fragment, { children: [status === "done" && _jsx(CheckIcon, { weight: "bold" }), (status === "current" || status === "agent") && _jsx("span", { className: stepDotCenter }), status === "blocked" && _jsx("span", { className: stepDotBar })] })) }));
109
98
  }
110
99
  /*
111
- * Stage strip: the stages in one row, each its dot, name and meta, joined by connectors that
112
- * stretch to fill the width, green out of a finished stage and grey ahead. The reader's stage is
113
- * a warm pill, a blocked one a grey pill with its meta in red. Every stage is a button that
114
- * chooses it. As the box narrows, metas go first, then every stage but the current and the chosen
100
+ * Stage strip: as the box narrows, metas go first, then every stage but the current and the chosen
115
101
  * one folds to its dot. Past `maxVisible` the finished stages fold into one "N done" stage and the
116
102
  * tail into a "+N" count, each listing its stages when pressed; the fold follows the current
117
103
  * stage, never the choice, so a stage stays where it was clicked.
@@ -134,8 +120,8 @@ const strip = css({
134
120
  });
135
121
  const stripItem = css({ display: "contents" });
136
122
  const connector = css({
137
- flex: "1 1 0",
138
- minWidth: "token(spacing.layout.controlGap)",
123
+ flex: "[1 1 0]",
124
+ minWidth: "[token(spacing.layout.controlGap)]",
139
125
  height: "border.hairline",
140
126
  borderRadius: "round",
141
127
  background: "border.divider",
@@ -145,10 +131,10 @@ const stage = css({
145
131
  display: "flex",
146
132
  alignItems: "center",
147
133
  gap: "control.iconGap",
148
- flex: "0 1 auto",
134
+ flex: "[0 1 auto]",
149
135
  minWidth: "0",
150
136
  paddingBlock: "panel.hairline",
151
- paddingInline: "0",
137
+ paddingInline: "none",
152
138
  border: "none",
153
139
  borderRadius: "round",
154
140
  background: "transparent",
@@ -161,28 +147,26 @@ const stage = css({
161
147
  whiteSpace: "nowrap",
162
148
  cursor: "pointer",
163
149
  "&[data-state=todo], &[data-state=locked]": { color: "fg.secondary" },
164
- // The reader's stage and a blocked one are pills: the current stage's warm glass, and the
165
- // selected glass in light, the red glass in dark. Their edge takes a pixel a side, as the kit's.
150
+ // Their edge takes a pixel a side, as the kit's.
166
151
  "&:is([data-state=current], [data-state=blocked])": {
167
152
  paddingInlineStart: "control.block",
168
153
  paddingInlineEnd: "control.iconInline",
169
154
  border: "1px solid transparent",
170
155
  },
171
156
  "&[data-state=current]": {
172
- background: "token(gradients.currentStageGlass)",
157
+ background: "[token(gradients.currentStageGlass)]",
173
158
  color: "accent.yellow",
174
159
  "--edge": "token(gradients.border.currentStageGlass)",
175
160
  },
176
161
  "&[data-state=blocked]": {
177
- background: "token(gradients.dangerGlass)",
178
- _light: { background: "token(gradients.selected)" },
162
+ background: "[token(gradients.dangerGlass)]",
163
+ _light: { background: "[token(gradients.selected)]" },
179
164
  "--edge": "token(gradients.border.raised)",
180
165
  "& [data-stage-meta]": { color: "accent.red" },
181
166
  },
182
- // A stage under the pointer, focused or chosen takes a faint pill, reaching past a plain one.
183
167
  "&:is(:hover, :focus-visible, [aria-pressed=true], [data-selected]):not([data-current])": {
184
168
  background: "bg.rowHover",
185
- boxShadow: "0 0 0 token(spacing.panel.hairline) token(colors.bg.rowHover)",
169
+ boxShadow: "[0 0 0 token(spacing.panel.hairline) token(colors.bg.rowHover)]",
186
170
  },
187
171
  _focusVisible: { focusRing: "outer" },
188
172
  });
@@ -191,9 +175,8 @@ const stageMeta = css({
191
175
  flexShrink: "0",
192
176
  color: "fg.label",
193
177
  fontSize: "code",
194
- "[data-state=current] > &": { color: "inherit" },
178
+ "[data-state=current] > &": { color: "[inherit]" },
195
179
  });
196
- // The tail past the fold: a quiet count that lists the stages it stands for.
197
180
  const moreStages = css({
198
181
  flexShrink: "0",
199
182
  padding: "none",
@@ -238,8 +221,14 @@ function stripItems(stages, maxVisible, currentIndex) {
238
221
  export function StageStrip({ stages, value, defaultValue, onValueChange, maxVisible = 7, className, ...props }) {
239
222
  const { labels } = useCiridaeLocale();
240
223
  const currentIndex = currentStageIndex(stages);
224
+ // Both hooks run before the checks below, so React sees the same hooks on every render.
241
225
  const [chosen, setChosen] = useControllableState(value, defaultValue ?? stages[currentIndex]?.id ?? "", onValueChange);
226
+ if (stages.length === 0)
227
+ throw new Error("StageStrip needs at least one stage");
242
228
  const chosenIndex = stages.findIndex((item) => item.id === chosen);
229
+ if (value !== undefined && chosenIndex < 0) {
230
+ throw new Error(`StageStrip's value "${value}" names none of its stages`);
231
+ }
243
232
  const selectedIndex = chosenIndex >= 0 ? chosenIndex : currentIndex;
244
233
  const menuItems = (indices) => indices.map((index) => ({
245
234
  label: stages[index].label,
@@ -263,9 +252,8 @@ export function StageStrip({ stages, value, defaultValue, onValueChange, maxVisi
263
252
  }) }));
264
253
  }
265
254
  /*
266
- * Current step: the attention row, with the inner card when expanded. Light paints the reader's
267
- * move, a ready step and a stuck one in their solid tint, dark in their hue's glass. The row sets
268
- * `--step-edge`, the hairline it and its card draw, in the tint's edge; the grey glass's otherwise.
255
+ * The row sets `--step-edge`, the hairline it and its card draw, in the tint's edge; the grey
256
+ * glass's otherwise.
269
257
  */
270
258
  const attentionRow = cva({
271
259
  base: {
@@ -282,29 +270,29 @@ const attentionRow = cva({
282
270
  variants: {
283
271
  tone: {
284
272
  warning: {
285
- background: "token(gradients.tinted)",
273
+ background: "[token(gradients.tinted)]",
286
274
  "--step-edge": "token(gradients.border.warningTint)",
287
275
  _light: { background: "bg.warningTint" },
288
276
  },
289
277
  success: {
290
- background: "token(gradients.successGlass)",
278
+ background: "[token(gradients.successGlass)]",
291
279
  "--step-edge": "token(gradients.border.successTint)",
292
280
  _light: { background: "bg.successTint" },
293
281
  },
294
282
  info: {
295
- background: "token(gradients.infoGlass)",
283
+ background: "[token(gradients.infoGlass)]",
296
284
  "--step-edge": "token(gradients.border.infoGlass)",
297
285
  },
298
286
  // Waiting: the raised glass in dark; in light the grey well inside a flat divider hairline.
299
287
  neutral: {
300
- background: "token(gradients.raised)",
288
+ background: "[token(gradients.raised)]",
301
289
  _light: {
302
290
  background: "bg.field",
303
291
  "--step-edge": "linear-gradient(token(colors.border.divider), token(colors.border.divider))",
304
292
  },
305
293
  },
306
294
  danger: {
307
- background: "token(gradients.dangerGlass)",
295
+ background: "[token(gradients.dangerGlass)]",
308
296
  "--step-edge": "token(gradients.border.errorTint)",
309
297
  _light: { background: "bg.errorTint" },
310
298
  },
@@ -312,8 +300,8 @@ const attentionRow = cva({
312
300
  },
313
301
  });
314
302
  /*
315
- * The fold toggle at the header's end: a 24px round button in its hue's glass. In dark it takes
316
- * the row's edge; in light the yellow and red ones keep their glass's own, softer than the tint's.
303
+ * In dark the fold toggle takes the row's edge; in light the yellow and red ones keep their
304
+ * glass's own, softer than the tint's.
317
305
  */
318
306
  const collapseToggle = cva({
319
307
  base: {
@@ -323,22 +311,22 @@ const collapseToggle = cva({
323
311
  width: "control.shortcut",
324
312
  height: "control.shortcut",
325
313
  borderRadius: "round",
326
- background: "token(gradients.raised)",
314
+ background: "[token(gradients.raised)]",
327
315
  color: "fg.primary",
328
316
  "--edge": "var(--step-edge)",
329
317
  },
330
318
  variants: {
331
319
  tone: {
332
320
  warning: {
333
- background: "token(gradients.tinted)",
321
+ background: "[token(gradients.tinted)]",
334
322
  _light: { "--edge": "token(gradients.border.tinted)" },
335
323
  },
336
- success: { background: "token(gradients.successGlass)" },
337
- info: { background: "token(gradients.infoGlass)" },
324
+ success: { background: "[token(gradients.successGlass)]" },
325
+ info: { background: "[token(gradients.infoGlass)]" },
338
326
  // The grey toggle keeps the raised glass's edge where its row draws a flat hairline.
339
327
  neutral: { _light: { "--edge": "token(gradients.border.raised)" } },
340
328
  danger: {
341
- background: "token(gradients.dangerGlass)",
329
+ background: "[token(gradients.dangerGlass)]",
342
330
  _light: { "--edge": "token(gradients.border.dangerGlass)" },
343
331
  },
344
332
  },
@@ -348,7 +336,7 @@ const attentionHeader = css({
348
336
  display: "flex",
349
337
  alignItems: "center",
350
338
  gap: "control.iconGap",
351
- width: "100%",
339
+ width: "full",
352
340
  height: "control.compact",
353
341
  paddingInline: "control.block",
354
342
  border: "none",
@@ -369,7 +357,6 @@ const attentionHeader = css({
369
357
  // A stuck step's header is the muted red the kit gives red text on its tint.
370
358
  "&[data-tone=danger]": { color: "accent.redDark" },
371
359
  });
372
- // The card holds the step on the page's own face: the solid card in light, the panel in dark.
373
360
  const attentionCard = css({
374
361
  display: "flex",
375
362
  alignItems: "center",
@@ -415,25 +402,14 @@ function StepActionButton({ action, variant, }) {
415
402
  return button;
416
403
  return (_jsx(Popover, { trigger: button, open: action.popover.open, onOpenChange: action.popover.onOpenChange, children: action.popover.content }));
417
404
  }
418
- /*
419
- * Help menu: the ways forward a stuck step offers behind "Not sure?", on the popover's glass. A
420
- * header says what the menu is for; each option is an icon on the raised tile, a title and a line
421
- * on what it does.
422
- */
423
- const helpPopup = css({
405
+ /** The positioner is the positioned element, so it carries the stacking order. */
406
+ const helpPositioner = css({ zIndex: "popover" });
407
+ const helpPopup = css(glassMenuSurface, {
424
408
  display: "grid",
425
409
  width: "overlay.helpMenu",
426
- maxWidth: "calc(100vw - token(spacing.panel.roomy))",
427
- padding: "menu.inset",
428
- border: "1px solid token(colors.border.divider)",
429
- borderRadius: "action",
430
- background: "bg.popover",
431
- backdropFilter: "blur(token(blurs.popover))",
432
- boxShadow: "soft",
433
- color: "fg.primary",
410
+ maxWidth: "[calc(100vw - token(spacing.panel.roomy))]",
434
411
  fontWeight: "medium",
435
412
  letterSpacing: "compact",
436
- outline: "none",
437
413
  });
438
414
  const helpHeader = css({
439
415
  display: "grid",
@@ -452,8 +428,8 @@ const helpOption = css({
452
428
  paddingInline: "control.compactInline",
453
429
  borderRadius: "control",
454
430
  cursor: "pointer",
455
- outline: "none",
456
- "&[data-highlighted]": { background: "token(gradients.selected)" },
431
+ outline: "0",
432
+ "&[data-highlighted]": { background: "[token(gradients.selected)]" },
457
433
  });
458
434
  const helpTile = css({
459
435
  display: "grid",
@@ -462,14 +438,14 @@ const helpTile = css({
462
438
  width: "control.roundSmall",
463
439
  height: "control.roundSmall",
464
440
  borderRadius: "action",
465
- background: "token(gradients.raised)",
441
+ background: "[token(gradients.raised)]",
466
442
  fontSize: "icon.small",
467
443
  "--edge": "token(gradients.border.raised)",
468
444
  });
469
445
  const helpCopy = css({ display: "grid", gap: "control.trackInset", minWidth: "0" });
470
446
  const helpTitle = css({ fontSize: "caption", lineHeight: "tight" });
471
447
  export function HelpMenu({ trigger, title, detail, options }) {
472
- return (_jsxs(BaseMenu.Root, { children: [_jsx(BaseMenu.Trigger, { render: trigger }), _jsx(BaseMenu.Portal, { children: _jsx(HotkeyLayer, { children: _jsx(BaseMenu.Positioner, { className: css({ zIndex: "popover" }), sideOffset: 6, align: "end", children: _jsxs(BaseMenu.Popup, { className: helpPopup, "data-ciridae-ui": "", children: [_jsxs("div", { className: helpHeader, role: "presentation", children: [title, detail !== undefined && _jsx("span", { className: helpDetail, children: detail })] }), options.map((option) => (_jsxs(BaseMenu.Item, { className: helpOption, onClick: option.onSelect, children: [option.icon && (_jsx("span", { className: helpTile, "data-ciridae-ui": "", "data-edge": "gradient", children: option.icon })), _jsxs("span", { className: helpCopy, children: [_jsx("span", { className: helpTitle, children: option.label }), option.detail && _jsx("span", { className: helpDetail, children: option.detail })] })] }, option.label)))] }) }) }) })] }));
448
+ return (_jsxs(BaseMenu.Root, { children: [_jsx(BaseMenu.Trigger, { render: trigger }), _jsx(BaseMenu.Portal, { children: _jsx(HotkeyLayer, { children: _jsx(BaseMenu.Positioner, { className: helpPositioner, sideOffset: 6, align: "end", children: _jsxs(BaseMenu.Popup, { className: helpPopup, "data-ciridae-ui": "", children: [_jsxs("div", { className: helpHeader, role: "presentation", children: [title, detail !== undefined && _jsx("span", { className: helpDetail, children: detail })] }), options.map((option) => (_jsxs(BaseMenu.Item, { className: helpOption, onClick: option.onSelect, children: [option.icon && (_jsx("span", { className: helpTile, "data-ciridae-ui": "", "data-edge": "gradient", children: option.icon })), _jsxs("span", { className: helpCopy, children: [_jsx("span", { className: helpTitle, children: option.label }), option.detail && _jsx("span", { className: helpDetail, children: option.detail })] })] }, option.label)))] }) }) }) })] }));
473
449
  }
474
450
  /** The step the reader acts on: a tinted header that folds the card with its title and actions. */
475
451
  export function CurrentStep({ tone, meta, title, description, primary, secondary, help, busy = false, expanded: ownExpanded, defaultExpanded = true, onExpandedChange, className, ...props }) {
@@ -477,17 +453,16 @@ export function CurrentStep({ tone, meta, title, description, primary, secondary
477
453
  const [expanded, setExpanded] = useControllableState(ownExpanded, defaultExpanded, onExpandedChange);
478
454
  return (_jsxs("div", { ...props, className: cx(attentionRow({ tone }), className), "data-ciridae-ui": "", "data-edge": "gradient", children: [_jsxs("button", { type: "button", className: attentionHeader, "data-tone": tone, "aria-expanded": expanded, onClick: () => setExpanded(!expanded), children: [busy ? (_jsx(Spinner, { size: "compact", "aria-hidden": "true" })) : (_jsx(StepDot, { status: toneStatus[tone], size: "small" })), _jsx("span", { className: css({ flex: "1" }), children: meta }), _jsx("span", { className: collapseToggle({ tone }), "data-ciridae-ui": "", "data-edge": "gradient", children: expanded ? (_jsx(CaretUpIcon, { className: icon({ size: "compact" }) })) : (_jsx(CaretDownIcon, { className: icon({ size: "compact" }) })) })] }), expanded && (_jsxs("div", { className: attentionCard, "data-ciridae-ui": "", "data-edge": "gradient", children: [_jsxs("div", { className: css({ minWidth: "0" }), children: [_jsx("div", { className: attentionTitle, children: title }), description !== undefined && _jsx("div", { className: attentionDescription, children: description })] }), (help || secondary || primary) && (_jsxs(Cluster, { gap: "4", className: stepActions, children: [help && (_jsx(HelpMenu, { ...help, trigger: _jsx(Button, { variant: "ghost", children: labels.record.notSure }) })), secondary && (_jsx(StepActionButton, { action: secondary, variant: tone === "warning" ? "tinted" : "secondary" })), primary && _jsx(StepActionButton, { action: primary, variant: "primary" })] }))] }))] }));
479
455
  }
480
- /* Confirmation row: the ready step's green, one 32px line inside a 4px inset. */
481
456
  const confirmation = css({
482
457
  display: "flex",
483
458
  alignItems: "center",
484
459
  gap: "control.iconGap",
485
- minHeight: "calc(token(sizes.control.compact) + token(spacing.panel.hairline) * 2)",
460
+ minHeight: "[calc(token(sizes.control.compact) + token(spacing.panel.hairline) * 2)]",
486
461
  padding: "panel.hairline",
487
462
  paddingInlineStart: "control.compactInline",
488
463
  border: "1px solid transparent",
489
464
  borderRadius: "action",
490
- background: "token(gradients.successGlass)",
465
+ background: "[token(gradients.successGlass)]",
491
466
  color: "accent.green",
492
467
  fontSize: "code",
493
468
  fontWeight: "medium",
@@ -501,9 +476,7 @@ export function ConfirmationRow({ message, at, onUndo, labels: ownLabels, classN
501
476
  return (_jsxs("div", { role: "status", ...props, className: cx(confirmation, className), "data-ciridae-ui": "", "data-edge": "gradient", children: [_jsx(StepDot, { status: "done", size: "small" }), _jsx("span", { className: css({ flex: "1" }), children: message }), _jsx(MutedText, { children: _jsx(DateTime, { value: at }) }), onUndo && (_jsx(Button, { variant: "secondary", size: "small", onClick: onUndo, children: labels.undo }))] }));
502
477
  }
503
478
  /*
504
- * Requirement: one thing a stage needs, as its 12px dot, its 13px name and a muted meta. A done
505
- * one steps back to the muted grey; a locked one fades, so what is coming stays in view; a
506
- * dependent one indents under the step it waits on.
479
+ * Requirement: a locked one fades, so what is coming stays in view.
507
480
  */
508
481
  const requirement = css({
509
482
  display: "inline-flex",
@@ -517,9 +490,12 @@ const requirement = css({
517
490
  lineHeight: "tight",
518
491
  "&[data-status=done]": { color: "fg.subtle" },
519
492
  // The row fades as a whole, so its dot does not fade a second time.
520
- "&[data-status=locked]": { opacity: "locked.requirement", "& > [data-status]": { opacity: "1" } },
493
+ "&[data-status=locked]": {
494
+ opacity: "locked.requirement",
495
+ "& > [data-status]": { opacity: "[1]" },
496
+ },
521
497
  "&[data-nested]": {
522
- paddingInlineStart: "calc(token(sizes.avatar.micro) + token(spacing.control.iconGap))",
498
+ paddingInlineStart: "[calc(token(sizes.avatar.micro) + token(spacing.control.iconGap))]",
523
499
  },
524
500
  });
525
501
  const requirementMeta = css({ flexShrink: "0", color: "fg.subtle", fontSize: "code" });
@@ -566,7 +542,7 @@ const stepChip = css({
566
542
  paddingInlineEnd: "control.block",
567
543
  border: "1px solid transparent",
568
544
  borderRadius: "pill",
569
- background: "token(gradients.raised)",
545
+ background: "[token(gradients.raised)]",
570
546
  boxShadow: "soft",
571
547
  color: "fg.label",
572
548
  fontSize: "code",
@@ -581,7 +557,7 @@ const stepChip = css({
581
557
  height: "control.shortcut",
582
558
  color: "accent.blue",
583
559
  "& > [data-label]": {
584
- background: "token(gradients.chart.progress)",
560
+ background: "[token(gradients.chart.progress)]",
585
561
  backgroundClip: "text",
586
562
  color: "transparent",
587
563
  },
@@ -592,35 +568,36 @@ export function StepChip({ status, children, className, ...props }) {
592
568
  return (_jsxs("span", { ...props, className: cx(stepChip, className), "data-ciridae-ui": "", "data-edge": "gradient", "data-status": status, children: [status === "agent" ? (_jsx(SparkleIcon, { weight: "fill", "aria-hidden": "true" })) : (_jsx(StepDot, { status: status, size: "chip" })), _jsx("span", { "data-label": "", children: children })] }));
593
569
  }
594
570
  /*
595
- * Step chain: the steps that follow from the expanded step, one row a lead: a tree line from the
596
- * step above, the lead's dot and words, then its steps as chips, each joined to the one before by
597
- * a short link in that one's hue: green after a done step, yellow after the current, grey ahead.
571
+ * Step chain: each chip is joined to the one before by a short link in that one's hue: green after
572
+ * a done step, yellow after the current, grey ahead.
598
573
  */
599
574
  const stepChain = css({
600
575
  display: "flex",
601
- alignItems: "flex-end",
576
+ alignItems: "flex-start",
602
577
  gap: "layout.tightGap",
603
- height: "control.compact",
578
+ minHeight: "control.compact",
604
579
  paddingInline: "control.iconGap",
605
580
  minWidth: "0",
606
581
  });
607
- // An L from the step above down to the lead, its corner rounded.
608
582
  const chainTree = css({
609
583
  flexShrink: "0",
610
584
  alignSelf: "flex-start",
611
- width: "9px",
612
- height: "calc(100% - token(spacing.panel.default) + 1px)",
585
+ width: "[9px]",
586
+ height: "[calc(token(sizes.control.compact) - token(spacing.panel.default) + 1px)]",
613
587
  borderInlineStart: "1px solid token(colors.border.divider)",
614
588
  borderBottom: "1px solid token(colors.border.divider)",
615
589
  borderEndStartRadius: "keycap",
616
590
  });
591
+ // Where the chain is wider than its row, its chips wrap, the first line staying level with the tree.
617
592
  const chainItems = css({
618
593
  display: "flex",
594
+ flexWrap: "wrap",
619
595
  alignItems: "center",
596
+ alignContent: "center",
620
597
  gap: "control.iconGap",
621
- height: "control.chip",
622
598
  minWidth: "0",
623
- overflow: "hidden",
599
+ minHeight: "control.compact",
600
+ paddingTop: "[calc(token(sizes.control.compact) - token(sizes.control.chip))]",
624
601
  });
625
602
  const chainLead = css({
626
603
  flexShrink: "0",
@@ -635,7 +612,7 @@ const chainLead = css({
635
612
  });
636
613
  const chainLink = css({
637
614
  flexShrink: "0",
638
- width: "token(spacing.control.compactInline)",
615
+ width: "[token(spacing.control.compactInline)]",
639
616
  height: "border.hairline",
640
617
  background: "border.divider",
641
618
  "&[data-after=done]": { background: "accent.green" },
@@ -644,11 +621,6 @@ const chainLink = css({
644
621
  export function StepChain({ lead, steps, className, ...props }) {
645
622
  return (_jsxs("div", { ...props, className: cx(stepChain, className), "data-ciridae-ui": "", children: [_jsx("span", { className: chainTree, "aria-hidden": "true" }), _jsxs("span", { className: chainItems, children: [_jsx(StepDot, { status: lead.status, size: "small" }), _jsx("span", { className: chainLead, "data-status": lead.status, children: lead.label }), steps.map((step, index) => (_jsxs("span", { className: css({ display: "contents" }), children: [_jsx("span", { className: chainLink, "aria-hidden": "true", "data-after": index === 0 ? lead.status : steps[index - 1].status }), _jsx(StepChip, { status: step.status, children: step.label })] }, step.id)))] })] }));
646
623
  }
647
- /*
648
- * Parallel chip: someone else's work under way beside the reader's, on the selected glass. A
649
- * person shows their avatar, the agent its dashed blue dot, the system a dashed grey one; then
650
- * who, what they are doing, and at most one action.
651
- */
652
624
  const parallelChip = css({
653
625
  display: "inline-flex",
654
626
  alignItems: "center",
@@ -659,7 +631,7 @@ const parallelChip = css({
659
631
  paddingInlineEnd: "control.compactInline",
660
632
  border: "1px solid transparent",
661
633
  borderRadius: "shell",
662
- background: "token(gradients.selected)",
634
+ background: "[token(gradients.selected)]",
663
635
  fontWeight: "medium",
664
636
  letterSpacing: "compact",
665
637
  lineHeight: "tight",
@@ -704,16 +676,16 @@ const partsLabel = css({ color: "fg.primary", fontSize: "caption" });
704
676
  const partsBar = css({
705
677
  display: "flex",
706
678
  gap: "layout.tightGap",
707
- width: "320px",
708
- maxWidth: "100%",
679
+ width: "[320px]",
680
+ maxWidth: "full",
709
681
  height: "progress.track",
710
682
  });
711
683
  const partsSegment = css({
712
- flex: "1 1 0",
684
+ flex: "[1 1 0]",
713
685
  borderRadius: "round",
714
686
  background: "chart.notStarted",
715
687
  "&[data-state=done]": { background: "accent.green" },
716
- "&[data-state=needsYou]": { background: "token(gradients.chart.atRisk)" },
688
+ "&[data-state=needsYou]": { background: "[token(gradients.chart.atRisk)]" },
717
689
  });
718
690
  const partsLegend = css({ color: "fg.muted", fontSize: "code", _light: { color: "fg.subtle" } });
719
691
  export function PartsRollup({ label, parts, legend, className, ...props }) {
@@ -17,10 +17,7 @@ export type SparklineProps = Omit<ComponentProps<"div">, "children"> & {
17
17
  strokeWidth?: number;
18
18
  endPointSize?: number;
19
19
  };
20
- /**
21
- * A run of values as a line filling its box; decorative, as the figure beside it says what it
22
- * shows. Under two values there is no line, and a dashed rule stands in for it.
23
- */
20
+ /** Decorative, as the figure beside it says what it shows. Under two values there is no line, and a dashed rule stands in for it. */
24
21
  export declare function Sparkline({ values, low: ownLow, high: ownHigh, strokeWidth, endPointSize, className, ...props }: SparklineProps): import("react").JSX.Element;
25
22
  export type MetricCardProps = Omit<useRender.ComponentProps<"div">, "children" | "onSelect"> & {
26
23
  label: ReactNode;
@@ -39,4 +36,4 @@ export type MetricCardProps = Omit<useRender.ComponentProps<"div">, "children" |
39
36
  */
40
37
  divider?: "card" | "left" | "none";
41
38
  };
42
- export declare function MetricCard({ label, value, change, sparkline, onSelect, href, divider, render, className, ...props }: MetricCardProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
39
+ export declare function MetricCard({ label, value, change, sparkline, onSelect, onClick, href, divider, render, className, ...props }: MetricCardProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;