@rozie-ui/data-table-solid 0.3.1 → 0.4.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.
@@ -32,4 +32,80 @@ const wrapAggregationFn = (fn: any) => {
32
32
  }
33
33
  }
34
34
 
35
- export { isSafeKey, wrapAggregationFn }
35
+ // ── B1 (quick 260906-afh) — nested group leaf def index ─────────────────────────────
36
+ // LOOKUP-ONLY. This map is never fed to table-core (it does not replace/reshape the
37
+ // columnDefs() array table-core consumes for createTable/setOptions — that stays
38
+ // byte-identical); it exists purely so `defFor(colId)` (columnChrome.rzts) can resolve
39
+ // a NESTED leaf's def (a `columns:` group child) in O(1), the same as a top-level leaf.
40
+ //
41
+ // collectNestedDefs: depth-first walk of a `columns` array (each entry may itself carry
42
+ // a nested `columns` array — 3+ levels deep is supported). Writes `out[String(d.id)] = d`
43
+ // ONLY when the id is ABSENT from `out` — first-write-wins so a caller can pre-seed `out`
44
+ // with the higher-precedence top-level defs and this pass only ever fills GAPS.
45
+ const collectNestedDefs = (list: any, out: any) => {
46
+ if (!Array.isArray(list)) return
47
+ for (const d of list) {
48
+ if (!d || d.id == null) continue
49
+ const id = String(d.id)
50
+ if (!(id in out)) out[id] = d
51
+ if (Array.isArray(d.columns)) collectNestedDefs(d.columns, out)
52
+ }
53
+ }
54
+
55
+ // indexDefsById: builds a null-prototype `{ id: def }` map from a `columnDefs()`-shaped
56
+ // array in TWO passes. Pass 1 registers every TOP-LEVEL def unconditionally — so any id
57
+ // that already resolves at HEAD (a top-level leaf OR a top-level group's OWN id) keeps
58
+ // resolving to the EXACT SAME def, the byte-identical-lookup guarantee for every
59
+ // pre-existing caller. Pass 2 walks each top-level entry's `columns` (if any) via
60
+ // collectNestedDefs, so a nested leaf only fills a GAP — it can never shadow a
61
+ // same-named top-level id (top-level wins regardless of array order). Object.create(null)
62
+ // (T-AFH-01): a consumer column id of "__proto__"/"constructor" cannot pollute
63
+ // Object.prototype through this map — mirrors the existing `byId` T-48-PP guard in
64
+ // columnBuilders.rzts.
65
+ const indexDefsById = (defs: any): any => {
66
+ const out = Object.create(null)
67
+ if (!Array.isArray(defs)) return out
68
+ for (const d of defs) {
69
+ if (!d || d.id == null) continue
70
+ out[String(d.id)] = d
71
+ }
72
+ for (const d of defs) {
73
+ if (d && Array.isArray(d.columns)) collectNestedDefs(d.columns, out)
74
+ }
75
+ return out
76
+ }
77
+
78
+ // ── C5+C6 (quick 260906-cvo) — groupable-leaf collection for the #groupBar ──────────────
79
+ // C5: buildConfigDef's GROUP branch (columnBuilders.rzts) returns `{ id, header, columns }`
80
+ // with NO `groupable` key and no accessor, so the OLD `groupableColumns()` loop's
81
+ // `d.groupable === false` skip never fired for a group column — it was wrongly OFFERED to
82
+ // the bar even though a group column can never produce a grouping value.
83
+ // C6: that same loop walked TOP-LEVEL `columnDefs()` entries only, so a genuinely groupable
84
+ // NESTED leaf (a `columns:` group child) was never offered at all.
85
+ //
86
+ // collectGroupableLeafDefs: a DEDICATED depth-first walk, NOT a reuse of `indexDefsById`.
87
+ // `indexDefsById` is a LOOKUP index — it deliberately registers group columns too (a group
88
+ // id must keep resolving for `defFor`), and its insertion order is all-top-level-first-then-
89
+ // nested, which would both offer group columns AND hand the group bar an order that does not
90
+ // match the rendered header order. This walk instead: recurses into a `columns:` array
91
+ // WITHOUT ever pushing the group entry itself (closes C5 — a group column has no accessor
92
+ // and cannot be a grouping target, so an explicit `groupable: true` on a group entry is
93
+ // meaningless and is likewise never pushed); pushes every other (leaf) entry unless it opts
94
+ // out via `groupable === false` (closes C6 — nested leaves are now reachable); walks in
95
+ // DECLARATION order, depth-first, matching the rendered header order.
96
+ const collectGroupableLeafDefs = (defs: any): any[] => {
97
+ const out: any[] = []
98
+ if (!Array.isArray(defs)) return out
99
+ for (const d of defs) {
100
+ if (!d) continue
101
+ if (Array.isArray(d.columns)) {
102
+ out.push(...collectGroupableLeafDefs(d.columns))
103
+ continue
104
+ }
105
+ if (d.groupable === false) continue
106
+ out.push(d)
107
+ }
108
+ return out
109
+ }
110
+
111
+ export { isSafeKey, wrapAggregationFn, collectNestedDefs, indexDefsById, collectGroupableLeafDefs }