@siyahi/ui 0.0.0-stage → 0.1.0-next.3

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 (192) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +174 -2
  3. package/THIRD_PARTY_NOTICES.md +51 -0
  4. package/dist/components/registry/dashboard-01/section-cards.d.ts +17 -0
  5. package/dist/components/registry/dashboard-01/section-cards.js +39 -0
  6. package/dist/components/registry/dashboardcn/bar-list.d.ts +24 -0
  7. package/dist/components/registry/dashboardcn/bar-list.js +71 -0
  8. package/dist/components/registry/heatmap/calendar-heatmap.d.ts +134 -0
  9. package/dist/components/registry/heatmap/calendar-heatmap.js +497 -0
  10. package/dist/components/registry/heatmap/status-heatmap.d.ts +120 -0
  11. package/dist/components/registry/heatmap/status-heatmap.js +330 -0
  12. package/dist/components/registry/heatmap/weekday-heatmap.d.ts +145 -0
  13. package/dist/components/registry/heatmap/weekday-heatmap.js +489 -0
  14. package/dist/components/registry/niko-table/components/data-table-column-actions.d.ts +26 -0
  15. package/dist/components/registry/niko-table/components/data-table-column-actions.js +32 -0
  16. package/dist/components/registry/niko-table/components/data-table-column-filter.d.ts +13 -0
  17. package/dist/components/registry/niko-table/components/data-table-column-filter.js +17 -0
  18. package/dist/components/registry/niko-table/components/data-table-column-header.d.ts +30 -0
  19. package/dist/components/registry/niko-table/components/data-table-column-header.js +35 -0
  20. package/dist/components/registry/niko-table/components/data-table-column-sort.d.ts +21 -0
  21. package/dist/components/registry/niko-table/components/data-table-column-sort.js +36 -0
  22. package/dist/components/registry/niko-table/components/data-table-column-title.d.ts +12 -0
  23. package/dist/components/registry/niko-table/components/data-table-column-title.js +18 -0
  24. package/dist/components/registry/niko-table/components/data-table-empty-state.d.ts +108 -0
  25. package/dist/components/registry/niko-table/components/data-table-empty-state.js +148 -0
  26. package/dist/components/registry/niko-table/components/data-table-faceted-filter.d.ts +46 -0
  27. package/dist/components/registry/niko-table/components/data-table-faceted-filter.js +133 -0
  28. package/dist/components/registry/niko-table/components/data-table-grouped-rows.d.ts +111 -0
  29. package/dist/components/registry/niko-table/components/data-table-grouped-rows.js +77 -0
  30. package/dist/components/registry/niko-table/components/data-table-row-context-menu-slot.d.ts +65 -0
  31. package/dist/components/registry/niko-table/components/data-table-row-context-menu-slot.js +65 -0
  32. package/dist/components/registry/niko-table/components/data-table-row-context-menu.d.ts +50 -0
  33. package/dist/components/registry/niko-table/components/data-table-row-context-menu.js +42 -0
  34. package/dist/components/registry/niko-table/components/data-table-row-menu.d.ts +51 -0
  35. package/dist/components/registry/niko-table/components/data-table-row-menu.js +65 -0
  36. package/dist/components/registry/niko-table/components/data-table-toolbar-section.d.ts +7 -0
  37. package/dist/components/registry/niko-table/components/data-table-toolbar-section.js +63 -0
  38. package/dist/components/registry/niko-table/config/data-table.d.ts +156 -0
  39. package/dist/components/registry/niko-table/config/data-table.js +279 -0
  40. package/dist/components/registry/niko-table/config/feature-detection.d.ts +39 -0
  41. package/dist/components/registry/niko-table/config/feature-detection.js +174 -0
  42. package/dist/components/registry/niko-table/core/data-table-context.d.ts +157 -0
  43. package/dist/components/registry/niko-table/core/data-table-context.js +326 -0
  44. package/dist/components/registry/niko-table/core/data-table-error-boundary.d.ts +85 -0
  45. package/dist/components/registry/niko-table/core/data-table-error-boundary.js +116 -0
  46. package/dist/components/registry/niko-table/core/data-table-grouped-row.d.ts +49 -0
  47. package/dist/components/registry/niko-table/core/data-table-grouped-row.js +112 -0
  48. package/dist/components/registry/niko-table/core/data-table-root.d.ts +62 -0
  49. package/dist/components/registry/niko-table/core/data-table-root.js +406 -0
  50. package/dist/components/registry/niko-table/core/data-table-structure.d.ts +153 -0
  51. package/dist/components/registry/niko-table/core/data-table-structure.js +370 -0
  52. package/dist/components/registry/niko-table/core/data-table.d.ts +30 -0
  53. package/dist/components/registry/niko-table/core/data-table.js +126 -0
  54. package/dist/components/registry/niko-table/filters/table-column-actions.d.ts +49 -0
  55. package/dist/components/registry/niko-table/filters/table-column-actions.js +48 -0
  56. package/dist/components/registry/niko-table/filters/table-column-sort.d.ts +51 -0
  57. package/dist/components/registry/niko-table/filters/table-column-sort.js +184 -0
  58. package/dist/components/registry/niko-table/filters/table-column-title.d.ts +17 -0
  59. package/dist/components/registry/niko-table/filters/table-column-title.js +20 -0
  60. package/dist/components/registry/niko-table/filters/table-faceted-filter.d.ts +40 -0
  61. package/dist/components/registry/niko-table/filters/table-faceted-filter.js +210 -0
  62. package/dist/components/registry/niko-table/hooks/use-derived-column-title.d.ts +29 -0
  63. package/dist/components/registry/niko-table/hooks/use-derived-column-title.js +40 -0
  64. package/dist/components/registry/niko-table/hooks/use-generated-options.d.ts +49 -0
  65. package/dist/components/registry/niko-table/hooks/use-generated-options.js +144 -0
  66. package/dist/components/registry/niko-table/lib/build-faceted-options.d.ts +59 -0
  67. package/dist/components/registry/niko-table/lib/build-faceted-options.js +82 -0
  68. package/dist/components/registry/niko-table/lib/column-resize-handle.d.ts +33 -0
  69. package/dist/components/registry/niko-table/lib/column-resize-handle.js +175 -0
  70. package/dist/components/registry/niko-table/lib/constants.d.ts +128 -0
  71. package/dist/components/registry/niko-table/lib/constants.js +123 -0
  72. package/dist/components/registry/niko-table/lib/create-scroll-handler.d.ts +35 -0
  73. package/dist/components/registry/niko-table/lib/create-scroll-handler.js +63 -0
  74. package/dist/components/registry/niko-table/lib/data-table-features.d.ts +218 -0
  75. package/dist/components/registry/niko-table/lib/data-table-features.js +127 -0
  76. package/dist/components/registry/niko-table/lib/filter-functions.d.ts +47 -0
  77. package/dist/components/registry/niko-table/lib/filter-functions.js +309 -0
  78. package/dist/components/registry/niko-table/lib/filter-rows.d.ts +14 -0
  79. package/dist/components/registry/niko-table/lib/filter-rows.js +28 -0
  80. package/dist/components/registry/niko-table/lib/flex-columns.d.ts +48 -0
  81. package/dist/components/registry/niko-table/lib/flex-columns.js +65 -0
  82. package/dist/components/registry/niko-table/lib/format.d.ts +33 -0
  83. package/dist/components/registry/niko-table/lib/format.js +99 -0
  84. package/dist/components/registry/niko-table/lib/render-cell-content.d.ts +17 -0
  85. package/dist/components/registry/niko-table/lib/render-cell-content.js +65 -0
  86. package/dist/components/registry/niko-table/lib/row-click.d.ts +67 -0
  87. package/dist/components/registry/niko-table/lib/row-click.js +28 -0
  88. package/dist/components/registry/niko-table/lib/styles.d.ts +6 -0
  89. package/dist/components/registry/niko-table/lib/styles.js +24 -0
  90. package/dist/components/registry/niko-table/lib/use-header-min-widths.d.ts +17 -0
  91. package/dist/components/registry/niko-table/lib/use-header-min-widths.js +82 -0
  92. package/dist/components/registry/niko-table/types/index.d.ts +141 -0
  93. package/dist/components/registry/niko-table/types/index.js +2 -0
  94. package/dist/components/registry/niko-table/ui/table.d.ts +13 -0
  95. package/dist/components/registry/niko-table/ui/table.js +74 -0
  96. package/dist/components/registry/sidebar-07/app-sidebar.d.ts +18 -0
  97. package/dist/components/registry/sidebar-07/app-sidebar.js +26 -0
  98. package/dist/components/registry/sidebar-07/nav-main.d.ts +15 -0
  99. package/dist/components/registry/sidebar-07/nav-main.js +25 -0
  100. package/dist/components/registry/sidebar-07/nav-projects.d.ts +9 -0
  101. package/dist/components/registry/sidebar-07/nav-projects.js +43 -0
  102. package/dist/components/registry/sidebar-07/nav-user.d.ts +9 -0
  103. package/dist/components/registry/sidebar-07/nav-user.js +70 -0
  104. package/dist/components/registry/sidebar-07/team-switcher.d.ts +10 -0
  105. package/dist/components/registry/sidebar-07/team-switcher.js +70 -0
  106. package/dist/components/siyahi/delta.d.ts +10 -0
  107. package/dist/components/siyahi/delta.js +27 -0
  108. package/dist/components/siyahi/local-time.d.ts +7 -0
  109. package/dist/components/siyahi/local-time.js +22 -0
  110. package/dist/components/siyahi/price-chart.d.ts +12 -0
  111. package/dist/components/siyahi/price-chart.js +80 -0
  112. package/dist/components/siyahi/siyahi-provider.d.ts +12 -0
  113. package/dist/components/siyahi/siyahi-provider.js +31 -0
  114. package/dist/components/siyahi/treemap.d.ts +14 -0
  115. package/dist/components/siyahi/treemap.js +58 -0
  116. package/dist/components/ui/alert.d.ts +12 -0
  117. package/dist/components/ui/alert.js +43 -0
  118. package/dist/components/ui/avatar.d.ts +13 -0
  119. package/dist/components/ui/avatar.js +50 -0
  120. package/dist/components/ui/badge.d.ts +9 -0
  121. package/dist/components/ui/badge.js +29 -0
  122. package/dist/components/ui/breadcrumb.d.ts +12 -0
  123. package/dist/components/ui/breadcrumb.js +72 -0
  124. package/dist/components/ui/button.d.ts +10 -0
  125. package/dist/components/ui/button.js +44 -0
  126. package/dist/components/ui/calendar.d.ts +12 -0
  127. package/dist/components/ui/calendar.js +107 -0
  128. package/dist/components/ui/card.d.ts +13 -0
  129. package/dist/components/ui/card.js +56 -0
  130. package/dist/components/ui/chart.d.ts +46 -0
  131. package/dist/components/ui/chart.js +149 -0
  132. package/dist/components/ui/collapsible.d.ts +7 -0
  133. package/dist/components/ui/collapsible.js +24 -0
  134. package/dist/components/ui/command.d.ts +21 -0
  135. package/dist/components/ui/command.js +88 -0
  136. package/dist/components/ui/context-menu.d.ts +31 -0
  137. package/dist/components/ui/context-menu.js +132 -0
  138. package/dist/components/ui/dialog.d.ts +19 -0
  139. package/dist/components/ui/dialog.js +91 -0
  140. package/dist/components/ui/dropdown-menu.d.ts +31 -0
  141. package/dist/components/ui/dropdown-menu.js +136 -0
  142. package/dist/components/ui/input-group.d.ts +20 -0
  143. package/dist/components/ui/input-group.js +79 -0
  144. package/dist/components/ui/input.d.ts +5 -0
  145. package/dist/components/ui/input.js +15 -0
  146. package/dist/components/ui/popover.d.ts +11 -0
  147. package/dist/components/ui/popover.js +55 -0
  148. package/dist/components/ui/progress.d.ts +9 -0
  149. package/dist/components/ui/progress.js +43 -0
  150. package/dist/components/ui/scroll-area.d.ts +7 -0
  151. package/dist/components/ui/scroll-area.js +36 -0
  152. package/dist/components/ui/select.d.ts +17 -0
  153. package/dist/components/ui/select.js +97 -0
  154. package/dist/components/ui/separator.d.ts +5 -0
  155. package/dist/components/ui/separator.js +15 -0
  156. package/dist/components/ui/sheet.d.ts +16 -0
  157. package/dist/components/ui/sheet.js +89 -0
  158. package/dist/components/ui/sidebar.d.ts +65 -0
  159. package/dist/components/ui/sidebar.js +385 -0
  160. package/dist/components/ui/skeleton.d.ts +4 -0
  161. package/dist/components/ui/skeleton.js +12 -0
  162. package/dist/components/ui/slider.d.ts +5 -0
  163. package/dist/components/ui/slider.js +33 -0
  164. package/dist/components/ui/table.d.ts +12 -0
  165. package/dist/components/ui/table.js +66 -0
  166. package/dist/components/ui/tabs.d.ts +12 -0
  167. package/dist/components/ui/tabs.js +45 -0
  168. package/dist/components/ui/textarea.d.ts +5 -0
  169. package/dist/components/ui/textarea.js +13 -0
  170. package/dist/components/ui/toggle-group.d.ts +13 -0
  171. package/dist/components/ui/toggle-group.js +52 -0
  172. package/dist/components/ui/toggle.d.ts +10 -0
  173. package/dist/components/ui/toggle.js +36 -0
  174. package/dist/components/ui/tooltip.d.ts +8 -0
  175. package/dist/components/ui/tooltip.js +41 -0
  176. package/dist/hooks/use-mobile.d.ts +3 -0
  177. package/dist/hooks/use-mobile.js +18 -0
  178. package/dist/index.d.ts +73 -0
  179. package/dist/index.js +71 -0
  180. package/dist/lib/format.d.ts +24 -0
  181. package/dist/lib/format.js +58 -0
  182. package/dist/lib/locale.d.ts +12 -0
  183. package/dist/lib/locale.js +8 -0
  184. package/dist/lib/recharts.d.ts +2 -0
  185. package/dist/lib/recharts.js +1 -0
  186. package/dist/lib/utils.d.ts +2 -0
  187. package/dist/lib/utils.js +1 -0
  188. package/package.json +78 -3
  189. package/registry.lock.json +413 -0
  190. package/report.css +129 -0
  191. package/styles/shadcn.css +643 -0
  192. package/styles/siyahi.css +189 -0
@@ -0,0 +1,62 @@
1
+ import { DataTableFeatures } from "../lib/data-table-features.js";
2
+ import { DataTableColumns, GlobalFilter } from "../types/index.js";
3
+ import React from "react";
4
+ import { ColumnFiltersState, ColumnOrderState, ColumnVisibilityState, ExpandedState, GroupingState, PaginationState, ReactTable, RowData, RowSelectionState, SortingState, TableOptions, Updater } from "@tanstack/react-table";
5
+ //#region src/components/registry/niko-table/core/data-table-root.d.ts
6
+ export interface DataTableConfig {
7
+ enablePagination?: boolean;
8
+ enableFilters?: boolean;
9
+ enableSorting?: boolean;
10
+ enableRowSelection?: boolean;
11
+ enableMultiSort?: boolean;
12
+ enableGrouping?: boolean;
13
+ enableExpanding?: boolean;
14
+ /**
15
+ * Enable drag-to-resize column widths (opt-in; off by default so existing
16
+ * tables are unaffected). When on, columns render at `column.getSize()` and a
17
+ * resize handle appears on each resizable header's right edge. Drop
18
+ * `<DataTableColumnResize />` inside the root to enable via feature detection.
19
+ * Double-click a grip to autosize; columns opt out with `enableResizing: false`.
20
+ */
21
+ enableColumnResizing?: boolean;
22
+ /**
23
+ * When grouping is active, how grouped columns are placed in the column flow.
24
+ * TanStack default: `'reorder'` (move grouped columns to the start).
25
+ * `'remove'` hides them; `false` leaves them in place.
26
+ */
27
+ groupedColumnMode?: false | "reorder" | "remove";
28
+ manualSorting?: boolean;
29
+ manualPagination?: boolean;
30
+ manualFiltering?: boolean;
31
+ pageCount?: number;
32
+ initialPageSize?: number;
33
+ initialPageIndex?: number;
34
+ autoResetPageIndex?: boolean;
35
+ autoResetExpanded?: boolean;
36
+ }
37
+ interface TableRootProps<TData extends RowData> extends Omit<Partial<TableOptions<DataTableFeatures, TData>>, "columns" | "data" | "getRowId" | "key"> {
38
+ table?: ReactTable<DataTableFeatures, TData>;
39
+ columns?: DataTableColumns<TData>;
40
+ data?: TData[];
41
+ children: React.ReactNode;
42
+ className?: string;
43
+ config?: DataTableConfig;
44
+ getRowId?: (originalRow: TData, index: number) => string;
45
+ isLoading?: boolean;
46
+ onGlobalFilterChange?: (value: GlobalFilter) => void;
47
+ onPaginationChange?: (updater: Updater<PaginationState>) => void;
48
+ onSortingChange?: (updater: Updater<SortingState>) => void;
49
+ onColumnVisibilityChange?: (updater: Updater<ColumnVisibilityState>) => void;
50
+ onColumnFiltersChange?: (updater: Updater<ColumnFiltersState>) => void;
51
+ onRowSelectionChange?: (updater: Updater<RowSelectionState>) => void;
52
+ onExpandedChange?: (updater: Updater<ExpandedState>) => void;
53
+ onGroupingChange?: (updater: Updater<GroupingState>) => void;
54
+ onColumnOrderChange?: (updater: Updater<ColumnOrderState>) => void;
55
+ onRowSelection?: (selectedRows: TData[]) => void;
56
+ }
57
+ export declare function DataTableRoot<TData extends RowData>({ table: externalTable, columns, data, children, className, isLoading, ...rest }: TableRootProps<TData>): React.JSX.Element;
58
+ export declare namespace DataTableRoot {
59
+ var displayName: string;
60
+ }
61
+ //#endregion
62
+ export {};
@@ -0,0 +1,406 @@
1
+ import { TooltipProvider } from "../../../ui/tooltip.js";
2
+ import { cn } from "../../../../lib/utils.js";
3
+ import { FILTER_VARIANTS, SYSTEM_COLUMN_IDS, SYSTEM_COLUMN_ID_LIST } from "../lib/constants.js";
4
+ import { DataTableProvider } from "./data-table-context.js";
5
+ import { detectFeaturesFromChildren } from "../config/feature-detection.js";
6
+ import { globalFilter } from "../lib/filter-functions.js";
7
+ import { features } from "../lib/data-table-features.js";
8
+ import React from "react";
9
+ import { jsx } from "react/jsx-runtime";
10
+ import { useTable } from "@tanstack/react-table";
11
+ //#region src/components/registry/niko-table/core/data-table-root.tsx
12
+ /**
13
+ * Delay (ms) before a tooltip inside a data table opens. Deliberately long so
14
+ * header help/sort tooltips don't pop while the assigner is scanning or
15
+ * clicking through sorts — they only appear on a considered hover. Scopes to
16
+ * the table via a nested `TooltipProvider`, so action-button tooltips outside
17
+ * the table keep their own (faster) provider delay.
18
+ */
19
+ const TABLE_TOOLTIP_DELAY_MS = 1e3;
20
+ /**
21
+ * Dual-generation tooltip delay: Radix's provider reads `delayDuration`,
22
+ * Base UI's reads `delay`, and each ignores the other prop. Spread as an
23
+ * object (not literal attributes) so it typechecks against both shadcn
24
+ * generations and the CLI's Base UI codemod leaves it alone.
25
+ */
26
+ const tooltipProviderDelay = {
27
+ delayDuration: TABLE_TOOLTIP_DELAY_MS,
28
+ delay: TABLE_TOOLTIP_DELAY_MS
29
+ };
30
+ function DataTableRootInternal({ columns, data, children, className, config, getRowId, isLoading, onGlobalFilterChange, onPaginationChange, onSortingChange, onColumnVisibilityChange, onColumnFiltersChange, onRowSelectionChange, onExpandedChange, onGroupingChange, onColumnOrderChange, onColumnPinningChange, onColumnSizingChange, onRowSelection, state: restState, initialState: restInitialState, globalFilterFn: restGlobalFilterFn, manualGrouping: manualGroupingProp, manualExpanding: manualExpandingProp, ...passthroughTableOptions }) {
31
+ const hasSelectColumn = React.useMemo(() => columns?.some((col) => col.id === SYSTEM_COLUMN_IDS.SELECT) ?? false, [columns]);
32
+ const hasExpandColumn = React.useMemo(() => columns?.some((col) => col.id === SYSTEM_COLUMN_IDS.EXPAND || col.meta && "expandedContent" in col.meta && col.meta.expandedContent) ?? false, [columns]);
33
+ const finalConfig = React.useMemo(() => ({
34
+ enablePagination: config?.enablePagination,
35
+ enableFilters: config?.enableFilters,
36
+ enableSorting: config?.enableSorting,
37
+ enableRowSelection: config?.enableRowSelection ?? hasSelectColumn,
38
+ enableMultiSort: config?.enableMultiSort,
39
+ enableGrouping: config?.enableGrouping,
40
+ enableExpanding: config?.enableExpanding ?? hasExpandColumn,
41
+ enableColumnResizing: config?.enableColumnResizing,
42
+ groupedColumnMode: config?.groupedColumnMode,
43
+ manualSorting: config?.manualSorting,
44
+ manualPagination: config?.manualPagination,
45
+ manualFiltering: config?.manualFiltering,
46
+ pageCount: config?.pageCount,
47
+ initialPageSize: config?.initialPageSize,
48
+ initialPageIndex: config?.initialPageIndex,
49
+ autoResetPageIndex: config?.autoResetPageIndex ?? false,
50
+ autoResetExpanded: config?.autoResetExpanded ?? false
51
+ }), [
52
+ config?.enablePagination,
53
+ config?.enableFilters,
54
+ config?.enableSorting,
55
+ config?.enableRowSelection,
56
+ hasSelectColumn,
57
+ config?.enableMultiSort,
58
+ config?.enableGrouping,
59
+ config?.enableExpanding,
60
+ config?.enableColumnResizing,
61
+ config?.groupedColumnMode,
62
+ hasExpandColumn,
63
+ config?.manualSorting,
64
+ config?.manualPagination,
65
+ config?.manualFiltering,
66
+ config?.pageCount,
67
+ config?.initialPageSize,
68
+ config?.initialPageIndex,
69
+ config?.autoResetPageIndex,
70
+ config?.autoResetExpanded
71
+ ]);
72
+ const detectedFeaturesRef = React.useRef(null);
73
+ if (detectedFeaturesRef.current === null) detectedFeaturesRef.current = detectFeaturesFromChildren(children, columns);
74
+ const detectFeatures = React.useMemo(() => {
75
+ const detectedFeatures = detectedFeaturesRef.current ?? {};
76
+ return {
77
+ enablePagination: finalConfig.enablePagination ?? detectedFeatures.enablePagination ?? false,
78
+ enableFilters: finalConfig.enableFilters ?? detectedFeatures.enableFilters ?? false,
79
+ enableRowSelection: finalConfig.enableRowSelection ?? detectedFeatures.enableRowSelection ?? false,
80
+ enableSorting: finalConfig.enableSorting ?? detectedFeatures.enableSorting ?? false,
81
+ enableMultiSort: finalConfig.enableMultiSort ?? detectedFeatures.enableMultiSort ?? true,
82
+ enableGrouping: finalConfig.enableGrouping ?? detectedFeatures.enableGrouping ?? false,
83
+ enableExpanding: finalConfig.enableExpanding ?? detectedFeatures.enableExpanding ?? finalConfig.enableGrouping ?? detectedFeatures.enableGrouping ?? false,
84
+ enableColumnResizing: finalConfig.enableColumnResizing ?? detectedFeatures.enableColumnResizing ?? false,
85
+ manualSorting: finalConfig.manualSorting ?? detectedFeatures.manualSorting ?? false,
86
+ manualPagination: finalConfig.manualPagination ?? detectedFeatures.manualPagination ?? false,
87
+ manualFiltering: finalConfig.manualFiltering ?? detectedFeatures.manualFiltering ?? false,
88
+ pageCount: finalConfig.pageCount ?? detectedFeatures.pageCount
89
+ };
90
+ }, [finalConfig]);
91
+ const [globalFilter$1, setGlobalFilter] = React.useState(restInitialState?.globalFilter ?? "");
92
+ const [rowSelection, setRowSelection] = React.useState(restInitialState?.rowSelection ?? {});
93
+ const [columnVisibility, setColumnVisibility] = React.useState(restInitialState?.columnVisibility ?? {});
94
+ const [columnFilters, setColumnFilters] = React.useState(restInitialState?.columnFilters ?? []);
95
+ const [sorting, setSorting] = React.useState(restInitialState?.sorting ?? []);
96
+ const [expanded, setExpanded] = React.useState(restInitialState?.expanded ?? {});
97
+ const [grouping, setGrouping] = React.useState(restInitialState?.grouping ?? []);
98
+ const [columnPinning, setColumnPinning] = React.useState({
99
+ start: restInitialState?.columnPinning?.start ?? [],
100
+ end: restInitialState?.columnPinning?.end ?? []
101
+ });
102
+ const [columnOrder, setColumnOrder] = React.useState(restInitialState?.columnOrder ?? []);
103
+ const [columnSizing, setColumnSizing] = React.useState(restInitialState?.columnSizing ?? {});
104
+ const [pagination, setPagination] = React.useState({
105
+ pageIndex: finalConfig.initialPageIndex ?? restInitialState?.pagination?.pageIndex ?? 0,
106
+ pageSize: finalConfig.initialPageSize ?? restInitialState?.pagination?.pageSize ?? 10
107
+ });
108
+ const isMountedRef = React.useRef(true);
109
+ React.useEffect(() => {
110
+ isMountedRef.current = true;
111
+ return () => {
112
+ isMountedRef.current = false;
113
+ };
114
+ }, []);
115
+ const handleGlobalFilterChange = React.useCallback((value) => {
116
+ if (isMountedRef.current) setGlobalFilter(value);
117
+ onGlobalFilterChange?.(value);
118
+ }, [onGlobalFilterChange]);
119
+ const rowIdMap = React.useMemo(() => {
120
+ const map = /* @__PURE__ */ new Map();
121
+ data?.forEach((row, idx) => {
122
+ const rowId = getRowId?.(row, idx) ?? row.id?.toString() ?? String(idx);
123
+ map.set(rowId, row);
124
+ });
125
+ return map;
126
+ }, [data, getRowId]);
127
+ const handleRowSelectionChange = React.useCallback((valueFn) => {
128
+ if (!isMountedRef.current) return;
129
+ if (typeof valueFn === "function") setRowSelection((prev) => valueFn(prev));
130
+ else setRowSelection(valueFn);
131
+ }, []);
132
+ /**
133
+ * PERFORMANCE: Stable mount-guarded fallback setters
134
+ *
135
+ * WHY: Inline `(u) => isMounted && setX(u)` closures inside `tableOptions` get
136
+ * recreated on every memo invalidation, and the 6 setX refs added noise to the
137
+ * dep array (state setters are already stable by React contract).
138
+ *
139
+ * IMPACT: tableOptions memo no longer depends on 6 setters; fallback handlers
140
+ * keep referential identity across renders.
141
+ *
142
+ * WHAT: Hoists each fallback to a `useCallback([])`. Mount-guard preserved so
143
+ * StrictMode-unmounted fibers don't receive setState calls.
144
+ */
145
+ const handleSortingChange = React.useCallback((u) => {
146
+ if (isMountedRef.current) setSorting(u);
147
+ }, []);
148
+ const handleColumnFiltersChange = React.useCallback((u) => {
149
+ if (isMountedRef.current) setColumnFilters(u);
150
+ }, []);
151
+ const handleColumnVisibilityChange = React.useCallback((u) => {
152
+ if (isMountedRef.current) setColumnVisibility(u);
153
+ }, []);
154
+ const handleColumnPinningChange = React.useCallback((updater) => {
155
+ if (!isMountedRef.current) return;
156
+ setColumnPinning((prev) => {
157
+ const next = typeof updater === "function" ? updater(prev) : updater;
158
+ return {
159
+ start: next.start ?? [],
160
+ end: next.end ?? []
161
+ };
162
+ });
163
+ }, []);
164
+ const handleColumnOrderChange = React.useCallback((u) => {
165
+ if (isMountedRef.current) setColumnOrder(u);
166
+ }, []);
167
+ const handleColumnSizingChange = React.useCallback((u) => {
168
+ if (isMountedRef.current) setColumnSizing(u);
169
+ }, []);
170
+ const handleExpandedChange = React.useCallback((u) => {
171
+ if (isMountedRef.current) setExpanded(u);
172
+ }, []);
173
+ const handleGroupingChange = React.useCallback((u) => {
174
+ if (isMountedRef.current) setGrouping(u);
175
+ }, []);
176
+ const handlePaginationChange = React.useCallback((u) => {
177
+ if (isMountedRef.current) setPagination(u);
178
+ }, []);
179
+ const skipInitialRowSelectionRef = React.useRef(true);
180
+ React.useEffect(() => {
181
+ if (!isMountedRef.current) return;
182
+ if (skipInitialRowSelectionRef.current) {
183
+ skipInitialRowSelectionRef.current = false;
184
+ return;
185
+ }
186
+ if (!onRowSelection) return;
187
+ onRowSelection(Object.keys(rowSelection).filter((key) => rowSelection[key]).map((key) => rowIdMap.get(key)).filter((row) => row !== void 0));
188
+ }, [
189
+ rowSelection,
190
+ rowIdMap,
191
+ onRowSelection
192
+ ]);
193
+ /**
194
+ * Auto-apply filterFn based on meta.variant if not explicitly provided
195
+ * This allows developers to set variant in meta and get the right filterFn automatically
196
+ */
197
+ const processedColumns = React.useMemo(() => {
198
+ return columns.map((col) => {
199
+ if (col.filterFn) return col;
200
+ const variant = (col.meta ?? {}).variant;
201
+ let autoFilterFn;
202
+ if (variant === FILTER_VARIANTS.RANGE || variant === FILTER_VARIANTS.NUMBER) autoFilterFn = "numberRange";
203
+ else if (variant === FILTER_VARIANTS.DATE || variant === FILTER_VARIANTS.DATE_RANGE) autoFilterFn = "dateRange";
204
+ if (autoFilterFn) return {
205
+ ...col,
206
+ filterFn: autoFilterFn
207
+ };
208
+ return col;
209
+ });
210
+ }, [columns]);
211
+ const defaultColumn = React.useMemo(() => ({
212
+ enableSorting: detectFeatures.enableSorting ?? false,
213
+ enableHiding: true,
214
+ filterFn: "extended",
215
+ size: void 0,
216
+ ...detectFeatures.enableColumnResizing ? { minSize: 40 } : {}
217
+ }), [detectFeatures.enableColumnResizing, detectFeatures.enableSorting]);
218
+ const controlledSorting = restState?.sorting ?? sorting;
219
+ const controlledColumnVisibility = restState?.columnVisibility ?? columnVisibility;
220
+ const controlledRowSelection = restState?.rowSelection ?? rowSelection;
221
+ const controlledColumnFilters = restState?.columnFilters ?? columnFilters;
222
+ const controlledGlobalFilter = restState?.globalFilter !== void 0 ? restState.globalFilter : globalFilter$1;
223
+ const controlledColumnPinning = restState?.columnPinning ?? columnPinning;
224
+ const controlledColumnOrder = restState?.columnOrder ?? columnOrder;
225
+ const controlledColumnSizing = restState?.columnSizing ?? columnSizing;
226
+ const controlledExpanded = restState?.expanded ?? expanded;
227
+ const controlledGrouping = restState?.grouping ?? grouping;
228
+ const controlledPagination = restState?.pagination ?? pagination;
229
+ const finalColumnPinning = React.useMemo(() => {
230
+ const getColumnId = (col) => {
231
+ if (col.id) return col.id;
232
+ if ("accessorKey" in col && typeof col.accessorKey === "string") return col.accessorKey;
233
+ };
234
+ const firstDataCol = columns.find((col) => {
235
+ const id = getColumnId(col);
236
+ return id && !SYSTEM_COLUMN_ID_LIST.includes(id);
237
+ });
238
+ if (!firstDataCol) return controlledColumnPinning;
239
+ const firstDataColId = getColumnId(firstDataCol);
240
+ if (!firstDataColId) return controlledColumnPinning;
241
+ const isPinnedStart = controlledColumnPinning.start?.includes(firstDataColId);
242
+ const isPinnedEnd = controlledColumnPinning.end?.includes(firstDataColId);
243
+ if (!isPinnedStart && !isPinnedEnd) return controlledColumnPinning;
244
+ const start = [...controlledColumnPinning.start ?? []];
245
+ const end = [...controlledColumnPinning.end ?? []];
246
+ const systemColsPresent = [];
247
+ if (hasSelectColumn) systemColsPresent.push(SYSTEM_COLUMN_IDS.SELECT);
248
+ if (hasExpandColumn) systemColsPresent.push(SYSTEM_COLUMN_IDS.EXPAND);
249
+ const cleanStart = start.filter((id) => !SYSTEM_COLUMN_ID_LIST.includes(id));
250
+ const cleanEnd = end.filter((id) => !SYSTEM_COLUMN_ID_LIST.includes(id));
251
+ if (isPinnedStart) return {
252
+ start: [...systemColsPresent, ...cleanStart],
253
+ end: cleanEnd
254
+ };
255
+ if (isPinnedEnd) return {
256
+ start: cleanStart,
257
+ end: [...systemColsPresent, ...cleanEnd]
258
+ };
259
+ return controlledColumnPinning;
260
+ }, [
261
+ controlledColumnPinning,
262
+ columns,
263
+ hasSelectColumn,
264
+ hasExpandColumn
265
+ ]);
266
+ const tableOptions = React.useMemo(() => ({
267
+ ...passthroughTableOptions,
268
+ features,
269
+ data,
270
+ columns: processedColumns,
271
+ defaultColumn,
272
+ state: {
273
+ ...restState,
274
+ sorting: controlledSorting,
275
+ columnVisibility: controlledColumnVisibility,
276
+ columnPinning: finalColumnPinning,
277
+ columnOrder: controlledColumnOrder,
278
+ columnSizing: controlledColumnSizing,
279
+ rowSelection: controlledRowSelection,
280
+ columnFilters: controlledColumnFilters,
281
+ globalFilter: controlledGlobalFilter,
282
+ expanded: controlledExpanded,
283
+ grouping: controlledGrouping,
284
+ pagination: controlledPagination
285
+ },
286
+ enableColumnResizing: detectFeatures.enableColumnResizing,
287
+ columnResizeMode: "onEnd",
288
+ onColumnSizingChange: onColumnSizingChange ?? handleColumnSizingChange,
289
+ enableRowSelection: detectFeatures.enableRowSelection,
290
+ enableFilters: detectFeatures.enableFilters,
291
+ enableSorting: detectFeatures.enableSorting,
292
+ enableMultiSort: detectFeatures.enableMultiSort,
293
+ enableGrouping: detectFeatures.enableGrouping,
294
+ enableExpanding: detectFeatures.enableExpanding || detectFeatures.enableGrouping,
295
+ groupedColumnMode: finalConfig.groupedColumnMode ?? "reorder",
296
+ manualSorting: detectFeatures.manualSorting || !detectFeatures.enableSorting,
297
+ manualPagination: detectFeatures.manualPagination || !detectFeatures.enablePagination,
298
+ manualFiltering: detectFeatures.manualFiltering || !detectFeatures.enableFilters,
299
+ manualGrouping: manualGroupingProp ?? !detectFeatures.enableGrouping,
300
+ manualExpanding: manualExpandingProp ?? !(detectFeatures.enableExpanding || detectFeatures.enableGrouping),
301
+ autoResetPageIndex: finalConfig.autoResetPageIndex,
302
+ autoResetExpanded: finalConfig.autoResetExpanded,
303
+ onGlobalFilterChange: handleGlobalFilterChange,
304
+ onRowSelectionChange: onRowSelectionChange ?? handleRowSelectionChange,
305
+ onSortingChange: onSortingChange ?? handleSortingChange,
306
+ onColumnFiltersChange: onColumnFiltersChange ?? handleColumnFiltersChange,
307
+ onColumnVisibilityChange: onColumnVisibilityChange ?? handleColumnVisibilityChange,
308
+ onColumnPinningChange: onColumnPinningChange ?? handleColumnPinningChange,
309
+ onColumnOrderChange: onColumnOrderChange ?? handleColumnOrderChange,
310
+ onExpandedChange: onExpandedChange ?? handleExpandedChange,
311
+ onGroupingChange: onGroupingChange ?? handleGroupingChange,
312
+ onPaginationChange: onPaginationChange ?? handlePaginationChange,
313
+ globalFilterFn: restGlobalFilterFn ?? globalFilter,
314
+ getRowId: getRowId ?? ((originalRow, index) => {
315
+ const rowWithId = originalRow;
316
+ if (rowWithId.id !== void 0 && rowWithId.id !== null) return String(rowWithId.id);
317
+ return String(index);
318
+ }),
319
+ pageCount: (() => {
320
+ if (!detectFeatures.manualPagination) return void 0;
321
+ return finalConfig.pageCount !== void 0 ? finalConfig.pageCount : detectFeatures.pageCount !== void 0 ? detectFeatures.pageCount : -1;
322
+ })()
323
+ }), [
324
+ restState,
325
+ restGlobalFilterFn,
326
+ data,
327
+ processedColumns,
328
+ defaultColumn,
329
+ detectFeatures,
330
+ finalConfig,
331
+ handleGlobalFilterChange,
332
+ onRowSelectionChange,
333
+ handleRowSelectionChange,
334
+ onSortingChange,
335
+ handleSortingChange,
336
+ onColumnFiltersChange,
337
+ handleColumnFiltersChange,
338
+ onColumnVisibilityChange,
339
+ handleColumnVisibilityChange,
340
+ onColumnPinningChange,
341
+ handleColumnPinningChange,
342
+ onColumnOrderChange,
343
+ handleColumnOrderChange,
344
+ onColumnSizingChange,
345
+ handleColumnSizingChange,
346
+ onExpandedChange,
347
+ handleExpandedChange,
348
+ onGroupingChange,
349
+ handleGroupingChange,
350
+ onPaginationChange,
351
+ handlePaginationChange,
352
+ getRowId,
353
+ manualGroupingProp,
354
+ manualExpandingProp,
355
+ controlledSorting,
356
+ controlledColumnVisibility,
357
+ controlledRowSelection,
358
+ controlledColumnFilters,
359
+ controlledGlobalFilter,
360
+ controlledColumnOrder,
361
+ controlledColumnSizing,
362
+ controlledExpanded,
363
+ controlledGrouping,
364
+ controlledPagination,
365
+ finalColumnPinning
366
+ ]);
367
+ const table = useTable(tableOptions);
368
+ return /* @__PURE__ */ jsx(DataTableProvider, {
369
+ table,
370
+ columns: processedColumns,
371
+ isLoading,
372
+ children: /* @__PURE__ */ jsx(TooltipProvider, {
373
+ ...tooltipProviderDelay,
374
+ children: /* @__PURE__ */ jsx("div", {
375
+ className: cn("w-full min-w-0 space-y-4", className),
376
+ children
377
+ })
378
+ })
379
+ });
380
+ }
381
+ function DataTableRoot({ table: externalTable, columns, data, children, className, isLoading, ...rest }) {
382
+ if (externalTable) return /* @__PURE__ */ jsx(DataTableProvider, {
383
+ table: externalTable,
384
+ columns,
385
+ isLoading,
386
+ children: /* @__PURE__ */ jsx(TooltipProvider, {
387
+ ...tooltipProviderDelay,
388
+ children: /* @__PURE__ */ jsx("div", {
389
+ className: cn("w-full min-w-0 space-y-4", className),
390
+ children
391
+ })
392
+ })
393
+ });
394
+ if (!columns || !data) throw new Error("DataTableRoot: Either provide a 'table' prop or both 'columns' and 'data' props");
395
+ return /* @__PURE__ */ jsx(DataTableRootInternal, {
396
+ columns,
397
+ data,
398
+ className,
399
+ isLoading,
400
+ ...rest,
401
+ children
402
+ });
403
+ }
404
+ DataTableRoot.displayName = "DataTableRoot";
405
+ //#endregion
406
+ export { DataTableRoot };
@@ -0,0 +1,153 @@
1
+ import { ScrollEvent } from "../lib/create-scroll-handler.js";
2
+ import React from "react";
3
+ import { RowData } from "@tanstack/react-table";
4
+ //#region src/components/registry/niko-table/core/data-table-structure.d.ts
5
+ export interface DataTableHeaderProps {
6
+ className?: string;
7
+ /**
8
+ * Makes the header sticky at the top when scrolling.
9
+ * @default true
10
+ */
11
+ sticky?: boolean;
12
+ }
13
+ export declare const DataTableHeader: React.MemoExoticComponent<({ className, sticky }: DataTableHeaderProps) => React.JSX.Element | null>;
14
+ export interface DataTableBodyProps<TData extends RowData> {
15
+ children?: React.ReactNode;
16
+ className?: string;
17
+ onScroll?: (event: ScrollEvent) => void;
18
+ onScrolledTop?: () => void;
19
+ onScrolledBottom?: () => void;
20
+ scrollThreshold?: number;
21
+ /**
22
+ * Click is dispatched per-row from each cell's onClick. The event's
23
+ * `currentTarget` is the `<td>` cell — typed as `HTMLElement` to
24
+ * stay consistent with the virtualized variants (which delegate on
25
+ * `<tbody>`). Consumers needing the row element can
26
+ * `event.target.closest("tr[data-row-id]")`.
27
+ */
28
+ onRowClick?: (row: TData, event: React.MouseEvent<HTMLElement>) => void;
29
+ /**
30
+ * Return a per-row memo invalidation key. When this key changes for a
31
+ * specific row, only that row re-renders.
32
+ */
33
+ getRowMemoKey?: (row: TData) => string;
34
+ /**
35
+ * Attach a native right-click context menu to each row. Return the menu
36
+ * items (`ContextMenuItem`, `ContextMenuSeparator`, `ContextMenuSub`, …)
37
+ * for the given row, or `null` to give that row no menu. The popup shell
38
+ * and portalling are handled internally.
39
+ *
40
+ * Wrap the callback in `useCallback` so memoized rows don't re-render.
41
+ */
42
+ renderRowContextMenu?: (row: TData) => React.ReactNode;
43
+ }
44
+ export declare function DataTableBody<TData extends RowData>({ children, className, onScroll, onScrolledTop, onScrolledBottom, scrollThreshold, onRowClick, getRowMemoKey, renderRowContextMenu }: DataTableBodyProps<TData>): React.JSX.Element;
45
+ export declare namespace DataTableBody {
46
+ var displayName: string;
47
+ }
48
+ export interface DataTableEmptyBodyProps {
49
+ children?: React.ReactNode;
50
+ colSpan?: number;
51
+ className?: string;
52
+ }
53
+ /**
54
+ * Empty state component for data tables.
55
+ * Use composition pattern with DataTableEmpty* components for full customization.
56
+ *
57
+ * @example
58
+ * <DataTableEmptyBody>
59
+ * <DataTableEmptyIcon>
60
+ * <PackageOpen className="size-12" />
61
+ * </DataTableEmptyIcon>
62
+ * <DataTableEmptyMessage>
63
+ * <DataTableEmptyTitle>No products found</DataTableEmptyTitle>
64
+ * <DataTableEmptyDescription>
65
+ * Get started by adding your first product
66
+ * </DataTableEmptyDescription>
67
+ * </DataTableEmptyMessage>
68
+ * <DataTableEmptyFilteredMessage>
69
+ * No matches found
70
+ * </DataTableEmptyFilteredMessage>
71
+ * <DataTableEmptyActions>
72
+ * <Button onClick={handleAdd}>Add Product</Button>
73
+ * </DataTableEmptyActions>
74
+ * </DataTableEmptyBody>
75
+ */
76
+ export declare function DataTableEmptyBody({ children, colSpan, className }: DataTableEmptyBodyProps): React.JSX.Element | null;
77
+ export declare namespace DataTableEmptyBody {
78
+ var displayName: string;
79
+ }
80
+ export interface DataTableSkeletonProps {
81
+ children?: React.ReactNode;
82
+ colSpan?: number;
83
+ /**
84
+ * Number of skeleton rows to display.
85
+ * @default 5
86
+ * @recommendation Set this to match your page size for better UX (e.g., if page size is 10, set rows={10})
87
+ */
88
+ rows?: number;
89
+ className?: string;
90
+ cellClassName?: string;
91
+ skeletonClassName?: string;
92
+ }
93
+ export declare function DataTableSkeleton({ children, colSpan, rows, className, cellClassName, skeletonClassName }: DataTableSkeletonProps): React.JSX.Element | null;
94
+ export declare namespace DataTableSkeleton {
95
+ var displayName: string;
96
+ }
97
+ export interface DataTableLoadingProps {
98
+ children?: React.ReactNode;
99
+ colSpan?: number;
100
+ className?: string;
101
+ }
102
+ export declare function DataTableLoading({ children, colSpan, className }: DataTableLoadingProps): React.JSX.Element | null;
103
+ export declare namespace DataTableLoading {
104
+ var displayName: string;
105
+ }
106
+ export interface DataTableLoadingMoreProps {
107
+ /**
108
+ * Whether a next-page fetch is currently in flight. Typically
109
+ * wired to tRPC's `useInfiniteQuery.isFetchingNextPage`. When
110
+ * false, this component renders nothing.
111
+ */
112
+ isFetching: boolean;
113
+ /**
114
+ * Optional custom content inside the loading-more row. Defaults
115
+ * to a spinner + "Loading more…" label. Pass children to
116
+ * customize the label per-table (e.g. "Loading more venues…").
117
+ */
118
+ children?: React.ReactNode;
119
+ colSpan?: number;
120
+ className?: string;
121
+ }
122
+ /**
123
+ * Composable "loading more" row for infinite-scroll tables. Renders
124
+ * a spinner + label row at the end of the body when `isFetching` is
125
+ * true, and nothing when false — designed to be dropped as a child
126
+ * of `DataTableBody` alongside `DataTableSkeleton` and
127
+ * `DataTableEmptyBody`.
128
+ *
129
+ * Mirror of `DataTableVirtualizedLoadingMore` for non-virtualized
130
+ * tables — same API, same styling, same self-gating behavior.
131
+ *
132
+ * @example
133
+ * const query = api.thing.list.useInfiniteQuery(...);
134
+ * <DataTableBody
135
+ * onScrolledBottom={() => {
136
+ * if (query.hasNextPage && !query.isFetchingNextPage) {
137
+ * void query.fetchNextPage();
138
+ * }
139
+ * }}
140
+ * >
141
+ * <DataTableSkeleton rows={5} />
142
+ * <DataTableEmptyBody>No results</DataTableEmptyBody>
143
+ * <DataTableLoadingMore isFetching={query.isFetchingNextPage}>
144
+ * Loading more things…
145
+ * </DataTableLoadingMore>
146
+ * </DataTableBody>
147
+ */
148
+ export declare function DataTableLoadingMore({ isFetching, children, colSpan, className }: DataTableLoadingMoreProps): React.JSX.Element | null;
149
+ export declare namespace DataTableLoadingMore {
150
+ var displayName: string;
151
+ }
152
+ //#endregion
153
+ export type { ScrollEvent };