@siyahi/ui 0.1.9-next.34 → 0.1.9-next.36

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 (101) hide show
  1. package/DESIGN.md +43 -26
  2. package/README.md +12 -14
  3. package/THIRD_PARTY_NOTICES.md +10 -11
  4. package/agents/examples/app-sidebar.tsx +0 -2
  5. package/agents/examples/chart-panels.tsx +0 -4
  6. package/agents/examples/{section-cards-select.tsx → metric-strip-select.tsx} +5 -5
  7. package/agents/examples/metric-strip-trend.tsx +33 -0
  8. package/agents/examples/overview-dashboard.tsx +4 -4
  9. package/agents/examples/scatter-chart.tsx +0 -1
  10. package/agents/examples/stale-blocks.tsx +9 -9
  11. package/agents/examples/surfaces.tsx +2 -3
  12. package/agents/manifest.json +27 -49
  13. package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +14 -6
  14. package/dist/components/registry/dashboardcn/kpi-row-card.js +49 -32
  15. package/dist/components/registry/niko-table/core/data-table-error-boundary.js +1 -1
  16. package/dist/components/registry/niko-table/filters/table-faceted-filter.js +2 -2
  17. package/dist/components/siyahi/panel-grid.d.ts +5 -6
  18. package/dist/components/siyahi/panel-grid.js +10 -9
  19. package/dist/components/siyahi/scatter-chart.d.ts +3 -3
  20. package/dist/components/siyahi/scatter-chart.js +6 -3
  21. package/dist/components/siyahi/siyahi-provider.d.ts +5 -6
  22. package/dist/components/siyahi/siyahi-provider.js +1 -1
  23. package/dist/components/siyahi/status-badge.js +1 -0
  24. package/dist/components/ui/alert-dialog.d.ts +20 -0
  25. package/dist/components/ui/alert-dialog.js +94 -0
  26. package/dist/components/ui/aspect-ratio.d.ts +6 -0
  27. package/dist/components/ui/aspect-ratio.js +13 -0
  28. package/dist/components/ui/attachment.d.ts +25 -0
  29. package/dist/components/ui/attachment.js +104 -0
  30. package/dist/components/ui/bubble.d.ts +18 -0
  31. package/dist/components/ui/bubble.js +73 -0
  32. package/dist/components/ui/button-group.d.ts +12 -0
  33. package/dist/components/ui/button-group.js +41 -0
  34. package/dist/components/ui/button.d.ts +1 -1
  35. package/dist/components/ui/button.js +1 -1
  36. package/dist/components/ui/carousel.d.ts +30 -0
  37. package/dist/components/ui/carousel.js +131 -0
  38. package/dist/components/ui/checkbox.d.ts +5 -0
  39. package/dist/components/ui/checkbox.js +20 -0
  40. package/dist/components/ui/combobox.d.ts +26 -0
  41. package/dist/components/ui/combobox.js +162 -0
  42. package/dist/components/ui/command.js +1 -1
  43. package/dist/components/ui/direction.d.ts +2 -0
  44. package/dist/components/ui/direction.js +1 -0
  45. package/dist/components/ui/drawer.d.ts +18 -0
  46. package/dist/components/ui/drawer.js +123 -0
  47. package/dist/components/ui/empty.d.ts +13 -0
  48. package/dist/components/ui/empty.js +59 -0
  49. package/dist/components/ui/field.js +1 -1
  50. package/dist/components/ui/hover-card.d.ts +7 -0
  51. package/dist/components/ui/hover-card.js +36 -0
  52. package/dist/components/ui/input-otp.d.ts +13 -0
  53. package/dist/components/ui/input-otp.js +46 -0
  54. package/dist/components/ui/item.d.ts +24 -0
  55. package/dist/components/ui/item.js +121 -0
  56. package/dist/components/ui/kbd.d.ts +5 -0
  57. package/dist/components/ui/kbd.js +19 -0
  58. package/dist/components/ui/marker.d.ts +12 -0
  59. package/dist/components/ui/marker.js +43 -0
  60. package/dist/components/ui/menubar.d.ts +31 -0
  61. package/dist/components/ui/menubar.js +136 -0
  62. package/dist/components/ui/message-scroller.d.ts +12 -0
  63. package/dist/components/ui/message-scroller.js +60 -0
  64. package/dist/components/ui/message.d.ts +12 -0
  65. package/dist/components/ui/message.js +49 -0
  66. package/dist/components/ui/native-select.d.ts +10 -0
  67. package/dist/components/ui/native-select.js +38 -0
  68. package/dist/components/ui/navigation-menu.d.ts +13 -0
  69. package/dist/components/ui/navigation-menu.js +82 -0
  70. package/dist/components/ui/pagination.d.ts +19 -0
  71. package/dist/components/ui/pagination.js +80 -0
  72. package/dist/components/ui/questionnaire.d.ts +21 -0
  73. package/dist/components/ui/questionnaire.js +170 -0
  74. package/dist/components/ui/radio-group.d.ts +7 -0
  75. package/dist/components/ui/radio-group.js +26 -0
  76. package/dist/components/ui/resizable.d.ts +9 -0
  77. package/dist/components/ui/resizable.js +28 -0
  78. package/dist/components/ui/sidebar.js +1 -1
  79. package/dist/components/ui/spinner.d.ts +4 -0
  80. package/dist/components/ui/spinner.js +15 -0
  81. package/dist/components/ui/switch.d.ts +7 -0
  82. package/dist/components/ui/switch.js +19 -0
  83. package/dist/components/ui/toast.d.ts +18 -0
  84. package/dist/components/ui/toast.js +123 -0
  85. package/dist/components/ui/trace.d.ts +20 -0
  86. package/dist/components/ui/trace.js +75 -0
  87. package/dist/index.d.ts +32 -3
  88. package/dist/index.js +35 -5
  89. package/dist/lib/chart-frame.d.ts +1 -1
  90. package/dist/lib/chart-frame.js +3 -1
  91. package/dist/lib/chart-series.d.ts +10 -2
  92. package/dist/lib/chart-series.js +10 -0
  93. package/package.json +5 -3
  94. package/registry.lock.json +0 -8
  95. package/styles/siyahi.css +257 -109
  96. package/agents/examples/section-cards-trend.tsx +0 -32
  97. package/agents/examples/section-cards.tsx +0 -48
  98. package/agents/report-rules.json +0 -7
  99. package/dist/components/registry/dashboard-01/section-cards.d.ts +0 -30
  100. package/dist/components/registry/dashboard-01/section-cards.js +0 -74
  101. package/report.css +0 -146
@@ -1,18 +1,20 @@
1
1
  import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../../ui/card.js";
2
2
  import { cn } from "../../../lib/utils.js";
3
+ import { StaleNote } from "../../siyahi/stale-note.js";
3
4
  import { Delta } from "../../siyahi/delta.js";
4
5
  import { Sparkline } from "./sparkline.js";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  import "react";
7
8
  //#region src/components/registry/dashboardcn/kpi-row-card.tsx
8
9
  const COLUMNS = {
9
- 1: "basis-full",
10
- 2: "basis-full @2xs/strip:basis-1/2",
11
- 3: "basis-full @lg/strip:basis-1/3",
12
- 4: "basis-full @2xs/strip:basis-1/2 @3xl/strip:basis-1/4",
13
- 5: "basis-full @2xs/strip:basis-1/2 @3xl/strip:basis-1/5",
14
- 6: "basis-full @2xs/strip:basis-1/2 @xl/strip:basis-1/3 @5xl/strip:basis-1/6",
15
- 8: "basis-full @2xs/strip:basis-1/2 @3xl/strip:basis-1/4 @7xl/strip:basis-1/8"
10
+ 1: "",
11
+ 2: "@2xs/strip:grid-cols-2",
12
+ 3: "@lg/strip:grid-cols-3",
13
+ 4: "@2xs/strip:grid-cols-2 @3xl/strip:grid-cols-4",
14
+ 5: "@lg/strip:grid-cols-3 @3xl/strip:grid-cols-5",
15
+ 6: "@2xs/strip:grid-cols-2 @xl/strip:grid-cols-3 @5xl/strip:grid-cols-6",
16
+ 7: "@2xl/strip:grid-cols-4 @7xl/strip:grid-cols-7",
17
+ 8: "@2xs/strip:grid-cols-2 @3xl/strip:grid-cols-4 @7xl/strip:grid-cols-8"
16
18
  };
17
19
  function trendColor(change) {
18
20
  if (change === void 0) return "var(--chart-1)";
@@ -20,8 +22,8 @@ function trendColor(change) {
20
22
  if (change < 0) return "var(--negative)";
21
23
  return "var(--muted-foreground)";
22
24
  }
23
- /** A card holding a row of small figures, each with its change and a sparkline: more numbers in less room than stat tiles. */
24
- function MetricStrip({ title, description, action, items, footer, className, ...props }) {
25
+ /** A row of figures, each with its change and recent run, optionally a picker that scopes the page. */
26
+ function MetricStrip({ title, description, action, items, footer, selected, onSelect, className, ...props }) {
25
27
  const columns = COLUMNS[Math.min(items.length, 8)] ?? COLUMNS[8];
26
28
  return /* @__PURE__ */ jsxs(Card, {
27
29
  className: cn("gap-4", className),
@@ -34,40 +36,55 @@ function MetricStrip({ title, description, action, items, footer, className, ...
34
36
  ] }),
35
37
  /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("div", {
36
38
  "data-slot": "metric-strip",
37
- className: "@container/strip -mx-4 -my-3 overflow-hidden",
39
+ className: "@container/strip",
38
40
  children: /* @__PURE__ */ jsx("div", {
39
- className: "-me-px -mb-px flex flex-wrap",
41
+ className: cn("grid grid-cols-1 gap-x-6 gap-y-5", columns),
40
42
  children: items.map((item) => /* @__PURE__ */ jsxs("div", {
41
43
  "data-slot": "metric-strip-item",
42
44
  "data-tone": item.tone,
43
- className: cn("flex min-w-0 flex-col gap-1.5 border-e border-b px-4 py-4", columns),
44
- children: [/* @__PURE__ */ jsx("div", {
45
- className: "truncate font-mono text-2xs tracking-wider text-muted-foreground uppercase",
46
- children: item.label
47
- }), /* @__PURE__ */ jsxs("div", {
48
- className: "flex flex-wrap items-end justify-between gap-x-3 gap-y-1",
49
- children: [/* @__PURE__ */ jsxs("div", {
50
- className: "flex min-w-0 flex-col gap-0.5",
51
- children: [/* @__PURE__ */ jsx("div", {
52
- className: "text-xl font-semibold tracking-tight tabular-nums",
53
- children: item.value
54
- }), (item.change !== void 0 || item.note) && /* @__PURE__ */ jsxs("div", {
55
- className: "flex flex-wrap items-center gap-x-1.5 text-xs",
56
- children: [item.change !== void 0 && /* @__PURE__ */ jsx(Delta, {
45
+ "data-stale": item.stale ? "" : void 0,
46
+ "data-picked": onSelect && item.label === selected ? "" : void 0,
47
+ className: cn("relative row-span-4 grid min-w-0 grid-rows-subgrid gap-y-1", onSelect && item.disabled && "opacity-60"),
48
+ children: [
49
+ onSelect && /* @__PURE__ */ jsx("button", {
50
+ type: "button",
51
+ "aria-label": item.label,
52
+ "aria-pressed": item.label === selected,
53
+ disabled: item.disabled,
54
+ onClick: () => onSelect(item.label),
55
+ className: "absolute -inset-2 z-10 outline-none focus-visible:ring-2 focus-visible:ring-ring"
56
+ }),
57
+ /* @__PURE__ */ jsx("div", {
58
+ "data-slot": "metric-strip-label",
59
+ className: "font-mono text-2xs tracking-wider break-words text-muted-foreground uppercase",
60
+ children: item.label
61
+ }),
62
+ /* @__PURE__ */ jsx("div", {
63
+ "data-slot": "metric-strip-value",
64
+ className: "text-xl font-semibold tracking-tight tabular-nums",
65
+ children: item.value
66
+ }),
67
+ /* @__PURE__ */ jsxs("div", {
68
+ className: "flex flex-wrap items-center gap-x-1.5 gap-y-1 self-start text-xs",
69
+ children: [
70
+ item.change !== void 0 && /* @__PURE__ */ jsx(Delta, {
57
71
  value: item.change,
58
72
  format: item.changeFormat
59
- }), item.note && /* @__PURE__ */ jsx("span", {
73
+ }),
74
+ item.note && /* @__PURE__ */ jsx("span", {
60
75
  className: "text-muted-foreground",
61
76
  children: item.note
62
- })]
63
- })]
64
- }), item.trend && item.trend.length > 1 && /* @__PURE__ */ jsx(Sparkline, {
77
+ }),
78
+ item.stale && /* @__PURE__ */ jsx(StaleNote, { since: item.stale })
79
+ ]
80
+ }),
81
+ item.trend && item.trend.length > 1 ? /* @__PURE__ */ jsx(Sparkline, {
65
82
  data: item.trend,
66
83
  variant: "line",
67
84
  color: trendColor(item.change),
68
- className: "h-9 w-20 shrink-0"
69
- })]
70
- })]
85
+ className: "mt-1 h-8 w-full"
86
+ }) : /* @__PURE__ */ jsx("div", {})
87
+ ]
71
88
  }, item.label))
72
89
  })
73
90
  }) }),
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { Alert, AlertDescription, AlertTitle } from "../../../ui/alert.js";
3
2
  import { Button } from "../../../ui/button.js";
3
+ import { Alert, AlertDescription, AlertTitle } from "../../../ui/alert.js";
4
4
  import { AlertCircle } from "lucide-react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  import React from "react";
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { Badge } from "../../../ui/badge.js";
3
2
  import { Button } from "../../../ui/button.js";
4
- import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from "../../../ui/command.js";
3
+ import { Badge } from "../../../ui/badge.js";
5
4
  import { Separator } from "../../../ui/separator.js";
5
+ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from "../../../ui/command.js";
6
6
  import { Popover, PopoverContent, PopoverTrigger } from "../../../ui/popover.js";
7
7
  import { cn } from "../../../../lib/utils.js";
8
8
  import { FILTER_OPERATORS, FILTER_VARIANTS, JOIN_OPERATORS } from "../lib/constants.js";
@@ -9,18 +9,17 @@ declare const COLUMNS: {
9
9
  export interface PanelGridProps {
10
10
  /**
11
11
  * Blocks across from a 42rem grid, so three short ones fit a reading column (an article's 55rem); 4 goes two across
12
- * there and four from 64rem. Below 42rem they sit one under another.
12
+ * there and four from 64rem. Below 42rem they sit one under another. From 140rem a grid of 2 takes a third across,
13
+ * and from 180rem a grid of 2 or 3 a fourth, when it holds that many blocks; 1 stays one.
13
14
  */
14
15
  columns?: keyof typeof COLUMNS | undefined;
15
16
  children: ReactNode;
16
17
  className?: string | undefined;
17
18
  }
18
19
  /**
19
- * Data blocks side by side: chart cards, tables, a MetricStrip. On a ruled surface, the default, the grid is filled
20
- * with the card colour and a hairline parts the blocks across and down, with a rule above and below the grid and none
21
- * on its sides; open leaves whitespace between them, and card an 8px gap between boxes. Each block's bottom and end
22
- * edges carry its rules and the grid clips the ones on its own edges, so an empty cell at the end of a short last row
23
- * is a blank stretch of the sheet, ruled off like the rest. The theme numbers each block's card title 01, 02.
20
+ * Data blocks side by side: chart cards, tables, a MetricStrip. On an open surface, the default, space parts the
21
+ * blocks: 24px across and 16px down, no box and no rule. A card surface sets them 8px apart, each in its own box. The
22
+ * theme numbers each block's card title 01, 02.
24
23
  */
25
24
  export declare function PanelGrid({ columns, children, className }: PanelGridProps): import("react").JSX.Element;
26
25
  //#endregion
@@ -9,25 +9,26 @@ const COLUMNS = {
9
9
  3: "@2xl/panels:grid-cols-3",
10
10
  4: "@2xl/panels:grid-cols-2 @5xl/panels:grid-cols-4"
11
11
  };
12
+ const WIDE_THREE = "@min-[140rem]/panels:grid-cols-3";
13
+ const WIDE_FOUR = "@min-[180rem]/panels:grid-cols-4";
12
14
  /**
13
- * Data blocks side by side: chart cards, tables, a MetricStrip. On a ruled surface, the default, the grid is filled
14
- * with the card colour and a hairline parts the blocks across and down, with a rule above and below the grid and none
15
- * on its sides; open leaves whitespace between them, and card an 8px gap between boxes. Each block's bottom and end
16
- * edges carry its rules and the grid clips the ones on its own edges, so an empty cell at the end of a short last row
17
- * is a blank stretch of the sheet, ruled off like the rest. The theme numbers each block's card title 01, 02.
15
+ * Data blocks side by side: chart cards, tables, a MetricStrip. On an open surface, the default, space parts the
16
+ * blocks: 24px across and 16px down, no box and no rule. A card surface sets them 8px apart, each in its own box. The
17
+ * theme numbers each block's card title 01, 02.
18
18
  */
19
19
  function PanelGrid({ columns = 2, children, className }) {
20
20
  const surface = useSurface();
21
- const ruled = surface === "ruled";
21
+ const blocks = Children.toArray(children).length;
22
+ const wide = cn(columns === 2 && blocks >= 3 && WIDE_THREE, (columns === 2 || columns === 3) && blocks >= 4 && WIDE_FOUR);
22
23
  return /* @__PURE__ */ jsx("div", {
23
24
  "data-slot": "panel-grid",
24
25
  "data-surface": surface,
25
- className: cn("@container/panels", ruled && "overflow-clip border-y", className),
26
+ className: cn("@container/panels", className),
26
27
  children: /* @__PURE__ */ jsx("div", {
27
- className: cn("grid grid-cols-1", COLUMNS[columns], ruled ? "-me-px -mb-px bg-card" : surface === "open" ? "gap-x-8 gap-y-6" : "gap-2"),
28
+ className: cn("grid grid-cols-1", COLUMNS[columns], wide, surface === "open" ? "gap-x-6 gap-y-4" : "gap-2"),
28
29
  children: Children.map(children, (child) => /* @__PURE__ */ jsx("div", {
29
30
  "data-slot": "panel",
30
- className: cn("min-w-0", ruled && "border-e border-b"),
31
+ className: "min-w-0",
31
32
  children: child
32
33
  }))
33
34
  })
@@ -25,8 +25,8 @@ export interface ScatterChartCardProps<T extends ScatterPoint> {
25
25
  action?: ReactNode;
26
26
  /** Most important first: earlier points take the labels. */
27
27
  points: T[];
28
- /** Height of the plot, in pixels. */
29
- height: number;
28
+ /** Height of the plot, in pixels. Left out, it follows the plot's width (fittedChartHeight). */
29
+ height?: number | undefined;
30
30
  /** What the x axis measures, under it, such as "Share of sales". */
31
31
  xLabel: string;
32
32
  /** What the y axis measures, beside it, such as "Growth on last year". */
@@ -64,6 +64,6 @@ export interface ScatterChartCardProps<T extends ScatterPoint> {
64
64
  sizeFormatter?: ((value: number) => string) | undefined;
65
65
  }
66
66
  /** Two measures per item as dots, such as size against growth, with the leading names beside their dots. */
67
- export declare function ScatterChartCard<T extends ScatterPoint>({ title, description, action, points, height, xLabel, yLabel, xScale, xScaleToggle, yScale, yScaleToggle, xFormatter, yFormatter, labels, details, selected, onSelect, footer, quadrants, sizeLabel, sizeFormatter }: ScatterChartCardProps<T>): import("react").JSX.Element;
67
+ export declare function ScatterChartCard<T extends ScatterPoint>({ title, description, action, points, height: fixedHeight, xLabel, yLabel, xScale, xScaleToggle, yScale, yScaleToggle, xFormatter, yFormatter, labels, details, selected, onSelect, footer, quadrants, sizeLabel, sizeFormatter }: ScatterChartCardProps<T>): import("react").JSX.Element;
68
68
  //#endregion
69
69
  export type { ScatterQuadrants };
@@ -2,7 +2,9 @@ import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader,
2
2
  import { ChartContainer } from "../ui/chart.js";
3
3
  import { LOG_BLOCKED, useAxisScale } from "./scale-toggle.js";
4
4
  import { useLocale } from "./siyahi-provider.js";
5
+ import { fittedChartHeight } from "../../lib/chart-series.js";
5
6
  import { fitsLog, ticksFor } from "../../lib/ticks.js";
7
+ import { useElementWidth } from "../../lib/use-element-width.js";
6
8
  import { fontLoads, useRenderWhenFontsLoad } from "../../lib/use-render-when-fonts-load.js";
7
9
  import { corners, dotSizes, placeLabels, quadrantSplit } from "../../lib/scatter.js";
8
10
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -19,9 +21,10 @@ const AXIS_TITLE = "fill-muted-foreground text-xs";
19
21
  const keyOf = (point) => point.key ?? point.name;
20
22
  const MONO_WIDTH = 7.2;
21
23
  /** Two measures per item as dots, such as size against growth, with the leading names beside their dots. */
22
- function ScatterChartCard({ title, description, action, points, height, xLabel, yLabel, xScale = "linear", xScaleToggle = false, yScale = "linear", yScaleToggle = false, xFormatter, yFormatter, labels = 12, details, selected = null, onSelect, footer, quadrants, sizeLabel = "Size", sizeFormatter }) {
24
+ function ScatterChartCard({ title, description, action, points, height: fixedHeight, xLabel, yLabel, xScale = "linear", xScaleToggle = false, yScale = "linear", yScaleToggle = false, xFormatter, yFormatter, labels = 12, details, selected = null, onSelect, footer, quadrants, sizeLabel = "Size", sizeFormatter }) {
23
25
  const { numberLocale } = useLocale();
24
- const plotRef = useRef(null);
26
+ const [plotRef, plotWidth] = useElementWidth();
27
+ const height = fixedHeight ?? fittedChartHeight(plotWidth);
25
28
  const [focusedKey, setFocusedKey] = useState(null);
26
29
  const keyed = useRef(null);
27
30
  useEffect(() => {
@@ -245,7 +248,7 @@ function PointTooltip({ active, payload, details }) {
245
248
  const point = active ? payload?.[0]?.payload : void 0;
246
249
  if (!point) return null;
247
250
  return /* @__PURE__ */ jsxs("div", {
248
- className: "grid min-w-32 gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
251
+ className: "grid min-w-32 gap-1.5 border border-border bg-background px-2.5 py-1.5 text-xs",
249
252
  children: [/* @__PURE__ */ jsx("span", {
250
253
  className: "font-medium",
251
254
  children: point.name
@@ -3,18 +3,17 @@ import { SiyahiLocale } from "../../lib/locale.js";
3
3
  import { ReactNode } from "react";
4
4
  //#region src/components/siyahi/siyahi-provider.d.ts
5
5
  /**
6
- * How a data block sits on the page. "ruled", the default: blocks filled with the card colour and parted by hairlines,
7
- * with a rule above and below each group and none on its sides. "card": a filled square card in a hairline ring, 8px
8
- * from the next, for a page of separate blocks. "open": no fill and no lines, the block's content level with the
9
- * page's text.
6
+ * How a data block sits on the page. "open", the default: no fill, no lines and no padding, the block's content level
7
+ * with the page's text and parted from the next by space. "card": a filled square card in a hairline ring, 8px from
8
+ * the next, for a page of separate blocks.
10
9
  */
11
- export type Surface = "ruled" | "card" | "open";
10
+ export type Surface = "open" | "card";
12
11
  export interface SiyahiProviderProps {
13
12
  /** Any setting left out keeps its default: en-IN, INR, Asia/Kolkata. */
14
13
  locale?: Optional<SiyahiLocale> | undefined;
15
14
  /**
16
15
  * Set it on a nested provider for one part of a page. Left out, a provider keeps the surface around it, so a
17
- * provider that only changes the locale changes nothing else; the outermost default is "ruled".
16
+ * provider that only changes the locale changes nothing else; the outermost default is "open".
18
17
  */
19
18
  surface?: Surface | undefined;
20
19
  children: ReactNode;
@@ -4,7 +4,7 @@ import { jsx } from "react/jsx-runtime";
4
4
  import { createContext, use, useMemo } from "react";
5
5
  //#region src/components/siyahi/siyahi-provider.tsx
6
6
  const LocaleContext = createContext(defaultLocale);
7
- const SurfaceContext = createContext("ruled");
7
+ const SurfaceContext = createContext("open");
8
8
  /** Wrap the app once. Carries the locale, the surface and the tooltip provider shadcn asks for. */
9
9
  function SiyahiProvider({ locale, surface, children }) {
10
10
  const { numberLocale = defaultLocale.numberLocale, currency = defaultLocale.currency, timeZone = defaultLocale.timeZone } = locale ?? {};
@@ -16,6 +16,7 @@ function StatusBadge({ tone = "neutral", className, children, ...props }) {
16
16
  ...props,
17
17
  children: [/* @__PURE__ */ jsx("span", {
18
18
  "aria-hidden": "true",
19
+ "data-slot": "status-dot",
19
20
  className: cn("size-1.5 rounded-full", TONES[tone].dot)
20
21
  }), children]
21
22
  });
@@ -0,0 +1,20 @@
1
+ import { Button } from "./button.js";
2
+ import * as React$1 from "react";
3
+ import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
4
+ //#region src/components/ui/alert-dialog.d.ts
5
+ declare function AlertDialog({ ...props }: AlertDialog$1.Root.Props): React$1.JSX.Element;
6
+ declare function AlertDialogTrigger({ ...props }: AlertDialog$1.Trigger.Props): React$1.JSX.Element;
7
+ declare function AlertDialogPortal({ ...props }: AlertDialog$1.Portal.Props): React$1.JSX.Element;
8
+ declare function AlertDialogOverlay({ className, ...props }: AlertDialog$1.Backdrop.Props): React$1.JSX.Element;
9
+ declare function AlertDialogContent({ className, size, ...props }: AlertDialog$1.Popup.Props & {
10
+ size?: "default" | "sm";
11
+ }): React$1.JSX.Element;
12
+ declare function AlertDialogHeader({ className, ...props }: React$1.ComponentProps<"div">): React$1.JSX.Element;
13
+ declare function AlertDialogFooter({ className, ...props }: React$1.ComponentProps<"div">): React$1.JSX.Element;
14
+ declare function AlertDialogMedia({ className, ...props }: React$1.ComponentProps<"div">): React$1.JSX.Element;
15
+ declare function AlertDialogTitle({ className, ...props }: React$1.ComponentProps<typeof AlertDialog$1.Title>): React$1.JSX.Element;
16
+ declare function AlertDialogDescription({ className, ...props }: React$1.ComponentProps<typeof AlertDialog$1.Description>): React$1.JSX.Element;
17
+ declare function AlertDialogAction({ className, ...props }: React$1.ComponentProps<typeof Button>): React$1.JSX.Element;
18
+ declare function AlertDialogCancel({ className, variant, size, ...props }: AlertDialog$1.Close.Props & Pick<React$1.ComponentProps<typeof Button>, "variant" | "size">): React$1.JSX.Element;
19
+ //#endregion
20
+ export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger };
@@ -0,0 +1,94 @@
1
+ import { Button } from "./button.js";
2
+ import { cn } from "cn";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import "react";
5
+ import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
6
+ //#region src/components/ui/alert-dialog.tsx
7
+ function AlertDialog({ ...props }) {
8
+ return /* @__PURE__ */ jsx(AlertDialog$1.Root, {
9
+ "data-slot": "alert-dialog",
10
+ ...props
11
+ });
12
+ }
13
+ function AlertDialogTrigger({ ...props }) {
14
+ return /* @__PURE__ */ jsx(AlertDialog$1.Trigger, {
15
+ "data-slot": "alert-dialog-trigger",
16
+ ...props
17
+ });
18
+ }
19
+ function AlertDialogPortal({ ...props }) {
20
+ return /* @__PURE__ */ jsx(AlertDialog$1.Portal, {
21
+ "data-slot": "alert-dialog-portal",
22
+ ...props
23
+ });
24
+ }
25
+ function AlertDialogOverlay({ className, ...props }) {
26
+ return /* @__PURE__ */ jsx(AlertDialog$1.Backdrop, {
27
+ "data-slot": "alert-dialog-overlay",
28
+ className: cn("fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0", className),
29
+ ...props
30
+ });
31
+ }
32
+ function AlertDialogContent({ className, size = "default", ...props }) {
33
+ return /* @__PURE__ */ jsxs(AlertDialogPortal, { children: [/* @__PURE__ */ jsx(AlertDialogOverlay, {}), /* @__PURE__ */ jsx(AlertDialog$1.Popup, {
34
+ "data-slot": "alert-dialog-content",
35
+ "data-size": size,
36
+ className: cn("group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
37
+ ...props
38
+ })] });
39
+ }
40
+ function AlertDialogHeader({ className, ...props }) {
41
+ return /* @__PURE__ */ jsx("div", {
42
+ "data-slot": "alert-dialog-header",
43
+ className: cn("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", className),
44
+ ...props
45
+ });
46
+ }
47
+ function AlertDialogFooter({ className, ...props }) {
48
+ return /* @__PURE__ */ jsx("div", {
49
+ "data-slot": "alert-dialog-footer",
50
+ className: cn("-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end", className),
51
+ ...props
52
+ });
53
+ }
54
+ function AlertDialogMedia({ className, ...props }) {
55
+ return /* @__PURE__ */ jsx("div", {
56
+ "data-slot": "alert-dialog-media",
57
+ className: cn("mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6", className),
58
+ ...props
59
+ });
60
+ }
61
+ function AlertDialogTitle({ className, ...props }) {
62
+ return /* @__PURE__ */ jsx(AlertDialog$1.Title, {
63
+ "data-slot": "alert-dialog-title",
64
+ className: cn("font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2", className),
65
+ ...props
66
+ });
67
+ }
68
+ function AlertDialogDescription({ className, ...props }) {
69
+ return /* @__PURE__ */ jsx(AlertDialog$1.Description, {
70
+ "data-slot": "alert-dialog-description",
71
+ className: cn("text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", className),
72
+ ...props
73
+ });
74
+ }
75
+ function AlertDialogAction({ className, ...props }) {
76
+ return /* @__PURE__ */ jsx(Button, {
77
+ "data-slot": "alert-dialog-action",
78
+ className: cn(className),
79
+ ...props
80
+ });
81
+ }
82
+ function AlertDialogCancel({ className, variant = "outline", size = "default", ...props }) {
83
+ return /* @__PURE__ */ jsx(AlertDialog$1.Close, {
84
+ "data-slot": "alert-dialog-cancel",
85
+ className: cn(className),
86
+ render: /* @__PURE__ */ jsx(Button, {
87
+ variant,
88
+ size
89
+ }),
90
+ ...props
91
+ });
92
+ }
93
+ //#endregion
94
+ export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger };
@@ -0,0 +1,6 @@
1
+ //#region src/components/ui/aspect-ratio.d.ts
2
+ declare function AspectRatio({ ratio, className, ...props }: React.ComponentProps<"div"> & {
3
+ ratio: number;
4
+ }): import("react").JSX.Element;
5
+ //#endregion
6
+ export { AspectRatio };
@@ -0,0 +1,13 @@
1
+ import { cn } from "cn";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/components/ui/aspect-ratio.tsx
4
+ function AspectRatio({ ratio, className, ...props }) {
5
+ return /* @__PURE__ */ jsx("div", {
6
+ "data-slot": "aspect-ratio",
7
+ style: { "--ratio": ratio },
8
+ className: cn("relative aspect-(--ratio)", className),
9
+ ...props
10
+ });
11
+ }
12
+ //#endregion
13
+ export { AspectRatio };
@@ -0,0 +1,25 @@
1
+ import { Button } from "./button.js";
2
+ import * as React$1 from "react";
3
+ import { VariantProps } from "class-variance-authority";
4
+ import { useRender } from "@base-ui/react/use-render";
5
+ //#region src/components/ui/attachment.d.ts
6
+ declare const attachmentVariants: (props?: ({
7
+ size?: "default" | "sm" | "xs" | null | undefined;
8
+ orientation?: "horizontal" | "vertical" | null | undefined;
9
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
10
+ declare function Attachment({ className, state, size, orientation, ...props }: React$1.ComponentProps<"div"> & VariantProps<typeof attachmentVariants> & {
11
+ state?: "idle" | "uploading" | "processing" | "error" | "done";
12
+ }): React$1.JSX.Element;
13
+ declare const attachmentMediaVariants: (props?: ({
14
+ variant?: "icon" | "image" | null | undefined;
15
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
16
+ declare function AttachmentMedia({ className, variant, ...props }: React$1.ComponentProps<"div"> & VariantProps<typeof attachmentMediaVariants>): React$1.JSX.Element;
17
+ declare function AttachmentContent({ className, ...props }: React$1.ComponentProps<"div">): React$1.JSX.Element;
18
+ declare function AttachmentTitle({ className, ...props }: React$1.ComponentProps<"span">): React$1.JSX.Element;
19
+ declare function AttachmentDescription({ className, ...props }: React$1.ComponentProps<"span">): React$1.JSX.Element;
20
+ declare function AttachmentActions({ className, ...props }: React$1.ComponentProps<"div">): React$1.JSX.Element;
21
+ declare function AttachmentAction({ className, variant, size, ...props }: React$1.ComponentProps<typeof Button>): React$1.JSX.Element;
22
+ declare function AttachmentTrigger({ className, render, type, ...props }: useRender.ComponentProps<"button">): React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>>;
23
+ declare function AttachmentGroup({ className, ...props }: React$1.ComponentProps<"div">): React$1.JSX.Element;
24
+ //#endregion
25
+ export { Attachment, AttachmentAction, AttachmentActions, AttachmentContent, AttachmentDescription, AttachmentGroup, AttachmentMedia, AttachmentTitle, AttachmentTrigger };
@@ -0,0 +1,104 @@
1
+ import { Button } from "./button.js";
2
+ import { cn } from "cn";
3
+ import { jsx } from "react/jsx-runtime";
4
+ import "react";
5
+ import { cva } from "class-variance-authority";
6
+ import { mergeProps } from "@base-ui/react/merge-props";
7
+ import { useRender } from "@base-ui/react/use-render";
8
+ //#region src/components/ui/attachment.tsx
9
+ const attachmentVariants = cva("group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed", { variants: {
10
+ size: {
11
+ default: "gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2",
12
+ sm: "gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5",
13
+ xs: "gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1"
14
+ },
15
+ orientation: {
16
+ horizontal: "min-w-40 items-center",
17
+ vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30"
18
+ }
19
+ } });
20
+ function Attachment({ className, state = "done", size = "default", orientation = "horizontal", ...props }) {
21
+ return /* @__PURE__ */ jsx("div", {
22
+ "data-slot": "attachment",
23
+ "data-state": state,
24
+ "data-size": size,
25
+ "data-orientation": orientation,
26
+ className: cn(attachmentVariants({
27
+ size,
28
+ orientation
29
+ }), className),
30
+ ...props
31
+ });
32
+ }
33
+ const attachmentMediaVariants = cva("relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted text-foreground group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md group-data-[state=error]/attachment:bg-destructive/10 group-data-[state=error]/attachment:text-destructive group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6! [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5", {
34
+ variants: { variant: {
35
+ icon: "",
36
+ image: "opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 *:[img]:aspect-square *:[img]:w-full *:[img]:object-cover"
37
+ } },
38
+ defaultVariants: { variant: "icon" }
39
+ });
40
+ function AttachmentMedia({ className, variant = "icon", ...props }) {
41
+ return /* @__PURE__ */ jsx("div", {
42
+ "data-slot": "attachment-media",
43
+ "data-variant": variant,
44
+ className: cn(attachmentMediaVariants({ variant }), className),
45
+ ...props
46
+ });
47
+ }
48
+ function AttachmentContent({ className, ...props }) {
49
+ return /* @__PURE__ */ jsx("div", {
50
+ "data-slot": "attachment-content",
51
+ className: cn("max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1", className),
52
+ ...props
53
+ });
54
+ }
55
+ function AttachmentTitle({ className, ...props }) {
56
+ return /* @__PURE__ */ jsx("span", {
57
+ "data-slot": "attachment-title",
58
+ className: cn("block max-w-full min-w-0 truncate font-medium group-data-[state=processing]/attachment:shimmer group-data-[state=uploading]/attachment:shimmer", className),
59
+ ...props
60
+ });
61
+ }
62
+ function AttachmentDescription({ className, ...props }) {
63
+ return /* @__PURE__ */ jsx("span", {
64
+ "data-slot": "attachment-description",
65
+ className: cn("mt-0.5 block min-w-0 truncate text-xs text-muted-foreground group-data-[state=error]/attachment:text-destructive/80", "max-w-full", className),
66
+ ...props
67
+ });
68
+ }
69
+ function AttachmentActions({ className, ...props }) {
70
+ return /* @__PURE__ */ jsx("div", {
71
+ "data-slot": "attachment-actions",
72
+ className: cn("relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:gap-1", className),
73
+ ...props
74
+ });
75
+ }
76
+ function AttachmentAction({ className, variant, size = "icon-xs", ...props }) {
77
+ return /* @__PURE__ */ jsx(Button, {
78
+ "data-slot": "attachment-action",
79
+ variant: variant ?? "ghost",
80
+ size,
81
+ className: cn(className),
82
+ ...props
83
+ });
84
+ }
85
+ function AttachmentTrigger({ className, render, type, ...props }) {
86
+ return useRender({
87
+ defaultTagName: "button",
88
+ props: mergeProps({
89
+ type: render ? type : type ?? "button",
90
+ className: cn("absolute inset-0 z-10 outline-none", className)
91
+ }, props),
92
+ render,
93
+ state: { slot: "attachment-trigger" }
94
+ });
95
+ }
96
+ function AttachmentGroup({ className, ...props }) {
97
+ return /* @__PURE__ */ jsx("div", {
98
+ "data-slot": "attachment-group",
99
+ className: cn("flex min-w-0 scroll-fade-x snap-x snap-mandatory scroll-px-1 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start", className),
100
+ ...props
101
+ });
102
+ }
103
+ //#endregion
104
+ export { Attachment, AttachmentAction, AttachmentActions, AttachmentContent, AttachmentDescription, AttachmentGroup, AttachmentMedia, AttachmentTitle, AttachmentTrigger };
@@ -0,0 +1,18 @@
1
+ import * as React$1 from "react";
2
+ import { VariantProps } from "class-variance-authority";
3
+ import { useRender } from "@base-ui/react/use-render";
4
+ //#region src/components/ui/bubble.d.ts
5
+ declare function BubbleGroup({ className, ...props }: React$1.ComponentProps<"div">): React$1.JSX.Element;
6
+ declare const bubbleVariants: (props?: ({
7
+ variant?: "default" | "destructive" | "ghost" | "muted" | "outline" | "secondary" | "tinted" | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
+ declare function Bubble({ variant, align, className, ...props }: React$1.ComponentProps<"div"> & VariantProps<typeof bubbleVariants> & {
10
+ align?: "start" | "end";
11
+ }): React$1.JSX.Element;
12
+ declare function BubbleContent({ className, render, ...props }: useRender.ComponentProps<"div">): React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>>;
13
+ declare function BubbleReactions({ side, align, className, ...props }: React$1.ComponentProps<"div"> & {
14
+ align?: "start" | "end";
15
+ side?: "top" | "bottom";
16
+ }): React$1.JSX.Element;
17
+ //#endregion
18
+ export { Bubble, BubbleContent, BubbleGroup, BubbleReactions };