@siyahi/ui 0.1.9-next.2 → 0.1.9-next.21

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 (196) hide show
  1. package/DESIGN.md +30 -0
  2. package/README.md +82 -176
  3. package/THIRD_PARTY_NOTICES.md +11 -11
  4. package/agents/examples/accordion.tsx +39 -0
  5. package/agents/examples/alert.tsx +23 -0
  6. package/agents/examples/app-sidebar.tsx +38 -0
  7. package/agents/examples/avatar.tsx +14 -0
  8. package/agents/examples/badge.tsx +18 -0
  9. package/agents/examples/bar-list-labels.tsx +22 -0
  10. package/agents/examples/bar-list-sides.tsx +38 -0
  11. package/agents/examples/bar-list.tsx +24 -0
  12. package/agents/examples/breadcrumb.tsx +28 -0
  13. package/agents/examples/button-states.tsx +23 -0
  14. package/agents/examples/button.tsx +21 -0
  15. package/agents/examples/calendar.tsx +15 -0
  16. package/agents/examples/callout.tsx +33 -0
  17. package/agents/examples/card.tsx +34 -0
  18. package/agents/examples/change-bar.tsx +104 -0
  19. package/agents/examples/chart-area.tsx +39 -0
  20. package/agents/examples/chart-bar-flows.tsx +32 -0
  21. package/agents/examples/chart-bar-hourly.tsx +28 -0
  22. package/agents/examples/chart-bar-losses.tsx +29 -0
  23. package/agents/examples/chart-bar-sectors.tsx +72 -0
  24. package/agents/examples/chart-bar-years.tsx +40 -0
  25. package/agents/examples/chart-bar.tsx +56 -0
  26. package/agents/examples/chart-category-ticks.tsx +50 -0
  27. package/agents/examples/chart-line-events.tsx +47 -0
  28. package/agents/examples/chart-line-timeline.tsx +41 -0
  29. package/agents/examples/chart-line.tsx +57 -0
  30. package/agents/examples/code-block.tsx +38 -0
  31. package/agents/examples/collapsible.tsx +16 -0
  32. package/agents/examples/command.tsx +27 -0
  33. package/agents/examples/context-menu.tsx +15 -0
  34. package/agents/examples/copy-button.tsx +8 -0
  35. package/agents/examples/data-bar.tsx +121 -0
  36. package/agents/examples/data-table-compact.tsx +95 -0
  37. package/agents/examples/data-table-filters.tsx +103 -0
  38. package/agents/examples/data-table.tsx +98 -0
  39. package/agents/examples/delta.tsx +13 -0
  40. package/agents/examples/dialog.tsx +28 -0
  41. package/agents/examples/distribution-bar-budget.tsx +30 -0
  42. package/agents/examples/distribution-bar-tug.tsx +72 -0
  43. package/agents/examples/dropdown-menu.tsx +31 -0
  44. package/agents/examples/formatters.tsx +42 -0
  45. package/agents/examples/heatmap-calendar.tsx +60 -0
  46. package/agents/examples/heatmap-status.tsx +57 -0
  47. package/agents/examples/heatmap-weekday.tsx +75 -0
  48. package/agents/examples/input-states.tsx +33 -0
  49. package/agents/examples/input.tsx +17 -0
  50. package/agents/examples/local-time.tsx +14 -0
  51. package/agents/examples/metric-strip.tsx +46 -0
  52. package/agents/examples/overview-dashboard.tsx +18 -0
  53. package/agents/examples/page-hero.tsx +38 -0
  54. package/agents/examples/page-section.tsx +52 -0
  55. package/agents/examples/popover.tsx +23 -0
  56. package/agents/examples/price-chart.tsx +32 -0
  57. package/agents/examples/progress-tone.tsx +28 -0
  58. package/agents/examples/progress.tsx +10 -0
  59. package/agents/examples/range-position-table.tsx +101 -0
  60. package/agents/examples/range-position.tsx +53 -0
  61. package/agents/examples/scroll-area.tsx +20 -0
  62. package/agents/examples/section-cards-select.tsx +30 -0
  63. package/agents/examples/section-cards-trend.tsx +30 -0
  64. package/agents/examples/section-cards.tsx +48 -0
  65. package/agents/examples/select.tsx +27 -0
  66. package/agents/examples/separator.tsx +13 -0
  67. package/agents/examples/sheet.tsx +15 -0
  68. package/agents/examples/skeleton.tsx +11 -0
  69. package/agents/examples/slider.tsx +5 -0
  70. package/agents/examples/surfaces.tsx +116 -0
  71. package/agents/examples/table.tsx +50 -0
  72. package/agents/examples/tabs.tsx +16 -0
  73. package/agents/examples/target-rows.tsx +70 -0
  74. package/agents/examples/toggle-group.tsx +12 -0
  75. package/agents/examples/toggle.tsx +11 -0
  76. package/agents/examples/tooltip.tsx +13 -0
  77. package/agents/examples/treemap.tsx +88 -0
  78. package/agents/manifest.json +1081 -0
  79. package/agents/report-rules.json +7 -0
  80. package/dist/components/registry/charts/area-chart-card.js +25 -7
  81. package/dist/components/registry/charts/bar-chart-card.d.ts +0 -1
  82. package/dist/components/registry/charts/bar-chart-card.js +40 -26
  83. package/dist/components/registry/charts/line-chart-card.js +2 -2
  84. package/dist/components/registry/dashboard-01/section-cards.d.ts +2 -0
  85. package/dist/components/registry/dashboard-01/section-cards.js +42 -35
  86. package/dist/components/registry/dashboardcn/bar-list.js +18 -11
  87. package/dist/components/registry/dashboardcn/distribution-bar.js +1 -1
  88. package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +29 -0
  89. package/dist/components/registry/dashboardcn/kpi-row-card.js +81 -0
  90. package/dist/components/registry/dashboardcn/sparkline.d.ts +22 -0
  91. package/dist/components/registry/dashboardcn/sparkline.js +117 -0
  92. package/dist/components/registry/heatmap/calendar-heatmap.d.ts +4 -2
  93. package/dist/components/registry/heatmap/calendar-heatmap.js +74 -33
  94. package/dist/components/registry/heatmap/status-heatmap.d.ts +5 -3
  95. package/dist/components/registry/heatmap/status-heatmap.js +37 -15
  96. package/dist/components/registry/heatmap/weekday-heatmap.d.ts +9 -3
  97. package/dist/components/registry/heatmap/weekday-heatmap.js +82 -47
  98. package/dist/components/registry/niko-table/core/data-table-context.d.ts +18 -1
  99. package/dist/components/registry/niko-table/core/data-table-context.js +7 -1
  100. package/dist/components/registry/niko-table/core/data-table-grouped-row.js +3 -1
  101. package/dist/components/registry/niko-table/core/data-table-root.js +39 -4
  102. package/dist/components/registry/niko-table/core/data-table-structure.js +17 -12
  103. package/dist/components/registry/niko-table/core/data-table.d.ts +2 -2
  104. package/dist/components/registry/niko-table/core/data-table.js +5 -1
  105. package/dist/components/registry/niko-table/filters/table-faceted-filter.js +4 -4
  106. package/dist/components/registry/niko-table/filters/table-search-filter.js +1 -1
  107. package/dist/components/registry/niko-table/lib/flex-columns.d.ts +1 -1
  108. package/dist/components/registry/niko-table/lib/flex-columns.js +3 -3
  109. package/dist/components/registry/niko-table/lib/styles.d.ts +1 -1
  110. package/dist/components/registry/niko-table/lib/styles.js +3 -3
  111. package/dist/components/registry/niko-table/types/index.d.ts +9 -0
  112. package/dist/components/registry/niko-table/ui/table.js +2 -2
  113. package/dist/components/registry/sidebar-07/app-sidebar.d.ts +1 -1
  114. package/dist/components/registry/sidebar-07/app-sidebar.js +3 -1
  115. package/dist/components/registry/sidebar-07/nav-main.d.ts +2 -1
  116. package/dist/components/registry/sidebar-07/nav-main.js +16 -3
  117. package/dist/components/siyahi/callout.d.ts +24 -0
  118. package/dist/components/siyahi/callout.js +40 -0
  119. package/dist/components/siyahi/change-bar.d.ts +21 -0
  120. package/dist/components/siyahi/change-bar.js +35 -0
  121. package/dist/components/siyahi/data-bar.d.ts +19 -0
  122. package/dist/components/siyahi/data-bar.js +29 -0
  123. package/dist/components/siyahi/data-table-compact-columns-toggle.d.ts +4 -0
  124. package/dist/components/siyahi/data-table-compact-columns-toggle.js +19 -0
  125. package/dist/components/siyahi/data-table-footnote.d.ts +12 -0
  126. package/dist/components/siyahi/data-table-footnote.js +35 -0
  127. package/dist/components/siyahi/default-sidebar-open.d.ts +8 -0
  128. package/dist/components/siyahi/default-sidebar-open.js +13 -0
  129. package/dist/components/siyahi/page-hero.d.ts +25 -0
  130. package/dist/components/siyahi/page-hero.js +41 -0
  131. package/dist/components/siyahi/page-section.d.ts +4 -1
  132. package/dist/components/siyahi/page-section.js +6 -3
  133. package/dist/components/siyahi/page-toc.d.ts +20 -0
  134. package/dist/components/siyahi/page-toc.js +76 -0
  135. package/dist/components/siyahi/panel-grid.d.ts +22 -0
  136. package/dist/components/siyahi/panel-grid.js +34 -0
  137. package/dist/components/siyahi/quote.d.ts +12 -0
  138. package/dist/components/siyahi/quote.js +23 -0
  139. package/dist/components/siyahi/range-position.d.ts +24 -0
  140. package/dist/components/siyahi/range-position.js +105 -0
  141. package/dist/components/siyahi/siyahi-provider.d.ts +13 -2
  142. package/dist/components/siyahi/siyahi-provider.js +17 -4
  143. package/dist/components/siyahi/target-rows.d.ts +34 -0
  144. package/dist/components/siyahi/target-rows.js +97 -0
  145. package/dist/components/siyahi/treemap.d.ts +4 -1
  146. package/dist/components/siyahi/treemap.js +78 -28
  147. package/dist/components/siyahi/warning-alert.d.ts +10 -0
  148. package/dist/components/siyahi/warning-alert.js +20 -0
  149. package/dist/components/ui/accordion.js +5 -5
  150. package/dist/components/ui/alert.js +2 -2
  151. package/dist/components/ui/badge.js +1 -1
  152. package/dist/components/ui/breadcrumb.js +2 -2
  153. package/dist/components/ui/button.js +10 -10
  154. package/dist/components/ui/calendar.js +1 -1
  155. package/dist/components/ui/card.js +4 -4
  156. package/dist/components/ui/chart.js +1 -1
  157. package/dist/components/ui/code-block.js +13 -12
  158. package/dist/components/ui/command.js +7 -6
  159. package/dist/components/ui/context-menu.js +7 -7
  160. package/dist/components/ui/dialog.js +5 -5
  161. package/dist/components/ui/dropdown-menu.js +8 -8
  162. package/dist/components/ui/input-group.js +11 -11
  163. package/dist/components/ui/input.js +1 -1
  164. package/dist/components/ui/popover.js +3 -3
  165. package/dist/components/ui/progress.js +1 -1
  166. package/dist/components/ui/select.js +6 -6
  167. package/dist/components/ui/sheet.js +5 -5
  168. package/dist/components/ui/sidebar.js +17 -18
  169. package/dist/components/ui/skeleton.js +1 -1
  170. package/dist/components/ui/slider.js +2 -2
  171. package/dist/components/ui/table.js +2 -2
  172. package/dist/components/ui/tabs.js +2 -2
  173. package/dist/components/ui/textarea.js +1 -1
  174. package/dist/components/ui/toggle-group.js +2 -2
  175. package/dist/components/ui/toggle.js +4 -4
  176. package/dist/components/ui/tooltip.js +2 -2
  177. package/dist/index.d.ts +21 -7
  178. package/dist/index.js +18 -4
  179. package/dist/lib/chart-frame.d.ts +25 -7
  180. package/dist/lib/chart-frame.js +251 -127
  181. package/dist/lib/chart-series.d.ts +12 -6
  182. package/dist/lib/compact-columns.d.ts +19 -0
  183. package/dist/lib/compact-columns.js +55 -0
  184. package/dist/lib/format.d.ts +7 -2
  185. package/dist/lib/format.js +54 -16
  186. package/dist/lib/heatmap-navigation.d.ts +8 -0
  187. package/dist/lib/heatmap-navigation.js +49 -0
  188. package/dist/lib/treemap.js +6 -1
  189. package/dist/lib/use-element-width.d.ts +5 -0
  190. package/dist/lib/use-element-width.js +15 -0
  191. package/package.json +4 -1
  192. package/registry.lock.json +16 -0
  193. package/report.css +33 -32
  194. package/styles/siyahi.css +221 -39
  195. package/dist/lib/recharts.d.ts +0 -2
  196. package/dist/lib/recharts.js +0 -1
@@ -149,7 +149,7 @@ function TableFacetedFilter({ column, title, options = [], multiple, onValueChan
149
149
  ] })
150
150
  ]
151
151
  }) }), /* @__PURE__ */ jsx(PopoverContent, {
152
- className: "w-52 p-0",
152
+ className: "w-max min-w-52 max-w-(--available-width) p-0",
153
153
  align: "start",
154
154
  children: /* @__PURE__ */ jsx(TableFacetedFilterContent, {
155
155
  title,
@@ -177,16 +177,16 @@ function TableFacetedFilterContent({ title, options, selectedValues, onItemSelec
177
177
  onSelect: () => onItemSelect(option, isSelected),
178
178
  children: [
179
179
  /* @__PURE__ */ jsx("div", {
180
- className: cn("mr-2 flex size-4 items-center justify-center rounded-sm border border-primary", isSelected ? "bg-primary text-primary-foreground" : "opacity-50 [&_svg]:invisible"),
180
+ className: cn("mr-2 flex size-4 shrink-0 items-center justify-center rounded-sm border border-primary", isSelected ? "bg-primary text-primary-foreground" : "opacity-50 [&_svg]:invisible"),
181
181
  children: /* @__PURE__ */ jsx(Check, { className: "size-4" })
182
182
  }),
183
183
  option.icon && /* @__PURE__ */ jsx(option.icon, { className: "mr-2 size-4" }),
184
184
  /* @__PURE__ */ jsx("span", {
185
- className: "truncate",
185
+ className: "min-w-0 flex-1 whitespace-normal wrap-anywhere",
186
186
  children: option.label
187
187
  }),
188
188
  option.count !== void 0 && /* @__PURE__ */ jsx("span", {
189
- className: "ml-auto font-mono text-xs",
189
+ className: "ml-auto shrink-0 font-mono text-xs",
190
190
  children: option.count
191
191
  })
192
192
  ]
@@ -62,7 +62,7 @@ function TableSearchFilter({ table, className, placeholder = "Search...", label
62
62
  ]);
63
63
  const hasValue = currentValue.length > 0;
64
64
  return /* @__PURE__ */ jsxs("div", {
65
- className: cn("relative flex flex-1 items-center", className),
65
+ className: cn("relative flex min-w-0 max-w-full flex-1 items-center", className),
66
66
  role: "search",
67
67
  children: [
68
68
  /* @__PURE__ */ jsx(Search, {
@@ -26,7 +26,7 @@ import { ColumnSizingState, RowData } from "@tanstack/react-table";
26
26
  * Returns the set of column ids to render widthless (empty when fill is off or
27
27
  * no eligible column exists — the table then sizes to its columns as before).
28
28
  */
29
- export declare function resolveFlexColumnIds<TData extends RowData>(table: DataTableInstance<TData>): ReadonlySet<string>;
29
+ export declare function resolveFlexColumnIds<TData extends RowData>(table: DataTableInstance<TData>, pinningEnabled?: boolean): ReadonlySet<string>;
30
30
  /**
31
31
  * The width to render for a single column. Centralizes the flex + header-fit
32
32
  * rules so the header, body cells, and the min-width lock all agree.
@@ -24,19 +24,19 @@
24
24
  * Returns the set of column ids to render widthless (empty when fill is off or
25
25
  * no eligible column exists — the table then sizes to its columns as before).
26
26
  */
27
- function resolveFlexColumnIds(table) {
27
+ function resolveFlexColumnIds(table, pinningEnabled = true) {
28
28
  const ids = /* @__PURE__ */ new Set();
29
29
  if (!table.options.enableColumnResizing) return ids;
30
30
  if (table.options.meta?.disableFlexFill) return ids;
31
31
  const leafColumns = table.getVisibleLeafColumns();
32
32
  const columnSizing = table.state.columnSizing;
33
33
  let hasExplicit = false;
34
- for (const column of leafColumns) if (column.columnDef.meta?.flex === true && !column.getIsPinned() && columnSizing[column.id] == null) {
34
+ for (const column of leafColumns) if (column.columnDef.meta?.flex === true && !(pinningEnabled && column.getIsPinned()) && columnSizing[column.id] == null) {
35
35
  ids.add(column.id);
36
36
  hasExplicit = true;
37
37
  }
38
38
  if (hasExplicit) return ids;
39
- const auto = leafColumns.find((column) => column.getCanResize() && !column.getIsPinned() && column.columnDef.meta?.flex !== false && columnSizing[column.id] == null);
39
+ const auto = leafColumns.find((column) => column.getCanResize() && !(pinningEnabled && column.getIsPinned()) && column.columnDef.meta?.flex !== false && columnSizing[column.id] == null);
40
40
  if (auto) ids.add(auto.id);
41
41
  return ids;
42
42
  }
@@ -2,5 +2,5 @@ import { DataTableFeatures } from "./data-table-features.js";
2
2
  import React from "react";
3
3
  import { Column, RowData } from "@tanstack/react-table";
4
4
  //#region src/components/registry/niko-table/lib/styles.d.ts
5
- export declare const getCommonPinningStyles: <TData extends RowData>(column: Column<DataTableFeatures, TData>, isHeader?: boolean) => React.CSSProperties;
5
+ export declare const getCommonPinningStyles: <TData extends RowData>(column: Column<DataTableFeatures, TData>, isHeader?: boolean, pinningEnabled?: boolean) => React.CSSProperties;
6
6
  //#endregion
@@ -1,8 +1,8 @@
1
1
  import "@tanstack/react-table";
2
2
  //#region src/components/registry/niko-table/lib/styles.ts
3
- const getCommonPinningStyles = (column, isHeader = false) => {
3
+ const getCommonPinningStyles = (column, isHeader = false, pinningEnabled = true) => {
4
4
  const isPinned = column.getIsPinned();
5
- if (!isPinned) return {};
5
+ if (!isPinned || !pinningEnabled) return {};
6
6
  const isLeft = isPinned === "start";
7
7
  const columnSize = column.getSize();
8
8
  return {
@@ -17,7 +17,7 @@ const getCommonPinningStyles = (column, isHeader = false) => {
17
17
  flexShrink: 0,
18
18
  zIndex: isHeader ? 20 : 10,
19
19
  backgroundColor: "var(--card)",
20
- ...isLeft ? { boxShadow: "inset -2px 0 0 0 color-mix(in oklab, var(--foreground) 40%, transparent), 4px 0 8px -2px color-mix(in oklab, var(--foreground) 14%, transparent)" } : { boxShadow: "inset 2px 0 0 0 color-mix(in oklab, var(--foreground) 40%, transparent), -4px 0 8px -2px color-mix(in oklab, var(--foreground) 14%, transparent)" }
20
+ boxShadow: isLeft ? "inset -1px 0 0 0 var(--border)" : "inset 1px 0 0 0 var(--border)"
21
21
  };
22
22
  };
23
23
  //#endregion
@@ -23,6 +23,15 @@ declare module "@tanstack/react-table" {
23
23
  * `TableMeta.disableFlexFill`.
24
24
  */
25
25
  flex?: boolean;
26
+ /**
27
+ * Never hide this column to fit. Once any column sets it, a table whose
28
+ * columns do not fit its width hides the others, rightmost first, until
29
+ * they do, and `<DataTableCompactColumnsToggle />` shows them all again.
30
+ * Mark the few a reader needs to answer the table's question: the name and
31
+ * its result. Read `useDataTable().compactColumns?.hidden` in a cell to
32
+ * fold a hidden figure under a kept one.
33
+ */
34
+ compact?: boolean;
26
35
  variant?: FilterVariant;
27
36
  options?: Option[];
28
37
  range?: [number, number];
@@ -52,14 +52,14 @@ function TableRow({ className, ...props }) {
52
52
  function TableHead({ className, ...props }) {
53
53
  return /* @__PURE__ */ jsx("th", {
54
54
  "data-slot": "table-head",
55
- className: cn("h-12 px-3 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]", className),
55
+ className: cn("h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]", className),
56
56
  ...props
57
57
  });
58
58
  }
59
59
  function TableCell({ className, ...props }) {
60
60
  return /* @__PURE__ */ jsx("td", {
61
61
  "data-slot": "table-cell",
62
- className: cn("p-3 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]", className),
62
+ className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]", className),
63
63
  ...props
64
64
  });
65
65
  }
@@ -14,5 +14,5 @@ export interface AppSidebarProps extends React$1.ComponentProps<typeof Sidebar>
14
14
  projects?: React$1.ComponentProps<typeof NavProjects>["projects"];
15
15
  user?: React$1.ComponentProps<typeof NavUser>["user"];
16
16
  }
17
- export declare function AppSidebar({ navMain, navLabel, header, teams, projects, user, collapsible, ...props }: AppSidebarProps): React$1.JSX.Element;
17
+ export declare function AppSidebar({ navMain, navLabel, header, teams, projects, user, collapsible, className, ...props }: AppSidebarProps): React$1.JSX.Element;
18
18
  //#endregion
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarRail } from "../../ui/sidebar.js";
3
+ import { cn } from "../../../lib/utils.js";
3
4
  import { NavMain } from "./nav-main.js";
4
5
  import { NavProjects } from "./nav-projects.js";
5
6
  import { NavUser } from "./nav-user.js";
@@ -7,9 +8,10 @@ import { TeamSwitcher } from "./team-switcher.js";
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
8
9
  import "react";
9
10
  //#region src/components/registry/sidebar-07/app-sidebar.tsx
10
- function AppSidebar({ navMain, navLabel, header, teams, projects, user, collapsible = "icon", ...props }) {
11
+ function AppSidebar({ navMain, navLabel, header, teams, projects, user, collapsible = "icon", className, ...props }) {
11
12
  return /* @__PURE__ */ jsxs(Sidebar, {
12
13
  collapsible,
14
+ className: cn(collapsible !== "none" && "h-auto", className),
13
15
  ...props,
14
16
  children: [
15
17
  (header || teams) && /* @__PURE__ */ jsx(SidebarHeader, { children: header ?? (teams && /* @__PURE__ */ jsx(TeamSwitcher, { teams })) }),
@@ -4,12 +4,13 @@ export declare function NavMain({ items, label }: {
4
4
  items: {
5
5
  title: string;
6
6
  url: string;
7
- icon?: React.ReactNode;
7
+ icon: React.ReactNode;
8
8
  isActive?: boolean;
9
9
  linkProps?: Omit<React.ComponentProps<"a">, "href">;
10
10
  items?: {
11
11
  title: string;
12
12
  url: string;
13
+ isActive?: boolean;
13
14
  }[];
14
15
  }[];
15
16
  }): import("react").JSX.Element;
@@ -2,9 +2,11 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../../ui/co
2
2
  import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, useSidebar } from "../../ui/sidebar.js";
3
3
  import { ChevronRightIcon } from "lucide-react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { useState } from "react";
5
6
  //#region src/components/registry/sidebar-07/nav-main.tsx
6
7
  function NavMain({ items, label = "Navigation" }) {
7
8
  const { isMobile, setOpenMobile } = useSidebar();
9
+ const [expanded, setExpanded] = useState({});
8
10
  const closeDrawer = () => {
9
11
  if (isMobile) setOpenMobile(false);
10
12
  };
@@ -19,18 +21,29 @@ function NavMain({ items, label = "Navigation" }) {
19
21
  onClick: closeDrawer,
20
22
  children: [item.icon, /* @__PURE__ */ jsx("span", { children: item.title })]
21
23
  }) }, item.title) : /* @__PURE__ */ jsxs(Collapsible, {
22
- defaultOpen: item.isActive,
24
+ open: expanded[item.title] ?? !!item.isActive,
25
+ onOpenChange: (open) => setExpanded((previous) => ({
26
+ ...previous,
27
+ [item.title]: open
28
+ })),
23
29
  className: "group/collapsible",
24
30
  render: /* @__PURE__ */ jsx(SidebarMenuItem, {}),
25
31
  children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
26
- render: /* @__PURE__ */ jsx(SidebarMenuButton, { tooltip: item.title }),
32
+ render: /* @__PURE__ */ jsx(SidebarMenuButton, {
33
+ tooltip: item.title,
34
+ isActive: item.isActive && !item.items?.some((subItem) => subItem.isActive)
35
+ }),
27
36
  children: [
28
37
  item.icon,
29
38
  /* @__PURE__ */ jsx("span", { children: item.title }),
30
39
  /* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto transition-transform duration-200 group-data-open/collapsible:rotate-90" })
31
40
  ]
32
41
  }), /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(SidebarMenuSub, { children: item.items?.map((subItem) => /* @__PURE__ */ jsx(SidebarMenuSubItem, { children: /* @__PURE__ */ jsx(SidebarMenuSubButton, {
33
- render: /* @__PURE__ */ jsx("a", { href: subItem.url }),
42
+ isActive: subItem.isActive,
43
+ render: /* @__PURE__ */ jsx("a", {
44
+ href: subItem.url,
45
+ "aria-current": subItem.isActive ? "page" : void 0
46
+ }),
34
47
  onClick: closeDrawer,
35
48
  children: /* @__PURE__ */ jsx("span", { children: subItem.title })
36
49
  }) }, subItem.title)) }) })]
@@ -0,0 +1,24 @@
1
+ import { ComponentProps, ReactNode } from "react";
2
+ //#region src/components/siyahi/callout.d.ts
3
+ declare const TONES: {
4
+ readonly neutral: "border-border bg-muted/50 [&_[data-slot=callout-icon]]:text-muted-foreground";
5
+ readonly accent: "border-chart-1/35 bg-chart-1/8 [&_[data-slot=callout-icon]]:text-link";
6
+ readonly warning: "border-warning/45 bg-warning/10 [&_[data-slot=callout-icon]]:text-warning";
7
+ readonly positive: "border-positive/40 bg-positive/8 [&_[data-slot=callout-icon]]:text-positive";
8
+ readonly negative: "border-negative/40 bg-negative/8 [&_[data-slot=callout-icon]]:text-negative";
9
+ };
10
+ export interface CalloutProps extends Omit<ComponentProps<"aside">, "title"> {
11
+ /** neutral for an aside, accent for a key point, warning for a caution, positive or negative for a gain or a loss. */
12
+ tone?: keyof typeof TONES;
13
+ /** A lucide icon, drawn in the tone's colour. */
14
+ icon?: ReactNode;
15
+ title?: ReactNode;
16
+ }
17
+ /**
18
+ * A point set apart from the prose: a takeaway, a caveat, a definition. The whole box takes the tone, a faint wash
19
+ * inside a border of the same colour; never a single coloured edge. For a notice that interrupts, use Alert or
20
+ * WarningAlert instead.
21
+ */
22
+ export declare function Callout({ tone, icon, title, className, children, ...props }: CalloutProps): import("react").JSX.Element;
23
+ //#endregion
24
+ export {};
@@ -0,0 +1,40 @@
1
+ import { cn } from "cn";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ //#region src/components/siyahi/callout.tsx
4
+ const TONES = {
5
+ neutral: "border-border bg-muted/50 [&_[data-slot=callout-icon]]:text-muted-foreground",
6
+ accent: "border-chart-1/35 bg-chart-1/8 [&_[data-slot=callout-icon]]:text-link",
7
+ warning: "border-warning/45 bg-warning/10 [&_[data-slot=callout-icon]]:text-warning",
8
+ positive: "border-positive/40 bg-positive/8 [&_[data-slot=callout-icon]]:text-positive",
9
+ negative: "border-negative/40 bg-negative/8 [&_[data-slot=callout-icon]]:text-negative"
10
+ };
11
+ /**
12
+ * A point set apart from the prose: a takeaway, a caveat, a definition. The whole box takes the tone, a faint wash
13
+ * inside a border of the same colour; never a single coloured edge. For a notice that interrupts, use Alert or
14
+ * WarningAlert instead.
15
+ */
16
+ function Callout({ tone = "neutral", icon, title, className, children, ...props }) {
17
+ return /* @__PURE__ */ jsxs("aside", {
18
+ "data-slot": "callout",
19
+ "data-tone": tone,
20
+ className: cn("flex gap-3 rounded-lg border px-4 py-3 text-sm", TONES[tone], className),
21
+ ...props,
22
+ children: [icon && /* @__PURE__ */ jsx("span", {
23
+ "data-slot": "callout-icon",
24
+ "aria-hidden": true,
25
+ className: "mt-0.5 shrink-0 [&>svg]:size-4",
26
+ children: icon
27
+ }), /* @__PURE__ */ jsxs("div", {
28
+ className: "flex min-w-0 flex-col gap-1",
29
+ children: [title && /* @__PURE__ */ jsx("p", {
30
+ className: "font-medium",
31
+ children: title
32
+ }), /* @__PURE__ */ jsx("div", {
33
+ className: "text-pretty text-muted-foreground [&_strong]:text-foreground",
34
+ children
35
+ })]
36
+ })]
37
+ });
38
+ }
39
+ //#endregion
40
+ export { Callout };
@@ -0,0 +1,21 @@
1
+ import { DeltaProps } from "./delta.js";
2
+ //#region src/components/siyahi/change-bar.d.ts
3
+ export interface ChangeBarProps {
4
+ /** The signed change, as Delta takes it. */
5
+ value: number;
6
+ /** The column's largest change by size: Math.max(...rows.map((row) => Math.abs(row.change))). */
7
+ max: number;
8
+ /**
9
+ * Draws the bar from a centre line, losses leftward and gains rightward. Pass it when the column holds both signs:
10
+ * rows.some((row) => row.change < 0) && rows.some((row) => row.change > 0).
11
+ */
12
+ diverging?: boolean;
13
+ format?: DeltaProps["format"];
14
+ className?: string;
15
+ }
16
+ /**
17
+ * A table cell's change as a Delta over a 3px bar whose length is the change's size against the column's largest, so
18
+ * the rows rank by eye. The bar is neutral because it shows size; the Delta above it carries the gain or loss colour.
19
+ */
20
+ export declare function ChangeBar({ value, max, diverging, format, className }: ChangeBarProps): import("react").JSX.Element;
21
+ //#endregion
@@ -0,0 +1,35 @@
1
+ import { Delta } from "./delta.js";
2
+ import { cn } from "cn";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/components/siyahi/change-bar.tsx
5
+ /**
6
+ * A table cell's change as a Delta over a 3px bar whose length is the change's size against the column's largest, so
7
+ * the rows rank by eye. The bar is neutral because it shows size; the Delta above it carries the gain or loss colour.
8
+ */
9
+ function ChangeBar({ value, max, diverging = false, format, className }) {
10
+ const share = max > 0 ? Math.min(1, Math.abs(value) / max) : 0;
11
+ const half = diverging ? 50 : 100;
12
+ const side = diverging && value < 0 ? "right" : "left";
13
+ return /* @__PURE__ */ jsxs("div", {
14
+ "data-slot": "change-bar",
15
+ className: cn("flex w-full flex-col items-end gap-1.5", className),
16
+ children: [/* @__PURE__ */ jsx(Delta, {
17
+ value,
18
+ format,
19
+ className: "font-medium"
20
+ }), /* @__PURE__ */ jsxs("div", {
21
+ "aria-hidden": "true",
22
+ className: "relative h-0.75 w-full rounded-full bg-muted",
23
+ children: [/* @__PURE__ */ jsx("div", {
24
+ "data-slot": "change-bar-fill",
25
+ className: "absolute inset-y-0 rounded-full bg-foreground",
26
+ style: {
27
+ [side]: diverging ? "50%" : 0,
28
+ width: `${share * half}%`
29
+ }
30
+ }), diverging && /* @__PURE__ */ jsx("div", { className: "absolute -inset-y-1 left-1/2 w-px -translate-x-1/2 bg-muted-foreground" })]
31
+ })]
32
+ });
33
+ }
34
+ //#endregion
35
+ export { ChangeBar };
@@ -0,0 +1,19 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/components/siyahi/data-bar.d.ts
3
+ export interface DataBarProps {
4
+ value: number;
5
+ /** The value a full bar stands for, usually the column's largest: Math.max(...rows.map((row) => row.value)). */
6
+ max: number;
7
+ /** "sign" draws a gain in --positive and a loss in --negative; by default every bar is --chart-1. */
8
+ tone?: "chart" | "sign";
9
+ /** The figure, as the page formats it. */
10
+ children: ReactNode;
11
+ className?: string;
12
+ }
13
+ /**
14
+ * A table cell's figure behind a short bar whose length is the figure's share of max, so a column reads as a chart.
15
+ * The bar has a fixed width, so every row draws to the same scale, and sits on the figure's line, so the row
16
+ * keeps its height.
17
+ */
18
+ export declare function DataBar({ value, max, tone, children, className }: DataBarProps): import("react").JSX.Element;
19
+ //#endregion
@@ -0,0 +1,29 @@
1
+ import { cn } from "cn";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ //#region src/components/siyahi/data-bar.tsx
4
+ /**
5
+ * A table cell's figure behind a short bar whose length is the figure's share of max, so a column reads as a chart.
6
+ * The bar has a fixed width, so every row draws to the same scale, and sits on the figure's line, so the row
7
+ * keeps its height.
8
+ */
9
+ function DataBar({ value, max, tone = "chart", children, className }) {
10
+ const share = max > 0 ? Math.min(1, Math.abs(value) / max) : 0;
11
+ const fill = tone === "chart" ? "bg-chart-1" : value < 0 ? "bg-negative" : "bg-positive";
12
+ return /* @__PURE__ */ jsxs("div", {
13
+ "data-slot": "data-bar",
14
+ className: cn("flex items-center gap-2", className),
15
+ children: [/* @__PURE__ */ jsx("div", {
16
+ "aria-hidden": "true",
17
+ className: "h-1.5 w-16 shrink-0 overflow-hidden rounded-full bg-muted",
18
+ children: /* @__PURE__ */ jsx("div", {
19
+ className: cn("h-full rounded-full", fill),
20
+ style: { width: `${share * 100}%` }
21
+ })
22
+ }), /* @__PURE__ */ jsx("span", {
23
+ className: "tabular-nums",
24
+ children
25
+ })]
26
+ });
27
+ }
28
+ //#endregion
29
+ export { DataBar };
@@ -0,0 +1,4 @@
1
+ //#region src/components/siyahi/data-table-compact-columns-toggle.d.ts
2
+ /** Renders only while some columns are hidden to fit, or the reader has shown them all. */
3
+ export declare function DataTableCompactColumnsToggle(): import("react").JSX.Element | null;
4
+ //#endregion
@@ -0,0 +1,19 @@
1
+ import { Button } from "../ui/button.js";
2
+ import { useDataTable } from "../registry/niko-table/core/data-table-context.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/components/siyahi/data-table-compact-columns-toggle.tsx
5
+ /** Renders only while some columns are hidden to fit, or the reader has shown them all. */
6
+ function DataTableCompactColumnsToggle() {
7
+ const { compactColumns } = useDataTable();
8
+ if (!compactColumns) return null;
9
+ const { collapsed, setCollapsed } = compactColumns;
10
+ return /* @__PURE__ */ jsx(Button, {
11
+ variant: "outline",
12
+ size: "sm",
13
+ "aria-pressed": !collapsed,
14
+ onClick: () => setCollapsed(!collapsed),
15
+ children: collapsed ? `All columns (+${compactColumns.hidden.size})` : "Key columns"
16
+ });
17
+ }
18
+ //#endregion
19
+ export { DataTableCompactColumnsToggle };
@@ -0,0 +1,12 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/components/siyahi/data-table-footnote.d.ts
3
+ export interface DataTableFootnoteProps {
4
+ /** One sentence on how to read the table, such as what each bar measures. */
5
+ children: ReactNode;
6
+ }
7
+ /**
8
+ * A full-width last row, inside `DataTable` after its body, that explains the table's encoding. On a table wider than
9
+ * its card the note stays put at the card's width while the columns scroll under it.
10
+ */
11
+ export declare function DataTableFootnote({ children }: DataTableFootnoteProps): import("react").JSX.Element;
12
+ //#endregion
@@ -0,0 +1,35 @@
1
+ import { useDataTable } from "../registry/niko-table/core/data-table-context.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ //#region src/components/siyahi/data-table-footnote.tsx
5
+ /**
6
+ * A full-width last row, inside `DataTable` after its body, that explains the table's encoding. On a table wider than
7
+ * its card the note stays put at the card's width while the columns scroll under it.
8
+ */
9
+ function DataTableFootnote({ children }) {
10
+ const { table, scrollContainer } = useDataTable();
11
+ const [viewport, setViewport] = useState();
12
+ useEffect(() => {
13
+ if (!scrollContainer) return;
14
+ const observer = new ResizeObserver(() => setViewport(scrollContainer.clientWidth));
15
+ observer.observe(scrollContainer);
16
+ return () => observer.disconnect();
17
+ }, [scrollContainer]);
18
+ return /* @__PURE__ */ jsx("tfoot", {
19
+ "data-slot": "data-table-footnote",
20
+ children: /* @__PURE__ */ jsx("tr", {
21
+ className: "border-t",
22
+ children: /* @__PURE__ */ jsx("td", {
23
+ colSpan: table.getVisibleLeafColumns().length,
24
+ className: "p-0",
25
+ children: /* @__PURE__ */ jsx("p", {
26
+ className: "sticky left-0 px-2 py-3 text-sm whitespace-normal text-muted-foreground",
27
+ style: { maxWidth: viewport },
28
+ children
29
+ })
30
+ })
31
+ })
32
+ });
33
+ }
34
+ //#endregion
35
+ export { DataTableFootnote };
@@ -0,0 +1,8 @@
1
+ //#region src/components/siyahi/default-sidebar-open.d.ts
2
+ /**
3
+ * SidebarProvider's `defaultOpen` for an app shell: the reader's last choice, which the provider keeps in the
4
+ * `sidebar_state` cookie, else open — except on a short landscape screen, a phone held sideways, where an open
5
+ * sidebar leaves no room for the page. There it starts as the icon rail.
6
+ */
7
+ export declare function defaultSidebarOpen(): boolean;
8
+ //#endregion
@@ -0,0 +1,13 @@
1
+ //#region src/components/siyahi/default-sidebar-open.ts
2
+ /**
3
+ * SidebarProvider's `defaultOpen` for an app shell: the reader's last choice, which the provider keeps in the
4
+ * `sidebar_state` cookie, else open — except on a short landscape screen, a phone held sideways, where an open
5
+ * sidebar leaves no room for the page. There it starts as the icon rail.
6
+ */
7
+ function defaultSidebarOpen() {
8
+ const saved = document.cookie.split("; ").find((entry) => entry.startsWith("sidebar_state="))?.slice(14);
9
+ if (saved !== void 0) return saved === "true";
10
+ return !matchMedia("(orientation: landscape) and (max-height: 30rem)").matches;
11
+ }
12
+ //#endregion
13
+ export { defaultSidebarOpen };
@@ -0,0 +1,25 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/components/siyahi/page-hero.d.ts
3
+ export interface PageHeroProps {
4
+ /** A short line above the title in the link colour, such as a package or a section name. */
5
+ eyebrow?: ReactNode;
6
+ /** The page's h1, set large. */
7
+ title: ReactNode;
8
+ /** What the page is, in a sentence or two, in the body colour. */
9
+ lead?: ReactNode;
10
+ /** Muted detail under the lead: scope, sources, what is left out. */
11
+ detail?: ReactNode;
12
+ /** The one or two places a reader goes next, usually a primary Button and an outline one. */
13
+ actions?: ReactNode;
14
+ /**
15
+ * A large decorative mark drawn faintly in the accent behind the top right, such as the product's logo as an
16
+ * SVG that paints with currentColor. It is hidden from assistive technology.
17
+ */
18
+ mark?: ReactNode;
19
+ }
20
+ /**
21
+ * The introduction at the top of a front page or a long explainer: a large title, what the page is, and where to
22
+ * go next, on a card with an optional watermark. One per page, above everything else; a section uses PageSection.
23
+ */
24
+ export declare function PageHero({ eyebrow, title, lead, detail, actions, mark }: PageHeroProps): import("react").JSX.Element;
25
+ //#endregion
@@ -0,0 +1,41 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ //#region src/components/siyahi/page-hero.tsx
3
+ /**
4
+ * The introduction at the top of a front page or a long explainer: a large title, what the page is, and where to
5
+ * go next, on a card with an optional watermark. One per page, above everything else; a section uses PageSection.
6
+ */
7
+ function PageHero({ eyebrow, title, lead, detail, actions, mark }) {
8
+ return /* @__PURE__ */ jsxs("header", {
9
+ "data-slot": "page-hero",
10
+ className: "relative isolate flex flex-col gap-4 overflow-hidden rounded-2xl border bg-card px-6 py-8 sm:px-10 sm:py-10",
11
+ children: [
12
+ mark && /* @__PURE__ */ jsx("div", {
13
+ "aria-hidden": true,
14
+ className: "pointer-events-none absolute -top-8 -right-10 -z-10 size-80 text-chart-1 opacity-10 sm:-top-12 sm:right-4 [&>svg]:size-full",
15
+ children: mark
16
+ }),
17
+ eyebrow && /* @__PURE__ */ jsx("p", {
18
+ className: "font-mono text-xs text-link",
19
+ children: eyebrow
20
+ }),
21
+ /* @__PURE__ */ jsx("h1", {
22
+ className: "text-5xl font-semibold tracking-tighter text-balance sm:text-6xl",
23
+ children: title
24
+ }),
25
+ lead && /* @__PURE__ */ jsx("div", {
26
+ className: "max-w-xl text-lg text-pretty",
27
+ children: lead
28
+ }),
29
+ detail && /* @__PURE__ */ jsx("div", {
30
+ className: "max-w-xl text-pretty text-muted-foreground",
31
+ children: detail
32
+ }),
33
+ actions && /* @__PURE__ */ jsx("div", {
34
+ className: "mt-2 flex flex-wrap gap-2",
35
+ children: actions
36
+ })
37
+ ]
38
+ });
39
+ }
40
+ //#endregion
41
+ export { PageHero };
@@ -12,7 +12,10 @@ export interface PageSectionProps {
12
12
  action?: ReactNode;
13
13
  children?: ReactNode;
14
14
  }
15
- /** One part of a long page: a rule above, then the heading and lead on the canvas, then its content. */
15
+ /**
16
+ * One part of a long page: a rule above, then the heading and lead on the canvas, then its content. Spaced for
17
+ * density, 24px under the rule and 16px to the content, so sections stacked 24px apart sit 24px either side of it.
18
+ */
16
19
  export declare function PageSection({ id, eyebrow, title, lead, action, children }: PageSectionProps): import("react").JSX.Element;
17
20
  /** A heading inside a PageSection, one level under its title. */
18
21
  export declare function PageSubheading({ children }: {
@@ -1,11 +1,14 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  //#region src/components/siyahi/page-section.tsx
3
- /** One part of a long page: a rule above, then the heading and lead on the canvas, then its content. */
3
+ /**
4
+ * One part of a long page: a rule above, then the heading and lead on the canvas, then its content. Spaced for
5
+ * density, 24px under the rule and 16px to the content, so sections stacked 24px apart sit 24px either side of it.
6
+ */
4
7
  function PageSection({ id, eyebrow, title, lead, action, children }) {
5
8
  return /* @__PURE__ */ jsxs("section", {
6
9
  id,
7
10
  "data-slot": "page-section",
8
- className: "flex scroll-mt-6 flex-col gap-6 border-t pt-10",
11
+ className: "flex scroll-mt-6 flex-col gap-4 border-t pt-6",
9
12
  children: [/* @__PURE__ */ jsxs("div", {
10
13
  className: "flex flex-wrap items-end justify-between gap-4",
11
14
  children: [/* @__PURE__ */ jsxs("div", {
@@ -16,7 +19,7 @@ function PageSection({ id, eyebrow, title, lead, action, children }) {
16
19
  children: eyebrow
17
20
  }),
18
21
  /* @__PURE__ */ jsx("h2", {
19
- className: "text-2xl font-semibold tracking-tight",
22
+ className: "text-xl font-semibold tracking-tight",
20
23
  children: title
21
24
  }),
22
25
  lead && /* @__PURE__ */ jsx("div", {
@@ -0,0 +1,20 @@
1
+ //#region src/components/siyahi/page-toc.d.ts
2
+ export interface PageTocItem {
3
+ /** The `id` of the PageSection it jumps to. */
4
+ id: string;
5
+ title: string;
6
+ }
7
+ export interface PageTocProps {
8
+ items: PageTocItem[];
9
+ /** Names the navigation for screen readers. */
10
+ label?: string;
11
+ /** Layout only, such as `top-14` under a sticky page header. */
12
+ className?: string;
13
+ }
14
+ /**
15
+ * A long page's sections as one sticky "On this page" index. It stays at the top while the reader scrolls,
16
+ * underlines the section in view in the link colour, and scrolls sideways on a phone with the current link kept
17
+ * in sight.
18
+ */
19
+ export declare function PageToc({ items, label, className }: PageTocProps): import("react").JSX.Element;
20
+ //#endregion