@shadng/sng-ui 1.0.0

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 (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +75 -0
  3. package/cli/sng-ui.js +331 -0
  4. package/ng-package.json +29 -0
  5. package/package.json +64 -0
  6. package/registry.json +72 -0
  7. package/src/lib/accordion/cn.ts +6 -0
  8. package/src/lib/accordion/index.ts +18 -0
  9. package/src/lib/accordion/sng-accordion-content.ts +131 -0
  10. package/src/lib/accordion/sng-accordion-item.ts +299 -0
  11. package/src/lib/accordion/sng-accordion-trigger.ts +137 -0
  12. package/src/lib/accordion/sng-accordion.ts +118 -0
  13. package/src/lib/accordion/sng-accordion.types.ts +82 -0
  14. package/src/lib/alert/cn.ts +6 -0
  15. package/src/lib/alert/index.ts +3 -0
  16. package/src/lib/alert/sng-alert-description.ts +49 -0
  17. package/src/lib/alert/sng-alert-title.ts +46 -0
  18. package/src/lib/alert/sng-alert.ts +48 -0
  19. package/src/lib/avatar/cn.ts +6 -0
  20. package/src/lib/avatar/index.ts +3 -0
  21. package/src/lib/avatar/sng-avatar-fallback.ts +50 -0
  22. package/src/lib/avatar/sng-avatar-image.ts +73 -0
  23. package/src/lib/avatar/sng-avatar.ts +60 -0
  24. package/src/lib/badge/cn.ts +6 -0
  25. package/src/lib/badge/index.ts +1 -0
  26. package/src/lib/badge/sng-badge.ts +36 -0
  27. package/src/lib/breadcrumb/cn.ts +6 -0
  28. package/src/lib/breadcrumb/index.ts +7 -0
  29. package/src/lib/breadcrumb/sng-breadcrumb-ellipsis.ts +61 -0
  30. package/src/lib/breadcrumb/sng-breadcrumb-item.ts +47 -0
  31. package/src/lib/breadcrumb/sng-breadcrumb-link.ts +43 -0
  32. package/src/lib/breadcrumb/sng-breadcrumb-list.ts +42 -0
  33. package/src/lib/breadcrumb/sng-breadcrumb-page.ts +44 -0
  34. package/src/lib/breadcrumb/sng-breadcrumb-separator.ts +60 -0
  35. package/src/lib/breadcrumb/sng-breadcrumb.ts +52 -0
  36. package/src/lib/button/cn.ts +6 -0
  37. package/src/lib/button/index.ts +2 -0
  38. package/src/lib/button/sng-button.ts +264 -0
  39. package/src/lib/calendar/cn.ts +6 -0
  40. package/src/lib/calendar/index.ts +2 -0
  41. package/src/lib/calendar/sng-calendar.ts +753 -0
  42. package/src/lib/card/cn.ts +6 -0
  43. package/src/lib/card/index.ts +6 -0
  44. package/src/lib/card/sng-card-content.ts +36 -0
  45. package/src/lib/card/sng-card-description.ts +38 -0
  46. package/src/lib/card/sng-card-footer.ts +34 -0
  47. package/src/lib/card/sng-card-header.ts +34 -0
  48. package/src/lib/card/sng-card-title.ts +48 -0
  49. package/src/lib/card/sng-card.ts +43 -0
  50. package/src/lib/carousel/cn.ts +6 -0
  51. package/src/lib/carousel/index.ts +18 -0
  52. package/src/lib/carousel/sng-carousel.ts +526 -0
  53. package/src/lib/checkbox/cn.ts +6 -0
  54. package/src/lib/checkbox/index.ts +1 -0
  55. package/src/lib/checkbox/sng-checkbox.ts +154 -0
  56. package/src/lib/code-block/cn.ts +6 -0
  57. package/src/lib/code-block/index.ts +1 -0
  58. package/src/lib/code-block/sng-code-block.ts +296 -0
  59. package/src/lib/dialog/cn.ts +6 -0
  60. package/src/lib/dialog/index.ts +37 -0
  61. package/src/lib/dialog/sng-dialog-close.ts +76 -0
  62. package/src/lib/dialog/sng-dialog-content.ts +132 -0
  63. package/src/lib/dialog/sng-dialog-description.ts +36 -0
  64. package/src/lib/dialog/sng-dialog-footer.ts +39 -0
  65. package/src/lib/dialog/sng-dialog-header.ts +39 -0
  66. package/src/lib/dialog/sng-dialog-title.ts +52 -0
  67. package/src/lib/dialog/sng-dialog.service.ts +222 -0
  68. package/src/lib/dialog/sng-dialog.ts +224 -0
  69. package/src/lib/drawer/cn.ts +6 -0
  70. package/src/lib/drawer/index.ts +36 -0
  71. package/src/lib/drawer/sng-drawer-close.ts +28 -0
  72. package/src/lib/drawer/sng-drawer-content.ts +135 -0
  73. package/src/lib/drawer/sng-drawer-description.ts +29 -0
  74. package/src/lib/drawer/sng-drawer-footer.ts +34 -0
  75. package/src/lib/drawer/sng-drawer-handle.ts +30 -0
  76. package/src/lib/drawer/sng-drawer-header.ts +30 -0
  77. package/src/lib/drawer/sng-drawer-title.ts +27 -0
  78. package/src/lib/drawer/sng-drawer-trigger.ts +21 -0
  79. package/src/lib/drawer/sng-drawer-wrapper.ts +27 -0
  80. package/src/lib/drawer/sng-drawer.ts +166 -0
  81. package/src/lib/file-input/cn.ts +6 -0
  82. package/src/lib/file-input/index.ts +1 -0
  83. package/src/lib/file-input/sng-file-input.ts +288 -0
  84. package/src/lib/hover-card/cn.ts +6 -0
  85. package/src/lib/hover-card/index.ts +3 -0
  86. package/src/lib/hover-card/sng-hover-card-content.ts +100 -0
  87. package/src/lib/hover-card/sng-hover-card-trigger.ts +43 -0
  88. package/src/lib/hover-card/sng-hover-card.ts +246 -0
  89. package/src/lib/input/cn.ts +6 -0
  90. package/src/lib/input/index.ts +1 -0
  91. package/src/lib/input/sng-input.ts +160 -0
  92. package/src/lib/layout/cn.ts +6 -0
  93. package/src/lib/layout/index.ts +98 -0
  94. package/src/lib/layout/sng-layout-footer.ts +37 -0
  95. package/src/lib/layout/sng-layout-header.ts +38 -0
  96. package/src/lib/layout/sng-layout-sidebar-content.ts +149 -0
  97. package/src/lib/layout/sng-layout-sidebar-footer.ts +54 -0
  98. package/src/lib/layout/sng-layout-sidebar-group-action.ts +67 -0
  99. package/src/lib/layout/sng-layout-sidebar-group-content.ts +41 -0
  100. package/src/lib/layout/sng-layout-sidebar-group-label.ts +53 -0
  101. package/src/lib/layout/sng-layout-sidebar-group.ts +41 -0
  102. package/src/lib/layout/sng-layout-sidebar-header.ts +54 -0
  103. package/src/lib/layout/sng-layout-sidebar-input.ts +112 -0
  104. package/src/lib/layout/sng-layout-sidebar-inset.ts +45 -0
  105. package/src/lib/layout/sng-layout-sidebar-menu-action.ts +84 -0
  106. package/src/lib/layout/sng-layout-sidebar-menu-badge.ts +47 -0
  107. package/src/lib/layout/sng-layout-sidebar-menu-button.ts +160 -0
  108. package/src/lib/layout/sng-layout-sidebar-menu-item.ts +40 -0
  109. package/src/lib/layout/sng-layout-sidebar-menu-skeleton.ts +71 -0
  110. package/src/lib/layout/sng-layout-sidebar-menu-sub-button.ts +142 -0
  111. package/src/lib/layout/sng-layout-sidebar-menu-sub-item.ts +38 -0
  112. package/src/lib/layout/sng-layout-sidebar-menu-sub.ts +48 -0
  113. package/src/lib/layout/sng-layout-sidebar-menu.ts +41 -0
  114. package/src/lib/layout/sng-layout-sidebar-provider.ts +189 -0
  115. package/src/lib/layout/sng-layout-sidebar-rail.ts +60 -0
  116. package/src/lib/layout/sng-layout-sidebar-separator.ts +38 -0
  117. package/src/lib/layout/sng-layout-sidebar-trigger.ts +97 -0
  118. package/src/lib/layout/sng-layout-sidebar.ts +254 -0
  119. package/src/lib/menu/cn.ts +6 -0
  120. package/src/lib/menu/index.ts +21 -0
  121. package/src/lib/menu/sng-context-trigger.ts +128 -0
  122. package/src/lib/menu/sng-menu-checkbox-item.ts +91 -0
  123. package/src/lib/menu/sng-menu-item.ts +80 -0
  124. package/src/lib/menu/sng-menu-label.ts +47 -0
  125. package/src/lib/menu/sng-menu-radio-group.ts +38 -0
  126. package/src/lib/menu/sng-menu-radio-item.ts +94 -0
  127. package/src/lib/menu/sng-menu-separator.ts +27 -0
  128. package/src/lib/menu/sng-menu-shortcut.ts +25 -0
  129. package/src/lib/menu/sng-menu-sub-content.ts +267 -0
  130. package/src/lib/menu/sng-menu-sub-trigger.ts +68 -0
  131. package/src/lib/menu/sng-menu-sub.ts +124 -0
  132. package/src/lib/menu/sng-menu-tokens.ts +52 -0
  133. package/src/lib/menu/sng-menu-trigger.ts +266 -0
  134. package/src/lib/menu/sng-menu.ts +100 -0
  135. package/src/lib/nav-menu/cn.ts +6 -0
  136. package/src/lib/nav-menu/index.ts +6 -0
  137. package/src/lib/nav-menu/sng-nav-menu-content.ts +72 -0
  138. package/src/lib/nav-menu/sng-nav-menu-item.ts +109 -0
  139. package/src/lib/nav-menu/sng-nav-menu-link.ts +54 -0
  140. package/src/lib/nav-menu/sng-nav-menu-list.ts +43 -0
  141. package/src/lib/nav-menu/sng-nav-menu-trigger.ts +98 -0
  142. package/src/lib/nav-menu/sng-nav-menu.ts +99 -0
  143. package/src/lib/otp-input/cn.ts +6 -0
  144. package/src/lib/otp-input/index.ts +14 -0
  145. package/src/lib/otp-input/sng-otp-input-group.ts +38 -0
  146. package/src/lib/otp-input/sng-otp-input-separator.ts +43 -0
  147. package/src/lib/otp-input/sng-otp-input-slot.ts +128 -0
  148. package/src/lib/otp-input/sng-otp-input-tokens.ts +20 -0
  149. package/src/lib/otp-input/sng-otp-input.ts +301 -0
  150. package/src/lib/popover/cn.ts +6 -0
  151. package/src/lib/popover/index.ts +3 -0
  152. package/src/lib/popover/sng-popover-content.ts +66 -0
  153. package/src/lib/popover/sng-popover-trigger.ts +44 -0
  154. package/src/lib/popover/sng-popover.ts +218 -0
  155. package/src/lib/preview-box/cn.ts +6 -0
  156. package/src/lib/preview-box/index.ts +5 -0
  157. package/src/lib/preview-box/sng-code-block.ts +80 -0
  158. package/src/lib/preview-box/sng-html-block.ts +79 -0
  159. package/src/lib/preview-box/sng-preview-block.ts +47 -0
  160. package/src/lib/preview-box/sng-preview-box.ts +369 -0
  161. package/src/lib/preview-box/sng-style-block.ts +80 -0
  162. package/src/lib/progress/cn.ts +6 -0
  163. package/src/lib/progress/index.ts +1 -0
  164. package/src/lib/progress/sng-progress.ts +65 -0
  165. package/src/lib/radio/cn.ts +6 -0
  166. package/src/lib/radio/index.ts +5 -0
  167. package/src/lib/radio/sng-radio-item.ts +100 -0
  168. package/src/lib/radio/sng-radio.ts +54 -0
  169. package/src/lib/resizable/cn.ts +6 -0
  170. package/src/lib/resizable/index.ts +3 -0
  171. package/src/lib/resizable/sng-resizable-group.ts +188 -0
  172. package/src/lib/resizable/sng-resizable-handle.ts +236 -0
  173. package/src/lib/resizable/sng-resizable-panel.ts +71 -0
  174. package/src/lib/search-input/cn.ts +6 -0
  175. package/src/lib/search-input/index.ts +16 -0
  176. package/src/lib/search-input/sng-search-input-context.ts +24 -0
  177. package/src/lib/search-input/sng-search-input-empty.ts +42 -0
  178. package/src/lib/search-input/sng-search-input-group.ts +69 -0
  179. package/src/lib/search-input/sng-search-input-item.ts +164 -0
  180. package/src/lib/search-input/sng-search-input-list.ts +34 -0
  181. package/src/lib/search-input/sng-search-input-separator.ts +32 -0
  182. package/src/lib/search-input/sng-search-input-shortcut.ts +29 -0
  183. package/src/lib/search-input/sng-search-input.ts +368 -0
  184. package/src/lib/select/cn.ts +6 -0
  185. package/src/lib/select/index.ts +7 -0
  186. package/src/lib/select/sng-select-content.ts +27 -0
  187. package/src/lib/select/sng-select-empty.ts +48 -0
  188. package/src/lib/select/sng-select-group.ts +29 -0
  189. package/src/lib/select/sng-select-item.ts +140 -0
  190. package/src/lib/select/sng-select-label.ts +29 -0
  191. package/src/lib/select/sng-select-separator.ts +29 -0
  192. package/src/lib/select/sng-select.ts +326 -0
  193. package/src/lib/separator/cn.ts +6 -0
  194. package/src/lib/separator/index.ts +1 -0
  195. package/src/lib/separator/sng-separator.ts +40 -0
  196. package/src/lib/skeleton/cn.ts +6 -0
  197. package/src/lib/skeleton/index.ts +1 -0
  198. package/src/lib/skeleton/sng-skeleton.ts +49 -0
  199. package/src/lib/slider/cn.ts +6 -0
  200. package/src/lib/slider/index.ts +2 -0
  201. package/src/lib/slider/sng-slider.ts +137 -0
  202. package/src/lib/sng-table/cn.ts +6 -0
  203. package/src/lib/sng-table/flex-render.ts +222 -0
  204. package/src/lib/sng-table/index.ts +85 -0
  205. package/src/lib/sng-table/sng-table-body.ts +59 -0
  206. package/src/lib/sng-table/sng-table-caption.ts +49 -0
  207. package/src/lib/sng-table/sng-table-cell.ts +62 -0
  208. package/src/lib/sng-table/sng-table-footer.ts +60 -0
  209. package/src/lib/sng-table/sng-table-head.ts +66 -0
  210. package/src/lib/sng-table/sng-table-header.ts +48 -0
  211. package/src/lib/sng-table/sng-table-pagination.ts +265 -0
  212. package/src/lib/sng-table/sng-table-row.ts +65 -0
  213. package/src/lib/sng-table/sng-table.ts +67 -0
  214. package/src/lib/sng-table-core/core/create-cell.ts +117 -0
  215. package/src/lib/sng-table-core/core/create-column.ts +266 -0
  216. package/src/lib/sng-table-core/core/create-header.ts +271 -0
  217. package/src/lib/sng-table-core/core/create-row.ts +293 -0
  218. package/src/lib/sng-table-core/core/create-table.ts +534 -0
  219. package/src/lib/sng-table-core/core/types.ts +1197 -0
  220. package/src/lib/sng-table-core/core/utils.ts +307 -0
  221. package/src/lib/sng-table-core/features/column-filtering.ts +376 -0
  222. package/src/lib/sng-table-core/features/column-ordering.ts +159 -0
  223. package/src/lib/sng-table-core/features/column-pinning.ts +219 -0
  224. package/src/lib/sng-table-core/features/column-sizing.ts +268 -0
  225. package/src/lib/sng-table-core/features/column-visibility.ts +128 -0
  226. package/src/lib/sng-table-core/features/faceting.ts +279 -0
  227. package/src/lib/sng-table-core/features/fuzzy-filtering.ts +188 -0
  228. package/src/lib/sng-table-core/features/global-filtering.ts +128 -0
  229. package/src/lib/sng-table-core/features/pagination.ts +179 -0
  230. package/src/lib/sng-table-core/features/row-expanding.ts +181 -0
  231. package/src/lib/sng-table-core/features/row-grouping.ts +235 -0
  232. package/src/lib/sng-table-core/features/row-pinning.ts +196 -0
  233. package/src/lib/sng-table-core/features/row-selection.ts +298 -0
  234. package/src/lib/sng-table-core/features/sorting.ts +425 -0
  235. package/src/lib/sng-table-core/features/virtualization.ts +298 -0
  236. package/src/lib/sng-table-core/index.ts +235 -0
  237. package/src/lib/sng-table-core/row-models/core-row-model.ts +256 -0
  238. package/src/lib/sng-table-core/row-models/expanded-row-model.ts +175 -0
  239. package/src/lib/sng-table-core/row-models/filtered-row-model.ts +307 -0
  240. package/src/lib/sng-table-core/row-models/grouped-row-model.ts +290 -0
  241. package/src/lib/sng-table-core/row-models/paginated-row-model.ts +135 -0
  242. package/src/lib/sng-table-core/row-models/sorted-row-model.ts +197 -0
  243. package/src/lib/styles/sng-themes.css +164 -0
  244. package/src/lib/switch/cn.ts +6 -0
  245. package/src/lib/switch/index.ts +1 -0
  246. package/src/lib/switch/sng-switch.ts +137 -0
  247. package/src/lib/tabs/cn.ts +6 -0
  248. package/src/lib/tabs/index.ts +4 -0
  249. package/src/lib/tabs/sng-tabs-content.ts +66 -0
  250. package/src/lib/tabs/sng-tabs-list.ts +55 -0
  251. package/src/lib/tabs/sng-tabs-trigger.ts +86 -0
  252. package/src/lib/tabs/sng-tabs.ts +83 -0
  253. package/src/lib/toast/cn.ts +6 -0
  254. package/src/lib/toast/index.ts +3 -0
  255. package/src/lib/toast/sng-toast.service.ts +258 -0
  256. package/src/lib/toast/sng-toast.ts +101 -0
  257. package/src/lib/toast/sng-toaster.ts +67 -0
  258. package/src/lib/toggle/cn.ts +6 -0
  259. package/src/lib/toggle/index.ts +6 -0
  260. package/src/lib/toggle/sng-toggle-group-item.ts +89 -0
  261. package/src/lib/toggle/sng-toggle-group.ts +85 -0
  262. package/src/lib/toggle/sng-toggle.ts +78 -0
  263. package/src/lib/toggle-group/index.ts +6 -0
  264. package/src/lib/tooltip/cn.ts +6 -0
  265. package/src/lib/tooltip/index.ts +5 -0
  266. package/src/lib/tooltip/sng-tooltip-content.ts +64 -0
  267. package/src/lib/tooltip/sng-tooltip.ts +216 -0
  268. package/src/public-api.ts +207 -0
  269. package/tsconfig.json +24 -0
  270. package/tsconfig.lib.json +17 -0
  271. package/tsconfig.lib.prod.json +11 -0
@@ -0,0 +1,256 @@
1
+ /**
2
+ * @fileoverview Core row model for sng-table-core
3
+ *
4
+ * The core row model is the foundation of all row processing.
5
+ * It takes raw data and converts it into Row instances.
6
+ */
7
+
8
+ import { Row, RowModel, Table, RowModelFn } from '../core/types';
9
+ import { buildRowsFromData, applyFeaturesToRow } from '../core/create-row';
10
+ import { memo, flattenBy } from '../core/utils';
11
+
12
+ // ============================================================================
13
+ // CORE ROW MODEL FACTORY
14
+ // ============================================================================
15
+
16
+ /**
17
+ * Factory function to create the core row model
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const table = createTable(() => ({
22
+ * data: myData,
23
+ * columns: myColumns,
24
+ * getCoreRowModel: getCoreRowModel(),
25
+ * }));
26
+ * ```
27
+ */
28
+ export function getCoreRowModel<TData>(): RowModelFn<TData> {
29
+ return (table: Table<TData>) => {
30
+ return memo(
31
+ // Dependencies - recompute when these change
32
+ () => [table.options.data],
33
+
34
+ // Compute function
35
+ () => buildCoreRowModel(table),
36
+
37
+ // Options
38
+ {
39
+ debug: table.options.debugRows,
40
+ debugLabel: 'getCoreRowModel',
41
+ }
42
+ );
43
+ };
44
+ }
45
+
46
+ // ============================================================================
47
+ // CORE ROW MODEL BUILDER
48
+ // ============================================================================
49
+
50
+ /**
51
+ * Build the core row model from data
52
+ */
53
+ function buildCoreRowModel<TData>(table: Table<TData>): RowModel<TData> {
54
+ const { data } = table.options;
55
+
56
+ // Build rows from data (without features applied yet)
57
+ const rows = buildRowsFromData(table, data);
58
+
59
+ // Flatten all rows (including sub-rows)
60
+ const flatRows = flattenBy(rows, (row) =>
61
+ row.subRows.length ? row.subRows : undefined
62
+ );
63
+
64
+ // Build rows by ID lookup
65
+ const rowsById: Record<string, Row<TData>> = {};
66
+ for (const row of flatRows) {
67
+ rowsById[row.id] = row;
68
+ }
69
+
70
+ // Apply features to all rows AFTER they're all built
71
+ // This prevents circular dependency during hierarchical row building
72
+ for (const row of flatRows) {
73
+ applyFeaturesToRow(row, table);
74
+ }
75
+
76
+ return {
77
+ rows,
78
+ flatRows,
79
+ rowsById,
80
+ };
81
+ }
82
+
83
+ // ============================================================================
84
+ // HELPER FUNCTIONS
85
+ // ============================================================================
86
+
87
+ /**
88
+ * Create an empty row model
89
+ */
90
+ export function createEmptyRowModel<TData>(): RowModel<TData> {
91
+ return {
92
+ rows: [],
93
+ flatRows: [],
94
+ rowsById: {},
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Filter rows while maintaining hierarchy
100
+ */
101
+ export function filterRows<TData>(
102
+ rows: Row<TData>[],
103
+ filterFn: (row: Row<TData>) => boolean,
104
+ options?: {
105
+ filterFromLeafRows?: boolean;
106
+ maxDepth?: number;
107
+ }
108
+ ): Row<TData>[] {
109
+ const { filterFromLeafRows = false, maxDepth = 100 } = options ?? {};
110
+
111
+ if (filterFromLeafRows) {
112
+ return filterRowsFromLeaves(rows, filterFn, maxDepth);
113
+ }
114
+
115
+ return filterRowsFromRoot(rows, filterFn, maxDepth);
116
+ }
117
+
118
+ /**
119
+ * Filter rows starting from root (parent-first)
120
+ * If parent matches, include all children
121
+ */
122
+ function filterRowsFromRoot<TData>(
123
+ rows: Row<TData>[],
124
+ filterFn: (row: Row<TData>) => boolean,
125
+ maxDepth: number,
126
+ currentDepth = 0
127
+ ): Row<TData>[] {
128
+ const result: Row<TData>[] = [];
129
+
130
+ for (const row of rows) {
131
+ const passes = filterFn(row);
132
+
133
+ if (passes) {
134
+ // Parent matches - include it with all sub-rows as-is
135
+ result.push(row);
136
+ } else if (currentDepth < maxDepth && row.subRows.length) {
137
+ // Parent doesn't match, but check children
138
+ const filteredSubRows = filterRowsFromRoot(
139
+ row.subRows,
140
+ filterFn,
141
+ maxDepth,
142
+ currentDepth + 1
143
+ );
144
+
145
+ if (filteredSubRows.length) {
146
+ // Some children match - create a copy of row with filtered children
147
+ result.push({
148
+ ...row,
149
+ subRows: filteredSubRows,
150
+ });
151
+ }
152
+ }
153
+ }
154
+
155
+ return result;
156
+ }
157
+
158
+ /**
159
+ * Filter rows starting from leaves (child-first)
160
+ * Include parent if any child matches
161
+ */
162
+ function filterRowsFromLeaves<TData>(
163
+ rows: Row<TData>[],
164
+ filterFn: (row: Row<TData>) => boolean,
165
+ maxDepth: number,
166
+ currentDepth = 0
167
+ ): Row<TData>[] {
168
+ const result: Row<TData>[] = [];
169
+
170
+ for (const row of rows) {
171
+ let filteredSubRows: Row<TData>[] = [];
172
+
173
+ if (currentDepth < maxDepth && row.subRows.length) {
174
+ // First, filter children
175
+ filteredSubRows = filterRowsFromLeaves(
176
+ row.subRows,
177
+ filterFn,
178
+ maxDepth,
179
+ currentDepth + 1
180
+ );
181
+ }
182
+
183
+ // Check if this row passes or has passing children
184
+ const passes = filterFn(row);
185
+
186
+ if (passes || filteredSubRows.length) {
187
+ result.push({
188
+ ...row,
189
+ subRows: filteredSubRows,
190
+ });
191
+ }
192
+ }
193
+
194
+ return result;
195
+ }
196
+
197
+ /**
198
+ * Sort rows while maintaining hierarchy
199
+ */
200
+ export function sortRows<TData>(
201
+ rows: Row<TData>[],
202
+ sortFn: (a: Row<TData>, b: Row<TData>) => number
203
+ ): Row<TData>[] {
204
+ // Sort this level
205
+ const sortedRows = [...rows].sort(sortFn);
206
+
207
+ // Recursively sort sub-rows
208
+ return sortedRows.map((row) => {
209
+ if (row.subRows.length) {
210
+ return {
211
+ ...row,
212
+ subRows: sortRows(row.subRows, sortFn),
213
+ };
214
+ }
215
+ return row;
216
+ });
217
+ }
218
+
219
+ /**
220
+ * Paginate rows (flat - doesn't handle hierarchy specially)
221
+ */
222
+ export function paginateRows<TData>(
223
+ rows: Row<TData>[],
224
+ pageIndex: number,
225
+ pageSize: number
226
+ ): Row<TData>[] {
227
+ const start = pageIndex * pageSize;
228
+ const end = start + pageSize;
229
+ return rows.slice(start, end);
230
+ }
231
+
232
+ /**
233
+ * Expand rows - include sub-rows of expanded rows in the flat list
234
+ */
235
+ export function expandRows<TData>(
236
+ rows: Row<TData>[],
237
+ isExpanded: (row: Row<TData>) => boolean
238
+ ): Row<TData>[] {
239
+ const result: Row<TData>[] = [];
240
+
241
+ function addRow(row: Row<TData>) {
242
+ result.push(row);
243
+
244
+ if (isExpanded(row) && row.subRows.length) {
245
+ for (const subRow of row.subRows) {
246
+ addRow(subRow);
247
+ }
248
+ }
249
+ }
250
+
251
+ for (const row of rows) {
252
+ addRow(row);
253
+ }
254
+
255
+ return result;
256
+ }
@@ -0,0 +1,175 @@
1
+ /**
2
+ * @fileoverview Expanded row model for sng-table-core
3
+ *
4
+ * Flattens expanded rows into a single list for rendering.
5
+ */
6
+
7
+ import { Row, RowModel, Table, RowModelFn, ExpandedState } from '../core/types';
8
+ import { memo } from '../core/utils';
9
+
10
+ // ============================================================================
11
+ // EXPANDED ROW MODEL FACTORY
12
+ // ============================================================================
13
+
14
+ /**
15
+ * Factory function to create the expanded row model
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const table = createTable(() => ({
20
+ * data: myData,
21
+ * columns: myColumns,
22
+ * getCoreRowModel: getCoreRowModel(),
23
+ * getExpandedRowModel: getExpandedRowModel(),
24
+ * enableExpanding: true,
25
+ * }));
26
+ * ```
27
+ */
28
+ export function getExpandedRowModel<TData>(): RowModelFn<TData> {
29
+ return (table: Table<TData>) => {
30
+ return memo(
31
+ // Dependencies
32
+ () => [
33
+ table.getState().expanded,
34
+ getPreExpandedRowModel(table),
35
+ ],
36
+
37
+ // Compute function
38
+ () => {
39
+ const { expanded } = table.getState();
40
+ const preExpandedRowModel = getPreExpandedRowModel(table);
41
+
42
+ // If no expansion state, return pre-expanded model
43
+ if (!expanded || (typeof expanded === 'object' && !Object.keys(expanded).length)) {
44
+ return preExpandedRowModel;
45
+ }
46
+
47
+ return buildExpandedRowModel(table, preExpandedRowModel, expanded);
48
+ },
49
+
50
+ // Options
51
+ {
52
+ debug: table.options.debugRows,
53
+ debugLabel: 'getExpandedRowModel',
54
+ }
55
+ );
56
+ };
57
+ }
58
+
59
+ // ============================================================================
60
+ // EXPANDED ROW MODEL BUILDER
61
+ // ============================================================================
62
+
63
+ /**
64
+ * Build the expanded row model
65
+ */
66
+ function buildExpandedRowModel<TData>(
67
+ table: Table<TData>,
68
+ rowModel: RowModel<TData>,
69
+ expanded: ExpandedState
70
+ ): RowModel<TData> {
71
+ const { paginateExpandedRows = true } = table.options;
72
+
73
+ // Expand rows
74
+ const expandedRows = expandRows(rowModel.rows, expanded, paginateExpandedRows);
75
+
76
+ // Flatten expanded rows
77
+ const flatRows = flattenExpandedRows(expandedRows, expanded);
78
+
79
+ // Build rows by ID lookup
80
+ const rowsById: Record<string, Row<TData>> = {};
81
+ for (const row of flatRows) {
82
+ rowsById[row.id] = row;
83
+ }
84
+
85
+ return {
86
+ rows: expandedRows,
87
+ flatRows,
88
+ rowsById,
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Get the row model before expansion (sorted or filtered or core)
94
+ */
95
+ function getPreExpandedRowModel<TData>(table: Table<TData>): RowModel<TData> {
96
+ // Pipeline: core -> filtered -> sorted -> expanded -> paginated
97
+ // We want the model just before expanded
98
+
99
+ // Try sorted first
100
+ if (table.getSortedRowModel) {
101
+ return table.getSortedRowModel();
102
+ }
103
+
104
+ // Then filtered
105
+ if (table.getFilteredRowModel) {
106
+ return table.getFilteredRowModel();
107
+ }
108
+
109
+ // Finally core
110
+ return table.getCoreRowModel();
111
+ }
112
+
113
+ /**
114
+ * Expand rows based on expanded state
115
+ */
116
+ function expandRows<TData>(
117
+ rows: Row<TData>[],
118
+ expanded: ExpandedState,
119
+ paginateExpandedRows: boolean
120
+ ): Row<TData>[] {
121
+ if (!paginateExpandedRows) {
122
+ // If not paginating expanded rows, just return as-is
123
+ // The pagination will handle expansion
124
+ return rows;
125
+ }
126
+
127
+ // Otherwise, we need to include sub-rows in the row list for pagination
128
+ const result: Row<TData>[] = [];
129
+
130
+ function processRow(row: Row<TData>) {
131
+ result.push(row);
132
+
133
+ const isExpanded = expanded === true || (expanded as Record<string, boolean>)[row.id];
134
+
135
+ if (isExpanded && row.subRows.length) {
136
+ for (const subRow of row.subRows) {
137
+ processRow(subRow);
138
+ }
139
+ }
140
+ }
141
+
142
+ for (const row of rows) {
143
+ processRow(row);
144
+ }
145
+
146
+ return result;
147
+ }
148
+
149
+ /**
150
+ * Flatten expanded rows
151
+ */
152
+ function flattenExpandedRows<TData>(
153
+ rows: Row<TData>[],
154
+ expanded: ExpandedState
155
+ ): Row<TData>[] {
156
+ const result: Row<TData>[] = [];
157
+
158
+ function processRow(row: Row<TData>) {
159
+ result.push(row);
160
+
161
+ const isExpanded = expanded === true || (expanded as Record<string, boolean>)[row.id];
162
+
163
+ if (isExpanded && row.subRows.length) {
164
+ for (const subRow of row.subRows) {
165
+ processRow(subRow);
166
+ }
167
+ }
168
+ }
169
+
170
+ for (const row of rows) {
171
+ processRow(row);
172
+ }
173
+
174
+ return result;
175
+ }