@cratis/components 1.5.1 → 1.6.7

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 (380) hide show
  1. package/dist/cjs/CommandDialog/CommandDialog.js +9 -2
  2. package/dist/cjs/CommandDialog/CommandDialog.js.map +1 -1
  3. package/dist/cjs/CommandDialog/StepperCommandDialog.js +21 -2
  4. package/dist/cjs/CommandDialog/StepperCommandDialog.js.map +1 -1
  5. package/dist/cjs/CommandDialog/index.js +2 -1
  6. package/dist/cjs/CommandDialog/index.js.map +1 -1
  7. package/dist/cjs/CommandForm/fields/CalendarField.js.map +1 -1
  8. package/dist/cjs/CommandForm/fields/CheckboxField.js.map +1 -1
  9. package/dist/cjs/CommandForm/fields/ChipsField.js.map +1 -1
  10. package/dist/cjs/CommandForm/fields/ColorPickerField.js.map +1 -1
  11. package/dist/cjs/CommandForm/fields/DropdownField.js.map +1 -1
  12. package/dist/cjs/CommandForm/fields/InputTextField.js.map +1 -1
  13. package/dist/cjs/CommandForm/fields/MultiSelectField.js.map +1 -1
  14. package/dist/cjs/CommandForm/fields/NumberField.js.map +1 -1
  15. package/dist/cjs/CommandForm/fields/SliderField.js.map +1 -1
  16. package/dist/cjs/CommandForm/fields/TextAreaField.js.map +1 -1
  17. package/dist/cjs/CommandForm/index.js +2 -34
  18. package/dist/cjs/CommandForm/index.js.map +1 -1
  19. package/dist/cjs/Common/ErrorBoundary.js.map +1 -1
  20. package/dist/cjs/Common/FormElement.js.map +1 -1
  21. package/dist/cjs/Common/Page.js.map +1 -1
  22. package/dist/cjs/Common/Tooltip.js +4 -0
  23. package/dist/cjs/Common/Tooltip.js.map +1 -1
  24. package/dist/cjs/Common/index.js +2 -1
  25. package/dist/cjs/Common/index.js.map +1 -1
  26. package/dist/cjs/DataPage/DataPage.js +6 -0
  27. package/dist/cjs/DataPage/DataPage.js.map +1 -1
  28. package/dist/cjs/DataPage/index.js +2 -1
  29. package/dist/cjs/DataPage/index.js.map +1 -1
  30. package/dist/cjs/DataTables/DataTableForObservableQuery.js +5 -0
  31. package/dist/cjs/DataTables/DataTableForObservableQuery.js.map +1 -1
  32. package/dist/cjs/DataTables/DataTableForQuery.js +5 -0
  33. package/dist/cjs/DataTables/DataTableForQuery.js.map +1 -1
  34. package/dist/cjs/DataTables/index.js +2 -1
  35. package/dist/cjs/DataTables/index.js.map +1 -1
  36. package/dist/cjs/Dialogs/BusyIndicatorDialog.js.map +1 -1
  37. package/dist/cjs/Dialogs/ConfirmationDialog.js.map +1 -1
  38. package/dist/cjs/Dialogs/Dialog.js +7 -1
  39. package/dist/cjs/Dialogs/Dialog.js.map +1 -1
  40. package/dist/cjs/Dialogs/index.js +2 -1
  41. package/dist/cjs/Dialogs/index.js.map +1 -1
  42. package/dist/cjs/Dropdown/Dropdown.js +1 -0
  43. package/dist/cjs/Dropdown/Dropdown.js.map +1 -1
  44. package/dist/cjs/Dropdown/index.js +2 -1
  45. package/dist/cjs/Dropdown/index.js.map +1 -1
  46. package/dist/cjs/ObjectContentEditor/ObjectContentEditor.js.map +1 -1
  47. package/dist/cjs/ObjectContentEditor/index.js +2 -1
  48. package/dist/cjs/ObjectContentEditor/index.js.map +1 -1
  49. package/dist/cjs/ObjectContentEditor/objectHelpers.js +6 -0
  50. package/dist/cjs/ObjectContentEditor/objectHelpers.js.map +1 -1
  51. package/dist/cjs/ObjectNavigationalBar/ObjectNavigationalBar.js.map +1 -1
  52. package/dist/cjs/ObjectNavigationalBar/breadcrumbHelpers.js +6 -0
  53. package/dist/cjs/ObjectNavigationalBar/breadcrumbHelpers.js.map +1 -1
  54. package/dist/cjs/ObjectNavigationalBar/index.js +2 -1
  55. package/dist/cjs/ObjectNavigationalBar/index.js.map +1 -1
  56. package/dist/cjs/PivotViewer/PivotViewer.js +28 -0
  57. package/dist/cjs/PivotViewer/PivotViewer.js.map +1 -1
  58. package/dist/cjs/PivotViewer/components/AxisLabels.js +4 -0
  59. package/dist/cjs/PivotViewer/components/AxisLabels.js.map +1 -1
  60. package/dist/cjs/PivotViewer/components/DetailPanel.js.map +1 -1
  61. package/dist/cjs/PivotViewer/components/FilterPanel.js +4 -0
  62. package/dist/cjs/PivotViewer/components/FilterPanel.js.map +1 -1
  63. package/dist/cjs/PivotViewer/components/FilterPanelContainer.js.map +1 -1
  64. package/dist/cjs/PivotViewer/components/PivotCanvas.js +138 -2
  65. package/dist/cjs/PivotViewer/components/PivotCanvas.js.map +1 -1
  66. package/dist/cjs/PivotViewer/components/PivotViewerMain.js +4 -0
  67. package/dist/cjs/PivotViewer/components/PivotViewerMain.js.map +1 -1
  68. package/dist/cjs/PivotViewer/components/RangeHistogramFilter.js.map +1 -1
  69. package/dist/cjs/PivotViewer/components/Spinner.js.map +1 -1
  70. package/dist/cjs/PivotViewer/components/Toolbar.js.map +1 -1
  71. package/dist/cjs/PivotViewer/components/ToolbarContainer.js.map +1 -1
  72. package/dist/cjs/PivotViewer/components/pivot/animation.js +8 -1
  73. package/dist/cjs/PivotViewer/components/pivot/animation.js.map +1 -1
  74. package/dist/cjs/PivotViewer/components/pivot/colorResolver.js +3 -1
  75. package/dist/cjs/PivotViewer/components/pivot/colorResolver.js.map +1 -1
  76. package/dist/cjs/PivotViewer/components/pivot/constants.js +8 -5
  77. package/dist/cjs/PivotViewer/components/pivot/constants.js.map +1 -1
  78. package/dist/cjs/PivotViewer/components/pivot/groups.js +15 -0
  79. package/dist/cjs/PivotViewer/components/pivot/groups.js.map +1 -1
  80. package/dist/cjs/PivotViewer/components/pivot/sprites.js +32 -13
  81. package/dist/cjs/PivotViewer/components/pivot/sprites.js.map +1 -1
  82. package/dist/cjs/PivotViewer/components/pivot/visibility.js +102 -3
  83. package/dist/cjs/PivotViewer/components/pivot/visibility.js.map +1 -1
  84. package/dist/cjs/PivotViewer/constants.js +2 -0
  85. package/dist/cjs/PivotViewer/constants.js.map +1 -1
  86. package/dist/cjs/PivotViewer/engine/layout.js +23 -0
  87. package/dist/cjs/PivotViewer/engine/layout.js.map +1 -1
  88. package/dist/cjs/PivotViewer/engine/store.js +29 -0
  89. package/dist/cjs/PivotViewer/engine/store.js.map +1 -1
  90. package/dist/cjs/PivotViewer/hooks/useAnimationModeTracking.js +8 -0
  91. package/dist/cjs/PivotViewer/hooks/useAnimationModeTracking.js.map +1 -1
  92. package/dist/cjs/PivotViewer/hooks/useCardSelection.js +10 -1
  93. package/dist/cjs/PivotViewer/hooks/useCardSelection.js.map +1 -1
  94. package/dist/cjs/PivotViewer/hooks/useContainerDimensions.js +11 -0
  95. package/dist/cjs/PivotViewer/hooks/useContainerDimensions.js.map +1 -1
  96. package/dist/cjs/PivotViewer/hooks/useCurrentFilters.js +6 -0
  97. package/dist/cjs/PivotViewer/hooks/useCurrentFilters.js.map +1 -1
  98. package/dist/cjs/PivotViewer/hooks/useDetailPanelClose.js +11 -1
  99. package/dist/cjs/PivotViewer/hooks/useDetailPanelClose.js.map +1 -1
  100. package/dist/cjs/PivotViewer/hooks/useDimensionState.js +2 -0
  101. package/dist/cjs/PivotViewer/hooks/useDimensionState.js.map +1 -1
  102. package/dist/cjs/PivotViewer/hooks/useFieldExtractors.js +2 -0
  103. package/dist/cjs/PivotViewer/hooks/useFieldExtractors.js.map +1 -1
  104. package/dist/cjs/PivotViewer/hooks/useFilterOptions.js +2 -0
  105. package/dist/cjs/PivotViewer/hooks/useFilterOptions.js.map +1 -1
  106. package/dist/cjs/PivotViewer/hooks/useFilterState.js +5 -0
  107. package/dist/cjs/PivotViewer/hooks/useFilterState.js.map +1 -1
  108. package/dist/cjs/PivotViewer/hooks/usePanning.js +14 -0
  109. package/dist/cjs/PivotViewer/hooks/usePanning.js.map +1 -1
  110. package/dist/cjs/PivotViewer/hooks/usePivotEngine.js +7 -0
  111. package/dist/cjs/PivotViewer/hooks/usePivotEngine.js.map +1 -1
  112. package/dist/cjs/PivotViewer/hooks/useScrollSync.js +6 -0
  113. package/dist/cjs/PivotViewer/hooks/useScrollSync.js.map +1 -1
  114. package/dist/cjs/PivotViewer/hooks/useViewModeScrollHandling.js +9 -0
  115. package/dist/cjs/PivotViewer/hooks/useViewModeScrollHandling.js.map +1 -1
  116. package/dist/cjs/PivotViewer/hooks/useWheelZoom.js +8 -2
  117. package/dist/cjs/PivotViewer/hooks/useWheelZoom.js.map +1 -1
  118. package/dist/cjs/PivotViewer/hooks/useZoomState.js +2 -0
  119. package/dist/cjs/PivotViewer/hooks/useZoomState.js.map +1 -1
  120. package/dist/cjs/PivotViewer/index.js +2 -1
  121. package/dist/cjs/PivotViewer/index.js.map +1 -1
  122. package/dist/cjs/PivotViewer/types.js +11 -0
  123. package/dist/cjs/PivotViewer/types.js.map +1 -1
  124. package/dist/cjs/PivotViewer/utils/animations.js +35 -2
  125. package/dist/cjs/PivotViewer/utils/animations.js.map +1 -1
  126. package/dist/cjs/PivotViewer/utils/cardPosition.js +21 -3
  127. package/dist/cjs/PivotViewer/utils/cardPosition.js.map +1 -1
  128. package/dist/cjs/PivotViewer/utils/constants.js +3 -0
  129. package/dist/cjs/PivotViewer/utils/constants.js.map +1 -1
  130. package/dist/cjs/PivotViewer/utils/idResolution.js +16 -0
  131. package/dist/cjs/PivotViewer/utils/idResolution.js.map +1 -1
  132. package/dist/cjs/PivotViewer/utils/selection.js +25 -0
  133. package/dist/cjs/PivotViewer/utils/selection.js.map +1 -1
  134. package/dist/cjs/PivotViewer/utils/utils.js +5 -0
  135. package/dist/cjs/PivotViewer/utils/utils.js.map +1 -1
  136. package/dist/cjs/SchemaEditor/NameCell.js.map +1 -1
  137. package/dist/cjs/SchemaEditor/SchemaEditor.js.map +1 -1
  138. package/dist/cjs/SchemaEditor/TypeCell.js.map +1 -1
  139. package/dist/cjs/SchemaEditor/index.js +2 -1
  140. package/dist/cjs/SchemaEditor/index.js.map +1 -1
  141. package/dist/cjs/SchemaEditor/schemaHelpers.js +8 -0
  142. package/dist/cjs/SchemaEditor/schemaHelpers.js.map +1 -1
  143. package/dist/cjs/TimeMachine/EventsView.js +2 -0
  144. package/dist/cjs/TimeMachine/EventsView.js.map +1 -1
  145. package/dist/cjs/TimeMachine/Properties.js.map +1 -1
  146. package/dist/cjs/TimeMachine/ReadModelView.js +1 -0
  147. package/dist/cjs/TimeMachine/ReadModelView.js.map +1 -1
  148. package/dist/cjs/TimeMachine/TimeMachine.js +11 -1
  149. package/dist/cjs/TimeMachine/TimeMachine.js.map +1 -1
  150. package/dist/cjs/TimeMachine/index.js +2 -1
  151. package/dist/cjs/TimeMachine/index.js.map +1 -1
  152. package/dist/cjs/TimeMachine/propertiesHelpers.js +5 -0
  153. package/dist/cjs/TimeMachine/propertiesHelpers.js.map +1 -1
  154. package/dist/cjs/Toolbar/Toolbar.css +8 -0
  155. package/dist/cjs/Toolbar/Toolbar.js +7 -1
  156. package/dist/cjs/Toolbar/Toolbar.js.map +1 -1
  157. package/dist/cjs/Toolbar/ToolbarButton.js +16 -2
  158. package/dist/cjs/Toolbar/ToolbarButton.js.map +1 -1
  159. package/dist/cjs/Toolbar/ToolbarContext.js +8 -0
  160. package/dist/cjs/Toolbar/ToolbarContext.js.map +1 -1
  161. package/dist/cjs/Toolbar/ToolbarDragContext.js +24 -0
  162. package/dist/cjs/Toolbar/ToolbarDragContext.js.map +1 -0
  163. package/dist/cjs/Toolbar/ToolbarFanOutItem.js +11 -0
  164. package/dist/cjs/Toolbar/ToolbarFanOutItem.js.map +1 -1
  165. package/dist/cjs/Toolbar/ToolbarSection.js +18 -1
  166. package/dist/cjs/Toolbar/ToolbarSection.js.map +1 -1
  167. package/dist/cjs/Toolbar/ToolbarSeparator.js +6 -0
  168. package/dist/cjs/Toolbar/ToolbarSeparator.js.map +1 -1
  169. package/dist/cjs/Toolbar/index.js +2 -1
  170. package/dist/cjs/Toolbar/index.js.map +1 -1
  171. package/dist/cjs/tailwind-utilities.css +16 -1
  172. package/dist/cjs/types/TypeFormat.js +2 -0
  173. package/dist/cjs/types/TypeFormat.js.map +1 -1
  174. package/dist/cjs/types/index.js +2 -1
  175. package/dist/cjs/types/index.js.map +1 -1
  176. package/dist/cjs/useOverlayZIndex.js +10 -0
  177. package/dist/cjs/useOverlayZIndex.js.map +1 -1
  178. package/dist/esm/CommandDialog/CommandDialog.d.ts +2 -2
  179. package/dist/esm/CommandDialog/CommandDialog.d.ts.map +1 -1
  180. package/dist/esm/CommandDialog/CommandDialog.js +9 -2
  181. package/dist/esm/CommandDialog/CommandDialog.js.map +1 -1
  182. package/dist/esm/CommandDialog/CommandDialog.stories.d.ts +1 -0
  183. package/dist/esm/CommandDialog/CommandDialog.stories.d.ts.map +1 -1
  184. package/dist/esm/CommandDialog/CommandDialog.stories.js +52 -0
  185. package/dist/esm/CommandDialog/CommandDialog.stories.js.map +1 -1
  186. package/dist/esm/CommandDialog/StepperCommandDialog.d.ts +2 -2
  187. package/dist/esm/CommandDialog/StepperCommandDialog.d.ts.map +1 -1
  188. package/dist/esm/CommandDialog/StepperCommandDialog.js +21 -2
  189. package/dist/esm/CommandDialog/StepperCommandDialog.js.map +1 -1
  190. package/dist/esm/CommandDialog/StepperCommandDialog.stories.d.ts +1 -0
  191. package/dist/esm/CommandDialog/StepperCommandDialog.stories.d.ts.map +1 -1
  192. package/dist/esm/CommandDialog/StepperCommandDialog.stories.js +54 -0
  193. package/dist/esm/CommandDialog/StepperCommandDialog.stories.js.map +1 -1
  194. package/dist/esm/CommandDialog/index.js +3 -0
  195. package/dist/esm/CommandDialog/index.js.map +1 -1
  196. package/dist/esm/CommandForm/fields/CalendarField.js.map +1 -1
  197. package/dist/esm/CommandForm/fields/CheckboxField.js.map +1 -1
  198. package/dist/esm/CommandForm/fields/ChipsField.js.map +1 -1
  199. package/dist/esm/CommandForm/fields/ColorPickerField.js.map +1 -1
  200. package/dist/esm/CommandForm/fields/DropdownField.js.map +1 -1
  201. package/dist/esm/CommandForm/fields/InputTextField.js.map +1 -1
  202. package/dist/esm/CommandForm/fields/MultiSelectField.js.map +1 -1
  203. package/dist/esm/CommandForm/fields/NumberField.js.map +1 -1
  204. package/dist/esm/CommandForm/fields/SliderField.js.map +1 -1
  205. package/dist/esm/CommandForm/fields/TextAreaField.js.map +1 -1
  206. package/dist/esm/CommandForm/index.d.ts +0 -1
  207. package/dist/esm/CommandForm/index.d.ts.map +1 -1
  208. package/dist/esm/CommandForm/index.js +3 -1
  209. package/dist/esm/CommandForm/index.js.map +1 -1
  210. package/dist/esm/Common/ErrorBoundary.js.map +1 -1
  211. package/dist/esm/Common/FormElement.js.map +1 -1
  212. package/dist/esm/Common/Page.js.map +1 -1
  213. package/dist/esm/Common/Tooltip.js +4 -0
  214. package/dist/esm/Common/Tooltip.js.map +1 -1
  215. package/dist/esm/Common/index.js +3 -0
  216. package/dist/esm/Common/index.js.map +1 -1
  217. package/dist/esm/DataPage/DataPage.js +6 -0
  218. package/dist/esm/DataPage/DataPage.js.map +1 -1
  219. package/dist/esm/DataPage/index.js +3 -0
  220. package/dist/esm/DataPage/index.js.map +1 -1
  221. package/dist/esm/DataTables/DataTableForObservableQuery.js +5 -0
  222. package/dist/esm/DataTables/DataTableForObservableQuery.js.map +1 -1
  223. package/dist/esm/DataTables/DataTableForQuery.js +5 -0
  224. package/dist/esm/DataTables/DataTableForQuery.js.map +1 -1
  225. package/dist/esm/DataTables/index.js +3 -0
  226. package/dist/esm/DataTables/index.js.map +1 -1
  227. package/dist/esm/Dialogs/BusyIndicatorDialog.js.map +1 -1
  228. package/dist/esm/Dialogs/ConfirmationDialog.js.map +1 -1
  229. package/dist/esm/Dialogs/Dialog.js +7 -1
  230. package/dist/esm/Dialogs/Dialog.js.map +1 -1
  231. package/dist/esm/Dialogs/index.js +3 -0
  232. package/dist/esm/Dialogs/index.js.map +1 -1
  233. package/dist/esm/Dropdown/Dropdown.js +1 -0
  234. package/dist/esm/Dropdown/Dropdown.js.map +1 -1
  235. package/dist/esm/Dropdown/index.js +3 -0
  236. package/dist/esm/Dropdown/index.js.map +1 -1
  237. package/dist/esm/ObjectContentEditor/ObjectContentEditor.js.map +1 -1
  238. package/dist/esm/ObjectContentEditor/index.js +3 -0
  239. package/dist/esm/ObjectContentEditor/index.js.map +1 -1
  240. package/dist/esm/ObjectContentEditor/objectHelpers.js +6 -0
  241. package/dist/esm/ObjectContentEditor/objectHelpers.js.map +1 -1
  242. package/dist/esm/ObjectNavigationalBar/ObjectNavigationalBar.js.map +1 -1
  243. package/dist/esm/ObjectNavigationalBar/breadcrumbHelpers.js +6 -0
  244. package/dist/esm/ObjectNavigationalBar/breadcrumbHelpers.js.map +1 -1
  245. package/dist/esm/ObjectNavigationalBar/index.js +3 -0
  246. package/dist/esm/ObjectNavigationalBar/index.js.map +1 -1
  247. package/dist/esm/PivotViewer/PivotViewer.js +28 -0
  248. package/dist/esm/PivotViewer/PivotViewer.js.map +1 -1
  249. package/dist/esm/PivotViewer/components/AxisLabels.js +4 -0
  250. package/dist/esm/PivotViewer/components/AxisLabels.js.map +1 -1
  251. package/dist/esm/PivotViewer/components/DetailPanel.js.map +1 -1
  252. package/dist/esm/PivotViewer/components/FilterPanel.js +4 -0
  253. package/dist/esm/PivotViewer/components/FilterPanel.js.map +1 -1
  254. package/dist/esm/PivotViewer/components/FilterPanelContainer.js.map +1 -1
  255. package/dist/esm/PivotViewer/components/PivotCanvas.js +138 -2
  256. package/dist/esm/PivotViewer/components/PivotCanvas.js.map +1 -1
  257. package/dist/esm/PivotViewer/components/PivotViewerMain.js +4 -0
  258. package/dist/esm/PivotViewer/components/PivotViewerMain.js.map +1 -1
  259. package/dist/esm/PivotViewer/components/RangeHistogramFilter.js.map +1 -1
  260. package/dist/esm/PivotViewer/components/Spinner.js.map +1 -1
  261. package/dist/esm/PivotViewer/components/Toolbar.js.map +1 -1
  262. package/dist/esm/PivotViewer/components/ToolbarContainer.js.map +1 -1
  263. package/dist/esm/PivotViewer/components/pivot/animation.js +8 -1
  264. package/dist/esm/PivotViewer/components/pivot/animation.js.map +1 -1
  265. package/dist/esm/PivotViewer/components/pivot/colorResolver.js +3 -1
  266. package/dist/esm/PivotViewer/components/pivot/colorResolver.js.map +1 -1
  267. package/dist/esm/PivotViewer/components/pivot/constants.js +8 -5
  268. package/dist/esm/PivotViewer/components/pivot/constants.js.map +1 -1
  269. package/dist/esm/PivotViewer/components/pivot/groups.js +15 -0
  270. package/dist/esm/PivotViewer/components/pivot/groups.js.map +1 -1
  271. package/dist/esm/PivotViewer/components/pivot/sprites.js +19 -0
  272. package/dist/esm/PivotViewer/components/pivot/sprites.js.map +1 -1
  273. package/dist/esm/PivotViewer/components/pivot/visibility.js +102 -3
  274. package/dist/esm/PivotViewer/components/pivot/visibility.js.map +1 -1
  275. package/dist/esm/PivotViewer/constants.js +2 -0
  276. package/dist/esm/PivotViewer/constants.js.map +1 -1
  277. package/dist/esm/PivotViewer/engine/layout.js +23 -0
  278. package/dist/esm/PivotViewer/engine/layout.js.map +1 -1
  279. package/dist/esm/PivotViewer/engine/store.js +29 -0
  280. package/dist/esm/PivotViewer/engine/store.js.map +1 -1
  281. package/dist/esm/PivotViewer/hooks/useAnimationModeTracking.js +8 -0
  282. package/dist/esm/PivotViewer/hooks/useAnimationModeTracking.js.map +1 -1
  283. package/dist/esm/PivotViewer/hooks/useCardSelection.js +10 -1
  284. package/dist/esm/PivotViewer/hooks/useCardSelection.js.map +1 -1
  285. package/dist/esm/PivotViewer/hooks/useContainerDimensions.js +11 -0
  286. package/dist/esm/PivotViewer/hooks/useContainerDimensions.js.map +1 -1
  287. package/dist/esm/PivotViewer/hooks/useCurrentFilters.js +6 -0
  288. package/dist/esm/PivotViewer/hooks/useCurrentFilters.js.map +1 -1
  289. package/dist/esm/PivotViewer/hooks/useDetailPanelClose.js +11 -1
  290. package/dist/esm/PivotViewer/hooks/useDetailPanelClose.js.map +1 -1
  291. package/dist/esm/PivotViewer/hooks/useDimensionState.js +2 -0
  292. package/dist/esm/PivotViewer/hooks/useDimensionState.js.map +1 -1
  293. package/dist/esm/PivotViewer/hooks/useFieldExtractors.js +2 -0
  294. package/dist/esm/PivotViewer/hooks/useFieldExtractors.js.map +1 -1
  295. package/dist/esm/PivotViewer/hooks/useFilterOptions.js +2 -0
  296. package/dist/esm/PivotViewer/hooks/useFilterOptions.js.map +1 -1
  297. package/dist/esm/PivotViewer/hooks/useFilterState.js +5 -0
  298. package/dist/esm/PivotViewer/hooks/useFilterState.js.map +1 -1
  299. package/dist/esm/PivotViewer/hooks/usePanning.js +14 -0
  300. package/dist/esm/PivotViewer/hooks/usePanning.js.map +1 -1
  301. package/dist/esm/PivotViewer/hooks/usePivotEngine.js +7 -0
  302. package/dist/esm/PivotViewer/hooks/usePivotEngine.js.map +1 -1
  303. package/dist/esm/PivotViewer/hooks/useScrollSync.js +6 -0
  304. package/dist/esm/PivotViewer/hooks/useScrollSync.js.map +1 -1
  305. package/dist/esm/PivotViewer/hooks/useViewModeScrollHandling.js +9 -0
  306. package/dist/esm/PivotViewer/hooks/useViewModeScrollHandling.js.map +1 -1
  307. package/dist/esm/PivotViewer/hooks/useWheelZoom.js +8 -2
  308. package/dist/esm/PivotViewer/hooks/useWheelZoom.js.map +1 -1
  309. package/dist/esm/PivotViewer/hooks/useZoomState.js +2 -0
  310. package/dist/esm/PivotViewer/hooks/useZoomState.js.map +1 -1
  311. package/dist/esm/PivotViewer/index.js +3 -0
  312. package/dist/esm/PivotViewer/index.js.map +1 -1
  313. package/dist/esm/PivotViewer/types.js +11 -0
  314. package/dist/esm/PivotViewer/types.js.map +1 -1
  315. package/dist/esm/PivotViewer/utils/animations.js +35 -2
  316. package/dist/esm/PivotViewer/utils/animations.js.map +1 -1
  317. package/dist/esm/PivotViewer/utils/cardPosition.js +21 -3
  318. package/dist/esm/PivotViewer/utils/cardPosition.js.map +1 -1
  319. package/dist/esm/PivotViewer/utils/constants.js +3 -0
  320. package/dist/esm/PivotViewer/utils/constants.js.map +1 -1
  321. package/dist/esm/PivotViewer/utils/idResolution.js +16 -0
  322. package/dist/esm/PivotViewer/utils/idResolution.js.map +1 -1
  323. package/dist/esm/PivotViewer/utils/selection.js +25 -0
  324. package/dist/esm/PivotViewer/utils/selection.js.map +1 -1
  325. package/dist/esm/PivotViewer/utils/utils.js +5 -0
  326. package/dist/esm/PivotViewer/utils/utils.js.map +1 -1
  327. package/dist/esm/SchemaEditor/NameCell.js.map +1 -1
  328. package/dist/esm/SchemaEditor/SchemaEditor.js.map +1 -1
  329. package/dist/esm/SchemaEditor/TypeCell.js.map +1 -1
  330. package/dist/esm/SchemaEditor/index.js +3 -0
  331. package/dist/esm/SchemaEditor/index.js.map +1 -1
  332. package/dist/esm/SchemaEditor/schemaHelpers.js +8 -0
  333. package/dist/esm/SchemaEditor/schemaHelpers.js.map +1 -1
  334. package/dist/esm/TimeMachine/EventsView.js +2 -0
  335. package/dist/esm/TimeMachine/EventsView.js.map +1 -1
  336. package/dist/esm/TimeMachine/Properties.js.map +1 -1
  337. package/dist/esm/TimeMachine/ReadModelView.js +1 -0
  338. package/dist/esm/TimeMachine/ReadModelView.js.map +1 -1
  339. package/dist/esm/TimeMachine/TimeMachine.js +11 -1
  340. package/dist/esm/TimeMachine/TimeMachine.js.map +1 -1
  341. package/dist/esm/TimeMachine/index.js +3 -0
  342. package/dist/esm/TimeMachine/index.js.map +1 -1
  343. package/dist/esm/TimeMachine/propertiesHelpers.js +5 -0
  344. package/dist/esm/TimeMachine/propertiesHelpers.js.map +1 -1
  345. package/dist/esm/Toolbar/Toolbar.css +8 -0
  346. package/dist/esm/Toolbar/Toolbar.d.ts +3 -1
  347. package/dist/esm/Toolbar/Toolbar.d.ts.map +1 -1
  348. package/dist/esm/Toolbar/Toolbar.js +7 -1
  349. package/dist/esm/Toolbar/Toolbar.js.map +1 -1
  350. package/dist/esm/Toolbar/Toolbar.stories.d.ts +1 -0
  351. package/dist/esm/Toolbar/Toolbar.stories.d.ts.map +1 -1
  352. package/dist/esm/Toolbar/Toolbar.stories.js +23 -0
  353. package/dist/esm/Toolbar/Toolbar.stories.js.map +1 -1
  354. package/dist/esm/Toolbar/ToolbarButton.d.ts +4 -1
  355. package/dist/esm/Toolbar/ToolbarButton.d.ts.map +1 -1
  356. package/dist/esm/Toolbar/ToolbarButton.js +16 -2
  357. package/dist/esm/Toolbar/ToolbarButton.js.map +1 -1
  358. package/dist/esm/Toolbar/ToolbarContext.js +8 -0
  359. package/dist/esm/Toolbar/ToolbarContext.js.map +1 -1
  360. package/dist/esm/Toolbar/ToolbarDragContext.d.ts +7 -0
  361. package/dist/esm/Toolbar/ToolbarDragContext.d.ts.map +1 -0
  362. package/dist/esm/Toolbar/ToolbarDragContext.js +21 -0
  363. package/dist/esm/Toolbar/ToolbarDragContext.js.map +1 -0
  364. package/dist/esm/Toolbar/ToolbarFanOutItem.js +11 -0
  365. package/dist/esm/Toolbar/ToolbarFanOutItem.js.map +1 -1
  366. package/dist/esm/Toolbar/ToolbarSection.js +18 -1
  367. package/dist/esm/Toolbar/ToolbarSection.js.map +1 -1
  368. package/dist/esm/Toolbar/ToolbarSeparator.js +6 -0
  369. package/dist/esm/Toolbar/ToolbarSeparator.js.map +1 -1
  370. package/dist/esm/Toolbar/index.js +3 -0
  371. package/dist/esm/Toolbar/index.js.map +1 -1
  372. package/dist/esm/tailwind-utilities.css +16 -1
  373. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  374. package/dist/esm/types/TypeFormat.js +2 -0
  375. package/dist/esm/types/TypeFormat.js.map +1 -1
  376. package/dist/esm/types/index.js +3 -0
  377. package/dist/esm/types/index.js.map +1 -1
  378. package/dist/esm/useOverlayZIndex.js +10 -0
  379. package/dist/esm/useOverlayZIndex.js.map +1 -1
  380. package/package.json +12 -13
@@ -1,6 +1,8 @@
1
1
  import * as PIXI from 'pixi.js';
2
2
  import { CARD_RADIUS, CARD_PADDING, CARD_GAP } from './constants.js';
3
3
 
4
+ // Copyright (c) Cratis. All rights reserved.
5
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
4
6
  const spritePool = [];
5
7
  function createCardSprite(id, x, y, items, onCardClick, onPanStart, cardWidth, cardHeight, cardColors, cardRenderer, resolveId) {
6
8
  if (spritePool.length > 0) {
@@ -15,21 +17,25 @@ function createCardSprite(id, x, y, items, onCardClick, onPanStart, cardWidth, c
15
17
  sprite.targetY = y;
16
18
  sprite.currentX = x;
17
19
  sprite.currentY = y;
20
+ // Reset animation state
18
21
  delete sprite.animationStartTime;
19
22
  delete sprite.animationDelay;
20
23
  delete sprite.startX;
21
24
  delete sprite.startY;
25
+ // Reset cache
22
26
  sprite.lastSelectedId = null;
23
27
  sprite.lastCardColors = undefined;
24
28
  sprite.lastTitle = undefined;
25
29
  sprite.lastLabels = undefined;
26
30
  sprite.lastValues = undefined;
31
+ // Recreate graphics if it was destroyed
27
32
  if (!sprite.graphics || sprite.graphics.destroyed) {
28
33
  sprite.graphics = new PIXI.Graphics();
29
34
  if (sprite.container) {
30
35
  sprite.container.addChildAt(sprite.graphics, 0);
31
36
  }
32
37
  }
38
+ // Recreate text objects if they were destroyed
33
39
  const offsetX = CARD_GAP / 2;
34
40
  const offsetY = CARD_GAP / 2;
35
41
  if (!sprite.titleText || sprite.titleText.destroyed) {
@@ -70,6 +76,7 @@ function createCardSprite(id, x, y, items, onCardClick, onPanStart, cardWidth, c
70
76
  sprite.container.addChild(sprite.valuesText);
71
77
  }
72
78
  }
79
+ // Update event context
73
80
  if (sprite.container) {
74
81
  sprite.container._eventContext = { items, onCardClick, id, cardRenderer, resolveId };
75
82
  }
@@ -79,7 +86,11 @@ function createCardSprite(id, x, y, items, onCardClick, onPanStart, cardWidth, c
79
86
  container.eventMode = 'static';
80
87
  container.cursor = 'pointer';
81
88
  container.position.set(x, y);
89
+ // Define hit area to match the visible card size (excluding gaps)
90
+ // This ensures the entire card is clickable and avoids issues with text blocking hits
82
91
  container.hitArea = new PIXI.Rectangle(CARD_GAP / 2, CARD_GAP / 2, cardWidth - CARD_GAP, cardHeight - CARD_GAP);
92
+ // Container configured for pointer interactions; hitArea matches visible card.
93
+ // Store context for event handlers
83
94
  container._eventContext = { items, onCardClick, id, cardRenderer, resolveId };
84
95
  const graphics = new PIXI.Graphics();
85
96
  const actualWidth = cardWidth - CARD_GAP;
@@ -130,6 +141,7 @@ function createCardSprite(id, x, y, items, onCardClick, onPanStart, cardWidth, c
130
141
  });
131
142
  container.on('pointerdown', (e) => {
132
143
  e.stopPropagation();
144
+ // onPanStart(e.nativeEvent as MouseEvent);
133
145
  });
134
146
  return {
135
147
  container,
@@ -148,20 +160,24 @@ function destroySprite(sprite) {
148
160
  if (sprite.container && sprite.container.parent) {
149
161
  sprite.container.parent.removeChild(sprite.container);
150
162
  }
163
+ // Reset visibility to ensure it doesn't ghost if something goes wrong
151
164
  if (sprite.container) {
152
165
  sprite.container.visible = false;
153
166
  }
154
167
  spritePool.push(sprite);
155
168
  }
169
+ // Updated: Text objects now recreated when recycling pooled sprites
156
170
  function updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, cardColors, cardRenderer) {
157
171
  if (!item)
158
172
  return;
173
+ // Selection rendering depends on sprite.itemId matching selectedId
159
174
  const colors = cardColors;
160
175
  const cardData = cardRenderer(item);
161
176
  const titleDisplay = cardData.title;
162
177
  const labelsText = (cardData.labels || []).join('\n');
163
178
  const valuesText = (cardData.values || []).join('\n');
164
179
  const colorsChanged = sprite.lastCardColors !== colors;
180
+ // Ensure text objects exist before using them
165
181
  if (!sprite.titleText || sprite.titleText.destroyed)
166
182
  return;
167
183
  if (!sprite.labelsText || sprite.labelsText.destroyed)
@@ -190,11 +206,13 @@ function updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, card
190
206
  sprite.labelsText.visible = true;
191
207
  sprite.valuesText.visible = true;
192
208
  const isSelected = sprite.itemId === selectedId;
209
+ // Only redraw graphics if selection state or colors changed
193
210
  if (sprite.lastSelectedId === selectedId && !colorsChanged && sprite.graphics) {
194
211
  return;
195
212
  }
196
213
  sprite.lastSelectedId = selectedId;
197
214
  sprite.lastCardColors = cardColors;
215
+ // Ensure graphics exists before attempting to use it
198
216
  if (!sprite.graphics || sprite.graphics.destroyed) {
199
217
  sprite.graphics = new PIXI.Graphics();
200
218
  if (sprite.container) {
@@ -218,6 +236,7 @@ function updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, card
218
236
  gradient.addColorStop(1, colors.base);
219
237
  }
220
238
  sprite.graphics.roundRect(offsetX, offsetY, actualWidth, actualHeight, CARD_RADIUS);
239
+ // Ensure graphics is still valid before filling
221
240
  if (sprite.graphics && !sprite.graphics.destroyed) {
222
241
  sprite.graphics.fill(gradient);
223
242
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sprites.js","sources":["../../../../../PivotViewer/components/pivot/sprites.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 { CARD_GAP, CARD_PADDING, CARD_RADIUS } from './constants';\nimport type { CardSprite, CardColors } from './constants';\n\nconst spritePool: CardSprite[] = [];\n\nexport function createCardSprite<TItem extends object>(\n id: number | string,\n x: number,\n y: number,\n items: TItem[],\n onCardClick: (item: TItem, e: MouseEvent, id: number | string) => void,\n onPanStart: (e: MouseEvent) => void,\n cardWidth: number,\n cardHeight: number,\n cardColors: CardColors,\n cardRenderer: (item: TItem) => { title: string; labels?: string[]; values?: string[] },\n resolveId: (item: TItem, index: number) => string | number,\n): CardSprite {\n if (spritePool.length > 0) {\n const sprite = spritePool.pop()!;\n if (sprite.container) {\n sprite.container.visible = true;\n sprite.container.alpha = 1;\n sprite.container.position.set(x, y);\n }\n sprite.itemId = id;\n sprite.targetX = x;\n sprite.targetY = y;\n sprite.currentX = x;\n sprite.currentY = y;\n\n // Reset animation state\n delete sprite.animationStartTime;\n delete sprite.animationDelay;\n delete sprite.startX;\n delete sprite.startY;\n\n // Reset cache\n sprite.lastSelectedId = null;\n sprite.lastCardColors = undefined;\n sprite.lastTitle = undefined;\n sprite.lastLabels = undefined;\n sprite.lastValues = undefined;\n\n // Recreate graphics if it was destroyed\n if (!sprite.graphics || sprite.graphics.destroyed) {\n sprite.graphics = new PIXI.Graphics();\n if (sprite.container) {\n sprite.container.addChildAt(sprite.graphics, 0);\n }\n }\n\n // Recreate text objects if they were destroyed\n const offsetX = CARD_GAP / 2;\n const offsetY = CARD_GAP / 2;\n \n if (!sprite.titleText || sprite.titleText.destroyed) {\n sprite.titleText = new PIXI.Text('', {\n fontSize: 13,\n fill: cardColors.text as string | number,\n fontWeight: '600',\n lineHeight: 18,\n wordWrap: false,\n } as PIXI.TextStyle);\n sprite.titleText.position.set(offsetX + CARD_PADDING, offsetY + CARD_PADDING);\n if (sprite.container) {\n sprite.container.addChild(sprite.titleText);\n }\n }\n\n if (!sprite.labelsText || sprite.labelsText.destroyed) {\n sprite.labelsText = new PIXI.Text('', {\n fontSize: 11,\n fill: cardColors.textSecondary as string | number,\n fontWeight: '400',\n lineHeight: 18,\n } as PIXI.TextStyle);\n sprite.labelsText.position.set(offsetX + CARD_PADDING, offsetY + CARD_PADDING + 40);\n if (sprite.container) {\n sprite.container.addChild(sprite.labelsText);\n }\n }\n\n if (!sprite.valuesText || sprite.valuesText.destroyed) {\n sprite.valuesText = new PIXI.Text('', {\n fontSize: 11,\n fill: cardColors.text as string | number,\n fontWeight: '500',\n lineHeight: 18,\n wordWrap: false,\n } as PIXI.TextStyle);\n sprite.valuesText.position.set(offsetX + CARD_PADDING + 65, offsetY + CARD_PADDING + 40);\n if (sprite.container) {\n sprite.container.addChild(sprite.valuesText);\n }\n }\n\n // Update event context\n if (sprite.container) {\n (sprite.container as unknown as { _eventContext: { items: TItem[]; onCardClick: (item: TItem, e: MouseEvent, id: number | string) => void; id: number | string; cardRenderer: (item: TItem) => { title: string; labels?: string[]; values?: string[] }; resolveId: (item: TItem, index: number) => string | number } })._eventContext = { items, onCardClick, id, cardRenderer, resolveId };\n }\n\n return sprite;\n }\n\n const container = new PIXI.Container();\n container.eventMode = 'static';\n container.cursor = 'pointer';\n container.position.set(x, y);\n\n // Define hit area to match the visible card size (excluding gaps)\n // This ensures the entire card is clickable and avoids issues with text blocking hits\n container.hitArea = new PIXI.Rectangle(\n CARD_GAP / 2,\n CARD_GAP / 2,\n cardWidth - CARD_GAP,\n cardHeight - CARD_GAP\n );\n\n // Container configured for pointer interactions; hitArea matches visible card.\n\n // Store context for event handlers\n (container as unknown as { _eventContext: { items: TItem[]; onCardClick: (item: TItem, e: MouseEvent, id: number | string) => void; id: number | string; cardRenderer: (item: TItem) => { title: string; labels?: string[]; values?: string[] }; resolveId: (item: TItem, index: number) => string | number } })._eventContext = { items, onCardClick, id, cardRenderer, resolveId };\n\n const graphics = new PIXI.Graphics();\n\n const actualWidth = cardWidth - CARD_GAP;\n const actualHeight = cardHeight - CARD_GAP;\n const offsetX = CARD_GAP / 2;\n const offsetY = CARD_GAP / 2;\n\n const gradient = new PIXI.FillGradient(0, offsetY, 0, offsetY + actualHeight);\n gradient.addColorStop(0, cardColors.mid);\n gradient.addColorStop(1, cardColors.base);\n\n graphics.roundRect(offsetX, offsetY, actualWidth, actualHeight, CARD_RADIUS);\n graphics.fill(gradient);\n\n container.addChild(graphics);\n\n const titleText = new PIXI.Text('', {\n fontSize: 13,\n fill: cardColors.text as string | number,\n fontWeight: '600',\n lineHeight: 18,\n wordWrap: false,\n } as PIXI.TextStyle);\n titleText.position.set(offsetX + CARD_PADDING, offsetY + CARD_PADDING);\n container.addChild(titleText);\n\n const labelsText = new PIXI.Text('', {\n fontSize: 11,\n fill: cardColors.textSecondary as string | number,\n fontWeight: '400',\n lineHeight: 18,\n } as PIXI.TextStyle);\n labelsText.position.set(offsetX + CARD_PADDING, offsetY + CARD_PADDING + 40);\n container.addChild(labelsText);\n\n const valuesText = new PIXI.Text('', {\n fontSize: 11,\n fill: cardColors.text as string | number,\n fontWeight: '500',\n lineHeight: 18,\n wordWrap: false,\n } as PIXI.TextStyle);\n valuesText.position.set(offsetX + CARD_PADDING + 65, offsetY + CARD_PADDING + 40);\n container.addChild(valuesText);\n\n container.on('click', (e: PIXI.FederatedPointerEvent) => {\n e.stopPropagation();\n const ctx = (container as unknown as { _eventContext: { items: TItem[]; onCardClick: (item: TItem, e: MouseEvent, id: number | string) => void; id: number | string } })._eventContext;\n const itemsArray = ctx.items;\n const numericId = typeof ctx.id === 'number' ? ctx.id : Number(ctx.id);\n const item = itemsArray[numericId];\n if (item) {\n ctx.onCardClick(item, e.nativeEvent as MouseEvent, ctx.id);\n }\n });\n\n container.on('pointerdown', (e: PIXI.FederatedPointerEvent) => {\n e.stopPropagation();\n // onPanStart(e.nativeEvent as MouseEvent);\n });\n\n return {\n container,\n graphics,\n titleText,\n labelsText,\n valuesText,\n itemId: id,\n targetX: x,\n targetY: y,\n currentX: x,\n currentY: y,\n };\n}\n\nexport function destroySprite(sprite: CardSprite) {\n if (sprite.container && sprite.container.parent) {\n sprite.container.parent.removeChild(sprite.container);\n }\n // Reset visibility to ensure it doesn't ghost if something goes wrong\n if (sprite.container) {\n sprite.container.visible = false;\n }\n spritePool.push(sprite);\n}\n\nexport function clearSpritePool() {\n for (const sprite of spritePool) {\n try {\n sprite.graphics?.destroy();\n sprite.titleText?.destroy();\n sprite.labelsText?.destroy();\n sprite.valuesText?.destroy();\n sprite.container?.destroy();\n } catch (e) {\n void e;\n }\n }\n spritePool.length = 0;\n}\n\n// Updated: Text objects now recreated when recycling pooled sprites\nexport function updateCardContent<TItem extends object>(\n sprite: CardSprite,\n item: TItem,\n selectedId: string | number | null,\n cardWidth: number,\n cardHeight: number,\n cardColors: CardColors,\n cardRenderer: (item: TItem) => { title: string; labels?: string[]; values?: string[] },\n) {\n if (!item) return;\n\n // Selection rendering depends on sprite.itemId matching selectedId\n\n const colors = cardColors;\n const cardData = cardRenderer(item);\n const titleDisplay = cardData.title;\n const labelsText = (cardData.labels || []).join('\\n');\n const valuesText = (cardData.values || []).join('\\n');\n const colorsChanged = sprite.lastCardColors !== colors;\n\n // Ensure text objects exist before using them\n if (!sprite.titleText || sprite.titleText.destroyed) return;\n if (!sprite.labelsText || sprite.labelsText.destroyed) return;\n if (!sprite.valuesText || sprite.valuesText.destroyed) return;\n\n if (sprite.lastTitle !== titleDisplay) {\n sprite.titleText.text = titleDisplay;\n sprite.lastTitle = titleDisplay;\n }\n\n if (sprite.lastLabels !== labelsText) {\n sprite.labelsText.text = labelsText;\n sprite.lastLabels = labelsText;\n }\n\n if (colorsChanged && sprite.labelsText.style) {\n (sprite.labelsText.style as unknown as { fill: string | number }).fill = colors.textSecondary;\n }\n\n if (sprite.lastValues !== valuesText) {\n sprite.valuesText.text = valuesText;\n sprite.lastValues = valuesText;\n }\n\n if (colorsChanged && sprite.valuesText.style) {\n (sprite.valuesText.style as unknown as { fill: string | number }).fill = colors.text;\n }\n\n sprite.titleText.visible = true;\n sprite.labelsText.visible = true;\n sprite.valuesText.visible = true;\n\n const isSelected = sprite.itemId === selectedId;\n\n // Only redraw graphics if selection state or colors changed\n if (sprite.lastSelectedId === selectedId && !colorsChanged && sprite.graphics) {\n return;\n }\n\n sprite.lastSelectedId = selectedId;\n sprite.lastCardColors = cardColors;\n\n // Ensure graphics exists before attempting to use it\n if (!sprite.graphics || sprite.graphics.destroyed) {\n sprite.graphics = new PIXI.Graphics();\n if (sprite.container) {\n sprite.container.addChildAt(sprite.graphics, 0);\n }\n } else {\n sprite.graphics.clear();\n }\n\n const actualWidth = cardWidth - CARD_GAP;\n const actualHeight = cardHeight - CARD_GAP;\n const offsetX = CARD_GAP / 2;\n const offsetY = CARD_GAP / 2;\n\n const gradient = new PIXI.FillGradient(0, offsetY, 0, offsetY + actualHeight);\n if (isSelected) {\n gradient.addColorStop(0, colors.gradient);\n gradient.addColorStop(1, colors.mid);\n } else {\n gradient.addColorStop(0, colors.mid);\n gradient.addColorStop(1, colors.base);\n }\n\n sprite.graphics.roundRect(offsetX, offsetY, actualWidth, actualHeight, CARD_RADIUS);\n \n // Ensure graphics is still valid before filling\n if (sprite.graphics && !sprite.graphics.destroyed) {\n sprite.graphics.fill(gradient);\n }\n\n if (isSelected) {\n if (sprite.graphics && !sprite.graphics.destroyed) {\n sprite.graphics.stroke({ width: 2, color: colors.border });\n }\n } else {\n if (sprite.graphics && !sprite.graphics.destroyed) {\n sprite.graphics.stroke({ width: 1, color: colors.border, alpha: 0.35 });\n }\n }\n}\n"],"names":[],"mappings":";;;AAOA,MAAM,UAAU,GAAiB,EAAE;AAE7B,SAAU,gBAAgB,CAC9B,EAAmB,EACnB,CAAS,EACT,CAAS,EACT,KAAc,EACd,WAAsE,EACtE,UAAmC,EACnC,SAAiB,EACjB,UAAkB,EAClB,UAAsB,EACtB,YAAsF,EACtF,SAA0D,EAAA;AAE1D,IAAA,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;AACzB,QAAA,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAG;AAChC,QAAA,IAAI,MAAM,CAAC,SAAS,EAAE;AACpB,YAAA,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,IAAI;AAC/B,YAAA,MAAM,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC;YAC1B,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QACrC;AACA,QAAA,MAAM,CAAC,MAAM,GAAG,EAAE;AAClB,QAAA,MAAM,CAAC,OAAO,GAAG,CAAC;AAClB,QAAA,MAAM,CAAC,OAAO,GAAG,CAAC;AAClB,QAAA,MAAM,CAAC,QAAQ,GAAG,CAAC;AACnB,QAAA,MAAM,CAAC,QAAQ,GAAG,CAAC;QAGnB,OAAO,MAAM,CAAC,kBAAkB;QAChC,OAAO,MAAM,CAAC,cAAc;QAC5B,OAAO,MAAM,CAAC,MAAM;QACpB,OAAO,MAAM,CAAC,MAAM;AAGpB,QAAA,MAAM,CAAC,cAAc,GAAG,IAAI;AAC5B,QAAA,MAAM,CAAC,cAAc,GAAG,SAAS;AACjC,QAAA,MAAM,CAAC,SAAS,GAAG,SAAS;AAC5B,QAAA,MAAM,CAAC,UAAU,GAAG,SAAS;AAC7B,QAAA,MAAM,CAAC,UAAU,GAAG,SAAS;QAG7B,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE;YACjD,MAAM,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE;AACrC,YAAA,IAAI,MAAM,CAAC,SAAS,EAAE;gBACpB,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;YACjD;QACF;AAGA,QAAA,MAAM,OAAO,GAAG,QAAQ,GAAG,CAAC;AAC5B,QAAA,MAAM,OAAO,GAAG,QAAQ,GAAG,CAAC;QAE5B,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE;YACnD,MAAM,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;AACnC,gBAAA,QAAQ,EAAE,EAAE;gBACZ,IAAI,EAAE,UAAU,CAAC,IAAuB;AACxC,gBAAA,UAAU,EAAE,KAAK;AACjB,gBAAA,UAAU,EAAE,EAAE;AACd,gBAAA,QAAQ,EAAE,KAAK;AACE,aAAA,CAAC;AACpB,YAAA,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,GAAG,YAAY,EAAE,OAAO,GAAG,YAAY,CAAC;AAC7E,YAAA,IAAI,MAAM,CAAC,SAAS,EAAE;gBACpB,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;YAC7C;QACF;QAEA,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE;YACrD,MAAM,CAAC,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;AACpC,gBAAA,QAAQ,EAAE,EAAE;gBACZ,IAAI,EAAE,UAAU,CAAC,aAAgC;AACjD,gBAAA,UAAU,EAAE,KAAK;AACjB,gBAAA,UAAU,EAAE,EAAE;AACG,aAAA,CAAC;AACpB,YAAA,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,GAAG,YAAY,EAAE,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;AACnF,YAAA,IAAI,MAAM,CAAC,SAAS,EAAE;gBACpB,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC;YAC9C;QACF;QAEA,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE;YACrD,MAAM,CAAC,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;AACpC,gBAAA,QAAQ,EAAE,EAAE;gBACZ,IAAI,EAAE,UAAU,CAAC,IAAuB;AACxC,gBAAA,UAAU,EAAE,KAAK;AACjB,gBAAA,UAAU,EAAE,EAAE;AACd,gBAAA,QAAQ,EAAE,KAAK;AACE,aAAA,CAAC;AACpB,YAAA,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,GAAG,YAAY,GAAG,EAAE,EAAE,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;AACxF,YAAA,IAAI,MAAM,CAAC,SAAS,EAAE;gBACpB,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC;YAC9C;QACF;AAGA,QAAA,IAAI,MAAM,CAAC,SAAS,EAAE;AACnB,YAAA,MAAM,CAAC,SAA+S,CAAC,aAAa,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE;QAC7X;AAEA,QAAA,OAAO,MAAM;IACf;AAEA,IAAA,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,EAAE;AACtC,IAAA,SAAS,CAAC,SAAS,GAAG,QAAQ;AAC9B,IAAA,SAAS,CAAC,MAAM,GAAG,SAAS;IAC5B,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;IAI5B,SAAS,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,CAClC,QAAQ,GAAG,CAAC,EACZ,QAAQ,GAAG,CAAC,EACZ,SAAS,GAAG,QAAQ,EACpB,UAAU,GAAG,QAAQ,CACxB;AAKA,IAAA,SAA+S,CAAC,aAAa,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE;AAEpX,IAAA,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE;AAEpC,IAAA,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ;AACxC,IAAA,MAAM,YAAY,GAAG,UAAU,GAAG,QAAQ;AAC1C,IAAA,MAAM,OAAO,GAAG,QAAQ,GAAG,CAAC;AAC5B,IAAA,MAAM,OAAO,GAAG,QAAQ,GAAG,CAAC;AAE5B,IAAA,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;IAC7E,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC;IACxC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC;AAEzC,IAAA,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,CAAC;AAC5E,IAAA,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;AAEvB,IAAA,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAE5B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;AAClC,QAAA,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,UAAU,CAAC,IAAuB;AACxC,QAAA,UAAU,EAAE,KAAK;AACjB,QAAA,UAAU,EAAE,EAAE;AACd,QAAA,QAAQ,EAAE,KAAK;AACE,KAAA,CAAC;AACpB,IAAA,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,GAAG,YAAY,EAAE,OAAO,GAAG,YAAY,CAAC;AACtE,IAAA,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC;IAE7B,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;AACnC,QAAA,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,UAAU,CAAC,aAAgC;AACjD,QAAA,UAAU,EAAE,KAAK;AACjB,QAAA,UAAU,EAAE,EAAE;AACG,KAAA,CAAC;AACpB,IAAA,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,GAAG,YAAY,EAAE,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;AAC5E,IAAA,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC;IAE9B,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;AACnC,QAAA,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,UAAU,CAAC,IAAuB;AACxC,QAAA,UAAU,EAAE,KAAK;AACjB,QAAA,UAAU,EAAE,EAAE;AACd,QAAA,QAAQ,EAAE,KAAK;AACE,KAAA,CAAC;AACpB,IAAA,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,GAAG,YAAY,GAAG,EAAE,EAAE,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;AACjF,IAAA,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC;IAE9B,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAA6B,KAAI;QACtD,CAAC,CAAC,eAAe,EAAE;AACnB,QAAA,MAAM,GAAG,GAAI,SAA2J,CAAC,aAAa;AACtL,QAAA,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK;QAC5B,MAAM,SAAS,GAAG,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,GAAG,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACtE,QAAA,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC;QAClC,IAAI,IAAI,EAAE;AACR,YAAA,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,WAAyB,EAAE,GAAG,CAAC,EAAE,CAAC;QAC5D;AACF,IAAA,CAAC,CAAC;IAEF,SAAS,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,CAA6B,KAAI;QAC5D,CAAC,CAAC,eAAe,EAAE;AAErB,IAAA,CAAC,CAAC;IAEF,OAAO;QACL,SAAS;QACT,QAAQ;QACR,SAAS;QACT,UAAU;QACV,UAAU;AACV,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,OAAO,EAAE,CAAC;AACV,QAAA,OAAO,EAAE,CAAC;AACV,QAAA,QAAQ,EAAE,CAAC;AACX,QAAA,QAAQ,EAAE,CAAC;KACZ;AACH;AAEM,SAAU,aAAa,CAAC,MAAkB,EAAA;IAC9C,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;QAC/C,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC;IACvD;AAEA,IAAA,IAAI,MAAM,CAAC,SAAS,EAAE;AACpB,QAAA,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,KAAK;IAClC;AACA,IAAA,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;AACzB;AAkBM,SAAU,iBAAiB,CAC/B,MAAkB,EAClB,IAAW,EACX,UAAkC,EAClC,SAAiB,EACjB,UAAkB,EAClB,UAAsB,EACtB,YAAsF,EAAA;AAEtF,IAAA,IAAI,CAAC,IAAI;QAAE;IAIX,MAAM,MAAM,GAAG,UAAU;AACzB,IAAA,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC;AACnC,IAAA,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK;AACnC,IAAA,MAAM,UAAU,GAAG,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC;AACrD,IAAA,MAAM,UAAU,GAAG,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC;AACrD,IAAA,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,KAAK,MAAM;IAGtD,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS;QAAE;IACrD,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS;QAAE;IACvD,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS;QAAE;AAEvD,IAAA,IAAI,MAAM,CAAC,SAAS,KAAK,YAAY,EAAE;AACrC,QAAA,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,YAAY;AACpC,QAAA,MAAM,CAAC,SAAS,GAAG,YAAY;IACjC;AAEE,IAAA,IAAI,MAAM,CAAC,UAAU,KAAK,UAAU,EAAE;AACtC,QAAA,MAAM,CAAC,UAAU,CAAC,IAAI,GAAG,UAAU;AACnC,QAAA,MAAM,CAAC,UAAU,GAAG,UAAU;IAChC;IAEA,IAAI,aAAa,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE;QAC3C,MAAM,CAAC,UAAU,CAAC,KAA8C,CAAC,IAAI,GAAG,MAAM,CAAC,aAAa;IAC/F;AAEA,IAAA,IAAI,MAAM,CAAC,UAAU,KAAK,UAAU,EAAE;AACpC,QAAA,MAAM,CAAC,UAAU,CAAC,IAAI,GAAG,UAAU;AACnC,QAAA,MAAM,CAAC,UAAU,GAAG,UAAU;IAChC;IAEA,IAAI,aAAa,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE;QAC3C,MAAM,CAAC,UAAU,CAAC,KAA8C,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI;IACtF;AAEA,IAAA,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,IAAI;AAC/B,IAAA,MAAM,CAAC,UAAU,CAAC,OAAO,GAAG,IAAI;AAChC,IAAA,MAAM,CAAC,UAAU,CAAC,OAAO,GAAG,IAAI;AAEhC,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,UAAU;AAG/C,IAAA,IAAI,MAAM,CAAC,cAAc,KAAK,UAAU,IAAI,CAAC,aAAa,IAAI,MAAM,CAAC,QAAQ,EAAE;QAC7E;IACF;AAEA,IAAA,MAAM,CAAC,cAAc,GAAG,UAAU;AAClC,IAAA,MAAM,CAAC,cAAc,GAAG,UAAU;IAGlC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE;QACjD,MAAM,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE;AACrC,QAAA,IAAI,MAAM,CAAC,SAAS,EAAE;YACpB,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjD;IACF;SAAO;AACL,QAAA,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE;IACzB;AAEA,IAAA,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ;AACxC,IAAA,MAAM,YAAY,GAAG,UAAU,GAAG,QAAQ;AAC1C,IAAA,MAAM,OAAO,GAAG,QAAQ,GAAG,CAAC;AAC5B,IAAA,MAAM,OAAO,GAAG,QAAQ,GAAG,CAAC;AAE5B,IAAA,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;IAC7E,IAAI,UAAU,EAAE;QACd,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;QACzC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC;IACtC;SAAO;QACL,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC;QACpC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC;IACvC;AAEA,IAAA,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,CAAC;IAGnF,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE;AACjD,QAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;IAChC;IAEA,IAAI,UAAU,EAAE;QACd,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE;AACjD,YAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC5D;IACF;SAAO;QACL,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE;YACjD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzE;IACF;AACF;;;;"}
1
+ {"version":3,"file":"sprites.js","sources":["../../../../../PivotViewer/components/pivot/sprites.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1,44 +1,101 @@
1
1
  import { CARD_GAP } from './constants.js';
2
2
  import { destroySprite } from './sprites.js';
3
3
 
4
+ // Copyright (c) Cratis. All rights reserved.
5
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
4
6
  function syncSpritesToViewport(params) {
5
7
  const { root, groupsContainer, container, sprites, layout, visibleIds: _visibleIds, items, cardWidth, cardHeight, panX, panY, panDeltaX, panDeltaY, viewportWidth, viewportHeight, createCardSprite, updateCardContent, zoomLevel, isViewTransition, viewMode, prevLayout, prevScrollTop, prevScrollLeft } = params;
6
8
  if (!root || !container)
7
9
  return;
10
+ // Use the container's measured client size for the viewport dimensions
11
+ // (in pixels). The passed `viewportWidth`/`viewportHeight` can be stale
12
+ // when the browser/device zoom changes; `clientWidth/clientHeight` are
13
+ // authoritative for the actual visible pixel area.
8
14
  const viewportPxWidth = container.clientWidth || viewportWidth;
9
15
  const viewportPxHeight = container.clientHeight || viewportHeight;
10
16
  const contentHeightPx = (layout.totalHeight || 0) * zoomLevel;
11
17
  let offsetY = 0;
18
+ // If content fits vertically within the viewport, align relative to bottom.
19
+ // The spacer ensures container isn't scrollable in this case (scrollTop=0).
20
+ // The items are at large Y coordinates relative to layout.totalHeight.
21
+ // We want the bottom of the layout (totalHeight) to align with viewport bottom.
12
22
  if (viewMode === 'grouped' && contentHeightPx < viewportPxHeight) {
23
+ // Calculate offset in pixels to shift the content down
13
24
  offsetY = viewportPxHeight - contentHeightPx;
14
25
  }
26
+ // Use the container's actual scroll position for positioning, not the passed panX/panY
27
+ // which may be stale (from React state) compared to live DOM scroll values.
15
28
  const actualScrollX = typeof container.scrollLeft === 'number' ? container.scrollLeft : (panX || 0);
16
29
  const actualScrollY = typeof container.scrollTop === 'number' ? container.scrollTop : (panY || 0);
30
+ // Apply scaling and position to root container
17
31
  if (root) {
18
32
  root.scale.set(zoomLevel);
33
+ // Standard position: -scrollX, -scrollY
34
+ // Plus vertical alignment offset if zoomed out
19
35
  root.position.set(-actualScrollX, offsetY - actualScrollY);
20
36
  }
37
+ // Apply synchronization to groups container if present
21
38
  if (groupsContainer) {
22
39
  groupsContainer.scale.set(zoomLevel);
23
40
  groupsContainer.position.set(-actualScrollX, offsetY - actualScrollY);
24
41
  }
42
+ // `visibleIds` comes from callers but this module iterates `layout.positions`
43
+ // Note: Pan delta compensation is NOT applied during view transitions because:
44
+ // 1. The time-based animation system handles position changes smoothly
45
+ // 2. Applying pan delta during animation interferes with the interpolation
46
+ // 3. The scroll position changes are a natural part of the view mode switch
47
+ // This compensation is only useful for rapid scrolling/panning where sprites
48
+ // need to maintain visual stability, which isn't the case during view transitions.
25
49
  const visibleSet = new Set();
50
+ // Increase buffer (in world units) to reduce edge cases where rapid
51
+ // scrolling skips sprite creation. Keep buffer in world units and convert
52
+ // DOM pixel measurements into world coordinates below to avoid mixing
53
+ // coordinate spaces which can cause precision drift at browser zooms.
26
54
  const baseBufferWorld = Math.max(cardWidth, cardHeight) * 4;
55
+ // Ensure buffer scales with viewport size (in world units) so that when
56
+ // zoomed out we still pre-create enough sprites ahead of the viewport.
27
57
  const invScale = zoomLevel && zoomLevel !== 0 ? 1 / zoomLevel : 1;
58
+ // The layout positions are in world units; when the root container is scaled
59
+ // (zoomed) the rendered pixel position = position * zoomLevel. The DOM
60
+ // scroll positions (`container.scrollLeft/Top`) are the authoritative pixel
61
+ // camera offsets; prefer them over the passed `panX/panY` to avoid stale
62
+ // values or race conditions between React state and direct DOM updates.
28
63
  const effectivePanX = typeof container.scrollLeft === 'number' ? container.scrollLeft : (panX || 0);
29
64
  const effectivePanY = typeof container.scrollTop === 'number' ? container.scrollTop : (panY || 0);
65
+ // Convert pixel-based DOM measurements into world units so we compare like
66
+ // with like. root.position is set using -pixels, so the mapping
67
+ // from DOM scroll (pixels) to world units is: world = pixels / zoomLevel.
68
+ // OffsetY is already in pixels and doesn't need scaling in panWorldY calc
69
+ // because panWorldY is used for viewport buffering/culling, which is relative
70
+ // to the "camera" position in world space.
71
+ // The camera world Y = (scrollTop - offsetY) / zoomLevel.
30
72
  const effectivePanYWithOffset = effectivePanY - offsetY;
31
73
  const panWorldX = effectivePanX * invScale;
32
74
  const panWorldY = effectivePanYWithOffset * invScale;
33
75
  const viewportWorldWidth = viewportPxWidth * invScale;
34
76
  const viewportWorldHeight = viewportPxHeight * invScale;
77
+ // Ensure bufferWorld is calculated from the actual measured viewport
78
+ // in world units (after converting client pixel dims using invScale).
79
+ // Make buffer adaptive to zoom: when zoomed out (invScale > 1) a small
80
+ // pixel scroll maps to a larger world delta, so increase the buffer.
81
+ // Use the larger of width/height to ensure we buffer enough in both directions.
35
82
  const bufferWorld = Math.max(baseBufferWorld * invScale, Math.max(viewportWorldWidth, viewportWorldHeight) * 2.0, baseBufferWorld);
83
+ // Do not clamp viewport edges to 0 — allow negative top/left values so the
84
+ // visible window correctly follows the scroll even when the buffer is
85
+ // larger than the current scroll offset.
36
86
  const viewportLeftWorld = panWorldX - bufferWorld;
37
87
  const viewportRightWorld = panWorldX + viewportWorldWidth + bufferWorld;
38
88
  const viewportTopWorld = panWorldY - bufferWorld;
39
89
  const viewportBottomWorld = panWorldY + viewportWorldHeight + bufferWorld;
40
90
  const inViewportIds = [];
91
+ // Small tolerance in world units to avoid floating-point edge cases when
92
+ // browser/device zoom or high scroll values produce tiny rounding errors.
93
+ // Scale epsilon with invScale so tolerance grows when zoomed out.
41
94
  const worldEpsilon = Math.max(0.5, 0.5 * invScale);
95
+ // Iterate layout positions directly to avoid depending on `visibleIds`
96
+ // which may be calculated in a different coordinate space or with
97
+ // different assumptions about zoom. Looping the positions map is
98
+ // deterministic and uses world coordinates directly.
42
99
  for (const [id, position] of layout.positions) {
43
100
  if (!position)
44
101
  continue;
@@ -54,21 +111,30 @@ function syncSpritesToViewport(params) {
54
111
  visibleSet.add(id);
55
112
  }
56
113
  }
114
+ // During view transitions, if no cards are visible and we're not animating yet,
115
+ // force-add the first few cards from the layout to ensure content appears.
116
+ // This prevents a blank screen when switching modes, especially in packaged builds
117
+ // where scroll stabilization might be delayed.
57
118
  if (isViewTransition && inViewportIds.length === 0 && layout.positions.size > 0) {
58
119
  let count = 0;
59
120
  for (const [id, position] of layout.positions) {
60
- if (count < 5 && position) {
121
+ if (count < 5 && position) { // Add up to 5 cards
61
122
  inViewportIds.push(id);
62
123
  visibleSet.add(id);
63
124
  count++;
64
125
  }
65
126
  }
66
127
  }
128
+ // Ensure last rows are present when the user scrolls near the bottom.
129
+ // Compute slot/row information and force-insert IDs from the last few
130
+ // rows to avoid missing tiles due to rounding/precision at zoom levels.
67
131
  try {
68
132
  const slotHeight = cardHeight + (CARD_GAP || 8);
69
133
  const totalRows = Math.ceil((layout.totalHeight || 0) / slotHeight) || 0;
134
+ // Determine how many rows are visible in the viewport (world units),
135
+ // then prefetch a fraction of that adjusted by zoom (invScale).
70
136
  const rowsVisible = Math.max(1, Math.ceil(viewportWorldHeight / slotHeight));
71
- const prefetchMultiplier = 0.75;
137
+ const prefetchMultiplier = 0.75; // fraction of viewport to prefetch
72
138
  const prefetchRows = Math.max(2, Math.ceil(rowsVisible * prefetchMultiplier * Math.max(1, invScale)));
73
139
  const lastRowThresholdY = Math.max(0, (totalRows - prefetchRows) * slotHeight);
74
140
  for (const [id, position] of layout.positions) {
@@ -82,6 +148,10 @@ function syncSpritesToViewport(params) {
82
148
  }
83
149
  catch (e) {
84
150
  }
151
+ // Fallback: if no sprites are calculated as visible (e.g., due to rounding
152
+ // or scroll/zoom race conditions), force a handful of cards into view so
153
+ // the canvas never renders empty at certain zoom levels.
154
+ // When transitioning views, be more aggressive to ensure content appears during the transition
85
155
  let injectedFallback = false;
86
156
  const fallbackCount = isViewTransition ? 30 : 12;
87
157
  if (inViewportIds.length === 0 && layout.positions.size > 0) {
@@ -95,6 +165,14 @@ function syncSpritesToViewport(params) {
95
165
  break;
96
166
  }
97
167
  }
168
+ // If we detect a very large discrepancy between created sprites and the
169
+ // computed in-viewport count, that's a signal our culling math may be
170
+ // unstable (especially at non-100% zoom). In that case, skip hiding this
171
+ // frame as a conservative safeguard to avoid mass disappearing tiles.
172
+ // However, disable this safeguard during view transitions to ensure old sprites are cleaned up.
173
+ // EXCEPT: During view transitions, if scroll position hasn't stabilized yet (e.g., switching to grouped
174
+ // mode triggers a scroll-to-bottom), keep all sprites visible to prevent flickering.
175
+ // Check scroll stabilization by comparing current scroll to previous scroll position.
98
176
  const currentScrollTop = container.scrollTop || 0;
99
177
  const currentScrollLeft = container.scrollLeft || 0;
100
178
  const scrollTopDelta = Math.abs(currentScrollTop - (prevScrollTop || currentScrollTop));
@@ -104,11 +182,14 @@ function syncSpritesToViewport(params) {
104
182
  (isViewTransition && !scrollStabilized));
105
183
  for (const [id, sprite] of sprites) {
106
184
  if (!visibleSet.has(id)) {
185
+ // If view transition is active, check if this sprite has a valid target in the new layout
186
+ // If so, keep it visible and animate it to the new position (even if off-screen)
107
187
  if (isViewTransition && layout.positions.has(id)) {
108
188
  const newPos = layout.positions.get(id);
109
189
  if (newPos) {
110
190
  sprite.targetX = newPos.x;
111
191
  sprite.targetY = newPos.y;
192
+ // Trigger animation if not already animating
112
193
  if (sprite.animationStartTime === undefined) {
113
194
  sprite.startX = sprite.currentX;
114
195
  sprite.startY = sprite.currentY;
@@ -121,12 +202,14 @@ function syncSpritesToViewport(params) {
121
202
  }
122
203
  catch (e) {
123
204
  }
205
+ // Don't mark as hidden, so it won't be swept
124
206
  if (sprite.__lastHiddenAt)
125
207
  delete sprite.__lastHiddenAt;
126
208
  continue;
127
209
  }
128
210
  }
129
211
  if (aggressiveCull) {
212
+ // Keep sprite visible this frame to avoid visual holes
130
213
  try {
131
214
  if (sprite.container)
132
215
  sprite.container.visible = true;
@@ -156,13 +239,15 @@ function syncSpritesToViewport(params) {
156
239
  }
157
240
  }
158
241
  }
242
+ // Sweep: actually destroy sprites that have been hidden longer than threshold
159
243
  try {
160
- const SWEEP_MS = 100;
244
+ const SWEEP_MS = 100; // keep hidden sprites for 100ms before destruction (reduced from 500ms for faster mode transitions)
161
245
  const now = Date.now();
162
246
  for (const [id, sprite] of sprites) {
163
247
  const lastHidden = sprite.__lastHiddenAt;
164
248
  if (lastHidden && now - lastHidden > SWEEP_MS) {
165
249
  try {
250
+ // remove from parent if present
166
251
  if (sprite.container && sprite.container.parent)
167
252
  sprite.container.parent.removeChild(sprite.container);
168
253
  }
@@ -181,6 +266,8 @@ function syncSpritesToViewport(params) {
181
266
  }
182
267
  catch (e) {
183
268
  }
269
+ // Limit the number of sprites created per frame to avoid choking the GPU/CPU
270
+ // when scrolling rapidly or zooming out significantly.
184
271
  const MAX_SPRITES_PER_FRAME = 50;
185
272
  let createdCount = 0;
186
273
  for (const id of inViewportIds) {
@@ -197,11 +284,15 @@ function syncSpritesToViewport(params) {
197
284
  let startX = position.x;
198
285
  let startY = position.y;
199
286
  let shouldAnimate = false;
287
+ // If view transition, try to find old position to fly in from
200
288
  if (isViewTransition && prevLayout && prevLayout.positions.has(id)) {
201
289
  const oldPos = prevLayout.positions.get(id);
202
290
  if (oldPos) {
203
291
  startX = oldPos.x;
204
292
  startY = oldPos.y;
293
+ // If we have a pan delta (camera jump), we need to adjust the start position
294
+ // so that the sprite appears at the same visual location relative to the NEW camera.
295
+ // StartWorld = OldWorld + PanDelta
205
296
  if (panDeltaX || panDeltaY) {
206
297
  const dx = (panDeltaX || 0) / (zoomLevel || 1);
207
298
  const dy = (panDeltaY || 0) / (zoomLevel || 1);
@@ -217,6 +308,8 @@ function syncSpritesToViewport(params) {
217
308
  root.addChild(sprite.container);
218
309
  sprite.currentX = startX;
219
310
  sprite.currentY = startY;
311
+ // Keep sprite.container positioned in world units; animation/update
312
+ // loop will apply root.scale/position to convert to pixels.
220
313
  sprite.container.position.set(startX, startY);
221
314
  }
222
315
  if (shouldAnimate) {
@@ -228,15 +321,21 @@ function syncSpritesToViewport(params) {
228
321
  sprite.animationDelay = Math.random() * 300;
229
322
  }
230
323
  }
324
+ // Check if target changed to trigger animation
231
325
  const targetChanged = sprite.targetX !== position.x || sprite.targetY !== position.y;
232
326
  if (targetChanged) {
233
327
  if (isViewTransition) {
328
+ // Only set up animation if not already animating - don't reset animation
329
+ // when targets change during layout recalculations
234
330
  if (sprite.animationStartTime === undefined) {
235
331
  sprite.startX = sprite.currentX;
236
332
  sprite.startY = sprite.currentY;
237
333
  sprite.animationStartTime = Date.now();
334
+ // Add random delay for "organic" fly effect
238
335
  sprite.animationDelay = Math.random() * 300;
239
336
  }
337
+ // Always update target to the new position (animation will smoothly
338
+ // adjust to the new target)
240
339
  sprite.targetX = position.x;
241
340
  sprite.targetY = position.y;
242
341
  }
@@ -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 groupsContainer?: 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 viewMode: string;\n prevLayout?: LayoutResult | null;\n prevScrollTop?: number;\n prevScrollLeft?: number;\n}\n\nexport function syncSpritesToViewport<TItem>(params: SyncParams<TItem>) {\n const { root, groupsContainer, container, sprites, layout, visibleIds: _visibleIds, items, cardWidth, cardHeight, panX, panY, panDeltaX, panDeltaY, viewportWidth, viewportHeight, createCardSprite, updateCardContent, zoomLevel, isViewTransition, viewMode, prevLayout, prevScrollTop, prevScrollLeft } = params;\n if (!root || !container) return;\n\n void _visibleIds;\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 contentHeightPx = (layout.totalHeight || 0) * zoomLevel;\n let offsetY = 0;\n\n // If content fits vertically within the viewport, align relative to bottom.\n // The spacer ensures container isn't scrollable in this case (scrollTop=0).\n // The items are at large Y coordinates relative to layout.totalHeight.\n // We want the bottom of the layout (totalHeight) to align with viewport bottom.\n if (viewMode === 'grouped' && contentHeightPx < viewportPxHeight) {\n // Calculate offset in pixels to shift the content down\n offsetY = viewportPxHeight - contentHeightPx;\n }\n\n // Use the container's actual scroll position for positioning, not the passed panX/panY\n // which may be stale (from React state) compared to live DOM scroll values.\n const actualScrollX = typeof container.scrollLeft === 'number' ? container.scrollLeft : (panX || 0);\n const actualScrollY = typeof container.scrollTop === 'number' ? container.scrollTop : (panY || 0);\n\n // Apply scaling and position to root container\n if (root) {\n root.scale.set(zoomLevel);\n // Standard position: -scrollX, -scrollY\n // Plus vertical alignment offset if zoomed out\n root.position.set(-actualScrollX, offsetY - actualScrollY);\n }\n \n // Apply synchronization to groups container if present\n if (groupsContainer) {\n groupsContainer.scale.set(zoomLevel);\n groupsContainer.position.set(-actualScrollX, offsetY - actualScrollY);\n }\n\n // `visibleIds` comes from callers but this module iterates `layout.positions`\n\n // Note: Pan delta compensation is NOT applied during view transitions because:\n // 1. The time-based animation system handles position changes smoothly\n // 2. Applying pan delta during animation interferes with the interpolation\n // 3. The scroll position changes are a natural part of the view mode switch\n // This compensation is only useful for rapid scrolling/panning where sprites\n // need to maintain visual stability, which isn't the case during view transitions.\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 // OffsetY is already in pixels and doesn't need scaling in panWorldY calc\n // because panWorldY is used for viewport buffering/culling, which is relative\n // to the \"camera\" position in world space.\n // The camera world Y = (scrollTop - offsetY) / zoomLevel.\n const effectivePanYWithOffset = effectivePanY - offsetY;\n const panWorldX = effectivePanX * invScale;\n const panWorldY = effectivePanYWithOffset * invScale;\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 // During view transitions, if no cards are visible and we're not animating yet,\n // force-add the first few cards from the layout to ensure content appears.\n // This prevents a blank screen when switching modes, especially in packaged builds\n // where scroll stabilization might be delayed.\n if (isViewTransition && inViewportIds.length === 0 && layout.positions.size > 0) {\n let count = 0;\n for (const [id, position] of layout.positions) {\n if (count < 5 && position) { // Add up to 5 cards\n inViewportIds.push(id);\n visibleSet.add(id);\n count++;\n }\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 // Fallback: if no sprites are calculated as visible (e.g., due to rounding\n // or scroll/zoom race conditions), force a handful of cards into view so\n // the canvas never renders empty at certain zoom levels.\n // When transitioning views, be more aggressive to ensure content appears during the transition\n let injectedFallback = false;\n const fallbackCount = isViewTransition ? 30 : 12;\n if (inViewportIds.length === 0 && layout.positions.size > 0) {\n injectedFallback = true;\n let count = 0;\n for (const [id] of layout.positions) {\n inViewportIds.push(id);\n visibleSet.add(id);\n count++;\n if (count >= fallbackCount) break;\n }\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 // Check scroll stabilization by comparing current scroll to previous scroll position.\n const currentScrollTop = container.scrollTop || 0;\n const currentScrollLeft = container.scrollLeft || 0;\n const scrollTopDelta = Math.abs(currentScrollTop - (prevScrollTop || currentScrollTop));\n const scrollLeftDelta = Math.abs(currentScrollLeft - (prevScrollLeft || currentScrollLeft));\n const scrollStabilized = scrollTopDelta < 10 && scrollLeftDelta < 10;\n const aggressiveCull = !injectedFallback && (\n (!isViewTransition && sprites.size > Math.max(120, Math.ceil(inViewportIds.length * 1.5))) ||\n (isViewTransition && !scrollStabilized)\n );\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 unknown as { __lastHiddenAt?: number }).__lastHiddenAt) delete (sprite as unknown as { __lastHiddenAt?: number }).__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 unknown as { __lastHiddenAt: number }).__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 unknown as { __lastHiddenAt?: number }).__lastHiddenAt) delete (sprite as unknown as { __lastHiddenAt?: number }).__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 unknown as { __lastHiddenAt?: number }).__lastHiddenAt;\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\n for (const id of inViewportIds) {\n const position = layout.positions.get(id);\n if (!position) {\n continue;\n }\n\n let sprite = sprites.get(id);\n if (!sprite) {\n if (createdCount >= MAX_SPRITES_PER_FRAME) {\n continue;\n }\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 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 const targetChanged = sprite.targetX !== position.x || sprite.targetY !== position.y;\n if (targetChanged) {\n if (isViewTransition) {\n // Only set up animation if not already animating - don't reset animation\n // when targets change during layout recalculations\n if (sprite.animationStartTime === undefined) {\n sprite.startX = sprite.currentX;\n sprite.startY = sprite.currentY;\n sprite.animationStartTime = Date.now();\n // Add random delay for \"organic\" fly effect\n sprite.animationDelay = Math.random() * 300;\n }\n // Always update target to the new position (animation will smoothly\n // adjust to the new target)\n sprite.targetX = position.x;\n sprite.targetY = position.y;\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[Number(id)];\n if (item) {\n updateCardContent(sprite, item);\n }\n }\n}\n"],"names":[],"mappings":";;;AAmCM,SAAU,qBAAqB,CAAQ,MAAyB,EAAA;IAClE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,MAAM;AACnT,IAAA,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS;QAAE;AAQzB,IAAA,MAAM,eAAe,GAAG,SAAS,CAAC,WAAW,IAAI,aAAa;AAC9D,IAAA,MAAM,gBAAgB,GAAG,SAAS,CAAC,YAAY,IAAI,cAAc;IAEjE,MAAM,eAAe,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,IAAI,SAAS;IAC7D,IAAI,OAAO,GAAG,CAAC;IAMf,IAAI,QAAQ,KAAK,SAAS,IAAI,eAAe,GAAG,gBAAgB,EAAE;AAE9D,QAAA,OAAO,GAAG,gBAAgB,GAAG,eAAe;IAChD;IAIA,MAAM,aAAa,GAAG,OAAO,SAAS,CAAC,UAAU,KAAK,QAAQ,GAAG,SAAS,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,CAAC;IACnG,MAAM,aAAa,GAAG,OAAO,SAAS,CAAC,SAAS,KAAK,QAAQ,GAAG,SAAS,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,CAAC;IAGjG,IAAI,IAAI,EAAE;AACN,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;AAGzB,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,OAAO,GAAG,aAAa,CAAC;IAC9D;IAGA,IAAI,eAAe,EAAE;AACjB,QAAA,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;AACpC,QAAA,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,OAAO,GAAG,aAAa,CAAC;IACzE;AAWA,IAAA,MAAM,UAAU,GAAG,IAAI,GAAG,EAAmB;AAM7C,IAAA,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC;AAG3D,IAAA,MAAM,QAAQ,GAAG,SAAS,IAAI,SAAS,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,GAAG,CAAC;IAMjE,MAAM,aAAa,GAAG,OAAO,SAAS,CAAC,UAAU,KAAK,QAAQ,GAAG,SAAS,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,CAAC;IACnG,MAAM,aAAa,GAAG,OAAO,SAAS,CAAC,SAAS,KAAK,QAAQ,GAAG,SAAS,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,CAAC;AASjG,IAAA,MAAM,uBAAuB,GAAG,aAAa,GAAG,OAAO;AACvD,IAAA,MAAM,SAAS,GAAG,aAAa,GAAG,QAAQ;AAC1C,IAAA,MAAM,SAAS,GAAG,uBAAuB,GAAG,QAAQ;AAEpD,IAAA,MAAM,kBAAkB,GAAG,eAAe,GAAG,QAAQ;AACrD,IAAA,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,QAAQ;IAOvD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,GAAG,GAAG,EAAE,eAAe,CAAC;AAKlI,IAAA,MAAM,iBAAiB,GAAG,SAAS,GAAG,WAAW;AACjD,IAAA,MAAM,kBAAkB,GAAG,SAAS,GAAG,kBAAkB,GAAG,WAAW;AACvE,IAAA,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW;AAChD,IAAA,MAAM,mBAAmB,GAAG,SAAS,GAAG,mBAAmB,GAAG,WAAW;IAEzE,MAAM,aAAa,GAAwB,EAAE;AAI7C,IAAA,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ,CAAC;IAMlD,KAAK,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE;AAC3C,QAAA,IAAI,CAAC,QAAQ;YAAE;AACf,QAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC;AACzB,QAAA,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC;QACzB,MAAM,UAAU,GAAG,SAAS;QAC5B,MAAM,UAAU,GAAG,UAAU;AAE7B,QAAA,IACI,MAAM,GAAG,UAAU,IAAI,iBAAiB,GAAG,YAAY;YACvD,MAAM,IAAI,kBAAkB,GAAG,YAAY;AAC3C,YAAA,MAAM,GAAG,UAAU,IAAI,gBAAgB,GAAG,YAAY;AACtD,YAAA,MAAM,IAAI,mBAAmB,GAAG,YAAY,EAC9C;AACE,YAAA,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;AACtB,YAAA,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB;IACJ;AAMA,IAAA,IAAI,gBAAgB,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,EAAE;QAC7E,IAAI,KAAK,GAAG,CAAC;QACb,KAAK,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE;AAC3C,YAAA,IAAI,KAAK,GAAG,CAAC,IAAI,QAAQ,EAAE;AACvB,gBAAA,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;AACtB,gBAAA,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;AAClB,gBAAA,KAAK,EAAE;YACX;QACJ;IACJ;AAKA,IAAA,IAAI;QACA,MAAM,UAAU,GAAG,UAAU,IAAI,QAAQ,IAAI,CAAC,CAAC;AAC/C,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC;AAGxE,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,GAAG,UAAU,CAAC,CAAC;QAC5E,MAAM,kBAAkB,GAAG,IAAI;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AACrG,QAAA,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,SAAS,GAAG,YAAY,IAAI,UAAU,CAAC;QAC9E,KAAK,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE;AAC3C,YAAA,IAAI,QAAQ,CAAC,CAAC,IAAI,iBAAiB,EAAE;gBACjC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AACrB,oBAAA,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;AACtB,oBAAA,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB;YACJ;QACJ;IACJ;IAAE,OAAO,CAAC,EAAE;IAEZ;IAMA,IAAI,gBAAgB,GAAG,KAAK;IAC5B,MAAM,aAAa,GAAG,gBAAgB,GAAG,EAAE,GAAG,EAAE;AAChD,IAAA,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,EAAE;QACzD,gBAAgB,GAAG,IAAI;QACvB,IAAI,KAAK,GAAG,CAAC;QACb,KAAK,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE;AACjC,YAAA,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;AACtB,YAAA,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;AAClB,YAAA,KAAK,EAAE;YACP,IAAI,KAAK,IAAI,aAAa;gBAAE;QAChC;IACJ;AAUA,IAAA,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,IAAI,CAAC;AACjD,IAAA,MAAM,iBAAiB,GAAG,SAAS,CAAC,UAAU,IAAI,CAAC;AACnD,IAAA,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,IAAI,aAAa,IAAI,gBAAgB,CAAC,CAAC;AACvF,IAAA,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,IAAI,cAAc,IAAI,iBAAiB,CAAC,CAAC;IAC3F,MAAM,gBAAgB,GAAG,cAAc,GAAG,EAAE,IAAI,eAAe,GAAG,EAAE;AACpE,IAAA,MAAM,cAAc,GAAG,CAAC,gBAAgB,KACpC,CAAC,CAAC,gBAAgB,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AACzF,SAAC,gBAAgB,IAAI,CAAC,gBAAgB,CAAC,CAC1C;IAED,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE;QAChC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAGrB,IAAI,gBAAgB,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvC,IAAI,MAAM,EAAE;AACR,oBAAA,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;AACzB,oBAAA,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;AAGzB,oBAAA,IAAI,MAAM,CAAC,kBAAkB,KAAK,SAAS,EAAE;AACzC,wBAAA,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ;AAC/B,wBAAA,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ;AAC/B,wBAAA,MAAM,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE;wBACtC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG;oBAC/C;AAEA,oBAAA,IAAI;wBAAE,IAAI,MAAM,CAAC,SAAS;AAAE,4BAAA,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,IAAI;oBAAE;oBAAE,OAAO,CAAC,EAAE;oBAAU;oBAEnF,IAAK,MAAiD,CAAC,cAAc;wBAAE,OAAQ,MAAiD,CAAC,cAAc;oBAC/I;gBACJ;YACJ;YAEA,IAAI,cAAc,EAAE;AAEhB,gBAAA,IAAI;oBAAE,IAAI,MAAM,CAAC,SAAS;AAAE,wBAAA,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,IAAI;gBAAE;gBAAE,OAAO,CAAC,EAAE;gBAAU;gBACnF;YACJ;AAEA,YAAA,IAAI;AACA,gBAAA,IAAI,MAAM,CAAC,SAAS,EAAE;AAClB,oBAAA,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,KAAK;gBACpC;AACC,gBAAA,MAAgD,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE;YACjF;YAAE,OAAO,CAAC,EAAE;YAEZ;QACJ;aAAO;AACH,YAAA,IAAI;AACA,gBAAA,IAAI,MAAM,CAAC,SAAS,EAAE;AAClB,oBAAA,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,IAAI;gBACnC;gBACA,IAAK,MAAiD,CAAC,cAAc;oBAAE,OAAQ,MAAiD,CAAC,cAAc;YACnJ;YAAE,OAAO,CAAC,EAAE;YAAU;QAC1B;IACJ;AAGA,IAAA,IAAI;QACA,MAAM,QAAQ,GAAG,GAAG;AACpB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;QACtB,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE;AAChC,YAAA,MAAM,UAAU,GAAI,MAAiD,CAAC,cAAc;YACpF,IAAI,UAAU,IAAI,GAAG,GAAG,UAAU,GAAG,QAAQ,EAAE;AAC3C,gBAAA,IAAI;oBAEA,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM;wBAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC;gBAC1G;gBAAE,OAAO,CAAC,EAAE;AACR,oBAAA,KAAK,CAAC;gBACV;AACA,gBAAA,IAAI;oBACA,aAAa,CAAC,MAAM,CAAC;gBACzB;gBAAE,OAAO,CAAC,EAAE;AACR,oBAAA,KAAK,CAAC;gBACV;AACA,gBAAA,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB;QACJ;IACJ;IAAE,OAAO,CAAC,EAAE;IAEZ;IAIA,MAAM,qBAAqB,GAAG,EAAE;IAChC,IAAI,YAAY,GAAG,CAAC;AAGpB,IAAA,KAAK,MAAM,EAAE,IAAI,aAAa,EAAE;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,QAAQ,EAAE;YACX;QACJ;QAEA,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,EAAE;AACT,YAAA,IAAI,YAAY,IAAI,qBAAqB,EAAE;gBACvC;YACJ;AACA,YAAA,YAAY,EAAE;AAEd,YAAA,IAAI,MAAM,GAAG,QAAQ,CAAC,CAAC;AACvB,YAAA,IAAI,MAAM,GAAG,QAAQ,CAAC,CAAC;YACvB,IAAI,aAAa,GAAG,KAAK;AAGzB,YAAA,IAAI,gBAAgB,IAAI,UAAU,IAAI,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBAChE,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3C,IAAI,MAAM,EAAE;AACR,oBAAA,MAAM,GAAG,MAAM,CAAC,CAAC;AACjB,oBAAA,MAAM,GAAG,MAAM,CAAC,CAAC;AAKjB,oBAAA,IAAI,SAAS,IAAI,SAAS,EAAE;AACxB,wBAAA,MAAM,EAAE,GAAG,CAAC,SAAS,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC;AAC9C,wBAAA,MAAM,EAAE,GAAG,CAAC,SAAS,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC;wBAC9C,MAAM,IAAI,EAAE;wBACZ,MAAM,IAAI,EAAE;oBAChB;oBAEA,aAAa,GAAG,IAAI;gBACxB;YACJ;YAEA,MAAM,GAAG,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC;AAC7C,YAAA,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC;AACvB,YAAA,IAAI,MAAM,CAAC,SAAS,EAAE;AAClB,gBAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;AAC/B,gBAAA,MAAM,CAAC,QAAQ,GAAG,MAAM;AACxB,gBAAA,MAAM,CAAC,QAAQ,GAAG,MAAM;gBAGxB,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;YACjD;YAEA,IAAI,aAAa,EAAE;AACf,gBAAA,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC;AAC3B,gBAAA,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC;AAC3B,gBAAA,MAAM,CAAC,MAAM,GAAG,MAAM;AACtB,gBAAA,MAAM,CAAC,MAAM,GAAG,MAAM;AACtB,gBAAA,MAAM,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE;gBACtC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG;YAC/C;QACJ;AAGA,QAAA,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC;QACpF,IAAI,aAAa,EAAE;YACf,IAAI,gBAAgB,EAAE;AAGlB,gBAAA,IAAI,MAAM,CAAC,kBAAkB,KAAK,SAAS,EAAE;AACzC,oBAAA,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ;AAC/B,oBAAA,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ;AAC/B,oBAAA,MAAM,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE;oBAEtC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG;gBAC/C;AAGA,gBAAA,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC;AAC3B,gBAAA,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC;YAC/B;iBAAO;AACH,gBAAA,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC;AAC3B,gBAAA,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC;gBAC3B,OAAO,MAAM,CAAC,kBAAkB;gBAChC,OAAO,MAAM,CAAC,cAAc;YAChC;QACJ;QAEA,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,IAAI,EAAE;AACN,YAAA,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC;QACnC;IACJ;AACJ;;;;"}
1
+ {"version":3,"file":"visibility.js","sources":["../../../../../PivotViewer/components/pivot/visibility.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
1
3
  const BASE_CARD_WIDTH = 200;
2
4
  const BASE_CARD_HEIGHT = 176;
3
5
  const CARDS_PER_COLUMN = 5;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../../PivotViewer/constants.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\nexport const BASE_CARD_WIDTH = 200;\nexport const BASE_CARD_HEIGHT = 176;\nexport const CARDS_PER_COLUMN = 5;\nexport const GROUP_SPACING = 20;\nexport const CARD_GAP = 10;\nexport const CANVAS_PADDING = 20;\n"],"names":[],"mappings":"AAGO,MAAM,eAAe,GAAG;AACxB,MAAM,gBAAgB,GAAG;AACzB,MAAM,gBAAgB,GAAG;AAEzB,MAAM,QAAQ,GAAG;AACjB,MAAM,cAAc,GAAG;;;;"}
1
+ {"version":3,"file":"constants.js","sources":["../../../PivotViewer/constants.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AAEO,MAAM,eAAe,GAAG;AACxB,MAAM,gBAAgB,GAAG;AACzB,MAAM,gBAAgB,GAAG;AAEzB,MAAM,QAAQ,GAAG;AACjB,MAAM,cAAc,GAAG;;;;"}
@@ -1,5 +1,7 @@
1
1
  import { CANVAS_PADDING, CARD_GAP } from '../constants.js';
2
2
 
3
+ // Copyright (c) Cratis. All rights reserved.
4
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
5
  function computeLayout(grouping, spec) {
4
6
  const positions = new Map();
5
7
  if (spec.viewMode === 'collection') {
@@ -13,6 +15,7 @@ function computeCollectionLayout(grouping, spec, positions) {
13
15
  const { cardWidth, cardHeight, containerWidth } = spec;
14
16
  const slotWidth = cardWidth + CARD_GAP;
15
17
  const slotHeight = cardHeight + CARD_GAP;
18
+ // Calculate how many cards fit per row based on container width (include gap)
16
19
  const cardsPerRow = Math.max(1, Math.floor((containerWidth + CARD_GAP - (CANVAS_PADDING * 2)) / slotWidth));
17
20
  let x = CANVAS_PADDING;
18
21
  let y = CANVAS_PADDING;
@@ -26,8 +29,10 @@ function computeCollectionLayout(grouping, spec, positions) {
26
29
  y,
27
30
  groupIndex: 0,
28
31
  });
32
+ // Move to next position horizontally (left to right)
29
33
  column++;
30
34
  x += slotWidth;
35
+ // Wrap to next row when we've filled the width
31
36
  if (column >= cardsPerRow) {
32
37
  column = 0;
33
38
  x = CANVAS_PADDING;
@@ -46,22 +51,32 @@ function computeCollectionLayout(grouping, spec, positions) {
46
51
  }
47
52
  function computeGroupedLayout(grouping, spec, positions) {
48
53
  const { cardWidth, cardHeight, cardsPerColumn } = spec;
54
+ // Override group spacing to ensure consistent card spacing across groups
55
+ // We want visual gap between groups to match gap between cards (CARD_GAP)
49
56
  const effectiveGroupSpacing = 0;
50
57
  const slotWidth = cardWidth + CARD_GAP;
51
58
  const slotHeight = cardHeight + CARD_GAP;
59
+ // Bottom gap = BOTTOM_MARGIN + CARD_GAP - CANVAS_PADDING.
60
+ // To match the left/right edge padding within each bucket (CARD_GAP / 2 = 5px):
61
+ // BOTTOM_MARGIN = CANVAS_PADDING - CARD_GAP + (CARD_GAP / 2) = CANVAS_PADDING - CARD_GAP / 2
52
62
  const BOTTOM_MARGIN = CANVAS_PADDING - CARD_GAP / 2;
63
+ // Fixed bucket width: 2 columns of cards per bucket (always)
53
64
  const COLUMNS_PER_BUCKET = 2;
54
65
  const bucketWidth = COLUMNS_PER_BUCKET * slotWidth;
55
66
  let groupX = 0;
67
+ // Use container height for layout, or fallback to cardsPerColumn height
56
68
  const layoutHeight = spec.containerHeight || (cardsPerColumn * slotHeight);
57
69
  const bucketWidths = [];
58
70
  const groupXs = [];
59
71
  let maxRows = 0;
72
+ // First pass: calculate max rows to determine total height
60
73
  for (const group of grouping.groups) {
61
74
  const itemsInGroup = group.ids.length;
62
75
  const rowsInGroup = Math.ceil(itemsInGroup / COLUMNS_PER_BUCKET);
63
76
  maxRows = Math.max(maxRows, rowsInGroup);
64
77
  }
78
+ // Calculate actual content height needed (ensure it's at least as tall as the container)
79
+ // We need to fit the tallest column plus the bottom margin
65
80
  const contentHeight = Math.max(layoutHeight, (maxRows * slotHeight) + BOTTOM_MARGIN);
66
81
  for (let groupIndex = 0; groupIndex < grouping.groups.length; groupIndex++) {
67
82
  const group = grouping.groups[groupIndex];
@@ -69,9 +84,15 @@ function computeGroupedLayout(grouping, spec, positions) {
69
84
  const itemsInGroup = group.ids.length;
70
85
  for (let i = 0; i < itemsInGroup; i++) {
71
86
  const id = group.ids[i];
87
+ // Cards fill from left to right, bottom to top
88
+ // For a 2-column bucket: i=0,1 in row 0; i=2,3 in row 1; etc.
72
89
  const col = i % COLUMNS_PER_BUCKET;
73
90
  const row = Math.floor(i / COLUMNS_PER_BUCKET);
91
+ // Center the cards within the bucket
92
+ // The bucket width fits 2 slots (2W + 2G). Cards take 2W + G.
93
+ // So we have G/2 padding on each side to center them.
74
94
  const x = groupX + (col * slotWidth) + (CARD_GAP / 2);
95
+ // Position cards from bottom of container, stacking upwards, starting at row 0 (bottom)
75
96
  const y = CANVAS_PADDING + contentHeight - BOTTOM_MARGIN - ((row + 1) * slotHeight);
76
97
  positions.set(id, {
77
98
  x,
@@ -79,7 +100,9 @@ function computeGroupedLayout(grouping, spec, positions) {
79
100
  groupIndex,
80
101
  });
81
102
  }
103
+ // Always use fixed bucket width
82
104
  bucketWidths.push(bucketWidth);
105
+ // Advance position by fixed bucket width + spacing
83
106
  groupX += bucketWidth;
84
107
  if (groupIndex < grouping.groups.length - 1) {
85
108
  groupX += effectiveGroupSpacing;