@gtkx/components 1.0.0-rc.4 → 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 (86) hide show
  1. package/README.md +5 -5
  2. package/dist/column-view.d.ts +2 -2
  3. package/dist/column-view.d.ts.map +1 -1
  4. package/dist/column-view.js +14 -12
  5. package/dist/column-view.js.map +1 -1
  6. package/dist/grid-view.js +1 -1
  7. package/dist/grid-view.js.map +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/internal/cells.d.ts +31 -23
  12. package/dist/internal/cells.d.ts.map +1 -1
  13. package/dist/internal/cells.js +168 -77
  14. package/dist/internal/cells.js.map +1 -1
  15. package/dist/internal/collection-index.d.ts +6 -10
  16. package/dist/internal/collection-index.d.ts.map +1 -1
  17. package/dist/internal/collection-index.js +32 -69
  18. package/dist/internal/collection-index.js.map +1 -1
  19. package/dist/internal/collection-model.d.ts +23 -2
  20. package/dist/internal/collection-model.d.ts.map +1 -1
  21. package/dist/internal/collection-model.js +210 -95
  22. package/dist/internal/collection-model.js.map +1 -1
  23. package/dist/internal/collection.d.ts +8 -11
  24. package/dist/internal/collection.d.ts.map +1 -1
  25. package/dist/internal/collection.js +38 -49
  26. package/dist/internal/collection.js.map +1 -1
  27. package/dist/internal/controlled-sync.d.ts +11 -0
  28. package/dist/internal/controlled-sync.d.ts.map +1 -0
  29. package/dist/internal/controlled-sync.js +19 -0
  30. package/dist/internal/controlled-sync.js.map +1 -0
  31. package/dist/internal/drop-down.d.ts.map +1 -1
  32. package/dist/internal/drop-down.js +27 -15
  33. package/dist/internal/drop-down.js.map +1 -1
  34. package/dist/internal/expansion.d.ts +3 -2
  35. package/dist/internal/expansion.d.ts.map +1 -1
  36. package/dist/internal/expansion.js +80 -47
  37. package/dist/internal/expansion.js.map +1 -1
  38. package/dist/internal/keys.d.ts +5 -0
  39. package/dist/internal/keys.d.ts.map +1 -0
  40. package/dist/internal/keys.js +13 -0
  41. package/dist/internal/keys.js.map +1 -0
  42. package/dist/internal/selection.d.ts +3 -2
  43. package/dist/internal/selection.d.ts.map +1 -1
  44. package/dist/internal/selection.js +68 -35
  45. package/dist/internal/selection.js.map +1 -1
  46. package/dist/internal/slots.d.ts +10 -0
  47. package/dist/internal/slots.d.ts.map +1 -0
  48. package/dist/internal/slots.js +43 -0
  49. package/dist/internal/slots.js.map +1 -0
  50. package/dist/internal/tree-expansion.d.ts +20 -0
  51. package/dist/internal/tree-expansion.d.ts.map +1 -0
  52. package/dist/internal/tree-expansion.js +68 -0
  53. package/dist/internal/tree-expansion.js.map +1 -0
  54. package/dist/internal/tree-order.d.ts +27 -0
  55. package/dist/internal/tree-order.d.ts.map +1 -0
  56. package/dist/internal/tree-order.js +71 -0
  57. package/dist/internal/tree-order.js.map +1 -0
  58. package/dist/internal/use-collection.d.ts +1 -1
  59. package/dist/internal/use-collection.d.ts.map +1 -1
  60. package/dist/internal/use-collection.js +4 -4
  61. package/dist/internal/use-collection.js.map +1 -1
  62. package/dist/list-view.d.ts.map +1 -1
  63. package/dist/list-view.js +6 -6
  64. package/dist/list-view.js.map +1 -1
  65. package/dist/types.d.ts +70 -21
  66. package/dist/types.d.ts.map +1 -1
  67. package/dist/types.js.map +1 -1
  68. package/package.json +7 -7
  69. package/src/column-view.tsx +28 -25
  70. package/src/grid-view.tsx +1 -1
  71. package/src/index.ts +3 -0
  72. package/src/internal/cells.tsx +339 -117
  73. package/src/internal/collection-index.ts +44 -92
  74. package/src/internal/collection-model.ts +259 -107
  75. package/src/internal/collection.ts +45 -67
  76. package/src/internal/controlled-sync.ts +34 -0
  77. package/src/internal/drop-down.tsx +41 -20
  78. package/src/internal/expansion.ts +104 -67
  79. package/src/internal/keys.ts +18 -0
  80. package/src/internal/selection.tsx +100 -51
  81. package/src/internal/slots.ts +67 -0
  82. package/src/internal/tree-expansion.ts +110 -0
  83. package/src/internal/tree-order.ts +138 -0
  84. package/src/internal/use-collection.tsx +5 -5
  85. package/src/list-view.tsx +14 -10
  86. package/src/types.ts +76 -19
@@ -1,129 +1,84 @@
1
1
  import type { ListItem, ListSection } from "../types.js";
2
+ import { encodePart } from "./keys.js";
2
3
 
3
4
  type Level = {
4
- key: string;
5
- ids: string[];
5
+ path: string;
6
+ items: ListItem[];
6
7
  expandableFlags: boolean[];
7
8
  };
8
9
 
9
10
  type CollectionIndex = {
10
11
  isTree: boolean;
11
- size: number;
12
12
  groups: Level[];
13
13
  children: Map<string, Level>;
14
- hasId: (id: string) => boolean;
15
- itemFor: (id: string) => ListItem | undefined;
16
- sectionFor: (id: string) => unknown;
17
- positionFor: (id: string) => number;
14
+ itemAt: (levelPath: string, slot: number) => ListItem | undefined;
15
+ sectionFor: (levelPath: string) => unknown;
16
+ expandablePathsFor: (id: string) => string[];
18
17
  };
19
18
 
20
19
  type IndexState = {
21
20
  isTree: boolean;
22
21
  groups: Level[];
23
22
  children: Map<string, Level>;
24
- itemsById: Map<string, ListItem>;
25
- sections: ListSection[] | undefined;
26
- positions: Map<string, number> | null;
27
- starts: number[] | null;
23
+ levels: Map<string, Level>;
24
+ expandablePaths: Map<string, string[]>;
25
+ sectionValues: Map<string, unknown>;
28
26
  };
29
27
 
30
- const ROOT_LEVEL_KEY = "";
28
+ const NO_PATHS: string[] = [];
31
29
 
32
30
  const hasChildren = (item: ListItem): boolean => item.children !== undefined && item.children.length > 0;
33
- const childLevelKey = (id: string): string => `child:${id}`;
34
31
 
35
- function collectChildren(state: IndexState, level: Level, item: ListItem): void {
36
- if (!state.isTree) {
37
- return;
38
- }
32
+ function pushPath(table: Map<string, string[]>, id: string, path: string): void {
33
+ const existing = table.get(id);
39
34
 
40
- const canExpand = hasChildren(item);
41
- level.expandableFlags.push(canExpand);
35
+ if (existing === undefined) {
36
+ table.set(id, [path]);
42
37
 
43
- if (!canExpand) {
44
38
  return;
45
39
  }
46
40
 
47
- const key = childLevelKey(item.id);
48
- state.children.set(key, collectLevel(state, key, item.children ?? []));
49
- }
50
-
51
- function collectLevel(state: IndexState, key: string, items: ListItem[]): Level {
52
- const level: Level = { key, ids: [], expandableFlags: [] };
53
-
54
- for (const item of items) {
55
- level.ids.push(item.id);
56
- state.itemsById.set(item.id, item);
57
- collectChildren(state, level, item);
58
- }
59
-
60
- return level;
61
- }
62
-
63
- function buildPositions(state: IndexState): void {
64
- const positions: Map<string, number> = new Map();
65
- const starts: number[] = [];
66
- let offset = 0;
67
-
68
- for (const level of state.groups) {
69
- starts.push(offset);
70
-
71
- for (const id of level.ids) {
72
- positions.set(id, offset);
73
- offset += 1;
74
- }
75
- }
76
-
77
- state.positions = positions;
78
- state.starts = starts;
41
+ existing.push(path);
79
42
  }
80
43
 
81
- function positionFor(state: IndexState, id: string): number {
82
- if (state.isTree) {
83
- return -1;
84
- }
44
+ function collectChildren(state: IndexState, level: Level, slotPath: string, item: ListItem): void {
45
+ const canExpand = hasChildren(item);
46
+ level.expandableFlags.push(canExpand);
85
47
 
86
- if (state.positions === null) {
87
- buildPositions(state);
48
+ if (!canExpand) {
49
+ return;
88
50
  }
89
51
 
90
- return state.positions?.get(id) ?? -1;
52
+ pushPath(state.expandablePaths, item.id, slotPath);
53
+ state.children.set(slotPath, collectLevel(state, slotPath, item.children ?? []));
91
54
  }
92
55
 
93
- function sectionAt(starts: number[], position: number): number {
94
- let low = 0;
95
- let high = starts.length - 1;
56
+ function collectLevel(state: IndexState, path: string, items: ListItem[]): Level {
57
+ const level: Level = { path, items, expandableFlags: [] };
58
+ state.levels.set(path, level);
96
59
 
97
- while (low < high) {
98
- const middle = Math.ceil((low + high) / 2);
99
-
100
- if ((starts[middle] ?? 0) <= position) {
101
- low = middle;
102
- } else {
103
- high = middle - 1;
104
- }
60
+ if (!state.isTree) {
61
+ return level;
105
62
  }
106
63
 
107
- return low;
108
- }
109
-
110
- function sectionFor(state: IndexState, id: string): unknown {
111
- const sections = state.sections;
112
- const position = positionFor(state, id);
113
-
114
- if (sections === undefined || position < 0 || state.starts === null) {
115
- return undefined;
64
+ for (const [slot, item] of items.entries()) {
65
+ collectChildren(state, level, path + encodePart(String(slot)), item);
116
66
  }
117
67
 
118
- return sections[sectionAt(state.starts, position)]?.value;
68
+ return level;
119
69
  }
120
70
 
121
71
  function buildGroups(state: IndexState, source: ListItem[], sections: ListSection[] | undefined): Level[] {
122
72
  if (sections === undefined) {
123
- return [collectLevel(state, ROOT_LEVEL_KEY, source)];
73
+ return [collectLevel(state, encodePart("0"), source)];
124
74
  }
125
75
 
126
- return sections.map((section) => collectLevel(state, section.id, section.data));
76
+ return sections.map((section, group) => {
77
+ const path = encodePart(String(group));
78
+ state.sectionValues.set(path, section.value);
79
+
80
+ return collectLevel(state, path, section.data);
81
+ });
127
82
  }
128
83
 
129
84
  function isTreeSource(source: ListItem[], sections: ListSection[] | undefined, isFlat: boolean): boolean {
@@ -145,24 +100,21 @@ function createCollectionIndex(
145
100
  isTree: isTreeSource(source, sections, isFlat),
146
101
  groups: [],
147
102
  children: new Map(),
148
- itemsById: new Map(),
149
- sections,
150
- positions: null,
151
- starts: null,
103
+ levels: new Map(),
104
+ expandablePaths: new Map(),
105
+ sectionValues: new Map(),
152
106
  };
153
107
 
154
108
  state.groups = buildGroups(state, source, sections);
155
109
 
156
110
  return {
157
111
  isTree: state.isTree,
158
- size: state.itemsById.size,
159
112
  groups: state.groups,
160
113
  children: state.children,
161
- hasId: (id) => state.itemsById.has(id),
162
- itemFor: (id) => state.itemsById.get(id),
163
- sectionFor: (id) => sectionFor(state, id),
164
- positionFor: (id) => positionFor(state, id),
114
+ itemAt: (levelPath, slot) => state.levels.get(levelPath)?.items[slot],
115
+ sectionFor: (levelPath) => state.sectionValues.get(levelPath),
116
+ expandablePathsFor: (id) => state.expandablePaths.get(id) ?? NO_PATHS,
165
117
  };
166
118
  }
167
119
 
168
- export { createCollectionIndex, childLevelKey, ROOT_LEVEL_KEY, type CollectionIndex, type Level };
120
+ export { createCollectionIndex, type CollectionIndex, type Level };