@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,144 @@
1
+ import { formatLabel } from "../lib/format.js";
2
+ import { FILTER_VARIANTS } from "../lib/constants.js";
3
+ import { getFilteredRowsExcludingColumn } from "../lib/filter-rows.js";
4
+ import * as React$1 from "react";
5
+ //#region src/components/registry/niko-table/hooks/use-generated-options.ts
6
+ /**
7
+ * Generate a map of options for select/multiSelect columns based on table data.
8
+ * Uses either filtered rows (dynamicCounts) or all core rows.
9
+ */
10
+ function useGeneratedOptions(table, config = {}) {
11
+ const { showCounts = true, dynamicCounts = true, limitToFilteredRows = true, includeColumns, excludeColumns, limitPerColumn, mergeStrategy } = config;
12
+ const state = table.state;
13
+ const columnFilters = state.columnFilters;
14
+ const globalFilter = state.globalFilter;
15
+ const columns = React$1.useMemo(() => table.getAllColumns(), [table, table.options.columns]);
16
+ const coreRows = table.getCoreRowModel().rows;
17
+ const includeKey = includeColumns?.join(",") ?? "";
18
+ const excludeKey = excludeColumns?.join(",") ?? "";
19
+ return React$1.useMemo(() => {
20
+ const result = {};
21
+ for (const column of columns) {
22
+ const meta = column.columnDef.meta ?? {};
23
+ const variant = meta.variant ?? FILTER_VARIANTS.TEXT;
24
+ if (variant !== FILTER_VARIANTS.SELECT && variant !== FILTER_VARIANTS.MULTI_SELECT) continue;
25
+ const colId = column.id;
26
+ if (includeColumns && !includeColumns.includes(colId)) continue;
27
+ if (excludeColumns && excludeColumns.includes(colId)) continue;
28
+ const colAutoOptions = meta.autoOptions ?? true;
29
+ const colShowCounts = meta.showCounts ?? showCounts;
30
+ const colDynamicCounts = meta.dynamicCounts ?? dynamicCounts;
31
+ const colMerge = meta.mergeStrategy ?? mergeStrategy;
32
+ const colAutoOptionsFormat = meta.autoOptionsFormat ?? true;
33
+ const colFormatOptionLabel = meta.formatOptionLabel;
34
+ if (!colAutoOptions) {
35
+ result[column.id] = meta.options ?? [];
36
+ continue;
37
+ }
38
+ const filteredRowsExcl = limitToFilteredRows || colDynamicCounts ? getFilteredRowsExcludingColumn(table, coreRows, colId, columnFilters, globalFilter) : coreRows;
39
+ const optionSourceRows = limitToFilteredRows ? filteredRowsExcl : coreRows;
40
+ const countSourceRows = colDynamicCounts ? filteredRowsExcl : coreRows;
41
+ if (meta.options && meta.options.length > 0 && colMerge === "augment") {
42
+ const countMap = /* @__PURE__ */ new Map();
43
+ for (const row of countSourceRows) {
44
+ const raw = row.getValue(colId);
45
+ const values = Array.isArray(raw) ? raw : [raw];
46
+ for (const v of values) {
47
+ if (v === null || v === void 0) continue;
48
+ const str = String(v);
49
+ if (str.trim() === "") continue;
50
+ countMap.set(str, (countMap.get(str) ?? 0) + 1);
51
+ }
52
+ }
53
+ let filteredStaticOptions = meta.options;
54
+ if (limitToFilteredRows) {
55
+ const occurrenceMap = /* @__PURE__ */ new Map();
56
+ for (const row of optionSourceRows) {
57
+ const raw = row.getValue(colId);
58
+ const values = Array.isArray(raw) ? raw : [raw];
59
+ for (const v of values) {
60
+ if (v == null) continue;
61
+ occurrenceMap.set(String(v), true);
62
+ }
63
+ }
64
+ filteredStaticOptions = meta.options.filter((opt) => occurrenceMap.has(opt.value));
65
+ }
66
+ result[colId] = filteredStaticOptions.map((opt) => ({
67
+ ...opt,
68
+ count: colShowCounts ? countMap.get(opt.value) ?? 0 : void 0
69
+ }));
70
+ continue;
71
+ }
72
+ const optionValues = /* @__PURE__ */ new Set();
73
+ for (const row of optionSourceRows) {
74
+ const raw = row.getValue(colId);
75
+ const values = Array.isArray(raw) ? raw : [raw];
76
+ for (const v of values) {
77
+ if (v === null || v === void 0) continue;
78
+ const str = String(v);
79
+ if (str.trim() === "") continue;
80
+ optionValues.add(str);
81
+ }
82
+ }
83
+ if (optionValues.size === 0) {
84
+ result[colId] = [];
85
+ continue;
86
+ }
87
+ const counts = /* @__PURE__ */ new Map();
88
+ for (const row of countSourceRows) {
89
+ const raw = row.getValue(colId);
90
+ const values = Array.isArray(raw) ? raw : [raw];
91
+ for (const v of values) {
92
+ if (v === null || v === void 0) continue;
93
+ const str = String(v);
94
+ if (str.trim() === "") continue;
95
+ if (optionValues.has(str)) counts.set(str, (counts.get(str) ?? 0) + 1);
96
+ }
97
+ }
98
+ const options = Array.from(optionValues).map((value) => ({
99
+ value,
100
+ label: colFormatOptionLabel ? colFormatOptionLabel(value) : colAutoOptionsFormat ? formatLabel(value) : value,
101
+ count: colShowCounts ? counts.get(value) ?? 0 : void 0
102
+ })).sort((a, b) => a.label.localeCompare(b.label));
103
+ const finalOptions = typeof limitPerColumn === "number" && limitPerColumn > 0 ? options.slice(0, limitPerColumn) : options;
104
+ if (meta.options && meta.options.length > 0 && (!colMerge || colMerge === "preserve")) {
105
+ if (limitToFilteredRows) {
106
+ const availableOptions = /* @__PURE__ */ new Set();
107
+ for (const row of optionSourceRows) {
108
+ const raw = row.getValue(colId);
109
+ const values = Array.isArray(raw) ? raw : [raw];
110
+ for (const v of values) if (v != null) availableOptions.add(String(v));
111
+ }
112
+ result[colId] = meta.options.filter((opt) => availableOptions.has(opt.value));
113
+ } else result[colId] = meta.options;
114
+ continue;
115
+ }
116
+ result[colId] = finalOptions;
117
+ }
118
+ return result;
119
+ }, [
120
+ columns,
121
+ coreRows,
122
+ table,
123
+ dynamicCounts,
124
+ showCounts,
125
+ includeKey,
126
+ excludeKey,
127
+ limitPerColumn,
128
+ mergeStrategy,
129
+ limitToFilteredRows,
130
+ columnFilters,
131
+ globalFilter
132
+ ]);
133
+ }
134
+ /**
135
+ * Convenience: generate options only for a specific column id
136
+ */
137
+ function useGeneratedOptionsForColumn(table, columnId, config) {
138
+ return useGeneratedOptions(table, {
139
+ ...config,
140
+ includeColumns: [columnId]
141
+ })[columnId] ?? [];
142
+ }
143
+ //#endregion
144
+ export { useGeneratedOptions, useGeneratedOptionsForColumn };
@@ -0,0 +1,59 @@
1
+ import { DataTableInstance, DataTableRow, Option } from "../types/index.js";
2
+ import { RowData } from "@tanstack/react-table";
3
+ //#region src/components/registry/niko-table/lib/build-faceted-options.d.ts
4
+ export interface BuildFacetedOptionsConfig {
5
+ /**
6
+ * If provided, these options are the source of truth and the returned list
7
+ * is a subset of them (optionally narrowed by `limitToFilteredRows` and
8
+ * enriched with live counts).
9
+ *
10
+ * If omitted, options are derived from the rows themselves — useful for
11
+ * columns that are not declared as `select`/`multiSelect` variants but are
12
+ * still being used with a faceted filter (boolean, text, etc.).
13
+ */
14
+ staticOptions?: Option[];
15
+ /**
16
+ * Narrow the returned options to values that exist in rows passing every
17
+ * *other* active filter (the current column's own filter is excluded).
18
+ */
19
+ limitToFilteredRows: boolean;
20
+ /**
21
+ * Compute counts against filtered rows (again, excluding the current
22
+ * column's filter) rather than against the full core row model.
23
+ */
24
+ dynamicCounts: boolean;
25
+ /**
26
+ * When false, `count` is stripped from the output for a consistent shape.
27
+ */
28
+ showCounts: boolean;
29
+ /**
30
+ * When deriving options from rows, run labels through `formatLabel` (title
31
+ * case etc.). Ignored when `staticOptions` is provided — callers' labels
32
+ * are always preserved as-is.
33
+ */
34
+ autoOptionsFormat: boolean;
35
+ /**
36
+ * Optional per-column label formatter. Wins over `autoOptionsFormat` when
37
+ * present. Receives the stringified row value, returns the display label.
38
+ * Ignored when `staticOptions` is provided.
39
+ */
40
+ formatOptionLabel?: (value: string) => string;
41
+ }
42
+ /**
43
+ * Pure builder for the option list surfaced by a faceted filter. Handles
44
+ * both explicit `staticOptions` (narrow + enrich with counts) and
45
+ * row-derived options. Plain function (not a hook) so the wrapper can
46
+ * gate it behind a single `useMemo`.
47
+ */
48
+ export declare function buildFacetedOptions<TData extends RowData>(table: DataTableInstance<TData>, coreRows: DataTableRow<TData>[], accessorKey: string, columnFilters: Array<{
49
+ id: string;
50
+ value: unknown;
51
+ }>, globalFilter: unknown, config: BuildFacetedOptionsConfig): Option[];
52
+ /**
53
+ * Extract the set of selected values from a single column's filter value,
54
+ * tolerating every shape it can take: the `ExtendedColumnFilter` object written
55
+ * by the faceted control and the advanced menu (`{ value: string | string[] }`),
56
+ * and the legacy bare array / scalar.
57
+ */
58
+ export declare function extractFilterSelectedValues(rawValue: unknown): Set<string>;
59
+ //#endregion
@@ -0,0 +1,82 @@
1
+ import { formatLabel } from "./format.js";
2
+ import { getFilteredRowsExcludingColumn } from "./filter-rows.js";
3
+ //#region src/components/registry/niko-table/lib/build-faceted-options.ts
4
+ /**
5
+ * Pure builder for the option list surfaced by a faceted filter. Handles
6
+ * both explicit `staticOptions` (narrow + enrich with counts) and
7
+ * row-derived options. Plain function (not a hook) so the wrapper can
8
+ * gate it behind a single `useMemo`.
9
+ */
10
+ function buildFacetedOptions(table, coreRows, accessorKey, columnFilters, globalFilter, config) {
11
+ const { staticOptions, limitToFilteredRows, dynamicCounts, showCounts, autoOptionsFormat, formatOptionLabel } = config;
12
+ if (staticOptions && !limitToFilteredRows && !showCounts) return staticOptions.map((opt) => ({
13
+ ...opt,
14
+ count: void 0
15
+ }));
16
+ const filteredRows = limitToFilteredRows || dynamicCounts ? getFilteredRowsExcludingColumn(table, coreRows, accessorKey, columnFilters, globalFilter) : coreRows;
17
+ const optionRows = limitToFilteredRows ? filteredRows : coreRows;
18
+ const countRows = dynamicCounts ? filteredRows : coreRows;
19
+ const availableValues = collectRowValues(optionRows, accessorKey);
20
+ const selectedValues = getSelectedValues(columnFilters, accessorKey);
21
+ const keepValue = (value) => availableValues.has(value) || selectedValues.has(value);
22
+ let baseOptions;
23
+ if (staticOptions) baseOptions = limitToFilteredRows ? staticOptions.filter((opt) => keepValue(opt.value)) : staticOptions;
24
+ else {
25
+ const optionValues = limitToFilteredRows ? /* @__PURE__ */ new Set([...availableValues, ...selectedValues]) : availableValues;
26
+ baseOptions = Array.from(optionValues).map((value) => ({
27
+ value,
28
+ label: formatOptionLabel ? formatOptionLabel(value) : autoOptionsFormat ? formatLabel(value) : value
29
+ })).sort((a, b) => a.label.localeCompare(b.label));
30
+ }
31
+ if (!showCounts) return baseOptions.map((opt) => ({
32
+ ...opt,
33
+ count: void 0
34
+ }));
35
+ const targetValues = new Set(baseOptions.map((opt) => opt.value));
36
+ const valueCounts = /* @__PURE__ */ new Map();
37
+ for (const row of countRows) {
38
+ const raw = row.getValue(accessorKey);
39
+ const values = Array.isArray(raw) ? raw : [raw];
40
+ for (const v of values) {
41
+ if (v == null) continue;
42
+ const str = String(v);
43
+ if (!str) continue;
44
+ if (targetValues.has(str)) valueCounts.set(str, (valueCounts.get(str) ?? 0) + 1);
45
+ }
46
+ }
47
+ return baseOptions.map((opt) => ({
48
+ ...opt,
49
+ count: opt.count ?? valueCounts.get(opt.value) ?? 0
50
+ }));
51
+ }
52
+ /**
53
+ * Extract the set of selected values from a single column's filter value,
54
+ * tolerating every shape it can take: the `ExtendedColumnFilter` object written
55
+ * by the faceted control and the advanced menu (`{ value: string | string[] }`),
56
+ * and the legacy bare array / scalar.
57
+ */
58
+ function extractFilterSelectedValues(rawValue) {
59
+ let raw = rawValue;
60
+ if (raw && typeof raw === "object" && !Array.isArray(raw) && "value" in raw) raw = raw.value;
61
+ if (raw == null || raw === "") return /* @__PURE__ */ new Set();
62
+ return new Set((Array.isArray(raw) ? raw : [raw]).filter((v) => v != null && v !== "").map(String));
63
+ }
64
+ function getSelectedValues(columnFilters, accessorKey) {
65
+ const entry = columnFilters.find((filter) => filter.id === accessorKey);
66
+ return entry ? extractFilterSelectedValues(entry.value) : /* @__PURE__ */ new Set();
67
+ }
68
+ function collectRowValues(rows, accessorKey) {
69
+ const set = /* @__PURE__ */ new Set();
70
+ for (const row of rows) {
71
+ const raw = row.getValue(accessorKey);
72
+ const values = Array.isArray(raw) ? raw : [raw];
73
+ for (const v of values) {
74
+ if (v == null) continue;
75
+ const str = String(v);
76
+ if (str) set.add(str);
77
+ }
78
+ }
79
+ return set;
80
+ }
81
+ //#endregion
82
+ export { buildFacetedOptions, extractFilterSelectedValues };
@@ -0,0 +1,33 @@
1
+ import { DEFAULT_MAX_COLUMN_SIZE, DEFAULT_MIN_COLUMN_SIZE } from "./constants.js";
2
+ import { DataTableHeader } from "../types/index.js";
3
+ import * as React$1 from "react";
4
+ import { RowData } from "@tanstack/react-table";
5
+ //#region src/components/registry/niko-table/lib/column-resize-handle.d.ts
6
+ /**
7
+ * Drag-to-resize / double-click-to-autosize grip on a header's right edge.
8
+ * Keyboard-operable (WAI-ARIA window-splitter): focusable, Arrow Left/Right
9
+ * nudge the width (Shift = larger step), Enter autosizes; exposes
10
+ * `aria-value*`.
11
+ */
12
+ export interface DataTableColumnResizeHandleProps<TData extends RowData> {
13
+ header: DataTableHeader<TData, unknown>;
14
+ /**
15
+ * This column is currently the flex (fill) column. Flex columns have no width
16
+ * TanStack can drive, so they resize through a custom pointer drag that starts
17
+ * from the rendered width (no jump) and, on release, writes an explicit width
18
+ * — which pins the column and hands the fill to the next eligible column.
19
+ */
20
+ isFlex?: boolean;
21
+ /**
22
+ * Drive the resize preview line during a flex drag (from the DataTable
23
+ * context). Passed `{ resizingColumnId, deltaOffset }` while dragging, `null`
24
+ * on release.
25
+ */
26
+ setResizePreview?: (info: {
27
+ resizingColumnId: string | null;
28
+ deltaOffset: number;
29
+ } | null) => void;
30
+ }
31
+ export declare function DataTableColumnResizeHandle<TData extends RowData>({ header, isFlex, setResizePreview }: DataTableColumnResizeHandleProps<TData>): React$1.JSX.Element;
32
+ //#endregion
33
+ export { DEFAULT_MAX_COLUMN_SIZE, DEFAULT_MIN_COLUMN_SIZE };
@@ -0,0 +1,175 @@
1
+ "use client";
2
+ import { cn } from "../../../../lib/utils.js";
3
+ import { DEFAULT_MAX_COLUMN_SIZE, DEFAULT_MIN_COLUMN_SIZE } from "./constants.js";
4
+ import * as React$1 from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/components/registry/niko-table/lib/column-resize-handle.tsx
7
+ /**
8
+ * niko-table — created by Semir N. (Semkoo, https://github.com/Semkoo) with AI assistance.
9
+ *
10
+ * Before reporting anything: please check the changelog first.
11
+ * - In-repo: ./CHANGELOG.md
12
+ * - Docs site: https://niko-table.com/changelog
13
+ *
14
+ * Found a bug or have a fix? Open an issue or PR on GitHub so other
15
+ * users (and future LLMs reading this code) benefit:
16
+ * https://github.com/Semkoo/niko-table-registry
17
+ */
18
+ /**
19
+ * Drag-to-resize / double-click-to-autosize grip used by DataTableHeader and
20
+ * DataTableVirtualizedHeader when `enableColumnResizing` is on. Lives in core
21
+ * so both bodies can import it without pulling the opt-in marker package.
22
+ */
23
+ /** Room for cell chrome the text measurement doesn't cover. */
24
+ const AUTOSIZE_CELL_PADDING = 24;
25
+ const AUTOSIZE_HEADER_CHROME = 52;
26
+ /** Keyboard resize step (px); the larger step applies while Shift is held. */
27
+ const KEYBOARD_RESIZE_STEP = 8;
28
+ const KEYBOARD_RESIZE_STEP_LARGE = 40;
29
+ /**
30
+ * Tightest width that fits every TEXT node in an element. Uses a DOM Range
31
+ * so `w-full` + `truncate` wrappers — whose `scrollWidth` echoes the current
32
+ * cell width — don't hide the natural content width. Autosize can grow AND
33
+ * shrink to fit.
34
+ */
35
+ function widestTextWidth(el) {
36
+ const range = document.createRange();
37
+ const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
38
+ let max = 0;
39
+ for (let n = walker.nextNode(); n; n = walker.nextNode()) {
40
+ if (!n.textContent || n.textContent.trim() === "") continue;
41
+ range.selectNodeContents(n);
42
+ max = Math.max(max, range.getBoundingClientRect().width);
43
+ }
44
+ return max;
45
+ }
46
+ /**
47
+ * Autosize a column to fit its content — measures the widest rendered
48
+ * cell/header text (mounted cells only — for virtualized tables, what's on
49
+ * screen) and sets that column's size.
50
+ */
51
+ function autosizeColumn(header, handle) {
52
+ const root = handle.closest("[data-slot=\"table\"]");
53
+ if (!root) return;
54
+ const cells = root.querySelectorAll(`[data-col-id="${CSS.escape(header.column.id)}"]`);
55
+ let content = 0;
56
+ cells.forEach((c) => {
57
+ const chrome = c.getAttribute("data-slot") === "table-head" ? AUTOSIZE_HEADER_CHROME : AUTOSIZE_CELL_PADDING;
58
+ content = Math.max(content, widestTextWidth(c) + chrome);
59
+ });
60
+ if (content <= 0) return;
61
+ const def = header.column.columnDef;
62
+ const width = Math.min(Math.max(Math.ceil(content), def.minSize ?? 40), def.maxSize ?? 1e3);
63
+ header.getContext().table.setColumnSizing((prev) => ({
64
+ ...prev,
65
+ [header.column.id]: width
66
+ }));
67
+ }
68
+ function DataTableColumnResizeHandle({ header, isFlex = false, setResizePreview }) {
69
+ const isResizing = header.column.getIsResizing();
70
+ const resize = header.getResizeHandler();
71
+ const def = header.column.columnDef;
72
+ const min = def.minSize ?? 40;
73
+ const max = def.maxSize ?? 1e3;
74
+ const [focusedWidth, setFocusedWidth] = React$1.useState(null);
75
+ const hasExplicitWidth = header.getContext().table.atoms.columnSizing?.get()?.[header.column.id] != null;
76
+ const ariaValueNow = Math.round(hasExplicitWidth ? header.column.getSize() : focusedWidth ?? header.column.getSize());
77
+ const nudge = (delta, fallbackWidth) => {
78
+ header.getContext().table.setColumnSizing((prev) => {
79
+ const current = prev[header.column.id] ?? fallbackWidth ?? header.column.getSize();
80
+ const next = Math.min(Math.max(current + delta, min), max);
81
+ return {
82
+ ...prev,
83
+ [header.column.id]: next
84
+ };
85
+ });
86
+ };
87
+ const flexDragTeardownRef = React$1.useRef(null);
88
+ React$1.useEffect(() => () => flexDragTeardownRef.current?.(), []);
89
+ const startFlexResize = (startClientX, handleEl) => {
90
+ const thEl = handleEl?.closest("[data-col-id]");
91
+ if (!thEl || !setResizePreview) return;
92
+ const startWidth = thEl.getBoundingClientRect().width;
93
+ const id = header.column.id;
94
+ setResizePreview({
95
+ resizingColumnId: id,
96
+ deltaOffset: 0
97
+ });
98
+ const onMove = (ev) => {
99
+ setResizePreview({
100
+ resizingColumnId: id,
101
+ deltaOffset: ev.clientX - startClientX
102
+ });
103
+ };
104
+ const teardown = () => {
105
+ flexDragTeardownRef.current = null;
106
+ window.removeEventListener("pointermove", onMove);
107
+ window.removeEventListener("pointerup", onUp);
108
+ window.removeEventListener("pointercancel", onCancel);
109
+ setResizePreview(null);
110
+ };
111
+ flexDragTeardownRef.current = teardown;
112
+ const onUp = (ev) => {
113
+ const next = Math.min(Math.max(startWidth + (ev.clientX - startClientX), min), max);
114
+ header.getContext().table.setColumnSizing((prev) => ({
115
+ ...prev,
116
+ [id]: next
117
+ }));
118
+ teardown();
119
+ };
120
+ const onCancel = () => teardown();
121
+ window.addEventListener("pointermove", onMove);
122
+ window.addEventListener("pointerup", onUp);
123
+ window.addEventListener("pointercancel", onCancel);
124
+ };
125
+ return /* @__PURE__ */ jsx("div", {
126
+ "data-slot": "column-resize-handle",
127
+ role: "separator",
128
+ "aria-orientation": "vertical",
129
+ "aria-label": "Resize column (arrow keys, or double-click to fit)",
130
+ "aria-valuenow": ariaValueNow,
131
+ "aria-valuemin": min,
132
+ "aria-valuemax": Math.max(max, ariaValueNow),
133
+ tabIndex: 0,
134
+ onFocus: (e) => {
135
+ const width = e.currentTarget.closest("[data-col-id]")?.getBoundingClientRect().width;
136
+ setFocusedWidth(width ?? null);
137
+ },
138
+ onBlur: () => setFocusedWidth(null),
139
+ onMouseDown: (e) => {
140
+ e.stopPropagation();
141
+ if (!isFlex) resize(e);
142
+ },
143
+ onTouchStart: (e) => {
144
+ e.stopPropagation();
145
+ if (!isFlex) resize(e);
146
+ },
147
+ onDoubleClick: (e) => autosizeColumn(header, e.currentTarget),
148
+ onClick: (e) => e.stopPropagation(),
149
+ onPointerDown: (e) => {
150
+ e.stopPropagation();
151
+ if (isFlex) {
152
+ e.preventDefault();
153
+ startFlexResize(e.clientX, e.currentTarget);
154
+ }
155
+ },
156
+ onKeyDown: (e) => {
157
+ const step = e.shiftKey ? KEYBOARD_RESIZE_STEP_LARGE : KEYBOARD_RESIZE_STEP;
158
+ const fallbackWidth = isFlex ? e.currentTarget.closest("[data-col-id]")?.getBoundingClientRect().width : void 0;
159
+ if (e.key === "ArrowLeft") {
160
+ e.preventDefault();
161
+ nudge(-step, fallbackWidth);
162
+ } else if (e.key === "ArrowRight") {
163
+ e.preventDefault();
164
+ nudge(step, fallbackWidth);
165
+ } else if (e.key === "Enter") {
166
+ e.preventDefault();
167
+ autosizeColumn(header, e.currentTarget);
168
+ }
169
+ },
170
+ className: "group/resize absolute top-0 right-0 z-10 flex h-full w-2 cursor-col-resize touch-none justify-end outline-none select-none",
171
+ children: /* @__PURE__ */ jsx("div", { className: cn("my-1.5 w-px rounded bg-border opacity-0 transition-all", "group-hover/resize:my-0 group-hover/resize:w-0.5 group-hover/resize:bg-primary group-hover/resize:opacity-100", "group-focus-visible/resize:my-0 group-focus-visible/resize:w-0.5 group-focus-visible/resize:bg-primary group-focus-visible/resize:opacity-100", isResizing && "my-0 w-0.5 bg-primary opacity-100") })
172
+ });
173
+ }
174
+ //#endregion
175
+ export { DEFAULT_MAX_COLUMN_SIZE, DEFAULT_MIN_COLUMN_SIZE, DataTableColumnResizeHandle };
@@ -0,0 +1,128 @@
1
+ //#region src/components/registry/niko-table/lib/constants.d.ts
2
+ export declare const JOIN_OPERATORS: {
3
+ /** Logical AND (all filters must match) */
4
+ readonly AND: "and";
5
+ /** Logical OR (any filter can match) */
6
+ readonly OR: "or";
7
+ /** Mixed logic (combination of AND/OR) */
8
+ readonly MIXED: "mixed";
9
+ };
10
+ /**
11
+ * Filter operator constants defining the comparison logic.
12
+ * Naming follows SQL/PostgREST standards (ilike, eq, ne, etc.).
13
+ */
14
+ export declare const FILTER_OPERATORS: {
15
+ /** SQL ILIKE (Case-insensitive search) */
16
+ readonly ILIKE: "ilike";
17
+ /** SQL NOT ILIKE */
18
+ readonly NOT_ILIKE: "not.ilike";
19
+ /** SQL EQUAL (=) */
20
+ readonly EQ: "eq";
21
+ /** SQL NOT EQUAL (!=) */
22
+ readonly NEQ: "neq";
23
+ /** SQL IN (one of) */
24
+ readonly IN: "in";
25
+ /** SQL NOT IN (none of) */
26
+ readonly NOT_IN: "not.in";
27
+ /** Value is null or empty string */
28
+ readonly EMPTY: "empty";
29
+ /** Value is not null and not empty string */
30
+ readonly NOT_EMPTY: "not.empty";
31
+ /** SQL LESS THAN (<) */
32
+ readonly LT: "lt";
33
+ /** SQL LESS THAN OR EQUAL (<=) */
34
+ readonly LTE: "lte";
35
+ /** SQL GREATER THAN (>) */
36
+ readonly GT: "gt";
37
+ /** SQL GREATER THAN OR EQUAL (>=) */
38
+ readonly GTE: "gte";
39
+ /** SQL BETWEEN (range) */
40
+ readonly BETWEEN: "between";
41
+ /** Relative date calculation (e.g., "today", "last-7-days") */
42
+ readonly RELATIVE: "relative";
43
+ };
44
+ /**
45
+ * Filter variant constants defining the UI control type.
46
+ */
47
+ export declare const FILTER_VARIANTS: {
48
+ /** Standard text input */
49
+ readonly TEXT: "text";
50
+ /** Numeric input */
51
+ readonly NUMBER: "number";
52
+ /** Two-value range input */
53
+ readonly RANGE: "range";
54
+ /** Single date picker */
55
+ readonly DATE: "date";
56
+ /** Date range picker */
57
+ readonly DATE_RANGE: "dateRange";
58
+ /** Single select dropdown */
59
+ readonly SELECT: "select";
60
+ /** Multi-select dropdown */
61
+ readonly MULTI_SELECT: "multiSelect";
62
+ /** Checkbox or toggle */
63
+ readonly BOOLEAN: "boolean";
64
+ };
65
+ /** Join operators for combining multiple filters */
66
+ export type JoinOperator = (typeof JOIN_OPERATORS)[keyof typeof JOIN_OPERATORS];
67
+ /** Filter operators supported by the data table */
68
+ export type FilterOperator = (typeof FILTER_OPERATORS)[keyof typeof FILTER_OPERATORS];
69
+ /** Filter variants supported by the data table (UI control type) */
70
+ export type FilterVariant = (typeof FILTER_VARIANTS)[keyof typeof FILTER_VARIANTS];
71
+ /** Global default values */
72
+ export declare const DEFAULT_VALUES: {
73
+ readonly JOIN_OPERATOR: "and";
74
+ readonly PAGE_SIZE: 10;
75
+ readonly PAGE_INDEX: 0;
76
+ };
77
+ /** System column IDs - used for smart pinning and feature detection */
78
+ export declare const SYSTEM_COLUMN_IDS: {
79
+ /** Row selection checkbox column */
80
+ readonly SELECT: "select";
81
+ /** Row expand/collapse column */
82
+ readonly EXPAND: "expand";
83
+ /** Row actions column (edit, delete, etc.) */
84
+ readonly ACTIONS: "actions";
85
+ };
86
+ /** Array of all system column IDs for filtering */
87
+ export declare const SYSTEM_COLUMN_ID_LIST: string[];
88
+ /** UI-related constraints and settings */
89
+ export declare const UI_CONSTANTS: {
90
+ /** Max characters allowed for a filter ID */
91
+ readonly FILTER_ID_MAX_LENGTH: 100;
92
+ /** Default max height for scrollable filter popovers */
93
+ readonly MAX_FILTER_DISPLAY_HEIGHT: 300;
94
+ /** Default debounce delay in milliseconds for search inputs */
95
+ readonly DEBOUNCE_DELAY: 300;
96
+ };
97
+ /** Default keyboard shortcut key mappings */
98
+ export declare const KEYBOARD_SHORTCUTS: {
99
+ /** Open/Toggle filter menu */
100
+ readonly FILTER_TOGGLE: "f";
101
+ /** Remove active filter (usually combined with Shift) */
102
+ readonly FILTER_REMOVE: "f";
103
+ /** Close active UI elements */
104
+ readonly ESCAPE: "escape";
105
+ /** Confirm or submit active action */
106
+ readonly ENTER: "enter";
107
+ /** Remove character or navigate back */
108
+ readonly BACKSPACE: "backspace";
109
+ /** Item deletion */
110
+ readonly DELETE: "delete";
111
+ };
112
+ /**
113
+ * Default column width bounds when a column omits `minSize` / `maxSize`.
114
+ * Shared by `DataTableRoot` (defaultColumn) and the resize handle clamp —
115
+ * keep these in constants so root does not import the resize-handle module.
116
+ */
117
+ export declare const DEFAULT_MIN_COLUMN_SIZE = 40;
118
+ export declare const DEFAULT_MAX_COLUMN_SIZE = 1000;
119
+ /** Standard internalized error messages */
120
+ export declare const ERROR_MESSAGES: {
121
+ /** Thrown when using the old global operator pattern */
122
+ readonly DEPRECATED_GLOBAL_JOIN_OPERATOR: "Global join operator is deprecated. Use individual filter join operators.";
123
+ /** General configuration error */
124
+ readonly INVALID_FILTER_CONFIGURATION: "Invalid filter configuration provided.";
125
+ /** Thrown when mandatory metadata is missing from columns */
126
+ readonly MISSING_COLUMN_META: "Column metadata is required for filtering.";
127
+ };
128
+ //#endregion