@siyahi/ui 0.1.8-next.4 → 0.1.9-next.2

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 (47) hide show
  1. package/README.md +38 -18
  2. package/THIRD_PARTY_NOTICES.md +11 -10
  3. package/dist/components/registry/charts/area-chart-card.d.ts +4 -3
  4. package/dist/components/registry/charts/area-chart-card.js +2 -2
  5. package/dist/components/registry/charts/bar-chart-card.d.ts +7 -1
  6. package/dist/components/registry/charts/bar-chart-card.js +20 -5
  7. package/dist/components/registry/charts/line-chart-card.d.ts +5 -2
  8. package/dist/components/registry/charts/line-chart-card.js +2 -2
  9. package/dist/components/registry/dashboard-01/section-cards.d.ts +9 -2
  10. package/dist/components/registry/dashboard-01/section-cards.js +32 -21
  11. package/dist/components/registry/dashboardcn/bar-list.d.ts +3 -1
  12. package/dist/components/registry/dashboardcn/bar-list.js +2 -2
  13. package/dist/components/registry/dashboardcn/distribution-bar.d.ts +38 -0
  14. package/dist/components/registry/dashboardcn/distribution-bar.js +118 -0
  15. package/dist/components/registry/minidev/copy-button.d.ts +11 -0
  16. package/dist/components/registry/minidev/copy-button.js +34 -0
  17. package/dist/components/registry/niko-table/components/data-table-search-filter.d.ts +35 -0
  18. package/dist/components/registry/niko-table/components/data-table-search-filter.js +44 -0
  19. package/dist/components/registry/niko-table/filters/table-search-filter.d.ts +38 -0
  20. package/dist/components/registry/niko-table/filters/table-search-filter.js +103 -0
  21. package/dist/components/siyahi/data-list.d.ts +14 -0
  22. package/dist/components/siyahi/data-list.js +25 -0
  23. package/dist/components/siyahi/data-table-row-count.d.ts +11 -0
  24. package/dist/components/siyahi/data-table-row-count.js +18 -0
  25. package/dist/components/siyahi/data-table-sort-header.d.ts +15 -0
  26. package/dist/components/siyahi/data-table-sort-header.js +36 -0
  27. package/dist/components/siyahi/inline-code.d.ts +7 -0
  28. package/dist/components/siyahi/inline-code.js +11 -0
  29. package/dist/components/siyahi/page-section.d.ts +21 -0
  30. package/dist/components/siyahi/page-section.js +39 -0
  31. package/dist/components/siyahi/tone-progress.d.ts +15 -0
  32. package/dist/components/siyahi/tone-progress.js +18 -0
  33. package/dist/components/siyahi/treemap.d.ts +7 -0
  34. package/dist/components/siyahi/treemap.js +69 -2
  35. package/dist/components/ui/code-block.d.ts +28 -0
  36. package/dist/components/ui/code-block.js +122 -0
  37. package/dist/index.d.ts +19 -8
  38. package/dist/index.js +14 -3
  39. package/dist/lib/chart-frame.d.ts +10 -3
  40. package/dist/lib/chart-frame.js +161 -55
  41. package/dist/lib/chart-series.d.ts +55 -3
  42. package/dist/lib/format.d.ts +3 -0
  43. package/dist/lib/format.js +6 -1
  44. package/dist/lib/treemap.d.ts +4 -0
  45. package/dist/lib/treemap.js +9 -4
  46. package/package.json +1 -1
  47. package/registry.lock.json +32 -0
package/README.md CHANGED
@@ -75,8 +75,12 @@ Every merge to `main` also attaches both tarballs to a GitHub release
75
75
  bar list, the `SectionCards` stat tile and the `sidebar-07` app shell.
76
76
  - **Siyahi components**: `Delta` (a signed figure with ▲ ▼), `PriceChart`
77
77
  (TradingView Lightweight Charts in theme colours), `Treemap` (holdings heat
78
- map; hover or tap a tile for its figures), `LocalTime` (a time in the configured zone with the viewer's own clock
79
- in a tooltip) and `SiyahiProvider`.
78
+ map; hover or tap a tile for its figures) with `TreemapLegend` (its colour
79
+ scale), `LocalTime` (a time in the configured zone with the viewer's own clock
80
+ in a tooltip), `ToneProgress` (Progress in a meaning colour), the page parts
81
+ `PageSection`, `PageSubheading`, `DataList` and `InlineCode`, the data table
82
+ parts `DataTableSortHeader` (sorts on one click) and `DataTableRowCount`
83
+ ("12 of 48"), and `SiyahiProvider`.
80
84
  - **Cards and badges as installed**: every `Card`, stat tiles included, keeps
81
85
  luma's `rounded-4xl`, `shadow-md` and faint ring. A category (a sector, a
82
86
  broker, a unit's kind) is an outline `Badge`: categories stay neutral, and
@@ -84,7 +88,7 @@ Every merge to `main` also attaches both tarballs to a GitHub release
84
88
  (header under 24rem, so any phone) a header action such as a toggle drops
85
89
  under the title and description, left-aligned; a stat tile's badge stays
86
90
  top right.
87
- - **Formatters**: `money`, `moneyCompact`, `pct` and `time`, or `useFormat()`
91
+ - **Formatters**: `count`, `money`, `moneyCompact`, `pct` and `time`, or `useFormat()`
88
92
  for the same bound to the provider's locale.
89
93
  `useFormat().time(value, { withDate: true })` (or
90
94
  `time(value, locale, { withDate: true })`) and `<LocalTime withDate>` write
@@ -94,26 +98,42 @@ Every merge to `main` also attaches both tarballs to a GitHub release
94
98
 
95
99
  ## Which component
96
100
 
97
- | Need | Component |
98
- | ----------------------------------------------------------------------- | ----------------------------------------------------------- |
99
- | Values over time or another ordered axis (months, hours, price buckets) | `BarChartCard`, `AreaChartCard` or `LineChartCard` |
100
- | Counts or amounts per period, one series or several | `BarChartCard`; `stacked` when the series add up to a total |
101
- | A running level, such as a portfolio's value against money put in | `AreaChartCard` |
102
- | Series compared point by point, such as a return against an index | `LineChartCard` |
103
- | Ranked counts or amounts by category (a name, a bar and a figure) | `BarList` |
104
- | Headline figures with their change | `SectionCards`, with a `Delta` in each badge |
105
- | One instrument's price history | `PriceChart` |
106
- | Holdings sized by weight and coloured by change | `Treemap` |
107
- | Activity by day, by weekday and hour, or a status over time | `CalendarHeatmap`, `WeekdayHeatmap`, `StatusHeatmap` |
108
- | Rows to sort and filter | `DataTable`, inside a `Card` |
109
- | A signed figure (a gain, a loss, a change) | `Delta` |
110
- | A time, with the viewer's own clock on hover | `LocalTime` |
101
+ | Need | Component |
102
+ | ----------------------------------------------------------------------- | ------------------------------------------------------------------- |
103
+ | Values over time or another ordered axis (months, hours, price buckets) | `BarChartCard`, `AreaChartCard` or `LineChartCard` |
104
+ | Counts or amounts per period, one series or several | `BarChartCard`; `stacked` when the series add up to a total |
105
+ | A running level, such as a portfolio's value against money put in | `AreaChartCard` |
106
+ | Series compared point by point, such as a return against an index | `LineChartCard` |
107
+ | Samples in time with limits and events marked | `LineChartCard` with `xDomain`, `xTicks` and `referenceLines` |
108
+ | Long category names, such as sectors | `BarChartCard` with `horizontal` |
109
+ | A gain above zero and a loss below it | a series with `color` and `negativeColor` |
110
+ | Ranked counts or amounts by category (a name, a bar and a figure) | `BarList`; give two lists one `max` to share a scale |
111
+ | Where a budget sits, a split of a whole, or losses against gains | `DistributionBar` |
112
+ | Headline figures with their change | `SectionCards`, with a `Delta` in each badge |
113
+ | One instrument's price history | `PriceChart` |
114
+ | Holdings sized by weight and coloured by change | `Treemap` |
115
+ | Activity by day, by weekday and hour, or a status over time | `CalendarHeatmap`, `WeekdayHeatmap`, `StatusHeatmap` |
116
+ | Rows to sort and filter | `DataTable`, inside a `Card` |
117
+ | A column that sorts on one click; a search and an "n of m" count | `DataTableSortHeader`; `DataTableSearchFilter`, `DataTableRowCount` |
118
+ | Stat tiles that pick a scope for the page | `SectionCards` with `selected` and `onSelect` |
119
+ | A share or a part of a whole, coloured as a gain or a loss | `ToneProgress` |
120
+ | The colour scale under a `Treemap` | `TreemapLegend`, with the map's `range` |
121
+ | One part of a long page: rule, eyebrow, heading, lead, action | `PageSection`, with `PageSubheading` inside |
122
+ | Label and value pairs, such as a record's fields | `DataList` and `DataListItem` |
123
+ | A command or file to copy, wrapped or scrolling | `CodeBlock` with `CodeBlockCopyButton` |
124
+ | A labelled copy action, such as "Copy all" for a section | `CopyButton` |
125
+ | A command, file or identifier inside prose | `InlineCode` |
126
+ | A signed figure (a gain, a loss, a change) | `Delta` |
127
+ | A time, with the viewer's own clock on hover | `LocalTime` |
111
128
 
112
129
  The three chart cards take the rows, the field the x axis reads and the series,
113
130
  and own everything else: the card and its header action (a range or mode
114
131
  toggle), the axes, the dashed horizontal grid, Geist Mono ticks, a tooltip that
115
132
  names the hovered point and gives each series' formatted value, and the legend
116
- below. A page never puts Recharts axes, grids or tooltips together itself.
133
+ below. Props cover the rest: a footer, a placeholder while data loads,
134
+ reference lines, a numeric x axis, a fixed value axis, axis titles, a second
135
+ line under each tick, a picked category, sideways bars and straight segments.
136
+ A page never puts Recharts axes, grids or tooltips together itself.
117
137
 
118
138
  ```tsx
119
139
  <BarChartCard
@@ -8,16 +8,17 @@ file as copied; `packages/ui/registry.lock.json` lists them all and
8
8
 
9
9
  ## Copied into `@siyahi/ui`
10
10
 
11
- | What | Where in the package | Origin | Licence |
12
- | ------------------------------------------------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
13
- | shadcn/ui core components (installed with `shadcn add`, never edited) | `src/components/ui/*`, `src/hooks/use-mobile.ts` | https://github.com/shadcn-ui/ui | MIT, Copyright (c) 2023 shadcn |
14
- | shadcn `tailwind.css` (variants and utilities the components use) | `styles/shadcn.css` | https://github.com/shadcn-ui/ui/tree/main/packages/shadcn | MIT, Copyright (c) 2023 shadcn |
15
- | shadcn block `sidebar-07` | `src/components/registry/sidebar-07/*` | https://ui.shadcn.com/r/styles/base-vega/sidebar-07.json | MIT, Copyright (c) 2023 shadcn |
16
- | shadcn block `dashboard-01`, `SectionCards` only | `src/components/registry/dashboard-01/section-cards.tsx` | https://ui.shadcn.com/r/styles/base-vega/dashboard-01.json | MIT, Copyright (c) 2023 shadcn |
17
- | Heatmaps: calendar, weekday by hour, status timeline | `src/components/registry/heatmap/*` | https://shadcn-heatmap.pages.dev/r/calendar-heatmap.json, https://shadcn-heatmap.pages.dev/r/weekday-heatmap.json, https://shadcn-heatmap.pages.dev/r/status-heatmap.json (source: https://github.com/rutopio/shadcn-heatmap) | MIT, Copyright (c) 2026 ChingRu |
18
- | niko-table data table on TanStack Table | `src/components/registry/niko-table/*` | https://niko-table.com/r/data-table.json, https://niko-table.com/r/data-table-core.json, https://niko-table.com/r/data-table-ui.json, https://niko-table.com/r/data-table-faceted-filter.json, https://niko-table.com/r/data-table-column-sort.json (source: https://github.com/Semkoo/niko-table-registry) | MIT, Copyright (c) 2025 Semir N.; original work Copyright (c) 2025 WebDevSimplified |
19
- | shadcn chart blocks `chart-bar-multiple`, `chart-area-stacked`, `chart-line-multiple` | `src/components/registry/charts/*` | https://ui.shadcn.com/r/styles/new-york-v4/chart-bar-multiple.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-area-stacked.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-line-multiple.json | MIT, Copyright (c) 2023 shadcn |
20
- | dashboardcn ranked list (`BarList`) | `src/components/registry/dashboardcn/bar-list.tsx` | https://dashboardcn.com/r/bar-list.json (source: https://github.com/NoahGdev/dashboardcn) | MIT, Copyright (c) 2026 dashboardcn contributors |
11
+ | What | Where in the package | Origin | Licence |
12
+ | ------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
13
+ | shadcn/ui core components (installed with `shadcn add`, never edited) | `src/components/ui/*`, `src/hooks/use-mobile.ts` | https://github.com/shadcn-ui/ui | MIT, Copyright (c) 2023 shadcn |
14
+ | shadcn `tailwind.css` (variants and utilities the components use) | `styles/shadcn.css` | https://github.com/shadcn-ui/ui/tree/main/packages/shadcn | MIT, Copyright (c) 2023 shadcn |
15
+ | shadcn block `sidebar-07` | `src/components/registry/sidebar-07/*` | https://ui.shadcn.com/r/styles/base-vega/sidebar-07.json | MIT, Copyright (c) 2023 shadcn |
16
+ | shadcn block `dashboard-01`, `SectionCards` only | `src/components/registry/dashboard-01/section-cards.tsx` | https://ui.shadcn.com/r/styles/base-vega/dashboard-01.json | MIT, Copyright (c) 2023 shadcn |
17
+ | Heatmaps: calendar, weekday by hour, status timeline | `src/components/registry/heatmap/*` | https://shadcn-heatmap.pages.dev/r/calendar-heatmap.json, https://shadcn-heatmap.pages.dev/r/weekday-heatmap.json, https://shadcn-heatmap.pages.dev/r/status-heatmap.json (source: https://github.com/rutopio/shadcn-heatmap) | MIT, Copyright (c) 2026 ChingRu |
18
+ | niko-table data table on TanStack Table | `src/components/registry/niko-table/*` | https://niko-table.com/r/data-table.json, https://niko-table.com/r/data-table-core.json, https://niko-table.com/r/data-table-ui.json, https://niko-table.com/r/data-table-faceted-filter.json, https://niko-table.com/r/data-table-column-sort.json, https://niko-table.com/r/data-table-search-filter.json (source: https://github.com/Semkoo/niko-table-registry) | MIT, Copyright (c) 2025 Semir N.; original work Copyright (c) 2025 WebDevSimplified |
19
+ | shadcn chart blocks `chart-bar-multiple`, `chart-area-stacked`, `chart-line-multiple` | `src/components/registry/charts/*` | https://ui.shadcn.com/r/styles/new-york-v4/chart-bar-multiple.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-area-stacked.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-line-multiple.json | MIT, Copyright (c) 2023 shadcn |
20
+ | dashboardcn ranked list (`BarList`) and stacked bar (`DistributionBar`) | `src/components/registry/dashboardcn/*` | https://dashboardcn.com/r/bar-list.json, https://dashboardcn.com/r/distribution-bar.json (source: https://github.com/NoahGdev/dashboardcn) | MIT, Copyright (c) 2026 dashboardcn contributors |
21
+ | MiniDev copy button (`CopyButton`) | `src/components/registry/minidev/copy-button.tsx` | https://ui.minidev.pro/r/copy-button.json (source: https://github.com/amankaushik481/minidev-ui) | MIT, Copyright (c) 2026 MiniDev |
21
22
 
22
23
  ## Runtime dependencies with attribution terms
23
24
 
@@ -1,9 +1,10 @@
1
- import { SeriesChartProps } from "../../../lib/chart-series.js";
1
+ import { ChartCurve, NumericXProps, SeriesChartProps } from "../../../lib/chart-series.js";
2
2
  //#region src/components/registry/charts/area-chart-card.d.ts
3
- export interface AreaChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K> {
3
+ export interface AreaChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps {
4
4
  /** Stack the series into a total instead of overlapping them. */
5
5
  stacked?: boolean;
6
+ curve?: ChartCurve;
6
7
  }
7
8
  /** Values over an ordered axis as filled areas: one series, or several overlapping or stacked. */
8
- export declare function AreaChartCard<T extends object, K extends keyof T>({ stacked, ...props }: AreaChartCardProps<T, K>): import("react").JSX.Element;
9
+ export declare function AreaChartCard<T extends object, K extends keyof T>({ stacked, curve, ...props }: AreaChartCardProps<T, K>): import("react").JSX.Element;
9
10
  //#endregion
@@ -4,13 +4,13 @@ import { jsx } from "react/jsx-runtime";
4
4
  import { Area, AreaChart } from "recharts";
5
5
  //#region src/components/registry/charts/area-chart-card.tsx
6
6
  /** Values over an ordered axis as filled areas: one series, or several overlapping or stacked. */
7
- function AreaChartCard({ stacked = false, ...props }) {
7
+ function AreaChartCard({ stacked = false, curve = "monotone", ...props }) {
8
8
  return /* @__PURE__ */ jsx(ChartFrame, {
9
9
  chart: AreaChart,
10
10
  ...props,
11
11
  children: props.series.map(({ key, color }) => /* @__PURE__ */ jsx(Area, {
12
12
  dataKey: key,
13
- type: "monotone",
13
+ type: curve,
14
14
  fill: color,
15
15
  fillOpacity: stacked ? .4 : .2,
16
16
  stroke: color,
@@ -3,7 +3,13 @@ import { SeriesChartProps } from "../../../lib/chart-series.js";
3
3
  export interface BarChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K> {
4
4
  /** Stack the series in one bar per point instead of side by side. */
5
5
  stacked?: boolean;
6
+ /** Bars run sideways, categories down the left: for long names, such as sectors. */
7
+ horizontal?: boolean;
8
+ /** The picked category's x value: its bars stay solid and the rest fade. */
9
+ selected?: T[K] | null;
10
+ /** Called with a clicked category's x value, or null when the picked one is clicked again. */
11
+ onSelect?: (value: T[K] | null) => void;
6
12
  }
7
13
  /** Values over an ordered axis as bars: one series, or several grouped or stacked. */
8
- export declare function BarChartCard<T extends object, K extends keyof T>({ stacked, ...props }: BarChartCardProps<T, K>): import("react").JSX.Element;
14
+ export declare function BarChartCard<T extends object, K extends keyof T>({ stacked, selected, onSelect, ...props }: BarChartCardProps<T, K>): import("react").JSX.Element;
9
15
  //#endregion
@@ -1,23 +1,38 @@
1
1
  "use client";
2
2
  import { ChartFrame } from "../../../lib/chart-frame.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
- import { Bar, BarChart } from "recharts";
4
+ import { Bar, BarChart, Cell } from "recharts";
5
5
  //#region src/components/registry/charts/bar-chart-card.tsx
6
6
  /** Values over an ordered axis as bars: one series, or several grouped or stacked. */
7
- function BarChartCard({ stacked = false, ...props }) {
7
+ function BarChartCard({ stacked = false, selected = null, onSelect, ...props }) {
8
8
  return /* @__PURE__ */ jsx(ChartFrame, {
9
9
  chart: BarChart,
10
10
  ...props,
11
- children: props.series.map(({ key, color }, index) => /* @__PURE__ */ jsx(Bar, {
11
+ stackOffset: stacked ? "sign" : void 0,
12
+ children: props.series.map(({ key, color, negativeColor }, index) => /* @__PURE__ */ jsx(Bar, {
12
13
  dataKey: key,
13
14
  fill: color,
14
15
  stackId: stacked ? "stack" : void 0,
15
- radius: !stacked ? 2 : index === props.series.length - 1 ? [
16
+ radius: !stacked ? 2 : index === props.series.length - 1 ? props.horizontal ? [
17
+ 0,
18
+ 2,
19
+ 2,
20
+ 0
21
+ ] : [
16
22
  2,
17
23
  2,
18
24
  0,
19
25
  0
20
- ] : 0
26
+ ] : 0,
27
+ className: onSelect ? "cursor-pointer" : void 0,
28
+ onClick: onSelect && ((bar) => {
29
+ const value = bar.payload?.[props.xKey];
30
+ if (value !== void 0) onSelect(value === selected ? null : value);
31
+ }),
32
+ children: (negativeColor || selected !== null) && props.data.map((row, i) => /* @__PURE__ */ jsx(Cell, {
33
+ fill: negativeColor && Number(row[key]) < 0 ? negativeColor : color,
34
+ fillOpacity: selected === null || row[props.xKey] === selected ? 1 : .35
35
+ }, i))
21
36
  }, key))
22
37
  });
23
38
  }
@@ -1,5 +1,8 @@
1
- import { SeriesChartProps } from "../../../lib/chart-series.js";
1
+ import { ChartCurve, NumericXProps, SeriesChartProps } from "../../../lib/chart-series.js";
2
2
  //#region src/components/registry/charts/line-chart-card.d.ts
3
+ export interface LineChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps {
4
+ curve?: ChartCurve;
5
+ }
3
6
  /** Values over an ordered axis as lines: one series, or several to compare, such as a portfolio against its index. */
4
- export declare function LineChartCard<T extends object, K extends keyof T>(props: SeriesChartProps<T, K>): import("react").JSX.Element;
7
+ export declare function LineChartCard<T extends object, K extends keyof T>({ curve, ...props }: LineChartCardProps<T, K>): import("react").JSX.Element;
5
8
  //#endregion
@@ -4,13 +4,13 @@ import { jsx } from "react/jsx-runtime";
4
4
  import { Line, LineChart } from "recharts";
5
5
  //#region src/components/registry/charts/line-chart-card.tsx
6
6
  /** Values over an ordered axis as lines: one series, or several to compare, such as a portfolio against its index. */
7
- function LineChartCard(props) {
7
+ function LineChartCard({ curve = "monotone", ...props }) {
8
8
  return /* @__PURE__ */ jsx(ChartFrame, {
9
9
  chart: LineChart,
10
10
  ...props,
11
11
  children: props.series.map(({ key, color }) => /* @__PURE__ */ jsx(Line, {
12
12
  dataKey: key,
13
- type: "monotone",
13
+ type: curve,
14
14
  stroke: color,
15
15
  strokeWidth: 2,
16
16
  dot: false
@@ -10,8 +10,15 @@ export interface SectionCard {
10
10
  headline?: React$1.ReactNode;
11
11
  /** Muted second footer line. */
12
12
  detail?: React$1.ReactNode;
13
+ /** In a picker, a tile that cannot be picked, such as one with nothing in it: faded, and its button disabled. */
14
+ disabled?: boolean;
13
15
  }
14
- export declare function SectionCards({ items }: {
16
+ export interface SectionCardsProps {
15
17
  items: SectionCard[];
16
- }): React$1.JSX.Element;
18
+ /** The label of the picked tile. */
19
+ selected?: string;
20
+ /** Makes each tile one button, so keep tile content non-interactive; gets the label of the tile picked. */
21
+ onSelect?: (label: string) => void;
22
+ }
23
+ export declare function SectionCards({ items, selected, onSelect }: SectionCardsProps): React$1.JSX.Element;
17
24
  //#endregion
@@ -12,33 +12,44 @@ const COLUMNS = {
12
12
  5: "@3xl/main:grid-cols-3 @7xl/main:grid-cols-5",
13
13
  6: "@3xl/main:grid-cols-3"
14
14
  };
15
- function SectionCards({ items }) {
15
+ function SectionCards({ items, selected, onSelect }) {
16
16
  return /* @__PURE__ */ jsx("div", {
17
17
  className: "@container/main",
18
18
  children: /* @__PURE__ */ jsx("div", {
19
19
  className: cn("grid grid-cols-1 gap-4", COLUMNS[items.length] ?? COLUMNS[4]),
20
20
  children: items.map((item) => /* @__PURE__ */ jsxs(Card, {
21
- className: "@container/card",
22
- children: [/* @__PURE__ */ jsxs(CardHeader, { children: [
23
- /* @__PURE__ */ jsx(CardDescription, { children: item.label }),
24
- /* @__PURE__ */ jsx(CardTitle, {
25
- className: "text-2xl font-semibold tabular-nums @[250px]/card:text-3xl",
26
- children: item.value
21
+ className: cn("@container/card", onSelect && "relative", item.label === selected && "ring-2 ring-primary!", onSelect && item.disabled && "opacity-60"),
22
+ children: [
23
+ onSelect && /* @__PURE__ */ jsx("button", {
24
+ type: "button",
25
+ "aria-label": item.label,
26
+ "aria-pressed": item.label === selected,
27
+ disabled: item.disabled,
28
+ onClick: () => onSelect(item.label),
29
+ className: "absolute inset-0 z-10 rounded-4xl outline-none focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:ring-inset"
27
30
  }),
28
- item.badge && /* @__PURE__ */ jsx(CardAction, { children: /* @__PURE__ */ jsx(Badge, {
29
- variant: "outline",
30
- children: item.badge
31
- }) })
32
- ] }), (item.headline || item.detail) && /* @__PURE__ */ jsxs(CardFooter, {
33
- className: "flex-col items-start gap-1.5 text-sm",
34
- children: [item.headline && /* @__PURE__ */ jsx("div", {
35
- className: "line-clamp-1 flex gap-2 font-medium",
36
- children: item.headline
37
- }), item.detail && /* @__PURE__ */ jsx("div", {
38
- className: "text-muted-foreground",
39
- children: item.detail
40
- })]
41
- })]
31
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
32
+ /* @__PURE__ */ jsx(CardDescription, { children: item.label }),
33
+ /* @__PURE__ */ jsx(CardTitle, {
34
+ className: "text-2xl font-semibold tabular-nums @[250px]/card:text-3xl",
35
+ children: item.value
36
+ }),
37
+ item.badge && /* @__PURE__ */ jsx(CardAction, { children: /* @__PURE__ */ jsx(Badge, {
38
+ variant: "outline",
39
+ children: item.badge
40
+ }) })
41
+ ] }),
42
+ (item.headline || item.detail) && /* @__PURE__ */ jsxs(CardFooter, {
43
+ className: "flex-col items-start gap-1.5 text-sm",
44
+ children: [item.headline && /* @__PURE__ */ jsx("div", {
45
+ className: "line-clamp-1 flex gap-2 font-medium",
46
+ children: item.headline
47
+ }), item.detail && /* @__PURE__ */ jsx("div", {
48
+ className: "text-muted-foreground",
49
+ children: item.detail
50
+ })]
51
+ })
52
+ ]
42
53
  }, item.label))
43
54
  })
44
55
  });
@@ -19,8 +19,10 @@ export interface BarListProps extends React$1.ComponentProps<"div"> {
19
19
  color?: string;
20
20
  /** Show each row's share of the total next to its value. */
21
21
  showPercentage?: boolean;
22
+ /** The value a full-width bar stands for. Give two lists the same max to draw them on one scale. Defaults to the largest value. */
23
+ max?: number;
22
24
  onItemClick?: (item: BarListItem) => void;
23
25
  }
24
- declare function BarList({ data, valueFormatter, sortOrder, color, showPercentage, onItemClick, className, ...props }: BarListProps): React$1.JSX.Element;
26
+ declare function BarList({ data, valueFormatter, sortOrder, color, showPercentage, max: scale, onItemClick, className, ...props }: BarListProps): React$1.JSX.Element;
25
27
  //#endregion
26
28
  export { BarList };
@@ -4,7 +4,7 @@ import { pct } from "../../../lib/format.js";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import * as React$1 from "react";
6
6
  //#region src/components/registry/dashboardcn/bar-list.tsx
7
- function BarList({ data, valueFormatter, sortOrder = "descending", color = "var(--chart-1)", showPercentage = false, onItemClick, className, ...props }) {
7
+ function BarList({ data, valueFormatter, sortOrder = "descending", color = "var(--chart-1)", showPercentage = false, max: scale, onItemClick, className, ...props }) {
8
8
  const locale = useLocale();
9
9
  const format = valueFormatter ?? ((value) => new Intl.NumberFormat(locale.numberLocale, {
10
10
  notation: "compact",
@@ -15,7 +15,7 @@ function BarList({ data, valueFormatter, sortOrder = "descending", color = "var(
15
15
  const sorted = [...data].sort((a, b) => a.value - b.value);
16
16
  return sortOrder === "descending" ? sorted.reverse() : sorted;
17
17
  }, [data, sortOrder]);
18
- const max = Math.max(...items.map((item) => item.value), 0);
18
+ const max = scale ?? Math.max(...items.map((item) => item.value), 0);
19
19
  const total = items.reduce((sum, item) => sum + item.value, 0);
20
20
  return /* @__PURE__ */ jsx("div", {
21
21
  "data-slot": "bar-list",
@@ -0,0 +1,38 @@
1
+ import { ChartColor } from "../../../lib/chart-series.js";
2
+ import * as React$1 from "react";
3
+ //#region src/components/registry/dashboardcn/distribution-bar.d.ts
4
+ export interface DistributionSegment {
5
+ name: string;
6
+ value: number;
7
+ /** Defaults to chart-1 through chart-5 in order; var(--muted) for space that is free. */
8
+ color?: ChartColor | "var(--muted)";
9
+ /** Stable key when names can repeat. */
10
+ key?: string;
11
+ }
12
+ export interface DistributionMarker {
13
+ /** The value the line marks, on the bar's scale. */
14
+ at: number;
15
+ label?: string;
16
+ }
17
+ export interface DistributionBarProps extends Omit<React$1.ComponentProps<"div">, "onMouseLeave"> {
18
+ segments: DistributionSegment[];
19
+ valueFormatter?: (value: number) => string;
20
+ showLegend?: boolean;
21
+ /** Show absolute values in the legend in addition to the share. */
22
+ showValues?: boolean;
23
+ /** The value the bar's right end stands for. Defaults to the positive segments' total. */
24
+ max?: number;
25
+ /**
26
+ * The value the bar's left end stands for. Defaults to the negative segments' total, or 0 when there are none.
27
+ * Above zero, segments (which start at zero) fall off the bar.
28
+ */
29
+ min?: number;
30
+ markers?: DistributionMarker[];
31
+ /** The key (or name) of the one segment to keep solid; the rest fade. */
32
+ highlighted?: string | null;
33
+ /** Called with the segment under the pointer, and null when it leaves the bar. */
34
+ onHover?: (segment: DistributionSegment | null) => void;
35
+ }
36
+ declare function DistributionBar({ segments, valueFormatter, showLegend, showValues, max, min, markers, highlighted, onHover, className, "aria-label": ariaLabel, ...props }: DistributionBarProps): React$1.JSX.Element;
37
+ //#endregion
38
+ export { DistributionBar };
@@ -0,0 +1,118 @@
1
+ import { useLocale } from "../../siyahi/siyahi-provider.js";
2
+ import { cn } from "../../../lib/utils.js";
3
+ import { pct } from "../../../lib/format.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import "react";
6
+ //#region src/components/registry/dashboardcn/distribution-bar.tsx
7
+ const defaultColors = [
8
+ "var(--chart-1)",
9
+ "var(--chart-2)",
10
+ "var(--chart-3)",
11
+ "var(--chart-4)",
12
+ "var(--chart-5)"
13
+ ];
14
+ function DistributionBar({ segments, valueFormatter, showLegend = true, showValues = false, max, min, markers = [], highlighted = null, onHover, className, "aria-label": ariaLabel, ...props }) {
15
+ const locale = useLocale();
16
+ const format = valueFormatter ?? ((value) => new Intl.NumberFormat(locale.numberLocale, {
17
+ notation: "compact",
18
+ maximumFractionDigits: 1
19
+ }).format(value));
20
+ const total = segments.reduce((sum, segment) => sum + Math.abs(segment.value), 0);
21
+ const gains = segments.reduce((sum, segment) => sum + Math.max(segment.value, 0), 0);
22
+ const losses = segments.reduce((sum, segment) => sum + Math.min(segment.value, 0), 0);
23
+ const bottom = min ?? losses;
24
+ const top = max ?? gains;
25
+ const span = top - bottom || 1;
26
+ const position = (value) => (value - bottom) / span * 100;
27
+ const shown = markers.filter((marker) => marker.at >= bottom && marker.at <= top).map((marker, index) => ({
28
+ ...marker,
29
+ key: `${marker.at}:${marker.label ?? ""}:${index}`
30
+ }));
31
+ let above = 0;
32
+ let below = 0;
33
+ const resolved = segments.map((segment, index) => {
34
+ const key = segment.key ?? segment.name;
35
+ const size = Math.abs(segment.value);
36
+ const start = segment.value < 0 ? below -= size : (above += size) - size;
37
+ return {
38
+ ...segment,
39
+ key,
40
+ color: segment.color ?? defaultColors[index % defaultColors.length],
41
+ share: total > 0 ? size / total : 0,
42
+ left: position(start),
43
+ width: size / span * 100
44
+ };
45
+ });
46
+ const figure = (segment) => max === void 0 ? pct(segment.share, locale) : format(segment.value);
47
+ return /* @__PURE__ */ jsxs("div", {
48
+ "data-slot": "distribution-bar",
49
+ className: cn("flex flex-col gap-3", className),
50
+ ...props,
51
+ children: [/* @__PURE__ */ jsxs("div", {
52
+ className: "relative",
53
+ children: [
54
+ shown.some((m) => m.label) ? /* @__PURE__ */ jsx("div", {
55
+ className: "text-muted-foreground relative h-4 font-mono text-xs",
56
+ children: shown.map((marker) => marker.label ? /* @__PURE__ */ jsx("span", {
57
+ className: cn("absolute top-0 whitespace-nowrap", position(marker.at) <= 5 ? "translate-x-0" : position(marker.at) >= 95 ? "-translate-x-full" : "-translate-x-1/2"),
58
+ style: { left: `${position(marker.at)}%` },
59
+ children: marker.label
60
+ }, marker.key) : null)
61
+ }) : null,
62
+ /* @__PURE__ */ jsx("div", {
63
+ role: "img",
64
+ "aria-label": ariaLabel ?? resolved.map((segment) => `${segment.name} ${figure(segment)}`).join(", "),
65
+ className: "bg-muted relative h-2.5 w-full overflow-hidden rounded-full",
66
+ onMouseLeave: onHover ? () => onHover(null) : void 0,
67
+ children: resolved.map((segment) => segment.width > 0 ? /* @__PURE__ */ jsx("div", {
68
+ "data-slot": "distribution-segment",
69
+ className: "border-card absolute inset-y-0 border-x transition-[width,left,opacity] duration-300",
70
+ style: {
71
+ left: `${segment.left}%`,
72
+ width: `${segment.width}%`,
73
+ backgroundColor: segment.color,
74
+ opacity: highlighted === null || highlighted === segment.key ? 1 : .35
75
+ },
76
+ onMouseEnter: onHover ? () => onHover(segment) : void 0
77
+ }, segment.key) : null)
78
+ }),
79
+ shown.map((marker) => /* @__PURE__ */ jsx("div", {
80
+ "data-slot": "distribution-marker",
81
+ "aria-hidden": "true",
82
+ className: "bg-foreground absolute bottom-0 h-2.5 w-0.5 -translate-x-1/2",
83
+ style: { left: `${position(marker.at)}%` }
84
+ }, marker.key))
85
+ ]
86
+ }), showLegend ? /* @__PURE__ */ jsx("ul", {
87
+ className: "flex flex-wrap gap-x-4 gap-y-1.5 text-sm",
88
+ children: resolved.map((segment) => /* @__PURE__ */ jsxs("li", {
89
+ className: "flex items-center gap-2",
90
+ children: [
91
+ /* @__PURE__ */ jsx("span", {
92
+ "aria-hidden": "true",
93
+ className: "size-2.5 shrink-0 rounded-xs",
94
+ style: { backgroundColor: segment.color }
95
+ }),
96
+ /* @__PURE__ */ jsx("span", {
97
+ className: "text-muted-foreground",
98
+ children: segment.name
99
+ }),
100
+ /* @__PURE__ */ jsx("span", {
101
+ className: "font-medium tabular-nums",
102
+ children: figure(segment)
103
+ }),
104
+ showValues && max === void 0 ? /* @__PURE__ */ jsxs("span", {
105
+ className: "text-muted-foreground tabular-nums",
106
+ children: [
107
+ "(",
108
+ format(segment.value),
109
+ ")"
110
+ ]
111
+ }) : null
112
+ ]
113
+ }, segment.key))
114
+ }) : null]
115
+ });
116
+ }
117
+ //#endregion
118
+ export { DistributionBar };
@@ -0,0 +1,11 @@
1
+ import { buttonVariants } from "../../ui/button.js";
2
+ import * as React$1 from "react";
3
+ import { VariantProps } from "class-variance-authority";
4
+ //#region src/components/registry/minidev/copy-button.d.ts
5
+ declare function CopyButton({ value, className, variant, size, label, copiedLabel, ...props }: {
6
+ value: string;
7
+ label?: string;
8
+ copiedLabel?: string;
9
+ } & React$1.ComponentProps<"button"> & VariantProps<typeof buttonVariants>): React$1.JSX.Element;
10
+ //#endregion
11
+ export { CopyButton };
@@ -0,0 +1,34 @@
1
+ "use client";
2
+ import { Button } from "../../ui/button.js";
3
+ import { cn } from "../../../lib/utils.js";
4
+ import { CheckIcon, CopyIcon } from "lucide-react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import * as React$1 from "react";
7
+ import "class-variance-authority";
8
+ //#region src/components/registry/minidev/copy-button.tsx
9
+ function CopyButton({ value, className, variant = "outline", size = "sm", label = "Copy", copiedLabel = "Copied", ...props }) {
10
+ const [copied, setCopied] = React$1.useState(false);
11
+ React$1.useEffect(() => {
12
+ if (!copied) return;
13
+ const timeout = setTimeout(() => setCopied(false), 2e3);
14
+ return () => clearTimeout(timeout);
15
+ }, [copied]);
16
+ return /* @__PURE__ */ jsxs(Button, {
17
+ type: "button",
18
+ variant,
19
+ size,
20
+ "data-slot": "copy-button",
21
+ className: cn(className),
22
+ "aria-label": copied ? copiedLabel : label,
23
+ onClick: async () => {
24
+ try {
25
+ await navigator.clipboard.writeText(value);
26
+ setCopied(true);
27
+ } catch {}
28
+ },
29
+ ...props,
30
+ children: [copied ? /* @__PURE__ */ jsx(CheckIcon, { "data-icon": "inline-start" }) : /* @__PURE__ */ jsx(CopyIcon, { "data-icon": "inline-start" }), copied ? copiedLabel : label]
31
+ });
32
+ }
33
+ //#endregion
34
+ export { CopyButton };
@@ -0,0 +1,35 @@
1
+ import { TableSearchFilterProps } from "../filters/table-search-filter.js";
2
+ import { RowData } from "@tanstack/react-table";
3
+ //#region src/components/registry/niko-table/components/data-table-search-filter.d.ts
4
+ type DataTableSearchFilterProps<TData extends RowData> = Omit<TableSearchFilterProps<TData>, "table">;
5
+ /**
6
+ * A search filter component for DataTable.
7
+ * Can be used in controlled or uncontrolled mode.
8
+ *
9
+ * @example
10
+ * // Uncontrolled (manages its own state)
11
+ * <DataTableSearchFilter placeholder="Search products..." />
12
+ *
13
+ * @example
14
+ * // Controlled (you manage the state)
15
+ * const [search, setSearch] = useState("")
16
+ * <DataTableSearchFilter
17
+ * value={search}
18
+ * onChange={setSearch}
19
+ * placeholder="Search..."
20
+ * />
21
+ *
22
+ * @example
23
+ * // With nuqs for URL state
24
+ * const [search, setSearch] = useQueryState('search')
25
+ * <DataTableSearchFilter
26
+ * value={search ?? ""}
27
+ * onChange={setSearch}
28
+ * />
29
+ */
30
+ export declare function DataTableSearchFilter<TData extends RowData>(props: DataTableSearchFilterProps<TData>): import("react").JSX.Element;
31
+ export declare namespace DataTableSearchFilter {
32
+ var displayName: string;
33
+ }
34
+ //#endregion
35
+ export {};