@squadbase/vantage 0.7.1-dev1.cee9cbf → 0.7.1-dev1.db30901

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.
@@ -1,7 +1,7 @@
1
1
  import { ChartFrameContext, useChartSurface, resolveChartColors, resolveFillColors, EChart, CHART_OTHER_COLOR } from './chunk-EG4PX726.js';
2
2
  import { Sparkline } from './chunk-P2KIHF65.js';
3
3
  import { formatDateRange, EMPTY_VALUE, toValueFormatter, formatDate, formatValue, formatPoints, formatKind, formatDelta, MINUS_SIGN, DEFAULT_LOCALE, formatDatesInText } from './chunk-XRKSIC5Z.js';
4
- import { Tooltip, TooltipTrigger, TooltipContent, Badge, SidebarProvider, Sidebar, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarFooter, SidebarRail, SidebarInset, SidebarTrigger, Separator, Input, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Skeleton, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, useIsMobile, Popover, PopoverTrigger, PopoverContent, Calendar, ToggleGroup, ToggleGroupItem, SelectGroup, SelectLabel, Collapsible, CollapsibleTrigger, SidebarMenuButton, SidebarMenuBadge, CollapsibleContent, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarMenuItem, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, Empty, Checkbox, Card, CardHeader, CardDescription, CardTitle, CardAction, CardFooter } from './chunk-MQUIAP66.js';
4
+ import { Tooltip, TooltipTrigger, TooltipContent, Badge, SidebarProvider, Sidebar, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarFooter, SidebarRail, SidebarInset, SidebarTrigger, Separator, Input, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Skeleton, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, useIsMobile, Popover, PopoverTrigger, PopoverContent, Calendar, ToggleGroup, ToggleGroupItem, SelectGroup, SelectLabel, Collapsible, CollapsibleTrigger, SidebarMenuButton, SidebarMenuBadge, CollapsibleContent, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarMenuItem, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, Empty, Checkbox, Card, CardHeader, CardDescription, CardTitle, CardAction, CardFooter } from './chunk-5HBUBVQ3.js';
5
5
  import { useLocale, uiLanguage, Button, weekStartsOn, resolveLocale, defaultFiscalYearStartMonth, FALLBACK_LOCALE } from './chunk-ROHNXP7J.js';
6
6
  import { cn } from './chunk-U736PVHY.js';
7
7
  import { forwardRef, useState, useEffect, createContext, useId, useMemo, useRef, useCallback, Fragment as Fragment$1, useContext, useInsertionEffect, useLayoutEffect } from 'react';
@@ -12,7 +12,7 @@ import { use, registerMap } from 'echarts/core';
12
12
  import { GraphicComponent, VisualMapComponent, GeoComponent } from 'echarts/components';
13
13
  import { ScatterChart as ScatterChart$1, HeatmapChart, MapChart, TreemapChart } from 'echarts/charts';
14
14
  import 'echarts';
15
- import { subMonths, subDays, endOfDay, startOfDay, startOfWeek, subWeeks, endOfWeek, startOfMonth, endOfMonth, isSameDay, addMonths, differenceInCalendarDays, parseISO } from 'date-fns';
15
+ import { subMonths, subDays, endOfDay, startOfDay, startOfWeek, subWeeks, endOfWeek, startOfMonth, endOfMonth, isSameDay, subYears, differenceInCalendarDays, addMonths, parseISO } from 'date-fns';
16
16
  import { flexRender, useReactTable, getPaginationRowModel, getFilteredRowModel, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
17
17
  import { ja } from 'date-fns/locale';
18
18
 
@@ -627,7 +627,7 @@ var DashboardCardFooter = forwardRef(
627
627
  {
628
628
  ref,
629
629
  "data-slot": "dashboard-card-footer",
630
- className: cn("flex items-center px-3 py-1.5 group-data-[size=sm]:px-2", className),
630
+ className: cn("-mx-1 -mb-1 flex min-w-0 items-center justify-between gap-3 border-t px-4 py-2.5 text-xs text-muted-foreground tabular-nums group-data-[size=sm]:px-3", className),
631
631
  ...props
632
632
  }
633
633
  )
@@ -653,6 +653,7 @@ function DashboardCardSkeleton({ className }) {
653
653
  function DashboardCardPreset({
654
654
  title,
655
655
  description,
656
+ headline,
656
657
  actions,
657
658
  footer,
658
659
  children,
@@ -664,15 +665,21 @@ function DashboardCardPreset({
664
665
  ...props
665
666
  }) {
666
667
  const sample = useSampleMark();
667
- const hasHeader = title || description || actions || sample;
668
- return /* @__PURE__ */ jsx(DashboardCard, { className, subgrid, ...props, children: /* @__PURE__ */ jsxs(SampleClaim, { children: [
668
+ const hasTitle = Boolean(title || description);
669
+ const floatingMark = sample && !hasTitle && !headline && !actions;
670
+ const hasHeader = hasTitle || headline || actions || sample && !floatingMark;
671
+ return /* @__PURE__ */ jsx(DashboardCard, { className: cn(floatingMark && "relative", className), subgrid, ...props, children: /* @__PURE__ */ jsxs(SampleClaim, { children: [
672
+ floatingMark && /* @__PURE__ */ jsx(SampleBadge, { label: sample.label, className: "absolute top-2 right-2 z-10" }),
669
673
  hasHeader && /* @__PURE__ */ jsxs(DashboardCardHeader, { className: cn(subgrid && "row-start-1", headerClassName), children: [
670
- (title || description) && /* @__PURE__ */ jsxs("div", { children: [
671
- title && /* @__PURE__ */ jsx(DashboardCardTitle, { children: title }),
674
+ (hasTitle || sample) && /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
675
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
676
+ title && /* @__PURE__ */ jsx(DashboardCardTitle, { children: title }),
677
+ sample && /* @__PURE__ */ jsx(SampleBadge, { label: sample.label })
678
+ ] }),
672
679
  description && /* @__PURE__ */ jsx(DashboardCardDescription, { children: description })
673
680
  ] }),
674
- (actions || sample) && /* @__PURE__ */ jsxs(DashboardCardAction, { className: cn(sample && actions && "flex items-center gap-2"), children: [
675
- sample && /* @__PURE__ */ jsx(SampleBadge, { label: sample.label }),
681
+ (headline || actions) && /* @__PURE__ */ jsxs(DashboardCardAction, { className: "flex items-center gap-2", children: [
682
+ headline && /* @__PURE__ */ jsx("div", { "data-slot": "dashboard-card-headline", className: "text-sm tabular-nums text-muted-foreground", children: headline }),
676
683
  actions
677
684
  ] })
678
685
  ] }),
@@ -1630,6 +1637,9 @@ function legendLines(items, plotWidth, reserve = 0) {
1630
1637
  return Math.min(3, Math.max(1, Math.ceil(width / budget)));
1631
1638
  }
1632
1639
  var ACTIONS_RESERVE = 80;
1640
+ var BAR_MAX_WIDTH = 40;
1641
+ var BAR_RADIUS = 3;
1642
+ var STACK_GAP = 1.5;
1633
1643
  var TIME_LABEL_WIDTH = 80;
1634
1644
  var HIGHLIGHT_LABEL_WIDTH = 96;
1635
1645
  var TARGET_NEAR_SHARE = 0.12;
@@ -1760,6 +1770,7 @@ function buildCartesianOption(cfg) {
1760
1770
  const compared = cartesianSeriesValues(data, [categories[compIdx]], "default")[0];
1761
1771
  return categories.map((_, i) => i === compIdx ? compared : main[mainIdx.indexOf(i)]);
1762
1772
  })();
1773
+ const diverging = kind === "bar" && values.some((s) => s.some((v) => typeof v === "number" && v < 0));
1763
1774
  const comparisonColor = guideColor ? withAlpha(guideColor, COMPARISON_OPACITY) : void 0;
1764
1775
  const labels = data.map((row) => String(row[index] ?? ""));
1765
1776
  const rawIndex = data.map((row) => row[index]);
@@ -1875,14 +1886,16 @@ function buildCartesianOption(cfg) {
1875
1886
  const seriesData = pad(values[c]);
1876
1887
  if (kind === "bar") {
1877
1888
  const rounded = horizontalBars ? [0, 4, 4, 0] : [4, 4, 0, 0];
1878
- const radius = stacked && c !== categories.length - 1 ? 0 : rounded;
1889
+ const radius = stacked ? BAR_RADIUS : rounded;
1890
+ const gapStyle = stacked && labelBackground ? { borderColor: labelBackground, borderWidth: STACK_GAP } : {};
1879
1891
  return {
1880
1892
  id: SERIES_ID_PREFIX + category,
1881
1893
  type: "bar",
1882
1894
  name: category,
1883
1895
  stack: stacked ? "total" : void 0,
1884
1896
  barCategoryGap,
1885
- itemStyle: { color, borderRadius: radius },
1897
+ barMaxWidth: BAR_MAX_WIDTH,
1898
+ itemStyle: { color, borderRadius: radius, ...gapStyle },
1886
1899
  markPoint: markPointFor(c, solid),
1887
1900
  markLine: void 0,
1888
1901
  data: seriesData.map((value, i) => {
@@ -2137,6 +2150,14 @@ function buildCartesianOption(cfg) {
2137
2150
  }
2138
2151
  });
2139
2152
  }
2153
+ if (diverging) {
2154
+ markLines.push({
2155
+ name: "zero",
2156
+ [horizontalBars ? "xAxis" : "yAxis"]: 0,
2157
+ lineStyle: { type: "solid", width: 1, color: guideColor },
2158
+ label: { show: false }
2159
+ });
2160
+ }
2140
2161
  if (forecast2) {
2141
2162
  const forecastSpan = plotWidth && labels.length > 1 ? Math.max(1, plotWidth - (showYAxis ? yAxisWidth ?? Y_AXIS_ESTIMATE : 0) - LINE_RIGHT_MARGIN) / (labels.length - 1) * (labels.length - 1 - lastActual) + LINE_RIGHT_MARGIN : null;
2142
2163
  markLines.push({
@@ -2268,6 +2289,8 @@ function buildCartesianOption(cfg) {
2268
2289
  show: horizontalBars ? showYAxis : showXAxis,
2269
2290
  boundaryGap: kind === "bar",
2270
2291
  inverse: horizontalBars,
2292
+ // Diverging: the axis stays at the plot's edge (not at 0, where labels would hit the negative bars); the zero line is a mark line.
2293
+ axisLine: diverging ? { show: false, onZero: false } : void 0,
2271
2294
  axisTick: { show: false },
2272
2295
  axisLabel: {
2273
2296
  hideOverlap: true,
@@ -2356,7 +2379,7 @@ function buildCartesianOption(cfg) {
2356
2379
  show: showLegend,
2357
2380
  top: 0,
2358
2381
  // Narrow: left-aligned and wrapping above the plot, so nothing is cut off at the right edge.
2359
- ...plotWidth !== void 0 && plotWidth < NARROW_PLOT_WIDTH ? { left: 0, right: 0 } : { right: reserveActions ? ACTIONS_RESERVE : 0 },
2382
+ ...plotWidth !== void 0 && plotWidth < NARROW_PLOT_WIDTH ? { left: 0, right: 0 } : { left: 0, right: reserveActions ? ACTIONS_RESERVE : 0 },
2360
2383
  // Plain wraps onto a second line at narrow widths instead of hiding items behind arrows.
2361
2384
  type: "plain",
2362
2385
  icon: "circle",
@@ -4386,8 +4409,8 @@ function buildScatterOption(config) {
4386
4409
  legend: {
4387
4410
  show: showLegend,
4388
4411
  ...legendBelow ? { bottom: 0 } : { top: 0 },
4389
- // With a heading the legend reads from the left, after it; otherwise it sits at the right edge.
4390
- ...headingWidth > 0 ? { left: headingWidth } : legendBelow ? { left: 0 } : { right: config.reserveActions ? 72 : 0 },
4412
+ // With a heading the legend reads from the left, after it; otherwise it sits at the left edge (as in every chart).
4413
+ ...headingWidth > 0 ? { left: headingWidth } : { left: 0, ...legendBelow ? {} : { right: config.reserveActions ? 72 : 0 } },
4391
4414
  type: "plain",
4392
4415
  icon: "circle",
4393
4416
  itemWidth: 8,
@@ -4631,7 +4654,7 @@ var TEXT11 = {
4631
4654
  ja: { legend: "\u51E1\u4F8B" },
4632
4655
  en: { legend: "Legend" }
4633
4656
  };
4634
- var Legend = forwardRef(function Legend2({ categories, colors, labels, layout = "horizontal", ariaLabel, className }, ref) {
4657
+ var Legend = forwardRef(function Legend2({ categories, colors, labels, layout = "horizontal", hidden = [], onHiddenChange, ariaLabel, className }, ref) {
4635
4658
  const t = TEXT11[uiLanguage(useLocale())];
4636
4659
  if (categories.length === 0) return null;
4637
4660
  const swatches = legendColors(categories, colors);
@@ -4643,10 +4666,23 @@ var Legend = forwardRef(function Legend2({ categories, colors, labels, layout =
4643
4666
  "data-layout": layout,
4644
4667
  "aria-label": ariaLabel ?? t.legend,
4645
4668
  className: cn("m-0 flex list-none gap-x-4 gap-y-1 p-0 text-xs", layout === "vertical" ? "flex-col" : "flex-row flex-wrap", className),
4646
- children: categories.map((category, i) => /* @__PURE__ */ jsxs("li", { "data-slot": "legend-item", className: "flex min-w-0 items-center gap-1.5", children: [
4647
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "size-2.5 shrink-0 rounded-[2px]", style: { background: swatches[i] } }),
4648
- /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-muted-foreground", children: labelOf(category, labels) })
4649
- ] }, category))
4669
+ children: categories.map((category, i) => {
4670
+ const off = hidden.includes(category);
4671
+ const chip = /* @__PURE__ */ jsxs(Fragment, { children: [
4672
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("size-2.5 shrink-0 rounded-[2px]", off && "opacity-30"), style: { background: swatches[i] } }),
4673
+ /* @__PURE__ */ jsx("span", { className: cn("min-w-0 truncate text-muted-foreground", off && "line-through opacity-60"), children: labelOf(category, labels) })
4674
+ ] });
4675
+ return /* @__PURE__ */ jsx("li", { "data-slot": "legend-item", "data-hidden": off || void 0, className: "flex min-w-0 items-center gap-1.5", children: onHiddenChange ? /* @__PURE__ */ jsx(
4676
+ "button",
4677
+ {
4678
+ type: "button",
4679
+ "aria-pressed": !off,
4680
+ onClick: () => onHiddenChange(off ? hidden.filter((c) => c !== category) : [...hidden, category]),
4681
+ className: "flex min-w-0 cursor-pointer items-center gap-1.5 rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
4682
+ children: chip
4683
+ }
4684
+ ) : chip }, category);
4685
+ })
4650
4686
  }
4651
4687
  );
4652
4688
  });
@@ -5446,7 +5482,7 @@ function buildPairedOption(cfg) {
5446
5482
  const right = 16;
5447
5483
  const option = {
5448
5484
  ...barOpt,
5449
- legend: { ...barOpt.legend, show: showLegend, data: legendNames, right: cfg.reserveActions ? 80 : 0 },
5485
+ legend: { ...barOpt.legend, show: showLegend, data: legendNames, left: 0, right: cfg.reserveActions ? 80 : 0 },
5450
5486
  grid: [
5451
5487
  { top, height: upper, left: gridLeft, right, containLabel: true },
5452
5488
  { top: top + upper + PANEL_GAP, bottom: 4, left: gridLeft, right, containLabel: true }
@@ -6214,11 +6250,11 @@ var legacyColorTones = {
6214
6250
  blue: "info"
6215
6251
  };
6216
6252
  var toneStyles = {
6217
- positive: { dot: "bg-positive", bg: "bg-positive-subtle", text: "text-positive", border: "border-positive/20 dark:border-positive/25" },
6218
- negative: { dot: "bg-negative", bg: "bg-negative-subtle", text: "text-negative", border: "border-negative/20 dark:border-negative/25" },
6219
- warning: { dot: "bg-warning", bg: "bg-warning-subtle", text: "text-warning", border: "border-warning/20 dark:border-warning/25" },
6220
- info: { dot: "bg-info", bg: "bg-info-subtle", text: "text-info", border: "border-info/20 dark:border-info/25" },
6221
- neutral: { dot: "bg-neutral", bg: "bg-neutral-subtle", text: "text-neutral", border: "border-neutral/20 dark:border-neutral/25" }
6253
+ positive: { dot: "bg-positive", bg: "bg-positive-subtle", text: "text-positive" },
6254
+ negative: { dot: "bg-negative", bg: "bg-negative-subtle", text: "text-negative" },
6255
+ warning: { dot: "bg-warning", bg: "bg-warning-subtle", text: "text-warning" },
6256
+ info: { dot: "bg-info", bg: "bg-info-subtle", text: "text-info" },
6257
+ neutral: { dot: "bg-neutral", bg: "bg-neutral-subtle", text: "text-neutral" }
6222
6258
  };
6223
6259
  var resolveTone = (color) => {
6224
6260
  if (color === void 0) return "neutral";
@@ -6236,7 +6272,7 @@ var StatusBadge = forwardRef(function StatusBadge2({ status, label: label2, colo
6236
6272
  ref,
6237
6273
  "data-slot": "status-badge",
6238
6274
  variant: "outline",
6239
- className: cn("gap-1.5 rounded-md", style.border, style.bg, style.text, className),
6275
+ className: cn("gap-1.5 rounded-md border-transparent", style.bg, style.text, className),
6240
6276
  "aria-label": displayLabel,
6241
6277
  children: [
6242
6278
  /* @__PURE__ */ jsx("span", { className: cn("inline-block size-1.5 rounded-full", style.dot), "aria-hidden": "true" }),
@@ -9229,6 +9265,7 @@ var FilterBarContext = createContext(null);
9229
9265
  var TEXT25 = {
9230
9266
  ja: {
9231
9267
  filters: "\u30D5\u30A3\u30EB\u30BF\u30FC",
9268
+ addFilter: "\u30D5\u30A3\u30EB\u30BF\u30FC\u3092\u8FFD\u52A0",
9232
9269
  selected: (count) => ` (${count}\u4EF6\u9078\u629E\u4E2D)`,
9233
9270
  remove: (filter, option) => `${filter}: ${option} \u3092\u524A\u9664`,
9234
9271
  clear: "\u30AF\u30EA\u30A2",
@@ -9236,6 +9273,7 @@ var TEXT25 = {
9236
9273
  },
9237
9274
  en: {
9238
9275
  filters: "Filters",
9276
+ addFilter: "Add filter",
9239
9277
  selected: (count) => ` (${count} selected)`,
9240
9278
  remove: (filter, option) => `Remove ${filter}: ${option}`,
9241
9279
  clear: "Clear",
@@ -9509,6 +9547,11 @@ function fiscalPeriodRange(date, {
9509
9547
  const periodStart = addMonths(startOfMonth(subMonths(date, into)), offset * length);
9510
9548
  return { from: periodStart, to: endOfMonth(addMonths(periodStart, length - 1)) };
9511
9549
  }
9550
+ function comparisonRange({ from, to }, kind) {
9551
+ if (kind === "previous-year") return { from: subYears(from, 1), to: subYears(to, 1) };
9552
+ const days = differenceInCalendarDays(to, from) + 1;
9553
+ return { from: subDays(from, days), to: subDays(from, 1) };
9554
+ }
9512
9555
  var PRESET_LABELS = {
9513
9556
  ja: {
9514
9557
  today: "\u4ECA\u65E5",
@@ -9546,8 +9589,16 @@ var PRESET_LABELS = {
9546
9589
  }
9547
9590
  };
9548
9591
  var TEXT26 = {
9549
- ja: { placeholder: "\u671F\u9593\u3092\u9078\u629E", rangeSeparator: " - " },
9550
- en: { placeholder: "Pick a date range", rangeSeparator: " \u2013 " }
9592
+ ja: {
9593
+ placeholder: "\u671F\u9593\u3092\u9078\u629E",
9594
+ rangeSeparator: " - ",
9595
+ comparison: { "previous-period": "\u524D\u671F\u9593", "previous-year": "\u524D\u5E74\u540C\u671F" }
9596
+ },
9597
+ en: {
9598
+ placeholder: "Pick a date range",
9599
+ rangeSeparator: " \u2013 ",
9600
+ comparison: { "previous-period": "vs. previous period", "previous-year": "vs. same period last year" }
9601
+ }
9551
9602
  };
9552
9603
  var calendarLocale = (locale) => uiLanguage(locale) === "ja" ? ja : void 0;
9553
9604
  function createDatePresets({
@@ -9636,6 +9687,7 @@ var DateRangePicker = forwardRef(
9636
9687
  showPresets = true,
9637
9688
  locale: localeProp,
9638
9689
  fiscalYearStartMonth,
9690
+ comparison,
9639
9691
  maxDate,
9640
9692
  minDate,
9641
9693
  placeholder,
@@ -9671,6 +9723,10 @@ var DateRangePicker = forwardRef(
9671
9723
  };
9672
9724
  const selectedPreset = findMatchingPreset(presets, value);
9673
9725
  const presetLabel = selectedPreset?.label;
9726
+ const comparisonText = comparison && value?.from && value.to ? (() => {
9727
+ const c = comparisonRange({ from: value.from, to: value.to }, comparison);
9728
+ return `${t.comparison[comparison]} ${formatDate(c.from, "date", locale)}${t.rangeSeparator}${formatDate(c.to, "date", locale)}`;
9729
+ })() : void 0;
9674
9730
  const endMonth = value?.to ?? value?.from;
9675
9731
  const defaultMonth = endMonth ? isMobile ? endMonth : subMonths(endMonth, 1) : void 0;
9676
9732
  const calendarSelected = value?.from ? { from: value.from, to: value.to ?? void 0 } : void 0;
@@ -9697,7 +9753,8 @@ var DateRangePicker = forwardRef(
9697
9753
  presetLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [
9698
9754
  /* @__PURE__ */ jsx("span", { children: presetLabel }),
9699
9755
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: formatDateRange2() })
9700
- ] }) : /* @__PURE__ */ jsx("span", { children: formatDateRange2() })
9756
+ ] }) : /* @__PURE__ */ jsx("span", { children: formatDateRange2() }),
9757
+ comparisonText && /* @__PURE__ */ jsx("span", { "data-slot": "date-range-picker-comparison", className: "text-muted-foreground", children: comparisonText })
9701
9758
  ]
9702
9759
  }
9703
9760
  ),
@@ -10144,7 +10201,7 @@ var deltaVariants = cva(
10144
10201
  {
10145
10202
  variants: {
10146
10203
  variant: {
10147
- badge: "h-5 rounded-md border px-2 py-0.5 text-xs font-medium [&>svg]:size-3",
10204
+ badge: "h-5 rounded-md px-2 py-0.5 text-xs font-medium [&>svg]:size-3",
10148
10205
  inline: "text-sm [&>svg]:size-3.5"
10149
10206
  },
10150
10207
  sentiment: {
@@ -10154,9 +10211,9 @@ var deltaVariants = cva(
10154
10211
  }
10155
10212
  },
10156
10213
  compoundVariants: [
10157
- { variant: "badge", sentiment: "positive", className: "border-positive/20 bg-positive-subtle dark:border-positive/25" },
10158
- { variant: "badge", sentiment: "negative", className: "border-negative/20 bg-negative-subtle dark:border-negative/25" },
10159
- { variant: "badge", sentiment: "neutral", className: "border-neutral/20 bg-neutral-subtle dark:border-neutral/25" }
10214
+ { variant: "badge", sentiment: "positive", className: "bg-positive-subtle" },
10215
+ { variant: "badge", sentiment: "negative", className: "bg-negative-subtle" },
10216
+ { variant: "badge", sentiment: "neutral", className: "bg-neutral-subtle" }
10160
10217
  ],
10161
10218
  defaultVariants: {
10162
10219
  variant: "badge",
@@ -10189,6 +10246,7 @@ function deltaAriaLabel(result, locale, change = "relative", format, digits) {
10189
10246
  if (amount === null) return t.none(label2);
10190
10247
  return t.change(label2, change === "points" ? amount.replace(/pt$/, t.points) : amount, direction === "up");
10191
10248
  }
10249
+ var SENTIMENT_TEXT = { positive: "text-positive", negative: "text-negative", neutral: "text-neutral" };
10192
10250
  var Delta = forwardRef(
10193
10251
  ({
10194
10252
  value,
@@ -10218,7 +10276,7 @@ var Delta = forwardRef(
10218
10276
  const comparable = result.direction !== "none";
10219
10277
  const Icon = result.direction === "up" ? ArrowUp : result.direction === "down" ? ArrowDown : ArrowRight;
10220
10278
  const text = formatChange(result, display, locale, format, changeDigits);
10221
- return /* @__PURE__ */ jsxs(
10279
+ return /* @__PURE__ */ jsx(
10222
10280
  "span",
10223
10281
  {
10224
10282
  ref,
@@ -10228,16 +10286,31 @@ var Delta = forwardRef(
10228
10286
  "data-sentiment": result.sentiment,
10229
10287
  "aria-label": deltaAriaLabel(result, locale, display, format, changeDigits),
10230
10288
  className: cn(
10231
- deltaVariants({ variant, sentiment: result.sentiment }),
10289
+ variant === "badge" ? "inline-flex w-fit shrink-0 items-center gap-1.5 font-medium whitespace-nowrap tabular-nums" : deltaVariants({ variant, sentiment: result.sentiment }),
10290
+ // The chip carries the colour of the change; the root repeats it for the "—" case and for `className` consumers.
10291
+ variant === "badge" && SENTIMENT_TEXT[result.sentiment],
10232
10292
  !comparable && "text-muted-foreground",
10233
10293
  className
10234
10294
  ),
10235
10295
  ...props,
10236
- children: [
10296
+ children: variant === "badge" ? /* @__PURE__ */ jsxs(Fragment, { children: [
10297
+ /* @__PURE__ */ jsxs(
10298
+ "span",
10299
+ {
10300
+ "data-slot": "delta-chip",
10301
+ className: cn(deltaVariants({ variant, sentiment: result.sentiment }), !comparable && "text-muted-foreground"),
10302
+ children: [
10303
+ comparable && /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }),
10304
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: text ?? DELTA_NOT_COMPARABLE })
10305
+ ]
10306
+ }
10307
+ ),
10308
+ showLabel && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-xs font-normal text-muted-foreground", children: result.label })
10309
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
10237
10310
  comparable && /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }),
10238
10311
  /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: text ?? DELTA_NOT_COMPARABLE }),
10239
10312
  showLabel && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "font-normal text-muted-foreground", children: result.label })
10240
- ]
10313
+ ] })
10241
10314
  }
10242
10315
  );
10243
10316
  }
@@ -10413,7 +10486,7 @@ function KpiCard({
10413
10486
  const targetBar = hasTarget && !neutral && !byPoints && !lower;
10414
10487
  if (summary !== void 0) warnShallowSummary(summary, t);
10415
10488
  const cardClass = cn("row-span-2 grid content-start gap-y-0 grid-rows-subgrid", className);
10416
- const valueSize = small ? "text-xl @[218px]/card:text-2xl" : "text-2xl @[218px]/card:text-4xl";
10489
+ const valueSize = small ? "text-xl @[218px]/card:text-2xl" : "text-2xl @[218px]/card:text-[26px]";
10417
10490
  if (isLoading) {
10418
10491
  return /* @__PURE__ */ jsxs(
10419
10492
  Card,
@@ -10518,7 +10591,8 @@ function KpiCard({
10518
10591
  format,
10519
10592
  change: display,
10520
10593
  digits,
10521
- locale
10594
+ locale,
10595
+ className: "min-w-0 shrink whitespace-normal"
10522
10596
  },
10523
10597
  i
10524
10598
  ));
@@ -10526,16 +10600,20 @@ function KpiCard({
10526
10600
  const longValue = valueText.length > LONG_VALUE_CHARS;
10527
10601
  return /* @__PURE__ */ jsxs(Card, { "data-slot": "kpi-card", size, className: cardClass, ...props, children: [
10528
10602
  /* @__PURE__ */ jsxs(CardHeader, { className: HEADER_CLASS, children: [
10529
- /* @__PURE__ */ jsx(CardDescription, { "data-slot": "kpi-card-label", title: label2, className: "col-start-1 min-w-0 truncate text-[13px] leading-snug font-medium text-muted-foreground", children: label2 }),
10603
+ /* @__PURE__ */ jsxs(CardDescription, { "data-slot": "kpi-card-label", title: label2, className: "col-start-1 flex min-w-0 items-center gap-2 text-[13px] leading-snug font-medium text-muted-foreground", children: [
10604
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: label2 }),
10605
+ sample && /* @__PURE__ */ jsx(SampleBadge, { label: sample.label, className: "shrink-0" })
10606
+ ] }),
10530
10607
  /* @__PURE__ */ jsxs(
10531
10608
  CardTitle,
10532
10609
  {
10533
10610
  "data-slot": "kpi-card-value",
10534
10611
  title: valueText,
10535
10612
  className: cn(
10536
- "col-start-1 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 leading-none font-semibold tracking-tight tabular-nums",
10613
+ "col-start-1 flex min-w-0 items-center gap-x-2 gap-y-1 leading-none font-medium tracking-tight tabular-nums",
10537
10614
  // Fixed size: the step follows the card width only, never the length of the value.
10538
- valueSize
10615
+ valueSize,
10616
+ (longValue || isProvisional) && "flex-wrap"
10539
10617
  ),
10540
10618
  children: [
10541
10619
  /* @__PURE__ */ jsx("span", { "data-slot": "kpi-card-value-text", className: longValue ? "min-w-0 break-words" : "whitespace-nowrap", children: longValue ? digitGroups(valueText).map((group, i) => /* @__PURE__ */ jsxs("span", { className: "whitespace-nowrap", children: [
@@ -10543,11 +10621,11 @@ function KpiCard({
10543
10621
  /* @__PURE__ */ jsx("wbr", {})
10544
10622
  ] }, i)) : valueText }),
10545
10623
  isProvisional && /* @__PURE__ */ jsx(Badge, { "data-slot": "kpi-card-provisional", variant: "outline", className: "align-middle", children: provisionalLabel }),
10546
- sample && /* @__PURE__ */ jsx(SampleBadge, { label: sample.label })
10624
+ comparison && !stacked && !longValue && deltas
10547
10625
  ]
10548
10626
  }
10549
10627
  ),
10550
- comparison && (stacked ? /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-comparisons", className: "flex flex-wrap items-center gap-1", children: deltas }) : /* @__PURE__ */ jsx(CardAction, { className: longValue ? DELTA_UNDER_PLACEMENT : DELTA_PLACEMENT, children: deltas })),
10628
+ comparison && (stacked ? /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-comparisons", className: "flex flex-wrap items-center gap-1", children: deltas }) : longValue && /* @__PURE__ */ jsx(CardAction, { className: DELTA_UNDER_PLACEMENT, children: deltas })),
10551
10629
  hasPrevious && comparison && /* @__PURE__ */ jsx("div", { "data-slot": "kpi-card-previous", className: "col-span-full text-sm text-muted-foreground tabular-nums", children: result?.previous != null ? t.previous(baseline ?? "", fmt(result.previous)) : t.noPrevious(baseline ?? "") }),
10552
10630
  bar && progress && /* @__PURE__ */ jsxs("div", { "data-slot": "kpi-card-target-progress", className: "col-span-full mt-1 flex min-w-0 flex-col gap-1.5", children: [
10553
10631
  /* @__PURE__ */ jsxs(
@@ -10760,5 +10838,5 @@ function DraftChartPreview({ children }) {
10760
10838
  }
10761
10839
 
10762
10840
  export { AppShell, AreaChart, AttentionList, BarChart, BarList, BoxPlotChart, COMPARISON_LABELS, CategoryBar, ChartFrame, ComboChart, DEFAULT_SAMPLE_LABEL, DELTA_NOT_COMPARABLE, DashboardCard, DashboardCardAction, DashboardCardContent, DashboardCardDescription, DashboardCardFooter, DashboardCardHeader, DashboardCardPreset, DashboardCardSkeleton, DashboardCardTitle, DataTable, DataTableColumnVisibility, DataTableContent, DataTableExport, DataTablePagination, DataTablePreset, DataTableToolbar, DateRangePicker, Delta, DonutChart, DraftChart, FilledMap, FilterBar, FilterBarActiveChips, FilterBarClearButton, FilterBarMultiSelect, FilterBarPreset, FilterBarSelect, ForecastChart, FunnelSteps, Heatmap, HistogramChart, KpiCard, Legend, LineChart, MetricUnit, MetricValue, MultiSelect, PageShell, PageShellActions, PageShellContent, PageShellDescription, PageShellHeader, PageShellHeaderEnd, PageShellHeading, PageShellMeta, PageShellSummary, PageShellSummaryCard, PageShellTitle, PairedChart, PivotTable, Placeholder, ProgressCircle, RECORD_MIN_POINTS, SampleBadge, SampleClaim, SampleData, ScatterChart, SearchableSelect, SectionHeader, SegmentedControl, StatusBadge, SymbolMap, Tracker, Treemap, TrendIndicator, UpdatedAt, WaterfallChart, comparisonBaseline, comparisonLabel, computeComparison, computeTargetProgress, defaultChangeDisplay, defaultPresets, deltaVariants, detectRecord, fillKpiTemplate, flattenOptions, formatChange, formatChangeAmount, formatRelativeTime, funnelStepsVariants, inferPeriodGrain, isGroupedOptions, metricValueVariants, pageShellSummaryCardVariants, tableToCsv, toCsv, toneForValue, useDataTable, useSampleMark };
10763
- //# sourceMappingURL=chunk-YJQCB3UP.js.map
10764
- //# sourceMappingURL=chunk-YJQCB3UP.js.map
10841
+ //# sourceMappingURL=chunk-SC7K2RD6.js.map
10842
+ //# sourceMappingURL=chunk-SC7K2RD6.js.map