@cratis/components 0.1.9 → 0.1.12

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 (258) hide show
  1. package/dist/cjs/CommandForm/CommandFormFields.js +9 -3
  2. package/dist/cjs/CommandForm/CommandFormFields.js.map +1 -1
  3. package/dist/cjs/CommandForm/ValidationMessage.js +24 -0
  4. package/dist/cjs/CommandForm/ValidationMessage.js.map +1 -0
  5. package/dist/cjs/CommandForm/asCommandFormField.js +47 -0
  6. package/dist/cjs/CommandForm/asCommandFormField.js.map +1 -0
  7. package/dist/cjs/CommandForm/fields/CheckboxField.js +13 -0
  8. package/dist/cjs/CommandForm/fields/CheckboxField.js.map +1 -0
  9. package/dist/cjs/CommandForm/fields/DropdownField.js +13 -0
  10. package/dist/cjs/CommandForm/fields/DropdownField.js.map +1 -0
  11. package/dist/cjs/CommandForm/fields/InputTextField.js +13 -0
  12. package/dist/cjs/CommandForm/fields/InputTextField.js.map +1 -0
  13. package/dist/cjs/CommandForm/fields/NumberField.js +13 -0
  14. package/dist/cjs/CommandForm/fields/NumberField.js.map +1 -0
  15. package/dist/cjs/CommandForm/fields/SliderField.js +17 -0
  16. package/dist/cjs/CommandForm/fields/SliderField.js.map +1 -0
  17. package/dist/cjs/CommandForm/fields/TextAreaField.js +13 -0
  18. package/dist/cjs/CommandForm/fields/TextAreaField.js.map +1 -0
  19. package/dist/cjs/CommandForm/index.js +15 -7
  20. package/dist/cjs/CommandForm/index.js.map +1 -1
  21. package/dist/cjs/PivotViewer/PivotViewer.css +1258 -0
  22. package/dist/cjs/PivotViewer/PivotViewer.js +14 -0
  23. package/dist/cjs/PivotViewer/PivotViewer.js.map +1 -1
  24. package/dist/cjs/PivotViewer/components/PivotCanvas.js +33 -10
  25. package/dist/cjs/PivotViewer/components/PivotCanvas.js.map +1 -1
  26. package/dist/cjs/PivotViewer/components/PivotViewerMain.js +1 -1
  27. package/dist/cjs/PivotViewer/components/PivotViewerMain.js.map +1 -1
  28. package/dist/cjs/PivotViewer/components/Spinner.css +77 -0
  29. package/dist/cjs/PivotViewer/components/pivot/sprites.js +79 -15
  30. package/dist/cjs/PivotViewer/components/pivot/sprites.js.map +1 -1
  31. package/dist/cjs/PivotViewer/components/pivot/visibility.js +36 -10
  32. package/dist/cjs/PivotViewer/components/pivot/visibility.js.map +1 -1
  33. package/dist/cjs/PivotViewer/engine/layout.js +2 -1
  34. package/dist/cjs/PivotViewer/engine/layout.js.map +1 -1
  35. package/dist/cjs/PivotViewer/hooks/usePivotEngine.js +37 -2
  36. package/dist/cjs/PivotViewer/hooks/usePivotEngine.js.map +1 -1
  37. package/dist/cjs/PivotViewer/index.js +3 -0
  38. package/dist/cjs/PivotViewer/index.js.map +1 -1
  39. package/dist/cjs/PivotViewer/types.js +22 -0
  40. package/dist/cjs/PivotViewer/types.js.map +1 -0
  41. package/dist/cjs/TimeMachine/EventsView.css +213 -0
  42. package/dist/cjs/TimeMachine/TimeMachine.css +567 -0
  43. package/dist/cjs/TimeMachine/TimeMachine.js +8 -3
  44. package/dist/cjs/TimeMachine/TimeMachine.js.map +1 -1
  45. package/dist/esm/CommandForm/CommandForm.stories.d.ts +1 -0
  46. package/dist/esm/CommandForm/CommandForm.stories.d.ts.map +1 -1
  47. package/dist/esm/CommandForm/CommandForm.stories.js +34 -1
  48. package/dist/esm/CommandForm/CommandForm.stories.js.map +1 -1
  49. package/dist/esm/CommandForm/CommandFormFields.d.ts.map +1 -1
  50. package/dist/esm/CommandForm/CommandFormFields.js +9 -3
  51. package/dist/esm/CommandForm/CommandFormFields.js.map +1 -1
  52. package/dist/esm/CommandForm/UserRegistrationCommand.d.ts +63 -0
  53. package/dist/esm/CommandForm/UserRegistrationCommand.d.ts.map +1 -0
  54. package/dist/esm/CommandForm/UserRegistrationCommand.js +143 -0
  55. package/dist/esm/CommandForm/UserRegistrationCommand.js.map +1 -0
  56. package/dist/esm/CommandForm/ValidationMessage.d.ts +8 -0
  57. package/dist/esm/CommandForm/ValidationMessage.d.ts.map +1 -0
  58. package/dist/esm/CommandForm/ValidationMessage.js +22 -0
  59. package/dist/esm/CommandForm/ValidationMessage.js.map +1 -0
  60. package/dist/esm/CommandForm/asCommandFormField.d.ts +32 -0
  61. package/dist/esm/CommandForm/asCommandFormField.d.ts.map +1 -0
  62. package/dist/esm/CommandForm/asCommandFormField.js +45 -0
  63. package/dist/esm/CommandForm/asCommandFormField.js.map +1 -0
  64. package/dist/esm/CommandForm/fields/CheckboxField.d.ts +10 -0
  65. package/dist/esm/CommandForm/fields/CheckboxField.d.ts.map +1 -0
  66. package/dist/esm/CommandForm/fields/CheckboxField.js +11 -0
  67. package/dist/esm/CommandForm/fields/CheckboxField.js.map +1 -0
  68. package/dist/esm/CommandForm/fields/DropdownField.d.ts +15 -0
  69. package/dist/esm/CommandForm/fields/DropdownField.d.ts.map +1 -0
  70. package/dist/esm/CommandForm/fields/DropdownField.js +11 -0
  71. package/dist/esm/CommandForm/fields/DropdownField.js.map +1 -0
  72. package/dist/esm/CommandForm/fields/InputTextField.d.ts +11 -0
  73. package/dist/esm/CommandForm/fields/InputTextField.d.ts.map +1 -0
  74. package/dist/esm/CommandForm/fields/InputTextField.js +11 -0
  75. package/dist/esm/CommandForm/fields/InputTextField.js.map +1 -0
  76. package/dist/esm/CommandForm/fields/NumberField.d.ts +13 -0
  77. package/dist/esm/CommandForm/fields/NumberField.d.ts.map +1 -0
  78. package/dist/esm/CommandForm/fields/NumberField.js +11 -0
  79. package/dist/esm/CommandForm/fields/NumberField.js.map +1 -0
  80. package/dist/esm/CommandForm/fields/SliderField.d.ts +12 -0
  81. package/dist/esm/CommandForm/fields/SliderField.d.ts.map +1 -0
  82. package/dist/esm/CommandForm/fields/SliderField.js +15 -0
  83. package/dist/esm/CommandForm/fields/SliderField.js.map +1 -0
  84. package/dist/esm/CommandForm/fields/TextAreaField.d.ts +12 -0
  85. package/dist/esm/CommandForm/fields/TextAreaField.d.ts.map +1 -0
  86. package/dist/esm/CommandForm/fields/TextAreaField.js +11 -0
  87. package/dist/esm/CommandForm/fields/TextAreaField.js.map +1 -0
  88. package/dist/esm/CommandForm/fields/index.d.ts +7 -0
  89. package/dist/esm/CommandForm/fields/index.d.ts.map +1 -0
  90. package/dist/esm/CommandForm/fields/index.js +7 -0
  91. package/dist/esm/CommandForm/fields/index.js.map +1 -0
  92. package/dist/esm/CommandForm/index.d.ts +3 -4
  93. package/dist/esm/CommandForm/index.d.ts.map +1 -1
  94. package/dist/esm/CommandForm/index.js +8 -4
  95. package/dist/esm/CommandForm/index.js.map +1 -1
  96. package/dist/esm/PivotViewer/PivotViewer.css +1258 -0
  97. package/dist/esm/PivotViewer/PivotViewer.d.ts.map +1 -1
  98. package/dist/esm/PivotViewer/PivotViewer.js +14 -0
  99. package/dist/esm/PivotViewer/PivotViewer.js.map +1 -1
  100. package/dist/esm/PivotViewer/PivotViewer.stories.d.ts +1 -0
  101. package/dist/esm/PivotViewer/PivotViewer.stories.d.ts.map +1 -1
  102. package/dist/esm/PivotViewer/PivotViewer.stories.js +43 -3
  103. package/dist/esm/PivotViewer/PivotViewer.stories.js.map +1 -1
  104. package/dist/esm/PivotViewer/components/PivotCanvas.d.ts.map +1 -1
  105. package/dist/esm/PivotViewer/components/PivotCanvas.js +33 -10
  106. package/dist/esm/PivotViewer/components/PivotCanvas.js.map +1 -1
  107. package/dist/esm/PivotViewer/components/PivotViewerMain.js +1 -1
  108. package/dist/esm/PivotViewer/components/PivotViewerMain.js.map +1 -1
  109. package/dist/esm/PivotViewer/components/Spinner.css +77 -0
  110. package/dist/esm/PivotViewer/components/pivot/sprites.d.ts.map +1 -1
  111. package/dist/esm/PivotViewer/components/pivot/sprites.js +79 -15
  112. package/dist/esm/PivotViewer/components/pivot/sprites.js.map +1 -1
  113. package/dist/esm/PivotViewer/components/pivot/visibility.d.ts.map +1 -1
  114. package/dist/esm/PivotViewer/components/pivot/visibility.js +36 -10
  115. package/dist/esm/PivotViewer/components/pivot/visibility.js.map +1 -1
  116. package/dist/esm/PivotViewer/engine/layout.js +2 -1
  117. package/dist/esm/PivotViewer/engine/layout.js.map +1 -1
  118. package/dist/esm/PivotViewer/engine/pivot.worker.d.ts.map +1 -1
  119. package/dist/esm/PivotViewer/engine/pivot.worker.js +22 -7
  120. package/dist/esm/PivotViewer/engine/pivot.worker.js.map +1 -1
  121. package/dist/esm/PivotViewer/hooks/useFilteredData.d.ts +2 -2
  122. package/dist/esm/PivotViewer/hooks/useFilteredData.d.ts.map +1 -1
  123. package/dist/esm/PivotViewer/hooks/useFilteredData.js +4 -2
  124. package/dist/esm/PivotViewer/hooks/useFilteredData.js.map +1 -1
  125. package/dist/esm/PivotViewer/hooks/usePivotEngine.d.ts.map +1 -1
  126. package/dist/esm/PivotViewer/hooks/usePivotEngine.js +37 -2
  127. package/dist/esm/PivotViewer/hooks/usePivotEngine.js.map +1 -1
  128. package/dist/esm/PivotViewer/index.d.ts +2 -1
  129. package/dist/esm/PivotViewer/index.d.ts.map +1 -1
  130. package/dist/esm/PivotViewer/index.js +1 -0
  131. package/dist/esm/PivotViewer/index.js.map +1 -1
  132. package/dist/esm/PivotViewer/types.d.ts +4 -1
  133. package/dist/esm/PivotViewer/types.d.ts.map +1 -1
  134. package/dist/esm/PivotViewer/types.js +19 -2
  135. package/dist/esm/PivotViewer/types.js.map +1 -1
  136. package/dist/esm/TimeMachine/EventsView.css +213 -0
  137. package/dist/esm/TimeMachine/TimeMachine.css +567 -0
  138. package/dist/esm/TimeMachine/TimeMachine.d.ts.map +1 -1
  139. package/dist/esm/TimeMachine/TimeMachine.js +8 -3
  140. package/dist/esm/TimeMachine/TimeMachine.js.map +1 -1
  141. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  142. package/package.json +31 -32
  143. package/.storybook/main.ts +0 -24
  144. package/CommandDialog/CommandDialog.stories.tsx +0 -25
  145. package/CommandDialog/CommandDialog.tsx +0 -161
  146. package/CommandDialog/index.ts +0 -4
  147. package/CommandForm/CommandForm.stories.tsx +0 -24
  148. package/CommandForm/CommandForm.tsx +0 -266
  149. package/CommandForm/CommandFormField.tsx +0 -27
  150. package/CommandForm/CommandFormFields.tsx +0 -142
  151. package/CommandForm/DatePickerField.tsx +0 -57
  152. package/CommandForm/DropdownField.tsx +0 -65
  153. package/CommandForm/InputTextField.tsx +0 -62
  154. package/CommandForm/SliderField.tsx +0 -68
  155. package/CommandForm/index.ts +0 -10
  156. package/Common/ErrorBoundary.stories.tsx +0 -10
  157. package/Common/ErrorBoundary.tsx +0 -41
  158. package/Common/FormElement.stories.tsx +0 -10
  159. package/Common/FormElement.tsx +0 -20
  160. package/Common/Page.stories.tsx +0 -10
  161. package/Common/Page.tsx +0 -21
  162. package/Common/index.ts +0 -6
  163. package/DataPage/DataPage.stories.tsx +0 -10
  164. package/DataPage/DataPage.tsx +0 -191
  165. package/DataPage/index.ts +0 -4
  166. package/DataTables/DataTableForObservableQuery.stories.tsx +0 -10
  167. package/DataTables/DataTableForObservableQuery.tsx +0 -97
  168. package/DataTables/DataTableForQuery.stories.tsx +0 -10
  169. package/DataTables/DataTableForQuery.tsx +0 -97
  170. package/DataTables/index.ts +0 -5
  171. package/Dialogs/BusyIndicatorDialog.stories.tsx +0 -26
  172. package/Dialogs/BusyIndicatorDialog.tsx +0 -26
  173. package/Dialogs/ConfirmationDialog.stories.tsx +0 -36
  174. package/Dialogs/ConfirmationDialog.tsx +0 -75
  175. package/Dialogs/index.ts +0 -5
  176. package/Dropdown/Dropdown.tsx +0 -23
  177. package/Dropdown/index.ts +0 -4
  178. package/PivotViewer/PivotViewer.stories.tsx +0 -24
  179. package/PivotViewer/PivotViewer.tsx +0 -791
  180. package/PivotViewer/components/AxisLabels.tsx +0 -69
  181. package/PivotViewer/components/DetailPanel.tsx +0 -108
  182. package/PivotViewer/components/FilterPanel.tsx +0 -189
  183. package/PivotViewer/components/FilterPanelContainer.tsx +0 -10
  184. package/PivotViewer/components/PivotCanvas.tsx +0 -660
  185. package/PivotViewer/components/PivotViewerMain.tsx +0 -229
  186. package/PivotViewer/components/RangeHistogramFilter.tsx +0 -220
  187. package/PivotViewer/components/Spinner.tsx +0 -21
  188. package/PivotViewer/components/Toolbar.tsx +0 -130
  189. package/PivotViewer/components/ToolbarContainer.tsx +0 -10
  190. package/PivotViewer/components/index.ts +0 -12
  191. package/PivotViewer/components/pivot/animation.ts +0 -108
  192. package/PivotViewer/components/pivot/buckets.ts +0 -152
  193. package/PivotViewer/components/pivot/colorResolver.ts +0 -67
  194. package/PivotViewer/components/pivot/constants.ts +0 -46
  195. package/PivotViewer/components/pivot/sprites.ts +0 -265
  196. package/PivotViewer/components/pivot/visibility.ts +0 -319
  197. package/PivotViewer/constants.ts +0 -9
  198. package/PivotViewer/engine/layout.ts +0 -149
  199. package/PivotViewer/engine/pivot.worker.ts +0 -86
  200. package/PivotViewer/engine/store.ts +0 -437
  201. package/PivotViewer/engine/types.ts +0 -255
  202. package/PivotViewer/hooks/index.ts +0 -13
  203. package/PivotViewer/hooks/useContainerDimensions.ts +0 -45
  204. package/PivotViewer/hooks/useDimensionState.ts +0 -53
  205. package/PivotViewer/hooks/useFilterOptions.ts +0 -36
  206. package/PivotViewer/hooks/useFilterPanelDrag.ts +0 -49
  207. package/PivotViewer/hooks/useFilterState.ts +0 -106
  208. package/PivotViewer/hooks/useFilteredData.ts +0 -119
  209. package/PivotViewer/hooks/usePanning.ts +0 -163
  210. package/PivotViewer/hooks/usePivotEngine.ts +0 -252
  211. package/PivotViewer/hooks/useSelectedItem.ts +0 -402
  212. package/PivotViewer/hooks/useWheelZoom.ts +0 -114
  213. package/PivotViewer/hooks/useZoomState.ts +0 -34
  214. package/PivotViewer/index.ts +0 -7
  215. package/PivotViewer/types.ts +0 -59
  216. package/PivotViewer/utils/animations.ts +0 -249
  217. package/PivotViewer/utils/constants.ts +0 -20
  218. package/PivotViewer/utils/index.ts +0 -6
  219. package/PivotViewer/utils/selection.ts +0 -292
  220. package/PivotViewer/utils/utils.ts +0 -259
  221. package/TimeMachine/EventsView.stories.tsx +0 -10
  222. package/TimeMachine/EventsView.tsx +0 -119
  223. package/TimeMachine/Properties.stories.tsx +0 -10
  224. package/TimeMachine/Properties.tsx +0 -98
  225. package/TimeMachine/ReadModelView.stories.tsx +0 -10
  226. package/TimeMachine/ReadModelView.tsx +0 -143
  227. package/TimeMachine/TimeMachine.stories.tsx +0 -10
  228. package/TimeMachine/TimeMachine.tsx +0 -244
  229. package/TimeMachine/index.ts +0 -8
  230. package/TimeMachine/types.ts +0 -23
  231. package/dist/cjs/CommandForm/DatePickerField.js +0 -31
  232. package/dist/cjs/CommandForm/DatePickerField.js.map +0 -1
  233. package/dist/cjs/CommandForm/DropdownField.js +0 -31
  234. package/dist/cjs/CommandForm/DropdownField.js.map +0 -1
  235. package/dist/cjs/CommandForm/InputTextField.js +0 -32
  236. package/dist/cjs/CommandForm/InputTextField.js.map +0 -1
  237. package/dist/cjs/CommandForm/SliderField.js +0 -34
  238. package/dist/cjs/CommandForm/SliderField.js.map +0 -1
  239. package/dist/esm/CommandForm/DatePickerField.d.ts +0 -20
  240. package/dist/esm/CommandForm/DatePickerField.d.ts.map +0 -1
  241. package/dist/esm/CommandForm/DatePickerField.js +0 -29
  242. package/dist/esm/CommandForm/DatePickerField.js.map +0 -1
  243. package/dist/esm/CommandForm/DropdownField.d.ts +0 -24
  244. package/dist/esm/CommandForm/DropdownField.d.ts.map +0 -1
  245. package/dist/esm/CommandForm/DropdownField.js +0 -29
  246. package/dist/esm/CommandForm/DropdownField.js.map +0 -1
  247. package/dist/esm/CommandForm/InputTextField.d.ts +0 -20
  248. package/dist/esm/CommandForm/InputTextField.d.ts.map +0 -1
  249. package/dist/esm/CommandForm/InputTextField.js +0 -30
  250. package/dist/esm/CommandForm/InputTextField.js.map +0 -1
  251. package/dist/esm/CommandForm/SliderField.d.ts +0 -23
  252. package/dist/esm/CommandForm/SliderField.d.ts.map +0 -1
  253. package/dist/esm/CommandForm/SliderField.js +0 -32
  254. package/dist/esm/CommandForm/SliderField.js.map +0 -1
  255. package/global.d.ts +0 -11
  256. package/index.ts +0 -22
  257. package/useOverlayZIndex.ts +0 -32
  258. package/vite.config.ts +0 -80
@@ -5,6 +5,14 @@ function syncSpritesToViewport(params) {
5
5
  const { root, container, sprites, layout, visibleIds, items, cardWidth, cardHeight, panX, panY, panDeltaX, panDeltaY, viewportWidth, viewportHeight, createCardSprite, updateCardContent, zoomLevel, isViewTransition, prevLayout } = params;
6
6
  if (!root || !container)
7
7
  return;
8
+ console.log('[syncSpritesToViewport] Called with', {
9
+ layoutPositionsSize: layout.positions.size,
10
+ visibleIdsSize: visibleIds.length,
11
+ spritesSize: sprites.size,
12
+ itemsLength: items.length,
13
+ isViewTransition,
14
+ zoomLevel
15
+ });
8
16
  if (isViewTransition && (panDeltaX || panDeltaY)) {
9
17
  const dx = (panDeltaX || 0) / (zoomLevel || 1);
10
18
  const dy = (panDeltaY || 0) / (zoomLevel || 1);
@@ -16,7 +24,7 @@ function syncSpritesToViewport(params) {
16
24
  sprite.startY += dy;
17
25
  sprite.currentX += dx;
18
26
  sprite.currentY += dy;
19
- sprite.container.position.set(sprite.currentX, sprite.currentY);
27
+ sprite.container?.position?.set(sprite.currentX, sprite.currentY);
20
28
  }
21
29
  }
22
30
  }
@@ -71,7 +79,9 @@ function syncSpritesToViewport(params) {
71
79
  }
72
80
  catch (e) {
73
81
  }
74
- const aggressiveCull = !isViewTransition && sprites.size > Math.max(120, Math.ceil(inViewportIds.length * 1.5));
82
+ const scrollStabilized = Math.abs(panWorldY - (container.scrollTop * invScale)) < 10;
83
+ const aggressiveCull = (!isViewTransition && sprites.size > Math.max(120, Math.ceil(inViewportIds.length * 1.5))) ||
84
+ (isViewTransition && !scrollStabilized);
75
85
  for (const [id, sprite] of sprites) {
76
86
  if (!visibleSet.has(id)) {
77
87
  if (isViewTransition && layout.positions.has(id)) {
@@ -127,7 +137,7 @@ function syncSpritesToViewport(params) {
127
137
  }
128
138
  }
129
139
  try {
130
- const SWEEP_MS = 500;
140
+ const SWEEP_MS = 100;
131
141
  const now = Date.now();
132
142
  for (const [id, sprite] of sprites) {
133
143
  const lastHidden = sprite.__lastHiddenAt;
@@ -153,15 +163,22 @@ function syncSpritesToViewport(params) {
153
163
  }
154
164
  const MAX_SPRITES_PER_FRAME = 50;
155
165
  let createdCount = 0;
166
+ console.log('[syncSpritesToViewport] About to create sprites for inViewportIds:', inViewportIds.length);
167
+ console.log('[syncSpritesToViewport] layout.positions IDs:', Array.from(layout.positions.keys()));
156
168
  for (const id of inViewportIds) {
157
169
  const position = layout.positions.get(id);
158
- if (!position)
170
+ if (!position) {
171
+ console.log('[syncSpritesToViewport] No position for id:', id, 'in layout.positions');
159
172
  continue;
173
+ }
160
174
  let sprite = sprites.get(id);
161
175
  if (!sprite) {
162
- if (createdCount >= MAX_SPRITES_PER_FRAME)
176
+ if (createdCount >= MAX_SPRITES_PER_FRAME) {
177
+ console.log('[syncSpritesToViewport] Max sprites per frame reached');
163
178
  continue;
179
+ }
164
180
  createdCount++;
181
+ console.log('[syncSpritesToViewport] Creating sprite for id:', id, 'at position:', position);
165
182
  let startX = position.x;
166
183
  let startY = position.y;
167
184
  let shouldAnimate = false;
@@ -181,10 +198,12 @@ function syncSpritesToViewport(params) {
181
198
  }
182
199
  sprite = createCardSprite(id, startX, startY);
183
200
  sprites.set(id, sprite);
184
- root.addChild(sprite.container);
185
- sprite.currentX = startX;
186
- sprite.currentY = startY;
187
- sprite.container.position.set(startX, startY);
201
+ if (sprite.container) {
202
+ root.addChild(sprite.container);
203
+ sprite.currentX = startX;
204
+ sprite.currentY = startY;
205
+ sprite.container.position.set(startX, startY);
206
+ }
188
207
  if (shouldAnimate) {
189
208
  sprite.targetX = position.x;
190
209
  sprite.targetY = position.y;
@@ -195,6 +214,10 @@ function syncSpritesToViewport(params) {
195
214
  }
196
215
  }
197
216
  if (sprite.targetX !== position.x || sprite.targetY !== position.y) {
217
+ console.log('[syncSpritesToViewport] Updating sprite target position for id:', id, 'from', {
218
+ oldX: sprite.targetX,
219
+ oldY: sprite.targetY
220
+ }, 'to', position);
198
221
  if (isViewTransition) {
199
222
  sprite.startX = sprite.currentX;
200
223
  sprite.startY = sprite.currentY;
@@ -210,7 +233,10 @@ function syncSpritesToViewport(params) {
210
233
  delete sprite.animationDelay;
211
234
  }
212
235
  }
213
- const item = items[String(id)];
236
+ else {
237
+ console.log('[syncSpritesToViewport] Sprite position unchanged for id:', id, 'at', position);
238
+ }
239
+ const item = items[Number(id)];
214
240
  if (item) {
215
241
  updateCardContent(sprite, item);
216
242
  }
@@ -1 +1 @@
1
- {"version":3,"file":"visibility.js","sources":["../../../../../PivotViewer/components/pivot/visibility.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport * as PIXI from 'pixi.js';\nimport type { CardSprite } from './constants';\nimport { CARD_GAP } from './constants';\nimport type { LayoutResult } from '../../engine/types';\nimport { destroySprite } from './sprites';\n\nexport interface SyncParams<TItem> {\n root: PIXI.Container | null;\n container: HTMLDivElement | null;\n sprites: Map<string | number, CardSprite>;\n layout: LayoutResult;\n visibleIds: Uint32Array;\n items: TItem[];\n cardWidth: number;\n cardHeight: number;\n panX: number;\n panY: number;\n panDeltaX?: number;\n panDeltaY?: number;\n viewportWidth: number;\n viewportHeight: number;\n zoomLevel: number;\n createCardSprite: (id: string | number, x: number, y: number) => CardSprite;\n updateCardContent: (sprite: CardSprite, item: TItem) => void;\n isViewTransition?: boolean;\n prevLayout?: LayoutResult | null;\n}\n\nexport function syncSpritesToViewport<TItem>(params: SyncParams<TItem>) {\n const { root, container, sprites, layout, visibleIds, items, cardWidth, cardHeight, panX, panY, panDeltaX, panDeltaY, viewportWidth, viewportHeight, createCardSprite, updateCardContent, zoomLevel, isViewTransition, prevLayout } = params;\n if (!root || !container) return;\n\n // `visibleIds` comes from callers but this module iterates `layout.positions`.\n // Keep a reference to avoid unused variable lint errors when callers include it.\n void visibleIds;\n\n // Apply pan delta to animating sprites to keep them visually stable during camera jumps\n if (isViewTransition && (panDeltaX || panDeltaY)) {\n const dx = (panDeltaX || 0) / (zoomLevel || 1);\n const dy = (panDeltaY || 0) / (zoomLevel || 1);\n\n for (const sprite of sprites.values()) {\n if (sprite.animationStartTime !== undefined) {\n if (sprite.startX !== undefined) sprite.startX += dx;\n if (sprite.startY !== undefined) sprite.startY += dy;\n sprite.currentX += dx;\n sprite.currentY += dy;\n sprite.container.position.set(sprite.currentX, sprite.currentY);\n }\n }\n }\n\n const visibleSet = new Set<string | number>();\n\n // Increase buffer (in world units) to reduce edge cases where rapid\n // scrolling skips sprite creation. Keep buffer in world units and convert\n // DOM pixel measurements into world coordinates below to avoid mixing\n // coordinate spaces which can cause precision drift at browser zooms.\n const baseBufferWorld = Math.max(cardWidth, cardHeight) * 4;\n // Ensure buffer scales with viewport size (in world units) so that when\n // zoomed out we still pre-create enough sprites ahead of the viewport.\n const invScale = zoomLevel && zoomLevel !== 0 ? 1 / zoomLevel : 1;\n // The layout positions are in world units; when the root container is scaled\n // (zoomed) the rendered pixel position = position * zoomLevel. The DOM\n // scroll positions (`container.scrollLeft/Top`) are the authoritative pixel\n // camera offsets; prefer them over the passed `panX/panY` to avoid stale\n // values or race conditions between React state and direct DOM updates.\n const effectivePanX = typeof container.scrollLeft === 'number' ? container.scrollLeft : (panX || 0);\n const effectivePanY = typeof container.scrollTop === 'number' ? container.scrollTop : (panY || 0);\n\n // Convert pixel-based DOM measurements into world units so we compare like\n // with like. root.position is set using -pixels, so the mapping\n // from DOM scroll (pixels) to world units is: world = pixels / zoomLevel.\n const panWorldX = effectivePanX * invScale;\n const panWorldY = effectivePanY * invScale;\n\n // Use the container's measured client size for the viewport dimensions\n // (in pixels). The passed `viewportWidth`/`viewportHeight` can be stale\n // when the browser/device zoom changes; `clientWidth/clientHeight` are\n // authoritative for the actual visible pixel area.\n const viewportPxWidth = container.clientWidth || viewportWidth;\n const viewportPxHeight = container.clientHeight || viewportHeight;\n\n const viewportWorldWidth = viewportPxWidth * invScale;\n const viewportWorldHeight = viewportPxHeight * invScale;\n\n // Ensure bufferWorld is calculated from the actual measured viewport\n // in world units (after converting client pixel dims using invScale).\n // Make buffer adaptive to zoom: when zoomed out (invScale > 1) a small\n // pixel scroll maps to a larger world delta, so increase the buffer.\n // Use the larger of width/height to ensure we buffer enough in both directions.\n const bufferWorld = Math.max(baseBufferWorld * invScale, Math.max(viewportWorldWidth, viewportWorldHeight) * 2.0, baseBufferWorld);\n\n // Do not clamp viewport edges to 0 — allow negative top/left values so the\n // visible window correctly follows the scroll even when the buffer is\n // larger than the current scroll offset.\n const viewportLeftWorld = panWorldX - bufferWorld;\n const viewportRightWorld = panWorldX + viewportWorldWidth + bufferWorld;\n const viewportTopWorld = panWorldY - bufferWorld;\n const viewportBottomWorld = panWorldY + viewportWorldHeight + bufferWorld;\n\n const inViewportIds: (string | number)[] = [];\n // Small tolerance in world units to avoid floating-point edge cases when\n // browser/device zoom or high scroll values produce tiny rounding errors.\n // Scale epsilon with invScale so tolerance grows when zoomed out.\n const worldEpsilon = Math.max(0.5, 0.5 * invScale);\n\n // Iterate layout positions directly to avoid depending on `visibleIds`\n // which may be calculated in a different coordinate space or with\n // different assumptions about zoom. Looping the positions map is\n // deterministic and uses world coordinates directly.\n for (const [id, position] of layout.positions) {\n if (!position) continue;\n const worldX = position.x;\n const worldY = position.y;\n const worldCardW = cardWidth;\n const worldCardH = cardHeight;\n\n if (\n worldX + worldCardW >= viewportLeftWorld - worldEpsilon &&\n worldX <= viewportRightWorld + worldEpsilon &&\n worldY + worldCardH >= viewportTopWorld - worldEpsilon &&\n worldY <= viewportBottomWorld + worldEpsilon\n ) {\n inViewportIds.push(id);\n visibleSet.add(id);\n }\n }\n\n // Ensure last rows are present when the user scrolls near the bottom.\n // Compute slot/row information and force-insert IDs from the last few\n // rows to avoid missing tiles due to rounding/precision at zoom levels.\n try {\n const slotHeight = cardHeight + (CARD_GAP || 8);\n const totalRows = Math.ceil((layout.totalHeight || 0) / slotHeight) || 0;\n // Determine how many rows are visible in the viewport (world units),\n // then prefetch a fraction of that adjusted by zoom (invScale).\n const rowsVisible = Math.max(1, Math.ceil(viewportWorldHeight / slotHeight));\n const prefetchMultiplier = 0.75; // fraction of viewport to prefetch\n const prefetchRows = Math.max(2, Math.ceil(rowsVisible * prefetchMultiplier * Math.max(1, invScale)));\n const lastRowThresholdY = Math.max(0, (totalRows - prefetchRows) * slotHeight);\n for (const [id, position] of layout.positions) {\n if (position.y >= lastRowThresholdY) {\n if (!visibleSet.has(id)) {\n inViewportIds.push(id);\n visibleSet.add(id);\n }\n }\n }\n } catch (e) {\n void e;\n }\n\n // If we detect a very large discrepancy between created sprites and the\n // computed in-viewport count, that's a signal our culling math may be\n // unstable (especially at non-100% zoom). In that case, skip hiding this\n // frame as a conservative safeguard to avoid mass disappearing tiles.\n // However, disable this safeguard during view transitions to ensure old sprites are cleaned up.\n const aggressiveCull = !isViewTransition && sprites.size > Math.max(120, Math.ceil(inViewportIds.length * 1.5));\n\n for (const [id, sprite] of sprites) {\n if (!visibleSet.has(id)) {\n // If view transition is active, check if this sprite has a valid target in the new layout\n // If so, keep it visible and animate it to the new position (even if off-screen)\n if (isViewTransition && layout.positions.has(id)) {\n const newPos = layout.positions.get(id);\n if (newPos) {\n sprite.targetX = newPos.x;\n sprite.targetY = newPos.y;\n\n // Trigger animation if not already animating\n if (sprite.animationStartTime === undefined) {\n sprite.startX = sprite.currentX;\n sprite.startY = sprite.currentY;\n sprite.animationStartTime = Date.now();\n sprite.animationDelay = Math.random() * 300;\n }\n\n try { if (sprite.container) sprite.container.visible = true; } catch (e) { void e; }\n // Don't mark as hidden, so it won't be swept\n if ((sprite as any).__lastHiddenAt) delete (sprite as any).__lastHiddenAt;\n continue;\n }\n }\n\n if (aggressiveCull) {\n // Keep sprite visible this frame to avoid visual holes\n try { if (sprite.container) sprite.container.visible = true; } catch (e) { void e; }\n continue;\n }\n\n try {\n if (sprite.container) {\n sprite.container.visible = false;\n }\n (sprite as any).__lastHiddenAt = Date.now();\n } catch (e) {\n void e;\n }\n } else {\n try {\n if (sprite.container) {\n sprite.container.visible = true;\n }\n if ((sprite as any).__lastHiddenAt) delete (sprite as any).__lastHiddenAt;\n } catch (e) { void e; }\n }\n }\n\n // Sweep: actually destroy sprites that have been hidden longer than threshold\n try {\n const SWEEP_MS = 500; // keep hidden sprites for 500ms before destruction\n const now = Date.now();\n for (const [id, sprite] of sprites) {\n const lastHidden = (sprite as any).__lastHiddenAt as number | undefined;\n if (lastHidden && now - lastHidden > SWEEP_MS) {\n try {\n // remove from parent if present\n if (sprite.container && sprite.container.parent) sprite.container.parent.removeChild(sprite.container);\n } catch (e) {\n void e;\n }\n try {\n destroySprite(sprite);\n } catch (e) {\n void e;\n }\n sprites.delete(id);\n }\n }\n } catch (e) {\n void e;\n }\n\n // Limit the number of sprites created per frame to avoid choking the GPU/CPU\n // when scrolling rapidly or zooming out significantly.\n const MAX_SPRITES_PER_FRAME = 50;\n let createdCount = 0;\n\n for (const id of inViewportIds) {\n const position = layout.positions.get(id);\n if (!position) continue;\n\n let sprite = sprites.get(id);\n if (!sprite) {\n if (createdCount >= MAX_SPRITES_PER_FRAME) continue;\n createdCount++;\n\n let startX = position.x;\n let startY = position.y;\n let shouldAnimate = false;\n\n // If view transition, try to find old position to fly in from\n if (isViewTransition && prevLayout && prevLayout.positions.has(id)) {\n const oldPos = prevLayout.positions.get(id);\n if (oldPos) {\n startX = oldPos.x;\n startY = oldPos.y;\n\n // If we have a pan delta (camera jump), we need to adjust the start position\n // so that the sprite appears at the same visual location relative to the NEW camera.\n // StartWorld = OldWorld + PanDelta\n if (panDeltaX || panDeltaY) {\n const dx = (panDeltaX || 0) / (zoomLevel || 1);\n const dy = (panDeltaY || 0) / (zoomLevel || 1);\n startX += dx;\n startY += dy;\n }\n\n shouldAnimate = true;\n }\n }\n\n sprite = createCardSprite(id, startX, startY);\n sprites.set(id, sprite);\n root.addChild(sprite.container);\n sprite.currentX = startX;\n sprite.currentY = startY;\n // Keep sprite.container positioned in world units; animation/update\n // loop will apply root.scale/position to convert to pixels.\n sprite.container.position.set(startX, startY);\n\n if (shouldAnimate) {\n sprite.targetX = position.x;\n sprite.targetY = position.y;\n sprite.startX = startX;\n sprite.startY = startY;\n sprite.animationStartTime = Date.now();\n sprite.animationDelay = Math.random() * 300;\n }\n }\n\n // Check if target changed to trigger animation\n if (sprite.targetX !== position.x || sprite.targetY !== position.y) {\n if (isViewTransition) {\n sprite.startX = sprite.currentX;\n sprite.startY = sprite.currentY;\n sprite.targetX = position.x;\n sprite.targetY = position.y;\n sprite.animationStartTime = Date.now();\n // Add random delay for \"organic\" fly effect\n sprite.animationDelay = Math.random() * 300;\n } else {\n sprite.targetX = position.x;\n sprite.targetY = position.y;\n delete sprite.animationStartTime;\n delete sprite.animationDelay;\n }\n }\n\n const item = (items as any)[String(id)];\n if (item) {\n updateCardContent(sprite, item);\n }\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"visibility.js","sources":["../../../../../PivotViewer/components/pivot/visibility.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport * as PIXI from 'pixi.js';\nimport type { CardSprite } from './constants';\nimport { CARD_GAP } from './constants';\nimport type { LayoutResult } from '../../engine/types';\nimport { destroySprite } from './sprites';\n\nexport interface SyncParams<TItem> {\n root: PIXI.Container | null;\n container: HTMLDivElement | null;\n sprites: Map<string | number, CardSprite>;\n layout: LayoutResult;\n visibleIds: Uint32Array;\n items: TItem[];\n cardWidth: number;\n cardHeight: number;\n panX: number;\n panY: number;\n panDeltaX?: number;\n panDeltaY?: number;\n viewportWidth: number;\n viewportHeight: number;\n zoomLevel: number;\n createCardSprite: (id: string | number, x: number, y: number) => CardSprite;\n updateCardContent: (sprite: CardSprite, item: TItem) => void;\n isViewTransition?: boolean;\n prevLayout?: LayoutResult | null;\n}\n\nexport function syncSpritesToViewport<TItem>(params: SyncParams<TItem>) {\n const { root, container, sprites, layout, visibleIds, items, cardWidth, cardHeight, panX, panY, panDeltaX, panDeltaY, viewportWidth, viewportHeight, createCardSprite, updateCardContent, zoomLevel, isViewTransition, prevLayout } = params;\n if (!root || !container) return;\n\n console.log('[syncSpritesToViewport] Called with', {\n layoutPositionsSize: layout.positions.size,\n visibleIdsSize: visibleIds.length,\n spritesSize: sprites.size,\n itemsLength: items.length,\n isViewTransition,\n zoomLevel\n });\n\n // `visibleIds` comes from callers but this module iterates `layout.positions`.\n // Keep a reference to avoid unused variable lint errors when callers include it.\n void visibleIds;\n\n // Apply pan delta to animating sprites to keep them visually stable during camera jumps\n if (isViewTransition && (panDeltaX || panDeltaY)) {\n const dx = (panDeltaX || 0) / (zoomLevel || 1);\n const dy = (panDeltaY || 0) / (zoomLevel || 1);\n\n for (const sprite of sprites.values()) {\n if (sprite.animationStartTime !== undefined) {\n if (sprite.startX !== undefined) sprite.startX += dx;\n if (sprite.startY !== undefined) sprite.startY += dy;\n sprite.currentX += dx;\n sprite.currentY += dy;\n sprite.container?.position?.set(sprite.currentX, sprite.currentY);\n }\n }\n }\n\n const visibleSet = new Set<string | number>();\n\n // Increase buffer (in world units) to reduce edge cases where rapid\n // scrolling skips sprite creation. Keep buffer in world units and convert\n // DOM pixel measurements into world coordinates below to avoid mixing\n // coordinate spaces which can cause precision drift at browser zooms.\n const baseBufferWorld = Math.max(cardWidth, cardHeight) * 4;\n // Ensure buffer scales with viewport size (in world units) so that when\n // zoomed out we still pre-create enough sprites ahead of the viewport.\n const invScale = zoomLevel && zoomLevel !== 0 ? 1 / zoomLevel : 1;\n // The layout positions are in world units; when the root container is scaled\n // (zoomed) the rendered pixel position = position * zoomLevel. The DOM\n // scroll positions (`container.scrollLeft/Top`) are the authoritative pixel\n // camera offsets; prefer them over the passed `panX/panY` to avoid stale\n // values or race conditions between React state and direct DOM updates.\n const effectivePanX = typeof container.scrollLeft === 'number' ? container.scrollLeft : (panX || 0);\n const effectivePanY = typeof container.scrollTop === 'number' ? container.scrollTop : (panY || 0);\n\n // Convert pixel-based DOM measurements into world units so we compare like\n // with like. root.position is set using -pixels, so the mapping\n // from DOM scroll (pixels) to world units is: world = pixels / zoomLevel.\n const panWorldX = effectivePanX * invScale;\n const panWorldY = effectivePanY * invScale;\n\n // Use the container's measured client size for the viewport dimensions\n // (in pixels). The passed `viewportWidth`/`viewportHeight` can be stale\n // when the browser/device zoom changes; `clientWidth/clientHeight` are\n // authoritative for the actual visible pixel area.\n const viewportPxWidth = container.clientWidth || viewportWidth;\n const viewportPxHeight = container.clientHeight || viewportHeight;\n\n const viewportWorldWidth = viewportPxWidth * invScale;\n const viewportWorldHeight = viewportPxHeight * invScale;\n\n // Ensure bufferWorld is calculated from the actual measured viewport\n // in world units (after converting client pixel dims using invScale).\n // Make buffer adaptive to zoom: when zoomed out (invScale > 1) a small\n // pixel scroll maps to a larger world delta, so increase the buffer.\n // Use the larger of width/height to ensure we buffer enough in both directions.\n const bufferWorld = Math.max(baseBufferWorld * invScale, Math.max(viewportWorldWidth, viewportWorldHeight) * 2.0, baseBufferWorld);\n\n // Do not clamp viewport edges to 0 — allow negative top/left values so the\n // visible window correctly follows the scroll even when the buffer is\n // larger than the current scroll offset.\n const viewportLeftWorld = panWorldX - bufferWorld;\n const viewportRightWorld = panWorldX + viewportWorldWidth + bufferWorld;\n const viewportTopWorld = panWorldY - bufferWorld;\n const viewportBottomWorld = panWorldY + viewportWorldHeight + bufferWorld;\n\n const inViewportIds: (string | number)[] = [];\n // Small tolerance in world units to avoid floating-point edge cases when\n // browser/device zoom or high scroll values produce tiny rounding errors.\n // Scale epsilon with invScale so tolerance grows when zoomed out.\n const worldEpsilon = Math.max(0.5, 0.5 * invScale);\n\n // Iterate layout positions directly to avoid depending on `visibleIds`\n // which may be calculated in a different coordinate space or with\n // different assumptions about zoom. Looping the positions map is\n // deterministic and uses world coordinates directly.\n for (const [id, position] of layout.positions) {\n if (!position) continue;\n const worldX = position.x;\n const worldY = position.y;\n const worldCardW = cardWidth;\n const worldCardH = cardHeight;\n\n if (\n worldX + worldCardW >= viewportLeftWorld - worldEpsilon &&\n worldX <= viewportRightWorld + worldEpsilon &&\n worldY + worldCardH >= viewportTopWorld - worldEpsilon &&\n worldY <= viewportBottomWorld + worldEpsilon\n ) {\n inViewportIds.push(id);\n visibleSet.add(id);\n }\n }\n\n // Ensure last rows are present when the user scrolls near the bottom.\n // Compute slot/row information and force-insert IDs from the last few\n // rows to avoid missing tiles due to rounding/precision at zoom levels.\n try {\n const slotHeight = cardHeight + (CARD_GAP || 8);\n const totalRows = Math.ceil((layout.totalHeight || 0) / slotHeight) || 0;\n // Determine how many rows are visible in the viewport (world units),\n // then prefetch a fraction of that adjusted by zoom (invScale).\n const rowsVisible = Math.max(1, Math.ceil(viewportWorldHeight / slotHeight));\n const prefetchMultiplier = 0.75; // fraction of viewport to prefetch\n const prefetchRows = Math.max(2, Math.ceil(rowsVisible * prefetchMultiplier * Math.max(1, invScale)));\n const lastRowThresholdY = Math.max(0, (totalRows - prefetchRows) * slotHeight);\n for (const [id, position] of layout.positions) {\n if (position.y >= lastRowThresholdY) {\n if (!visibleSet.has(id)) {\n inViewportIds.push(id);\n visibleSet.add(id);\n }\n }\n }\n } catch (e) {\n void e;\n }\n\n // If we detect a very large discrepancy between created sprites and the\n // computed in-viewport count, that's a signal our culling math may be\n // unstable (especially at non-100% zoom). In that case, skip hiding this\n // frame as a conservative safeguard to avoid mass disappearing tiles.\n // However, disable this safeguard during view transitions to ensure old sprites are cleaned up.\n // EXCEPT: During view transitions, if scroll position hasn't stabilized yet (e.g., switching to grouped\n // mode triggers a scroll-to-bottom), keep all sprites visible to prevent flickering\n const scrollStabilized = Math.abs(panWorldY - (container.scrollTop * invScale)) < 10;\n const aggressiveCull = (!isViewTransition && sprites.size > Math.max(120, Math.ceil(inViewportIds.length * 1.5))) || \n (isViewTransition && !scrollStabilized);\n\n for (const [id, sprite] of sprites) {\n if (!visibleSet.has(id)) {\n // If view transition is active, check if this sprite has a valid target in the new layout\n // If so, keep it visible and animate it to the new position (even if off-screen)\n if (isViewTransition && layout.positions.has(id)) {\n const newPos = layout.positions.get(id);\n if (newPos) {\n sprite.targetX = newPos.x;\n sprite.targetY = newPos.y;\n\n // Trigger animation if not already animating\n if (sprite.animationStartTime === undefined) {\n sprite.startX = sprite.currentX;\n sprite.startY = sprite.currentY;\n sprite.animationStartTime = Date.now();\n sprite.animationDelay = Math.random() * 300;\n }\n\n try { if (sprite.container) sprite.container.visible = true; } catch (e) { void e; }\n // Don't mark as hidden, so it won't be swept\n if ((sprite as any).__lastHiddenAt) delete (sprite as any).__lastHiddenAt;\n continue;\n }\n }\n\n if (aggressiveCull) {\n // Keep sprite visible this frame to avoid visual holes\n try { if (sprite.container) sprite.container.visible = true; } catch (e) { void e; }\n continue;\n }\n\n try {\n if (sprite.container) {\n sprite.container.visible = false;\n }\n (sprite as any).__lastHiddenAt = Date.now();\n } catch (e) {\n void e;\n }\n } else {\n try {\n if (sprite.container) {\n sprite.container.visible = true;\n }\n if ((sprite as any).__lastHiddenAt) delete (sprite as any).__lastHiddenAt;\n } catch (e) { void e; }\n }\n }\n\n // Sweep: actually destroy sprites that have been hidden longer than threshold\n try {\n const SWEEP_MS = 100; // keep hidden sprites for 100ms before destruction (reduced from 500ms for faster mode transitions)\n const now = Date.now();\n for (const [id, sprite] of sprites) {\n const lastHidden = (sprite as any).__lastHiddenAt as number | undefined;\n if (lastHidden && now - lastHidden > SWEEP_MS) {\n try {\n // remove from parent if present\n if (sprite.container && sprite.container.parent) sprite.container.parent.removeChild(sprite.container);\n } catch (e) {\n void e;\n }\n try {\n destroySprite(sprite);\n } catch (e) {\n void e;\n }\n sprites.delete(id);\n }\n }\n } catch (e) {\n void e;\n }\n\n // Limit the number of sprites created per frame to avoid choking the GPU/CPU\n // when scrolling rapidly or zooming out significantly.\n const MAX_SPRITES_PER_FRAME = 50;\n let createdCount = 0;\n\n console.log('[syncSpritesToViewport] About to create sprites for inViewportIds:', inViewportIds.length);\n console.log('[syncSpritesToViewport] layout.positions IDs:', Array.from(layout.positions.keys()));\n\n for (const id of inViewportIds) {\n const position = layout.positions.get(id);\n if (!position) {\n console.log('[syncSpritesToViewport] No position for id:', id, 'in layout.positions');\n continue;\n }\n\n let sprite = sprites.get(id);\n if (!sprite) {\n if (createdCount >= MAX_SPRITES_PER_FRAME) {\n console.log('[syncSpritesToViewport] Max sprites per frame reached');\n continue;\n }\n createdCount++;\n\n console.log('[syncSpritesToViewport] Creating sprite for id:', id, 'at position:', position);\n\n let startX = position.x;\n let startY = position.y;\n let shouldAnimate = false;\n\n // If view transition, try to find old position to fly in from\n if (isViewTransition && prevLayout && prevLayout.positions.has(id)) {\n const oldPos = prevLayout.positions.get(id);\n if (oldPos) {\n startX = oldPos.x;\n startY = oldPos.y;\n\n // If we have a pan delta (camera jump), we need to adjust the start position\n // so that the sprite appears at the same visual location relative to the NEW camera.\n // StartWorld = OldWorld + PanDelta\n if (panDeltaX || panDeltaY) {\n const dx = (panDeltaX || 0) / (zoomLevel || 1);\n const dy = (panDeltaY || 0) / (zoomLevel || 1);\n startX += dx;\n startY += dy;\n }\n\n shouldAnimate = true;\n }\n }\n\n sprite = createCardSprite(id, startX, startY);\n sprites.set(id, sprite);\n if (sprite.container) {\n root.addChild(sprite.container);\n sprite.currentX = startX;\n sprite.currentY = startY;\n // Keep sprite.container positioned in world units; animation/update\n // loop will apply root.scale/position to convert to pixels.\n sprite.container.position.set(startX, startY);\n }\n\n if (shouldAnimate) {\n sprite.targetX = position.x;\n sprite.targetY = position.y;\n sprite.startX = startX;\n sprite.startY = startY;\n sprite.animationStartTime = Date.now();\n sprite.animationDelay = Math.random() * 300;\n }\n }\n\n // Check if target changed to trigger animation\n if (sprite.targetX !== position.x || sprite.targetY !== position.y) {\n console.log('[syncSpritesToViewport] Updating sprite target position for id:', id, 'from', {\n oldX: sprite.targetX,\n oldY: sprite.targetY\n }, 'to', position);\n if (isViewTransition) {\n sprite.startX = sprite.currentX;\n sprite.startY = sprite.currentY;\n sprite.targetX = position.x;\n sprite.targetY = position.y;\n sprite.animationStartTime = Date.now();\n // Add random delay for \"organic\" fly effect\n sprite.animationDelay = Math.random() * 300;\n } else {\n sprite.targetX = position.x;\n sprite.targetY = position.y;\n delete sprite.animationStartTime;\n delete sprite.animationDelay;\n }\n } else {\n console.log('[syncSpritesToViewport] Sprite position unchanged for id:', id, 'at', position);\n }\n\n const item = items[Number(id)];\n if (item) {\n updateCardContent(sprite, item);\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -68,7 +68,8 @@ function computeGroupedLayout(grouping, spec, positions) {
68
68
  const col = i % COLUMNS_PER_BUCKET;
69
69
  const row = Math.floor(i / COLUMNS_PER_BUCKET);
70
70
  const x = groupX + col * slotWidth;
71
- const y = contentHeight - (row + 1) * slotHeight + CANVAS_PADDING;
71
+ const rowsInGroup = Math.ceil(itemsInGroup / COLUMNS_PER_BUCKET);
72
+ const y = CANVAS_PADDING + contentHeight - (rowsInGroup - row) * slotHeight;
72
73
  positions.set(id, {
73
74
  x,
74
75
  y,
@@ -1 +1 @@
1
- {"version":3,"file":"layout.js","sources":["../../../../PivotViewer/engine/layout.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport type {\n LayoutSpec,\n LayoutResult,\n ItemPosition,\n GroupingResult,\n ItemId,\n} from './types';\nimport { CARD_GAP, CANVAS_PADDING } from '../constants';\n\nexport function computeLayout(\n grouping: GroupingResult,\n spec: LayoutSpec\n): LayoutResult {\n const positions = new Map<ItemId, ItemPosition>();\n\n if (spec.viewMode === 'collection') {\n return computeCollectionLayout(grouping, spec, positions);\n } else {\n return computeGroupedLayout(grouping, spec, positions);\n }\n}\n\nfunction computeCollectionLayout(\n grouping: GroupingResult,\n spec: LayoutSpec,\n positions: Map<ItemId, ItemPosition>\n): LayoutResult {\n const { cardWidth, cardHeight, containerWidth } = spec;\n const slotWidth = cardWidth + CARD_GAP;\n const slotHeight = cardHeight + CARD_GAP;\n\n // Calculate how many cards fit per row based on container width (include gap)\n const cardsPerRow = Math.max(1, Math.floor((containerWidth + CARD_GAP - (CANVAS_PADDING * 2)) / slotWidth));\n\n let x = CANVAS_PADDING;\n let y = CANVAS_PADDING;\n let column = 0;\n let itemCount = 0;\n\n for (const group of grouping.groups) {\n for (let i = 0; i < group.ids.length; i++) {\n const id = group.ids[i];\n\n positions.set(id, {\n x,\n y,\n groupIndex: 0,\n });\n\n // Move to next position horizontally (left to right)\n column++;\n x += slotWidth;\n\n // Wrap to next row when we've filled the width\n if (column >= cardsPerRow) {\n column = 0;\n x = CANVAS_PADDING;\n y += slotHeight;\n }\n\n itemCount++;\n }\n }\n\n const rows = Math.ceil(itemCount / cardsPerRow);\n const contentWidth = Math.min(itemCount, cardsPerRow) * slotWidth;\n\n return {\n positions,\n totalWidth: Math.max(containerWidth, contentWidth + (CANVAS_PADDING * 2)),\n totalHeight: (rows * slotHeight) + (CANVAS_PADDING * 2),\n };\n}\n\nfunction computeGroupedLayout(\n grouping: GroupingResult,\n spec: LayoutSpec,\n positions: Map<ItemId, ItemPosition>\n): LayoutResult {\n const { cardWidth, cardHeight, cardsPerColumn, groupSpacing } = spec;\n const slotWidth = cardWidth + CARD_GAP;\n const slotHeight = cardHeight + CARD_GAP;\n\n // Fixed bucket width: 2 columns of cards per bucket (always)\n const COLUMNS_PER_BUCKET = 2;\n const bucketWidth = COLUMNS_PER_BUCKET * slotWidth;\n\n let groupX = CANVAS_PADDING;\n // Use container height for layout, or fallback to cardsPerColumn height\n const layoutHeight = spec.containerHeight || (cardsPerColumn * slotHeight);\n const bucketWidths: number[] = [];\n let maxRows = 0;\n\n // First pass: calculate max rows to determine total height\n for (const group of grouping.groups) {\n const itemsInGroup = group.ids.length;\n const rowsInGroup = Math.ceil(itemsInGroup / COLUMNS_PER_BUCKET);\n maxRows = Math.max(maxRows, rowsInGroup);\n }\n\n // Calculate actual content height needed (ensure it's at least as tall as the container)\n const contentHeight = Math.max(layoutHeight, maxRows * slotHeight);\n\n for (let groupIndex = 0; groupIndex < grouping.groups.length; groupIndex++) {\n const group = grouping.groups[groupIndex];\n\n const itemsInGroup = group.ids.length;\n\n for (let i = 0; i < itemsInGroup; i++) {\n const id = group.ids[i];\n\n // Cards fill from left to right, bottom to top\n // For a 2-column bucket: i=0,1 in row 0; i=2,3 in row 1; etc.\n const col = i % COLUMNS_PER_BUCKET;\n const row = Math.floor(i / COLUMNS_PER_BUCKET);\n\n const x = groupX + col * slotWidth;\n // Stack from bottom of total content upward:\n // row 0 (first card) at bottom: contentHeight - slotHeight\n // row 1 above it: contentHeight - 2*slotHeight, etc.\n const y = contentHeight - (row + 1) * slotHeight + CANVAS_PADDING;\n\n positions.set(id, {\n x,\n y,\n groupIndex,\n });\n }\n\n // Always use fixed bucket width\n bucketWidths.push(bucketWidth);\n\n // Advance position by fixed bucket width + spacing\n groupX += bucketWidth;\n if (groupIndex < grouping.groups.length - 1) {\n groupX += groupSpacing;\n }\n }\n\n return {\n positions,\n totalWidth: groupX + CANVAS_PADDING,\n totalHeight: contentHeight + (CANVAS_PADDING * 2),\n bucketWidths,\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"layout.js","sources":["../../../../PivotViewer/engine/layout.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport type {\n LayoutSpec,\n LayoutResult,\n ItemPosition,\n GroupingResult,\n ItemId,\n} from './types';\nimport { CARD_GAP, CANVAS_PADDING } from '../constants';\n\nexport function computeLayout(\n grouping: GroupingResult,\n spec: LayoutSpec\n): LayoutResult {\n const positions = new Map<ItemId, ItemPosition>();\n\n if (spec.viewMode === 'collection') {\n return computeCollectionLayout(grouping, spec, positions);\n } else {\n return computeGroupedLayout(grouping, spec, positions);\n }\n}\n\nfunction computeCollectionLayout(\n grouping: GroupingResult,\n spec: LayoutSpec,\n positions: Map<ItemId, ItemPosition>\n): LayoutResult {\n const { cardWidth, cardHeight, containerWidth } = spec;\n const slotWidth = cardWidth + CARD_GAP;\n const slotHeight = cardHeight + CARD_GAP;\n\n // Calculate how many cards fit per row based on container width (include gap)\n const cardsPerRow = Math.max(1, Math.floor((containerWidth + CARD_GAP - (CANVAS_PADDING * 2)) / slotWidth));\n\n let x = CANVAS_PADDING;\n let y = CANVAS_PADDING;\n let column = 0;\n let itemCount = 0;\n\n for (const group of grouping.groups) {\n for (let i = 0; i < group.ids.length; i++) {\n const id = group.ids[i];\n\n positions.set(id, {\n x,\n y,\n groupIndex: 0,\n });\n\n // Move to next position horizontally (left to right)\n column++;\n x += slotWidth;\n\n // Wrap to next row when we've filled the width\n if (column >= cardsPerRow) {\n column = 0;\n x = CANVAS_PADDING;\n y += slotHeight;\n }\n\n itemCount++;\n }\n }\n\n const rows = Math.ceil(itemCount / cardsPerRow);\n const contentWidth = Math.min(itemCount, cardsPerRow) * slotWidth;\n\n return {\n positions,\n totalWidth: Math.max(containerWidth, contentWidth + (CANVAS_PADDING * 2)),\n totalHeight: (rows * slotHeight) + (CANVAS_PADDING * 2),\n };\n}\n\nfunction computeGroupedLayout(\n grouping: GroupingResult,\n spec: LayoutSpec,\n positions: Map<ItemId, ItemPosition>\n): LayoutResult {\n const { cardWidth, cardHeight, cardsPerColumn, groupSpacing } = spec;\n const slotWidth = cardWidth + CARD_GAP;\n const slotHeight = cardHeight + CARD_GAP;\n\n // Fixed bucket width: 2 columns of cards per bucket (always)\n const COLUMNS_PER_BUCKET = 2;\n const bucketWidth = COLUMNS_PER_BUCKET * slotWidth;\n\n let groupX = CANVAS_PADDING;\n // Use container height for layout, or fallback to cardsPerColumn height\n const layoutHeight = spec.containerHeight || (cardsPerColumn * slotHeight);\n const bucketWidths: number[] = [];\n let maxRows = 0;\n\n // First pass: calculate max rows to determine total height\n for (const group of grouping.groups) {\n const itemsInGroup = group.ids.length;\n const rowsInGroup = Math.ceil(itemsInGroup / COLUMNS_PER_BUCKET);\n maxRows = Math.max(maxRows, rowsInGroup);\n }\n\n // Calculate actual content height needed (ensure it's at least as tall as the container)\n const contentHeight = Math.max(layoutHeight, maxRows * slotHeight);\n\n for (let groupIndex = 0; groupIndex < grouping.groups.length; groupIndex++) {\n const group = grouping.groups[groupIndex];\n\n const itemsInGroup = group.ids.length;\n\n for (let i = 0; i < itemsInGroup; i++) {\n const id = group.ids[i];\n\n // Cards fill from left to right, bottom to top\n // For a 2-column bucket: i=0,1 in row 0; i=2,3 in row 1; etc.\n const col = i % COLUMNS_PER_BUCKET;\n const row = Math.floor(i / COLUMNS_PER_BUCKET);\n\n const x = groupX + col * slotWidth;\n // Position cards from bottom of container, stacking upwards\n // Start from contentHeight and subtract row positions\n const rowsInGroup = Math.ceil(itemsInGroup / COLUMNS_PER_BUCKET);\n const y = CANVAS_PADDING + contentHeight - (rowsInGroup - row) * slotHeight;\n\n positions.set(id, {\n x,\n y,\n groupIndex,\n });\n }\n\n // Always use fixed bucket width\n bucketWidths.push(bucketWidth);\n\n // Advance position by fixed bucket width + spacing\n groupX += bucketWidth;\n if (groupIndex < grouping.groups.length - 1) {\n groupX += groupSpacing;\n }\n }\n\n return {\n positions,\n totalWidth: groupX + CANVAS_PADDING,\n totalHeight: contentHeight + (CANVAS_PADDING * 2),\n bucketWidths,\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pivot.worker.d.ts","sourceRoot":"","sources":["../../../../PivotViewer/engine/pivot.worker.ts"],"names":[],"mappings":"AAqFA,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"pivot.worker.d.ts","sourceRoot":"","sources":["../../../../PivotViewer/engine/pivot.worker.ts"],"names":[],"mappings":"AAwGA,OAAO,EAAE,CAAC"}
@@ -3,15 +3,27 @@ let store = null;
3
3
  let indexes = null;
4
4
  self.onmessage = (e) => {
5
5
  const message = e.data;
6
+ console.log('[Worker] Received message:', message.type);
6
7
  switch (message.type) {
7
8
  case 'buildIndexes': {
8
- store = message.store;
9
- indexes = buildIndexes(store, message.fields);
10
- const response = {
11
- type: 'indexesReady',
12
- indexes,
9
+ console.log('[Worker] Building indexes for', message.store.items.length, 'items');
10
+ const fieldsArray = message.store.fields;
11
+ const fieldsMap = new Map(fieldsArray);
12
+ store = {
13
+ ...message.store,
14
+ fields: fieldsMap,
13
15
  };
14
- self.postMessage(response);
16
+ console.log('[Worker] Store converted, fields:', Array.from(fieldsMap.keys()));
17
+ if (store) {
18
+ indexes = buildIndexes(store, message.fields);
19
+ console.log('[Worker] Indexes built');
20
+ const response = {
21
+ type: 'indexesReady',
22
+ indexes,
23
+ };
24
+ console.log('[Worker] Posting indexesReady');
25
+ self.postMessage(response);
26
+ }
15
27
  break;
16
28
  }
17
29
  case 'applyFilters': {
@@ -29,14 +41,17 @@ self.onmessage = (e) => {
29
41
  }
30
42
  case 'computeGrouping': {
31
43
  if (!store || !indexes) {
32
- console.error('Store or indexes not initialized');
44
+ console.error('[Worker] Store or indexes not initialized');
33
45
  return;
34
46
  }
47
+ console.log('[Worker] Computing grouping for', message.visibleIds.length, 'items, groupBy:', message.groupBy);
35
48
  const result = computeGrouping(store, indexes, message.visibleIds, message.groupBy);
49
+ console.log('[Worker] Grouping computed:', result.groups.length, 'groups');
36
50
  const response = {
37
51
  type: 'groupingResult',
38
52
  result,
39
53
  };
54
+ console.log('[Worker] Posting groupingResult');
40
55
  self.postMessage(response);
41
56
  break;
42
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pivot.worker.js","sourceRoot":"","sources":["../../../../PivotViewer/engine/pivot.worker.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAE/E,IAAI,KAAK,GAAsB,IAAI,CAAC;AACpC,IAAI,OAAO,GAAwB,IAAI,CAAC;AAExC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAgC,EAAE,EAAE;IACpD,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC;IAEvB,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YACtB,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAE9C,MAAM,QAAQ,GAAqB;gBACjC,IAAI,EAAE,cAAc;gBACpB,OAAO;aACR,CAAC;YACF,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC3B,MAAM;QACR,CAAC;QAED,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;gBACvB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBAClD,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAE7D,MAAM,QAAQ,GAAqB;gBACjC,IAAI,EAAE,cAAc;gBACpB,MAAM;aACP,CAAC;YACF,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC3B,MAAM;QACR,CAAC;QAED,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;gBACvB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBAClD,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,eAAe,CAC5B,KAAK,EACL,OAAO,EACP,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,OAAO,CAChB,CAAC;YAEF,MAAM,QAAQ,GAAqB;gBACjC,IAAI,EAAE,gBAAgB;gBACtB,MAAM;aACP,CAAC;YACF,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC3B,MAAM;QACR,CAAC;QAED,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;gBACvC,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAE3D,MAAM,QAAQ,GAAqB;gBACjC,IAAI,EAAE,YAAY;gBAClB,MAAM;aACP,CAAC;YACF,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC3B,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC,CAAC"}
1
+ {"version":3,"file":"pivot.worker.js","sourceRoot":"","sources":["../../../../PivotViewer/engine/pivot.worker.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import type { PivotDimension, PivotFilter, PivotGroup } from '../types';
1
+ import type { PivotDimension, PivotFilter, PivotGroup, PropertyAccessor } from '../types';
2
2
  import type { FilterState, RangeFilterState } from '../utils/utils';
3
- export declare function useFilteredData<TItem extends object>(data: TItem[], filters: PivotFilter<TItem>[] | undefined, filterState: FilterState, rangeFilterState: RangeFilterState, activeDimension: PivotDimension<TItem> | undefined, dimensionFilter: string | null, searchTerm: string, searchFields?: (keyof TItem)[]): {
3
+ export declare function useFilteredData<TItem extends object>(data: TItem[], filters: PivotFilter<TItem>[] | undefined, filterState: FilterState, rangeFilterState: RangeFilterState, activeDimension: PivotDimension<TItem> | undefined, dimensionFilter: string | null, searchTerm: string, searchFields?: PropertyAccessor<TItem>[]): {
4
4
  filteredData: TItem[];
5
5
  allGroupsForBuckets: PivotGroup<TItem>[];
6
6
  groupedGroups: PivotGroup<TItem>[];
@@ -1 +1 @@
1
- {"version":3,"file":"useFilteredData.d.ts","sourceRoot":"","sources":["../../../../PivotViewer/hooks/useFilteredData.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEpE,wBAAgB,eAAe,CAAC,KAAK,SAAS,MAAM,EAClD,IAAI,EAAE,KAAK,EAAE,EACb,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,SAAS,EACzC,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,eAAe,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,SAAS,EAClD,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;;;;;EAsG/B"}
1
+ {"version":3,"file":"useFilteredData.d.ts","sourceRoot":"","sources":["../../../../PivotViewer/hooks/useFilteredData.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAG1F,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEpE,wBAAgB,eAAe,CAAC,KAAK,SAAS,MAAM,EAClD,IAAI,EAAE,KAAK,EAAE,EACb,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,SAAS,EACzC,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,eAAe,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,SAAS,EAClD,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE;;;;;EAuGzC"}
@@ -1,4 +1,5 @@
1
1
  import { useMemo } from 'react';
2
+ import { getPropertyPath, getValueByPath } from '../types';
2
3
  import { applyFilters, groupData, toKey } from '../utils/utils';
3
4
  export function useFilteredData(data, filters, filterState, rangeFilterState, activeDimension, dimensionFilter, searchTerm, searchFields) {
4
5
  const filteredData = useMemo(() => {
@@ -15,8 +16,9 @@ export function useFilteredData(data, filters, filterState, rangeFilterState, ac
15
16
  }
16
17
  return dataWithFilters.filter((item) => {
17
18
  if (searchFields && searchFields.length) {
18
- for (const field of searchFields) {
19
- const value = item[field];
19
+ for (const accessor of searchFields) {
20
+ const propertyPath = getPropertyPath(accessor);
21
+ const value = getValueByPath(item, propertyPath);
20
22
  if (value !== undefined && String(value).toLowerCase().indexOf(searchTerm) !== -1) {
21
23
  return true;
22
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useFilteredData.js","sourceRoot":"","sources":["../../../../PivotViewer/hooks/useFilteredData.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useFilteredData.js","sourceRoot":"","sources":["../../../../PivotViewer/hooks/useFilteredData.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePivotEngine.d.ts","sourceRoot":"","sources":["../../../../PivotViewer/hooks/usePivotEngine.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,cAAc,EAGd,UAAU,EACX,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,qBAAqB,CAAC,KAAK,SAAS,MAAM;IACzD,IAAI,EAAE,KAAK,EAAE,CAAC;IACd,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,UAAU,CAAC,CAAC;IAC1D,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1F,OAAO,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CAC5E;AAED,wBAAgB,cAAc,CAAC,KAAK,SAAS,MAAM,EAAE,EACnD,IAAI,EACJ,eAAe,EACf,WAAW,GACZ,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,oBAAoB,CAyNrD"}
1
+ {"version":3,"file":"usePivotEngine.d.ts","sourceRoot":"","sources":["../../../../PivotViewer/hooks/usePivotEngine.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,cAAc,EAGd,UAAU,EACX,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,qBAAqB,CAAC,KAAK,SAAS,MAAM;IACzD,IAAI,EAAE,KAAK,EAAE,CAAC;IACd,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,UAAU,CAAC,CAAC;IAC1D,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1F,OAAO,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CAC5E;AAED,wBAAgB,cAAc,CAAC,KAAK,SAAS,MAAM,EAAE,EACnD,IAAI,EACJ,eAAe,EACf,WAAW,GACZ,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,oBAAoB,CA+PrD"}
@@ -9,10 +9,13 @@ function usePivotEngine({ data, fieldExtractors, indexFields, }) {
9
9
  const storeRef = useRef(null);
10
10
  const pendingCallbacksRef = useRef(new Map());
11
11
  useEffect(() => {
12
+ console.log('[PivotEngine] Creating worker');
12
13
  const worker = new Worker(new URL('../engine/pivot.worker.ts', import.meta.url), { type: 'module' });
13
14
  workerRef.current = worker;
15
+ console.log('[PivotEngine] Worker created, setting up message handlers');
14
16
  worker.onmessage = (e) => {
15
17
  const message = e.data;
18
+ console.log('[PivotEngine] Received message from worker:', message.type);
16
19
  switch (message.type) {
17
20
  case 'indexesReady':
18
21
  console.log('[PivotEngine] Indexes ready');
@@ -21,25 +24,38 @@ function usePivotEngine({ data, fieldExtractors, indexFields, }) {
21
24
  case 'filterResult': {
22
25
  const callback = pendingCallbacksRef.current.get('filter');
23
26
  if (callback) {
27
+ console.log('[PivotEngine] Calling filter callback and deleting');
24
28
  callback(message.result);
25
29
  pendingCallbacksRef.current.delete('filter');
26
30
  }
31
+ else {
32
+ console.warn('[PivotEngine] No callback registered for filter result - ignoring duplicate message');
33
+ }
27
34
  break;
28
35
  }
29
36
  case 'groupingResult': {
37
+ console.log('[PivotEngine] Received groupingResult:', message.result);
30
38
  const callback = pendingCallbacksRef.current.get('grouping');
31
39
  if (callback) {
40
+ console.log('[PivotEngine] Calling grouping callback and deleting');
32
41
  callback(message.result);
33
42
  pendingCallbacksRef.current.delete('grouping');
34
43
  }
44
+ else {
45
+ console.warn('[PivotEngine] No callback registered for grouping result - ignoring duplicate message');
46
+ }
35
47
  break;
36
48
  }
37
49
  case 'sortResult': {
38
50
  const callback = pendingCallbacksRef.current.get('sort');
39
51
  if (callback) {
52
+ console.log('[PivotEngine] Calling sort callback and deleting');
40
53
  callback(message.result);
41
54
  pendingCallbacksRef.current.delete('sort');
42
55
  }
56
+ else {
57
+ console.warn('[PivotEngine] No callback registered for sort result - ignoring duplicate message');
58
+ }
43
59
  break;
44
60
  }
45
61
  }
@@ -64,12 +80,15 @@ function usePivotEngine({ data, fieldExtractors, indexFields, }) {
64
80
  };
65
81
  }, []);
66
82
  useEffect(() => {
67
- if (!workerRef.current)
83
+ if (!workerRef.current) {
84
+ console.warn('[PivotEngine] Worker not available in data effect');
68
85
  return;
86
+ }
69
87
  console.log('[PivotEngine] Building indexes for', data.length, 'items');
70
88
  setReady(false);
71
89
  const store = buildStore(data, fieldExtractors);
72
90
  storeRef.current = store;
91
+ console.log('[PivotEngine] Store built with', store.items.length, 'items and', store.fields.size, 'fields');
73
92
  try {
74
93
  indexesRef.current = buildIndexes(store, indexFields);
75
94
  }
@@ -78,11 +97,17 @@ function usePivotEngine({ data, fieldExtractors, indexFields, }) {
78
97
  indexesRef.current = null;
79
98
  }
80
99
  if (workerRef.current) {
100
+ const fieldsArray = Array.from(store.fields.entries());
101
+ const serializableStore = {
102
+ ...store,
103
+ fields: fieldsArray,
104
+ };
81
105
  const message = {
82
106
  type: 'buildIndexes',
83
- store,
107
+ store: serializableStore,
84
108
  fields: indexFields,
85
109
  };
110
+ console.log('[PivotEngine] Posting buildIndexes with', fieldsArray.length, 'fields');
86
111
  workerRef.current.postMessage(message);
87
112
  }
88
113
  else {
@@ -116,13 +141,20 @@ function usePivotEngine({ data, fieldExtractors, indexFields, }) {
116
141
  });
117
142
  }, [ready]);
118
143
  const computeGroupingCallback = useCallback((visibleIds, groupBy) => {
144
+ console.log('[PivotEngine] computeGroupingCallback called with', visibleIds.length, 'visibleIds');
145
+ if (pendingCallbacksRef.current.has('grouping')) {
146
+ console.warn('[PivotEngine] Grouping already in progress, ignoring duplicate request');
147
+ return Promise.resolve({ groups: [] });
148
+ }
119
149
  return new Promise((resolve) => {
120
150
  if (!workerRef.current || fallbackRef.current) {
151
+ console.log('[PivotEngine] Using synchronous fallback for grouping');
121
152
  try {
122
153
  const store = storeRef.current;
123
154
  const indexes = indexesRef.current;
124
155
  if (store && indexes) {
125
156
  const result = computeGrouping(store, indexes, visibleIds, groupBy);
157
+ console.log('[PivotEngine] Fallback grouping result:', result);
126
158
  resolve(result);
127
159
  return;
128
160
  }
@@ -130,9 +162,11 @@ function usePivotEngine({ data, fieldExtractors, indexFields, }) {
130
162
  catch (e) {
131
163
  console.error('[PivotEngine] fallback computeGrouping error:', e);
132
164
  }
165
+ console.warn('[PivotEngine] No store/indexes for fallback, returning empty');
133
166
  resolve({ groups: [] });
134
167
  return;
135
168
  }
169
+ console.log('[PivotEngine] Setting grouping callback and posting to worker');
136
170
  pendingCallbacksRef.current.set('grouping', resolve);
137
171
  const message = {
138
172
  type: 'computeGrouping',
@@ -140,6 +174,7 @@ function usePivotEngine({ data, fieldExtractors, indexFields, }) {
140
174
  groupBy,
141
175
  };
142
176
  workerRef.current.postMessage(message);
177
+ console.log('[PivotEngine] Message posted to worker');
143
178
  });
144
179
  }, [ready]);
145
180
  const sortIdsCallback = useCallback((visibleIds, sortBy) => {
@@ -1 +1 @@
1
- {"version":3,"file":"usePivotEngine.js","sources":["../../../../PivotViewer/hooks/usePivotEngine.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport type {\n PivotStore,\n PivotIndexes,\n FilterSpec,\n FilterResult,\n GroupSpec,\n GroupingResult,\n WorkerInMessage,\n WorkerOutMessage,\n FieldValue,\n} from '../engine/types';\nimport { buildStore, buildIndexes, applyFilters, computeGrouping, sortIds } from '../engine/store';\n\nexport interface UsePivotEngineOptions<TItem extends object> {\n data: TItem[];\n fieldExtractors: Map<string, (item: TItem) => FieldValue>;\n indexFields: string[];\n}\n\nexport interface UsePivotEngineResult {\n ready: boolean;\n applyFilters: (filters: FilterSpec[]) => Promise<FilterResult>;\n computeGrouping: (visibleIds: Uint32Array, groupBy: GroupSpec) => Promise<GroupingResult>;\n sortIds: (visibleIds: Uint32Array, sortBy: string) => Promise<Uint32Array>;\n}\n\nexport function usePivotEngine<TItem extends object>({\n data,\n fieldExtractors,\n indexFields,\n}: UsePivotEngineOptions<TItem>): UsePivotEngineResult {\n const [ready, setReady] = useState(false);\n const workerRef = useRef<Worker | null>(null);\n const indexesRef = useRef<PivotIndexes | null>(null);\n const fallbackRef = useRef(false);\n const storeRef = useRef<PivotStore | null>(null);\n const pendingCallbacksRef = useRef<Map<string, (result: unknown) => void>>(new Map());\n\n useEffect(() => {\n const worker = new Worker(\n new URL('../engine/pivot.worker.ts', import.meta.url),\n { type: 'module' }\n );\n\n workerRef.current = worker;\n\n worker.onmessage = (e: MessageEvent<WorkerOutMessage>) => {\n const message = e.data;\n\n switch (message.type) {\n case 'indexesReady':\n console.log('[PivotEngine] Indexes ready');\n setReady(true);\n break;\n\n case 'filterResult': {\n const callback = pendingCallbacksRef.current.get('filter');\n if (callback) {\n callback(message.result);\n pendingCallbacksRef.current.delete('filter');\n }\n break;\n }\n\n case 'groupingResult': {\n const callback = pendingCallbacksRef.current.get('grouping');\n if (callback) {\n callback(message.result);\n pendingCallbacksRef.current.delete('grouping');\n }\n break;\n }\n\n case 'sortResult': {\n const callback = pendingCallbacksRef.current.get('sort');\n if (callback) {\n callback(message.result);\n pendingCallbacksRef.current.delete('sort');\n }\n break;\n }\n }\n };\n\n worker.onerror = (error) => {\n console.error('[PivotEngine] Worker error:', error);\n // enable synchronous fallback so UI can still function without worker\n fallbackRef.current = true;\n workerRef.current = null;\n // if we already built store/indexes, mark ready so UI can use fallback\n if (storeRef.current) {\n try {\n indexesRef.current = buildIndexes(storeRef.current, indexFields);\n } catch (e) {\n console.error('[PivotEngine] Failed to build indexes in fallback:', e);\n indexesRef.current = null;\n }\n setReady(true);\n }\n };\n\n return () => {\n worker.terminate();\n };\n }, []);\n\n useEffect(() => {\n if (!workerRef.current) return;\n\n console.log('[PivotEngine] Building indexes for', data.length, 'items');\n setReady(false);\n\n const store = buildStore(data, fieldExtractors);\n storeRef.current = store;\n\n // compute indexes locally for immediate fallback and cache\n try {\n indexesRef.current = buildIndexes(store, indexFields);\n } catch (e) {\n console.error('[PivotEngine] buildIndexes failed:', e);\n indexesRef.current = null;\n }\n\n if (workerRef.current) {\n const message: WorkerInMessage = {\n type: 'buildIndexes',\n store,\n fields: indexFields,\n };\n\n workerRef.current.postMessage(message);\n } else {\n // no worker available, mark ready to allow fallback synchronous usage\n setReady(true);\n }\n }, [data, fieldExtractors, indexFields]);\n\n const applyFiltersCallback = useCallback(\n (filters: FilterSpec[]): Promise<FilterResult> => {\n return new Promise((resolve) => {\n // If worker is not available, use synchronous fallback using local indexes\n if (!workerRef.current || fallbackRef.current) {\n try {\n const store = storeRef.current;\n const indexes = indexesRef.current;\n if (store && indexes) {\n const result = applyFilters(store, indexes, filters);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback applyFilters error:', e);\n }\n\n // if fallback not possible, return empty result\n resolve({ visibleIds: new Uint32Array(0), count: 0 });\n return;\n }\n\n pendingCallbacksRef.current.set('filter', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'applyFilters',\n filters,\n };\n\n workerRef.current.postMessage(message);\n });\n },\n [ready]\n );\n\n const computeGroupingCallback = useCallback(\n (visibleIds: Uint32Array, groupBy: GroupSpec): Promise<GroupingResult> => {\n return new Promise((resolve) => {\n // synchronous fallback if worker unavailable\n if (!workerRef.current || fallbackRef.current) {\n try {\n const store = storeRef.current;\n const indexes = indexesRef.current;\n if (store && indexes) {\n const result = computeGrouping(store, indexes, visibleIds, groupBy);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback computeGrouping error:', e);\n }\n\n resolve({ groups: [] });\n return;\n }\n\n pendingCallbacksRef.current.set('grouping', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'computeGrouping',\n visibleIds,\n groupBy,\n };\n\n workerRef.current.postMessage(message);\n });\n },\n [ready]\n );\n\n const sortIdsCallback = useCallback(\n (visibleIds: Uint32Array, sortBy: string): Promise<Uint32Array> => {\n return new Promise((resolve) => {\n // synchronous fallback if worker unavailable\n if (!workerRef.current || fallbackRef.current) {\n try {\n const store = storeRef.current;\n if (store) {\n const result = sortIds(store, visibleIds, sortBy);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback sortIds error:', e);\n }\n\n resolve(visibleIds);\n return;\n }\n\n pendingCallbacksRef.current.set('sort', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'sort',\n ids: visibleIds,\n sortBy,\n };\n\n workerRef.current.postMessage(message);\n });\n },\n [ready]\n );\n\n return {\n ready,\n applyFilters: applyFiltersCallback,\n computeGrouping: computeGroupingCallback,\n sortIds: sortIdsCallback,\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"usePivotEngine.js","sources":["../../../../PivotViewer/hooks/usePivotEngine.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport type {\n PivotStore,\n PivotIndexes,\n FilterSpec,\n FilterResult,\n GroupSpec,\n GroupingResult,\n WorkerInMessage,\n WorkerOutMessage,\n FieldValue,\n} from '../engine/types';\nimport { buildStore, buildIndexes, applyFilters, computeGrouping, sortIds } from '../engine/store';\n\nexport interface UsePivotEngineOptions<TItem extends object> {\n data: TItem[];\n fieldExtractors: Map<string, (item: TItem) => FieldValue>;\n indexFields: string[];\n}\n\nexport interface UsePivotEngineResult {\n ready: boolean;\n applyFilters: (filters: FilterSpec[]) => Promise<FilterResult>;\n computeGrouping: (visibleIds: Uint32Array, groupBy: GroupSpec) => Promise<GroupingResult>;\n sortIds: (visibleIds: Uint32Array, sortBy: string) => Promise<Uint32Array>;\n}\n\nexport function usePivotEngine<TItem extends object>({\n data,\n fieldExtractors,\n indexFields,\n}: UsePivotEngineOptions<TItem>): UsePivotEngineResult {\n const [ready, setReady] = useState(false);\n const workerRef = useRef<Worker | null>(null);\n const indexesRef = useRef<PivotIndexes | null>(null);\n const fallbackRef = useRef(false);\n const storeRef = useRef<PivotStore | null>(null);\n const pendingCallbacksRef = useRef<Map<string, (result: unknown) => void>>(new Map());\n\n useEffect(() => {\n console.log('[PivotEngine] Creating worker');\n const worker = new Worker(\n new URL('../engine/pivot.worker.ts', import.meta.url),\n { type: 'module' }\n );\n\n workerRef.current = worker;\n console.log('[PivotEngine] Worker created, setting up message handlers');\n\n worker.onmessage = (e: MessageEvent<WorkerOutMessage>) => {\n const message = e.data;\n console.log('[PivotEngine] Received message from worker:', message.type);\n\n switch (message.type) {\n case 'indexesReady':\n console.log('[PivotEngine] Indexes ready');\n setReady(true);\n break;\n\n case 'filterResult': {\n const callback = pendingCallbacksRef.current.get('filter');\n if (callback) {\n console.log('[PivotEngine] Calling filter callback and deleting');\n callback(message.result);\n pendingCallbacksRef.current.delete('filter');\n } else {\n console.warn('[PivotEngine] No callback registered for filter result - ignoring duplicate message');\n }\n break;\n }\n\n case 'groupingResult': {\n console.log('[PivotEngine] Received groupingResult:', message.result);\n const callback = pendingCallbacksRef.current.get('grouping');\n if (callback) {\n console.log('[PivotEngine] Calling grouping callback and deleting');\n callback(message.result);\n pendingCallbacksRef.current.delete('grouping');\n } else {\n console.warn('[PivotEngine] No callback registered for grouping result - ignoring duplicate message');\n }\n break;\n }\n\n case 'sortResult': {\n const callback = pendingCallbacksRef.current.get('sort');\n if (callback) {\n console.log('[PivotEngine] Calling sort callback and deleting');\n callback(message.result);\n pendingCallbacksRef.current.delete('sort');\n } else {\n console.warn('[PivotEngine] No callback registered for sort result - ignoring duplicate message');\n }\n break;\n }\n }\n };\n\n worker.onerror = (error) => {\n console.error('[PivotEngine] Worker error:', error);\n // enable synchronous fallback so UI can still function without worker\n fallbackRef.current = true;\n workerRef.current = null;\n // if we already built store/indexes, mark ready so UI can use fallback\n if (storeRef.current) {\n try {\n indexesRef.current = buildIndexes(storeRef.current, indexFields);\n } catch (e) {\n console.error('[PivotEngine] Failed to build indexes in fallback:', e);\n indexesRef.current = null;\n }\n setReady(true);\n }\n };\n\n return () => {\n worker.terminate();\n };\n }, []);\n\n useEffect(() => {\n if (!workerRef.current) {\n console.warn('[PivotEngine] Worker not available in data effect');\n return;\n }\n\n console.log('[PivotEngine] Building indexes for', data.length, 'items');\n setReady(false);\n\n const store = buildStore(data, fieldExtractors);\n storeRef.current = store;\n console.log('[PivotEngine] Store built with', store.items.length, 'items and', store.fields.size, 'fields');\n\n // compute indexes locally for immediate fallback and cache\n try {\n indexesRef.current = buildIndexes(store, indexFields);\n } catch (e) {\n console.error('[PivotEngine] buildIndexes failed:', e);\n indexesRef.current = null;\n }\n\n if (workerRef.current) {\n // Convert Map to array for serialization\n const fieldsArray = Array.from(store.fields.entries());\n const serializableStore = {\n ...store,\n fields: fieldsArray,\n };\n\n const message: WorkerInMessage = {\n type: 'buildIndexes',\n store: serializableStore as any,\n fields: indexFields,\n };\n\n console.log('[PivotEngine] Posting buildIndexes with', fieldsArray.length, 'fields');\n workerRef.current.postMessage(message);\n } else {\n // no worker available, mark ready to allow fallback synchronous usage\n setReady(true);\n }\n }, [data, fieldExtractors, indexFields]);\n\n const applyFiltersCallback = useCallback(\n (filters: FilterSpec[]): Promise<FilterResult> => {\n return new Promise((resolve) => {\n // If worker is not available, use synchronous fallback using local indexes\n if (!workerRef.current || fallbackRef.current) {\n try {\n const store = storeRef.current;\n const indexes = indexesRef.current;\n if (store && indexes) {\n const result = applyFilters(store, indexes, filters);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback applyFilters error:', e);\n }\n\n // if fallback not possible, return empty result\n resolve({ visibleIds: new Uint32Array(0), count: 0 });\n return;\n }\n\n pendingCallbacksRef.current.set('filter', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'applyFilters',\n filters,\n };\n\n workerRef.current.postMessage(message);\n });\n },\n [ready]\n );\n\n const computeGroupingCallback = useCallback(\n (visibleIds: Uint32Array, groupBy: GroupSpec): Promise<GroupingResult> => {\n console.log('[PivotEngine] computeGroupingCallback called with', visibleIds.length, 'visibleIds');\n \n // Check if there's already a pending grouping request\n if (pendingCallbacksRef.current.has('grouping')) {\n console.warn('[PivotEngine] Grouping already in progress, ignoring duplicate request');\n return Promise.resolve({ groups: [] });\n }\n \n return new Promise((resolve) => {\n // synchronous fallback if worker unavailable\n if (!workerRef.current || fallbackRef.current) {\n console.log('[PivotEngine] Using synchronous fallback for grouping');\n try {\n const store = storeRef.current;\n const indexes = indexesRef.current;\n if (store && indexes) {\n const result = computeGrouping(store, indexes, visibleIds, groupBy);\n console.log('[PivotEngine] Fallback grouping result:', result);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback computeGrouping error:', e);\n }\n\n console.warn('[PivotEngine] No store/indexes for fallback, returning empty');\n resolve({ groups: [] });\n return;\n }\n\n console.log('[PivotEngine] Setting grouping callback and posting to worker');\n pendingCallbacksRef.current.set('grouping', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'computeGrouping',\n visibleIds,\n groupBy,\n };\n\n workerRef.current.postMessage(message);\n console.log('[PivotEngine] Message posted to worker');\n });\n },\n [ready]\n );\n\n const sortIdsCallback = useCallback(\n (visibleIds: Uint32Array, sortBy: string): Promise<Uint32Array> => {\n return new Promise((resolve) => {\n // synchronous fallback if worker unavailable\n if (!workerRef.current || fallbackRef.current) {\n try {\n const store = storeRef.current;\n if (store) {\n const result = sortIds(store, visibleIds, sortBy);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback sortIds error:', e);\n }\n\n resolve(visibleIds);\n return;\n }\n\n pendingCallbacksRef.current.set('sort', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'sort',\n ids: visibleIds,\n sortBy,\n };\n\n workerRef.current.postMessage(message);\n });\n },\n [ready]\n );\n\n return {\n ready,\n applyFilters: applyFiltersCallback,\n computeGrouping: computeGroupingCallback,\n sortIds: sortIdsCallback,\n };\n}\n"],"names":[],"mappings":";;;AA8BM,SAAU,cAAc,CAAuB,EACnD,IAAI,EACJ,eAAe,EACf,WAAW,GACkB,EAAA;IAC7B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;AACzC,IAAA,MAAM,SAAS,GAAG,MAAM,CAAgB,IAAI,CAAC;AAC7C,IAAA,MAAM,UAAU,GAAG,MAAM,CAAsB,IAAI,CAAC;AACpD,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;AACjC,IAAA,MAAM,QAAQ,GAAG,MAAM,CAAoB,IAAI,CAAC;IAChD,MAAM,mBAAmB,GAAG,MAAM,CAAyC,IAAI,GAAG,EAAE,CAAC;IAErF,SAAS,CAAC,MAAK;AACb,QAAA,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,IAAI,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EACrD,EAAE,IAAI,EAAE,QAAQ,EAAE,CACnB;AAED,QAAA,SAAS,CAAC,OAAO,GAAG,MAAM;AAC1B,QAAA,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC;AAExE,QAAA,MAAM,CAAC,SAAS,GAAG,CAAC,CAAiC,KAAI;AACvD,YAAA,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI;YACtB,OAAO,CAAC,GAAG,CAAC,6CAA6C,EAAE,OAAO,CAAC,IAAI,CAAC;AAExE,YAAA,QAAQ,OAAO,CAAC,IAAI;AAClB,gBAAA,KAAK,cAAc;AACjB,oBAAA,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC;oBAC1C,QAAQ,CAAC,IAAI,CAAC;oBACd;gBAEF,KAAK,cAAc,EAAE;oBACnB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAC1D,IAAI,QAAQ,EAAE;AACZ,wBAAA,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC;AACjE,wBAAA,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;AACxB,wBAAA,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;oBAC9C;yBAAO;AACL,wBAAA,OAAO,CAAC,IAAI,CAAC,qFAAqF,CAAC;oBACrG;oBACA;gBACF;gBAEA,KAAK,gBAAgB,EAAE;oBACrB,OAAO,CAAC,GAAG,CAAC,wCAAwC,EAAE,OAAO,CAAC,MAAM,CAAC;oBACrE,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;oBAC5D,IAAI,QAAQ,EAAE;AACZ,wBAAA,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC;AACnE,wBAAA,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;AACxB,wBAAA,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;oBAChD;yBAAO;AACL,wBAAA,OAAO,CAAC,IAAI,CAAC,uFAAuF,CAAC;oBACvG;oBACA;gBACF;gBAEA,KAAK,YAAY,EAAE;oBACjB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;oBACxD,IAAI,QAAQ,EAAE;AACZ,wBAAA,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC;AAC/D,wBAAA,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;AACxB,wBAAA,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;oBAC5C;yBAAO;AACL,wBAAA,OAAO,CAAC,IAAI,CAAC,mFAAmF,CAAC;oBACnG;oBACA;gBACF;;AAEJ,QAAA,CAAC;AAED,QAAA,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,KAAI;AACzB,YAAA,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC;AAEnD,YAAA,WAAW,CAAC,OAAO,GAAG,IAAI;AAC1B,YAAA,SAAS,CAAC,OAAO,GAAG,IAAI;AAExB,YAAA,IAAI,QAAQ,CAAC,OAAO,EAAE;AACpB,gBAAA,IAAI;oBACF,UAAU,CAAC,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;gBAClE;gBAAE,OAAO,CAAC,EAAE;AACV,oBAAA,OAAO,CAAC,KAAK,CAAC,oDAAoD,EAAE,CAAC,CAAC;AACtE,oBAAA,UAAU,CAAC,OAAO,GAAG,IAAI;gBAC3B;gBACA,QAAQ,CAAC,IAAI,CAAC;YAChB;AACF,QAAA,CAAC;AAED,QAAA,OAAO,MAAK;YACV,MAAM,CAAC,SAAS,EAAE;AACpB,QAAA,CAAC;IACH,CAAC,EAAE,EAAE,CAAC;IAEN,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE;AACtB,YAAA,OAAO,CAAC,IAAI,CAAC,mDAAmD,CAAC;YACjE;QACF;QAEA,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;QACvE,QAAQ,CAAC,KAAK,CAAC;QAEf,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,eAAe,CAAC;AAC/C,QAAA,QAAQ,CAAC,OAAO,GAAG,KAAK;QACxB,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;AAG3G,QAAA,IAAI;YACF,UAAU,CAAC,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC;QACvD;QAAE,OAAO,CAAC,EAAE;AACV,YAAA,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,CAAC,CAAC;AACtD,YAAA,UAAU,CAAC,OAAO,GAAG,IAAI;QAC3B;AAEA,QAAA,IAAI,SAAS,CAAC,OAAO,EAAE;AAErB,YAAA,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;AACtD,YAAA,MAAM,iBAAiB,GAAG;AACxB,gBAAA,GAAG,KAAK;AACR,gBAAA,MAAM,EAAE,WAAW;aACpB;AAED,YAAA,MAAM,OAAO,GAAoB;AAC/B,gBAAA,IAAI,EAAE,cAAc;AACpB,gBAAA,KAAK,EAAE,iBAAwB;AAC/B,gBAAA,MAAM,EAAE,WAAW;aACpB;YAED,OAAO,CAAC,GAAG,CAAC,yCAAyC,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC;AACpF,YAAA,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;QACxC;aAAO;YAEL,QAAQ,CAAC,IAAI,CAAC;QAChB;IACF,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;AAExC,IAAA,MAAM,oBAAoB,GAAG,WAAW,CACtC,CAAC,OAAqB,KAA2B;AAC/C,QAAA,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAI;YAE7B,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE;AAC7C,gBAAA,IAAI;AACF,oBAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO;AAC9B,oBAAA,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO;AAClC,oBAAA,IAAI,KAAK,IAAI,OAAO,EAAE;wBACpB,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC;wBACpD,OAAO,CAAC,MAAM,CAAC;wBACf;oBACF;gBACF;gBAAE,OAAO,CAAC,EAAE;AACV,oBAAA,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,CAAC,CAAC;gBAChE;AAGA,gBAAA,OAAO,CAAC,EAAE,UAAU,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;gBACrD;YACF;YAEA,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAoC,CAAC;AAE/E,YAAA,MAAM,OAAO,GAAoB;AAC/B,gBAAA,IAAI,EAAE,cAAc;gBACpB,OAAO;aACR;AAED,YAAA,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;AACxC,QAAA,CAAC,CAAC;AACJ,IAAA,CAAC,EACD,CAAC,KAAK,CAAC,CACR;IAED,MAAM,uBAAuB,GAAG,WAAW,CACzC,CAAC,UAAuB,EAAE,OAAkB,KAA6B;QACvE,OAAO,CAAC,GAAG,CAAC,mDAAmD,EAAE,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC;QAGjG,IAAI,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;AAC/C,YAAA,OAAO,CAAC,IAAI,CAAC,wEAAwE,CAAC;YACtF,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACxC;AAEA,QAAA,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAI;YAE7B,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE;AAC7C,gBAAA,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC;AACpE,gBAAA,IAAI;AACF,oBAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO;AAC9B,oBAAA,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO;AAClC,oBAAA,IAAI,KAAK,IAAI,OAAO,EAAE;AACpB,wBAAA,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC;AACnE,wBAAA,OAAO,CAAC,GAAG,CAAC,yCAAyC,EAAE,MAAM,CAAC;wBAC9D,OAAO,CAAC,MAAM,CAAC;wBACf;oBACF;gBACF;gBAAE,OAAO,CAAC,EAAE;AACV,oBAAA,OAAO,CAAC,KAAK,CAAC,+CAA+C,EAAE,CAAC,CAAC;gBACnE;AAEA,gBAAA,OAAO,CAAC,IAAI,CAAC,8DAA8D,CAAC;AAC5E,gBAAA,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;gBACvB;YACF;AAEA,YAAA,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC;YAC5E,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,OAAoC,CAAC;AAEjF,YAAA,MAAM,OAAO,GAAoB;AAC/B,gBAAA,IAAI,EAAE,iBAAiB;gBACvB,UAAU;gBACV,OAAO;aACR;AAED,YAAA,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;AACtC,YAAA,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC;AACvD,QAAA,CAAC,CAAC;AACJ,IAAA,CAAC,EACD,CAAC,KAAK,CAAC,CACR;IAED,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,UAAuB,EAAE,MAAc,KAA0B;AAChE,QAAA,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAI;YAE7B,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE;AAC7C,gBAAA,IAAI;AACF,oBAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO;oBAC9B,IAAI,KAAK,EAAE;wBACT,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC;wBACjD,OAAO,CAAC,MAAM,CAAC;wBACf;oBACF;gBACF;gBAAE,OAAO,CAAC,EAAE;AACV,oBAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,CAAC,CAAC;gBAC3D;gBAEA,OAAO,CAAC,UAAU,CAAC;gBACnB;YACF;YAEA,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAoC,CAAC;AAE7E,YAAA,MAAM,OAAO,GAAoB;AAC/B,gBAAA,IAAI,EAAE,MAAM;AACZ,gBAAA,GAAG,EAAE,UAAU;gBACf,MAAM;aACP;AAED,YAAA,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;AACxC,QAAA,CAAC,CAAC;AACJ,IAAA,CAAC,EACD,CAAC,KAAK,CAAC,CACR;IAED,OAAO;QACL,KAAK;AACL,QAAA,YAAY,EAAE,oBAAoB;AAClC,QAAA,eAAe,EAAE,uBAAuB;AACxC,QAAA,OAAO,EAAE,eAAe;KACzB;AACH;;;;"}