@cratis/components 4.26.4 → 4.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/compat-manifest.json +11 -11
  2. package/dist/esm/Common/CratisComponentsProvider.d.ts +4 -0
  3. package/dist/esm/Common/CratisComponentsProvider.d.ts.map +1 -1
  4. package/dist/esm/Common/CratisComponentsProvider.js +1 -0
  5. package/dist/esm/Common/CratisComponentsProvider.js.map +1 -1
  6. package/dist/esm/DataPage/DataPage.d.ts +2 -0
  7. package/dist/esm/DataPage/DataPage.d.ts.map +1 -1
  8. package/dist/esm/DataPage/DataPage.js.map +1 -1
  9. package/dist/esm/DataTables/DataTableForObservableQuery.d.ts +2 -0
  10. package/dist/esm/DataTables/DataTableForObservableQuery.d.ts.map +1 -1
  11. package/dist/esm/DataTables/DataTableForObservableQuery.js +1 -1
  12. package/dist/esm/DataTables/DataTableForObservableQuery.js.map +1 -1
  13. package/dist/esm/DataTables/DataTableForQuery.d.ts +2 -0
  14. package/dist/esm/DataTables/DataTableForQuery.d.ts.map +1 -1
  15. package/dist/esm/DataTables/DataTableForQuery.js +1 -1
  16. package/dist/esm/DataTables/DataTableForQuery.js.map +1 -1
  17. package/dist/esm/DataTables/PaginatorPageItem.d.ts +13 -0
  18. package/dist/esm/DataTables/PaginatorPageItem.d.ts.map +1 -0
  19. package/dist/esm/DataTables/PaginatorPageItem.js +4 -0
  20. package/dist/esm/DataTables/PaginatorPageItem.js.map +1 -0
  21. package/dist/esm/DataTables/TablePaginator.d.ts +22 -2
  22. package/dist/esm/DataTables/TablePaginator.d.ts.map +1 -1
  23. package/dist/esm/DataTables/TablePaginator.js.map +1 -1
  24. package/dist/esm/DataTables/TablePaginatorImplementation.d.ts +1 -1
  25. package/dist/esm/DataTables/TablePaginatorImplementation.d.ts.map +1 -1
  26. package/dist/esm/DataTables/TablePaginatorImplementation.js +8 -3
  27. package/dist/esm/DataTables/TablePaginatorImplementation.js.map +1 -1
  28. package/dist/esm/DataTables/TablePaginatorPages.d.ts +9 -0
  29. package/dist/esm/DataTables/TablePaginatorPages.d.ts.map +1 -0
  30. package/dist/esm/DataTables/TablePaginatorPages.js +20 -0
  31. package/dist/esm/DataTables/TablePaginatorPages.js.map +1 -0
  32. package/dist/esm/DataTables/index.d.ts +2 -0
  33. package/dist/esm/DataTables/index.d.ts.map +1 -1
  34. package/dist/esm/DataTables/index.js +1 -0
  35. package/dist/esm/DataTables/index.js.map +1 -1
  36. package/dist/esm/DataTables/paginatorPages.d.ts +15 -0
  37. package/dist/esm/DataTables/paginatorPages.d.ts.map +1 -0
  38. package/dist/esm/DataTables/paginatorPages.js +40 -0
  39. package/dist/esm/DataTables/paginatorPages.js.map +1 -0
  40. package/dist/esm/Filter/FilterGroup.d.ts +23 -0
  41. package/dist/esm/Filter/FilterGroup.d.ts.map +1 -0
  42. package/dist/esm/Filter/FilterGroup.js +51 -0
  43. package/dist/esm/Filter/FilterGroup.js.map +1 -0
  44. package/dist/esm/Filter/FilterPanel.d.ts.map +1 -1
  45. package/dist/esm/Filter/FilterPanel.js +24 -257
  46. package/dist/esm/Filter/FilterPanel.js.map +1 -1
  47. package/dist/esm/Filter/FilterSearchBox.d.ts +10 -0
  48. package/dist/esm/Filter/FilterSearchBox.d.ts.map +1 -0
  49. package/dist/esm/Filter/FilterSearchBox.js +10 -0
  50. package/dist/esm/Filter/FilterSearchBox.js.map +1 -0
  51. package/dist/esm/Filter/measurePanelPlacement.d.ts +31 -0
  52. package/dist/esm/Filter/measurePanelPlacement.d.ts.map +1 -0
  53. package/dist/esm/Filter/measurePanelPlacement.js +132 -0
  54. package/dist/esm/Filter/measurePanelPlacement.js.map +1 -0
  55. package/dist/esm/Filter/usePanelDismissal.d.ts +32 -0
  56. package/dist/esm/Filter/usePanelDismissal.d.ts.map +1 -0
  57. package/dist/esm/Filter/usePanelDismissal.js +63 -0
  58. package/dist/esm/Filter/usePanelDismissal.js.map +1 -0
  59. package/dist/esm/Filter/usePanelPosition.d.ts +24 -0
  60. package/dist/esm/Filter/usePanelPosition.d.ts.map +1 -0
  61. package/dist/esm/Filter/usePanelPosition.js +85 -0
  62. package/dist/esm/Filter/usePanelPosition.js.map +1 -0
  63. package/dist/esm/Filter/useResolvedAnchor.d.ts +17 -0
  64. package/dist/esm/Filter/useResolvedAnchor.d.ts.map +1 -0
  65. package/dist/esm/Filter/useResolvedAnchor.js +16 -0
  66. package/dist/esm/Filter/useResolvedAnchor.js.map +1 -0
  67. package/dist/esm/PivotViewer/PivotViewer.d.ts.map +1 -1
  68. package/dist/esm/PivotViewer/PivotViewer.js +47 -207
  69. package/dist/esm/PivotViewer/PivotViewer.js.map +1 -1
  70. package/dist/esm/PivotViewer/components/pivot/visibility.d.ts +1 -1
  71. package/dist/esm/PivotViewer/components/pivot/visibility.d.ts.map +1 -1
  72. package/dist/esm/PivotViewer/components/pivot/visibility.js +24 -222
  73. package/dist/esm/PivotViewer/components/pivot/visibility.js.map +1 -1
  74. package/dist/esm/PivotViewer/components/pivot/visibilityHelpers.d.ts +114 -0
  75. package/dist/esm/PivotViewer/components/pivot/visibilityHelpers.d.ts.map +1 -0
  76. package/dist/esm/PivotViewer/components/pivot/visibilityHelpers.js +306 -0
  77. package/dist/esm/PivotViewer/components/pivot/visibilityHelpers.js.map +1 -0
  78. package/dist/esm/PivotViewer/hooks/useColorCssVariables.d.ts +9 -0
  79. package/dist/esm/PivotViewer/hooks/useColorCssVariables.d.ts.map +1 -0
  80. package/dist/esm/PivotViewer/hooks/useColorCssVariables.js +32 -0
  81. package/dist/esm/PivotViewer/hooks/useColorCssVariables.js.map +1 -0
  82. package/dist/esm/PivotViewer/hooks/usePivotViewerGrouping.d.ts +27 -0
  83. package/dist/esm/PivotViewer/hooks/usePivotViewerGrouping.d.ts.map +1 -0
  84. package/dist/esm/PivotViewer/hooks/usePivotViewerGrouping.js +40 -0
  85. package/dist/esm/PivotViewer/hooks/usePivotViewerGrouping.js.map +1 -0
  86. package/dist/esm/PivotViewer/hooks/usePivotViewerInteractions.d.ts +27 -0
  87. package/dist/esm/PivotViewer/hooks/usePivotViewerInteractions.d.ts.map +1 -0
  88. package/dist/esm/PivotViewer/hooks/usePivotViewerInteractions.js +46 -0
  89. package/dist/esm/PivotViewer/hooks/usePivotViewerInteractions.js.map +1 -0
  90. package/dist/esm/PivotViewer/hooks/useRawGrouping.d.ts +22 -0
  91. package/dist/esm/PivotViewer/hooks/useRawGrouping.d.ts.map +1 -0
  92. package/dist/esm/PivotViewer/hooks/useRawGrouping.js +56 -0
  93. package/dist/esm/PivotViewer/hooks/useRawGrouping.js.map +1 -0
  94. package/dist/esm/PivotViewer/hooks/useScrollPositionTracking.d.ts +12 -0
  95. package/dist/esm/PivotViewer/hooks/useScrollPositionTracking.d.ts.map +1 -0
  96. package/dist/esm/PivotViewer/hooks/useScrollPositionTracking.js +20 -0
  97. package/dist/esm/PivotViewer/hooks/useScrollPositionTracking.js.map +1 -0
  98. package/dist/esm/PivotViewer/hooks/useViewerLayout.d.ts +16 -0
  99. package/dist/esm/PivotViewer/hooks/useViewerLayout.d.ts.map +1 -0
  100. package/dist/esm/PivotViewer/hooks/useViewerLayout.js +29 -0
  101. package/dist/esm/PivotViewer/hooks/useViewerLayout.js.map +1 -0
  102. package/dist/esm/PivotViewer/hooks/useVisibleIds.d.ts +21 -0
  103. package/dist/esm/PivotViewer/hooks/useVisibleIds.d.ts.map +1 -0
  104. package/dist/esm/PivotViewer/hooks/useVisibleIds.js +34 -0
  105. package/dist/esm/PivotViewer/hooks/useVisibleIds.js.map +1 -0
  106. package/dist/esm/SchemaEditor/SchemaEditor.d.ts +4 -1
  107. package/dist/esm/SchemaEditor/SchemaEditor.d.ts.map +1 -1
  108. package/dist/esm/SchemaEditor/SchemaEditor.js.map +1 -1
  109. package/dist/esm/SchemaEditor/SchemaEditorLabels.d.ts +6 -0
  110. package/dist/esm/SchemaEditor/SchemaEditorLabels.d.ts.map +1 -1
  111. package/dist/esm/SchemaEditor/SchemaEditorLabels.js.map +1 -1
  112. package/dist/esm/SchemaEditor/Tree/GeneratedToggle.d.ts +11 -0
  113. package/dist/esm/SchemaEditor/Tree/GeneratedToggle.d.ts.map +1 -0
  114. package/dist/esm/SchemaEditor/Tree/GeneratedToggle.js +24 -0
  115. package/dist/esm/SchemaEditor/Tree/GeneratedToggle.js.map +1 -0
  116. package/dist/esm/SchemaEditor/Tree/Property.d.ts +6 -0
  117. package/dist/esm/SchemaEditor/Tree/Property.d.ts.map +1 -1
  118. package/dist/esm/SchemaEditor/Tree/Property.js.map +1 -1
  119. package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.d.ts +2 -0
  120. package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.d.ts.map +1 -1
  121. package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.js.map +1 -1
  122. package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.d.ts +2 -0
  123. package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.d.ts.map +1 -1
  124. package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.js.map +1 -1
  125. package/dist/esm/SchemaEditor/Tree/SchemaOrderedProperty.d.ts +12 -0
  126. package/dist/esm/SchemaEditor/Tree/SchemaOrderedProperty.d.ts.map +1 -0
  127. package/dist/esm/SchemaEditor/Tree/SchemaOrderedProperty.js +13 -0
  128. package/dist/esm/SchemaEditor/Tree/SchemaOrderedProperty.js.map +1 -0
  129. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.d.ts.map +1 -1
  130. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.js +2 -2
  131. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.js.map +1 -1
  132. package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.d.ts +8 -1
  133. package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.d.ts.map +1 -1
  134. package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.js +15 -11
  135. package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.js.map +1 -1
  136. package/dist/esm/SchemaEditor/Tree/schemaConversion.d.ts +15 -3
  137. package/dist/esm/SchemaEditor/Tree/schemaConversion.d.ts.map +1 -1
  138. package/dist/esm/SchemaEditor/Tree/schemaConversion.js +83 -27
  139. package/dist/esm/SchemaEditor/Tree/schemaConversion.js.map +1 -1
  140. package/dist/esm/SchemaEditor/Tree/schemaInOriginalOrder.d.ts +3 -0
  141. package/dist/esm/SchemaEditor/Tree/schemaInOriginalOrder.d.ts.map +1 -0
  142. package/dist/esm/SchemaEditor/Tree/schemaInOriginalOrder.js +7 -0
  143. package/dist/esm/SchemaEditor/Tree/schemaInOriginalOrder.js.map +1 -0
  144. package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.d.ts.map +1 -1
  145. package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.js +3 -0
  146. package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.js.map +1 -1
  147. package/dist/esm/SchemaEditor/index.d.ts +1 -1
  148. package/dist/esm/SchemaEditor/index.d.ts.map +1 -1
  149. package/dist/esm/SchemaEditor/index.js +1 -1
  150. package/dist/esm/configuration/CratisComponentsDefaults.d.ts.map +1 -1
  151. package/dist/esm/configuration/CratisComponentsDefaults.js +2 -0
  152. package/dist/esm/configuration/CratisComponentsDefaults.js.map +1 -1
  153. package/dist/esm/styles.DataPage.css +51 -6
  154. package/dist/esm/styles.DataTables.css +51 -6
  155. package/dist/esm/styles.SchemaEditor.css +58 -16
  156. package/dist/esm/styles.css +58 -16
  157. package/dist/esm/styles.renderer.builtin.css +51 -6
  158. package/dist/esm/types/parts.d.ts +6 -2
  159. package/dist/esm/types/parts.d.ts.map +1 -1
  160. package/dist/esm/types/parts.js +6 -2
  161. package/dist/esm/types/parts.js.map +1 -1
  162. package/package.json +1 -1
@@ -1,11 +1,9 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { useRef, useState, useEffect, useMemo, useCallback } from 'react';
3
- import { usePivotEngine } from './hooks/usePivotEngine.js';
4
- import { computeLayout } from './engine/layout.js';
2
+ import { useRef, useState, useEffect } from 'react';
5
3
  import { useFilterState } from './hooks/useFilterState.js';
6
4
  import { useDimensionState } from './hooks/useDimensionState.js';
7
5
  import { useZoomState } from './hooks/useZoomState.js';
8
- import { BASE_CARD_HEIGHT, BASE_CARD_WIDTH, CARDS_PER_COLUMN } from './constants.js';
6
+ import { BASE_CARD_HEIGHT, BASE_CARD_WIDTH } from './constants.js';
9
7
  import { PivotViewerMain } from './components/PivotViewerMain.js';
10
8
  import { FilterPanelContainer } from './components/FilterPanelContainer.js';
11
9
  import { ToolbarContainer } from './components/ToolbarContainer.js';
@@ -14,18 +12,32 @@ import { usePanning } from './hooks/usePanning.js';
14
12
  import { useWheelZoom } from './hooks/useWheelZoom.js';
15
13
  import { useZoomScrollAnchor } from './hooks/useZoomScrollAnchor.js';
16
14
  import 'react-dom';
17
- import { useFieldExtractors } from './hooks/useFieldExtractors.js';
18
- import { useCurrentFilters, useCurrentGroupBy } from './hooks/useCurrentFilters.js';
19
- import { useCardSelection } from './hooks/useCardSelection.js';
20
- import { useDetailPanelClose } from './hooks/useDetailPanelClose.js';
21
- import { useScrollSync } from './hooks/useScrollSync.js';
22
- import { useAnimationModeTracking } from './hooks/useAnimationModeTracking.js';
23
- import { useViewModeScrollHandling } from './hooks/useViewModeScrollHandling.js';
24
15
  import { useContainerDimensions } from './hooks/useContainerDimensions.js';
25
- import { presentGrouping } from './utils/presentGrouping.js';
26
- import { filterVisibleIdsBySearch } from './utils/search.js';
27
- import { resolveInternalItemIndex } from './utils/idResolution.js';
16
+ import { useColorCssVariables } from './hooks/useColorCssVariables.js';
17
+ import { useViewerLayout } from './hooks/useViewerLayout.js';
18
+ import { useScrollPositionTracking } from './hooks/useScrollPositionTracking.js';
19
+ import { usePivotViewerGrouping } from './hooks/usePivotViewerGrouping.js';
20
+ import { usePivotViewerInteractions } from './hooks/usePivotViewerInteractions.js';
28
21
 
22
+ function countActiveFilters(filterState, rangeFilterState) {
23
+ const selectionCount = Object.values(filterState).reduce((sum, vals) => sum + vals.size, 0);
24
+ return selectionCount + Object.values(rangeFilterState).filter((r) => r !== null).length;
25
+ }
26
+ function filtersClassName(hasFilters, filtersOpen) {
27
+ if (!hasFilters)
28
+ return 'no-filters';
29
+ return filtersOpen ? 'filters-open' : 'filters-closed';
30
+ }
31
+ function buildViewerClassName(className, hasFilters, filtersOpen, viewMode) {
32
+ return [
33
+ 'pivot-viewer',
34
+ className,
35
+ filtersClassName(hasFilters, filtersOpen),
36
+ viewMode === 'grouped' ? 'grouped-mode' : 'collection-mode',
37
+ ]
38
+ .filter(Boolean)
39
+ .join(' ');
40
+ }
29
41
  function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRenderer, detailRenderer, getItemId, searchFields, title, className, emptyContent, isLoading = false, loadingLabel, labels, colors, }) {
30
42
  const containerRef = useRef(null);
31
43
  const filterButtonRef = useRef(null);
@@ -36,8 +48,6 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
36
48
  const [filtersOpen, setFiltersOpen] = useState(false);
37
49
  const [selectedItem, setSelectedItem] = useState(null);
38
50
  const [isZooming, setIsZooming] = useState(false);
39
- const [visibleIds, setVisibleIds] = useState(new Uint32Array(0));
40
- const [rawGrouping, setRawGrouping] = useState({ groups: [] });
41
51
  const [hoveredGroupIndex, setHoveredGroupIndex] = useState(null);
42
52
  const [preSelectionState, setPreSelectionState] = useState(null);
43
53
  const [, setAnimationMode] = useState('layout');
@@ -49,143 +59,22 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
49
59
  useWheelZoom(containerRef, zoomLevel, setZoomLevel);
50
60
  useZoomScrollAnchor(containerRef, spacerRef, viewMode);
51
61
  const containerDimensions = useContainerDimensions(containerRef, isLoading);
52
- useEffect(() => {
53
- const container = containerRef.current;
54
- if (!container)
55
- return;
56
- const handleScroll = () => {
57
- setScrollPosition({
58
- x: container.scrollLeft,
59
- y: container.scrollTop,
60
- });
61
- };
62
- container.addEventListener('scroll', handleScroll);
63
- return () => container.removeEventListener('scroll', handleScroll);
64
- }, []);
65
- const { fieldExtractors, indexFields } = useFieldExtractors(dimensions, filters);
66
- const { ready, applyFilters: engineApplyFilters, computeGrouping, sortIds, } = usePivotEngine({
62
+ useScrollPositionTracking(containerRef, setScrollPosition);
63
+ const { ready, visibleIds, grouping } = usePivotViewerGrouping({
67
64
  data,
68
- fieldExtractors,
69
- indexFields,
70
- });
71
- const currentFilters = useCurrentFilters(filters, filterState, rangeFilterState, dimensionFilter, activeDimension);
72
- const currentGroupBy = useCurrentGroupBy(activeDimensionKey, dimensions);
73
- useEffect(() => {
74
- if (!ready)
75
- return;
76
- let cancelled = false;
77
- void engineApplyFilters(currentFilters).then((result) => {
78
- if (cancelled)
79
- return;
80
- let ids = result.visibleIds;
81
- if (ids.length === 0 && currentFilters.length === 0 && data.length > 0) {
82
- const fallbackIds = new Uint32Array(data.length);
83
- for (let i = 0; i < data.length; i++) {
84
- fallbackIds[i] = i;
85
- }
86
- ids = fallbackIds;
87
- }
88
- setVisibleIds(filterVisibleIdsBySearch(data, ids, search, searchFields));
89
- });
90
- return () => {
91
- cancelled = true;
92
- };
93
- }, [ready, currentFilters, engineApplyFilters, data, search, searchFields]);
94
- useEffect(() => {
95
- if (!ready || visibleIds.length === 0) {
96
- setRawGrouping({ groups: [] });
97
- return;
98
- }
99
- let cancelled = false;
100
- if (viewMode === 'collection') {
101
- if (activeDimensionKey) {
102
- void sortIds(visibleIds, activeDimensionKey).then((sortedIds) => {
103
- if (cancelled)
104
- return;
105
- setRawGrouping({
106
- groups: [
107
- {
108
- key: 'all',
109
- label: 'All Items',
110
- value: 'all',
111
- ids: sortedIds,
112
- count: sortedIds.length,
113
- },
114
- ],
115
- });
116
- });
117
- }
118
- else {
119
- setRawGrouping({
120
- groups: [
121
- {
122
- key: 'all',
123
- label: 'All Items',
124
- value: 'all',
125
- ids: visibleIds,
126
- count: visibleIds.length,
127
- },
128
- ],
129
- });
130
- }
131
- }
132
- else {
133
- void computeGrouping(visibleIds, currentGroupBy).then((result) => {
134
- if (!cancelled)
135
- setRawGrouping(result);
136
- });
137
- }
138
- return () => {
139
- cancelled = true;
140
- };
141
- }, [
142
- ready,
143
- visibleIds,
144
- currentGroupBy,
145
- viewMode,
146
- computeGrouping,
147
- sortIds,
65
+ dimensions,
66
+ filters,
67
+ filterState,
68
+ rangeFilterState,
69
+ dimensionFilter,
70
+ activeDimension,
148
71
  activeDimensionKey,
149
- ]);
150
- const grouping = useMemo(() => viewMode === 'grouped' ? presentGrouping(rawGrouping, activeDimension, data) : rawGrouping, [viewMode, rawGrouping, activeDimension, data]);
151
- const layout = useMemo(() => {
152
- const cardWidth = BASE_CARD_WIDTH;
153
- const cardHeight = BASE_CARD_HEIGHT;
154
- const containerWidth = containerDimensions.width / zoomLevel;
155
- const containerHeight = viewMode === 'collection'
156
- ? containerDimensions.height / zoomLevel
157
- : containerDimensions.height;
158
- const result = computeLayout(grouping, {
159
- viewMode,
160
- cardWidth,
161
- cardHeight,
162
- cardsPerColumn: CARDS_PER_COLUMN,
163
- containerWidth,
164
- containerHeight,
165
- });
166
- return result;
167
- }, [
168
- grouping,
169
- viewMode,
170
- zoomLevel,
171
- containerDimensions.width,
172
- containerDimensions.height,
173
- ]);
174
- const resolveId = useCallback((item) => resolveInternalItemIndex(data, item, getItemId), [data, getItemId]);
175
- useAnimationModeTracking(filterState, rangeFilterState, search, activeDimensionKey, viewMode, setAnimationMode);
176
- useScrollSync(containerRef, axisLabelsRef, viewMode);
177
- useViewModeScrollHandling({
178
- containerRef,
72
+ searchFields,
73
+ search,
179
74
  viewMode,
180
- grouping,
181
- layout,
182
- selectedItem,
183
- zoomLevel,
184
- resolveId,
185
- data,
186
- setPreSelectionState,
187
75
  });
188
- const handleCardClick = useCardSelection({
76
+ const layout = useViewerLayout(grouping, viewMode, zoomLevel, containerDimensions);
77
+ const { resolveId, handleCardClick, closeDetail } = usePivotViewerInteractions({
189
78
  data,
190
79
  isPanning,
191
80
  selectedItem,
@@ -193,29 +82,18 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
193
82
  viewMode,
194
83
  layout,
195
84
  containerRef,
85
+ axisLabelsRef,
196
86
  spacerRef,
197
87
  containerDimensions,
198
88
  scrollPosition,
199
89
  preSelectionState,
200
90
  grouping,
201
91
  getItemId,
202
- resolveId,
203
- setZoomLevel,
204
- setIsZooming,
205
- setSelectedItem,
206
- setPreSelectionState,
207
- });
208
- const closeDetail = useDetailPanelClose({
209
- selectedItem,
210
- preSelectionState,
211
- zoomLevel,
212
- viewMode,
213
- layout,
214
- containerRef,
215
- containerDimensions,
216
- grouping,
217
- data,
218
- resolveId,
92
+ filterState,
93
+ rangeFilterState,
94
+ search,
95
+ activeDimensionKey,
96
+ setAnimationMode,
219
97
  setZoomLevel,
220
98
  setIsZooming,
221
99
  setSelectedItem,
@@ -225,50 +103,12 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
225
103
  const cardHeight = BASE_CARD_HEIGHT;
226
104
  const filterOptions = useFilterOptions(data, filters, filterState, rangeFilterState);
227
105
  const hasFilters = Boolean(filters && filters.length > 0);
228
- const activeFilterCount = Object.values(filterState).reduce((sum, vals) => sum + vals.size, 0) + Object.values(rangeFilterState).filter((r) => r !== null).length;
229
- const viewerClassName = [
230
- 'pivot-viewer',
231
- className,
232
- hasFilters ? (filtersOpen ? 'filters-open' : 'filters-closed') : 'no-filters',
233
- viewMode === 'grouped' ? 'grouped-mode' : 'collection-mode',
234
- ]
235
- .filter(Boolean)
236
- .join(' ');
106
+ const activeFilterCount = countActiveFilters(filterState, rangeFilterState);
107
+ const viewerClassName = buildViewerClassName(className, hasFilters, filtersOpen, viewMode);
237
108
  useEffect(() => {
238
109
  setSelectedItem(null);
239
110
  }, [viewMode]);
240
- const cssVariables = useMemo(() => {
241
- const vars = {};
242
- if (!colors)
243
- return vars;
244
- if (colors.primaryColor)
245
- vars['--cratis-primary-color'] = colors.primaryColor;
246
- if (colors.primaryColorText)
247
- vars['--cratis-primary-color-text'] = colors.primaryColorText;
248
- if (colors.primary500)
249
- vars['--cratis-primary-500'] = colors.primary500;
250
- if (colors.surfaceGround)
251
- vars['--cratis-surface-ground'] = colors.surfaceGround;
252
- if (colors.surfaceCard)
253
- vars['--cratis-surface-card'] = colors.surfaceCard;
254
- if (colors.surfaceSection)
255
- vars['--cratis-surface-section'] = colors.surfaceSection;
256
- if (colors.surfaceOverlay)
257
- vars['--cratis-surface-overlay'] = colors.surfaceOverlay;
258
- if (colors.surfaceBorder)
259
- vars['--cratis-surface-border'] = colors.surfaceBorder;
260
- if (colors.textColor)
261
- vars['--cratis-text-color'] = colors.textColor;
262
- if (colors.textColorSecondary)
263
- vars['--cratis-text-color-secondary'] = colors.textColorSecondary;
264
- if (colors.highlightBg)
265
- vars['--cratis-highlight-bg'] = colors.highlightBg;
266
- if (colors.maskbg)
267
- vars['--cratis-maskbg'] = colors.maskbg;
268
- if (colors.focusRing)
269
- vars['--cratis-focus-ring'] = colors.focusRing;
270
- return vars;
271
- }, [colors]);
111
+ const cssVariables = useColorCssVariables(colors);
272
112
  return (jsxs("div", { className: viewerClassName, style: cssVariables, children: [jsx(FilterPanelContainer, { isOpen: filtersOpen && hasFilters, filterLabel: labels?.filters, searchPlaceholder: labels?.search, searchGroup: labels?.searchGroup, search: search, filterState: filterState, rangeFilterState: rangeFilterState, expandedFilterKey: expandedFilterKey, filterOptions: filterOptions, anchorRef: filterButtonRef, onClose: () => setFiltersOpen(false), onSearchChange: setSearch, onFilterToggle: handleToggleFilter, onFilterClear: handleClearFilter, onRangeChange: handleRangeChange, onExpandedFilterChange: setExpandedFilterKey }), jsxs("main", { className: 'pv-main', children: [jsx(ToolbarContainer, { hasFilters: hasFilters, filtersOpen: filtersOpen, filteredCount: visibleIds.length, viewMode: viewMode, zoomLevel: zoomLevel, activeDimensionKey: activeDimensionKey, dimensions: dimensions, activeFilterCount: activeFilterCount, title: title, labels: labels, onFiltersToggle: () => setFiltersOpen((prev) => !prev), onViewModeChange: setViewMode, onZoomIn: handleZoomIn, onZoomOut: handleZoomOut, onZoomSlider: handleZoomSlider, onZoomReset: handleZoomReset, onZoomChange: handleZoomChange, onDimensionChange: setActiveDimensionKey, filterButtonRef: filterButtonRef }), jsx(PivotViewerMain, { data: data, ready: ready, isLoading: isLoading, loadingLabel: loadingLabel ?? labels?.loading ?? 'Loading…', viewportLabel: labels?.viewport ?? 'Card area', visibleIds: visibleIds, grouping: grouping, layout: layout, cardWidth: cardWidth, cardHeight: cardHeight, zoomLevel: zoomLevel, scrollPosition: scrollPosition, containerDimensions: containerDimensions, selectedItem: selectedItem, hoveredGroupIndex: hoveredGroupIndex, isZooming: isZooming, viewMode: viewMode, cardRenderer: cardRenderer, colorOverrides: colors, detailRenderer: detailRenderer, resolveId: resolveId, emptyContent: emptyContent, dimensionFilter: dimensionFilter, onCardClick: handleCardClick, onPanStart: handlePanStart, onPanMove: handlePanMove, onPanEnd: handlePanEnd, onGroupHover: setHoveredGroupIndex, onAxisLabelClick: handleAxisLabelClick, onCloseDetail: closeDetail, containerRef: containerRef, axisLabelsRef: axisLabelsRef, spacerRef: spacerRef })] })] }));
273
113
  }
274
114
 
@@ -1 +1 @@
1
- {"version":3,"file":"PivotViewer.js","sources":["../../../PivotViewer/PivotViewer.tsx"],"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 { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { PivotViewerProps } from './types';\nimport type { GroupingResult } from './engine/types';\nimport { usePivotEngine } from './hooks/usePivotEngine';\nimport { computeLayout } from './engine/layout';\nimport { useFilterState } from './hooks/useFilterState';\nimport { useDimensionState } from './hooks/useDimensionState';\nimport { useZoomState } from './hooks/useZoomState';\nimport {\n BASE_CARD_WIDTH,\n BASE_CARD_HEIGHT,\n CARDS_PER_COLUMN,\n GROUP_SPACING,\n} from './constants';\nimport { PivotViewerMain } from './components/PivotViewerMain';\nimport { FilterPanelContainer } from './components/FilterPanelContainer';\nimport { ToolbarContainer } from './components/ToolbarContainer';\nimport { usePanning, useWheelZoom, useZoomScrollAnchor, useFilterOptions } from './hooks';\nimport { useContainerDimensions } from './hooks/useContainerDimensions';\nimport type { ViewMode } from './components/Toolbar';\nimport { useFieldExtractors } from './hooks/useFieldExtractors';\nimport { presentGrouping } from './utils/presentGrouping';\nimport { useCurrentFilters, useCurrentGroupBy } from './hooks/useCurrentFilters';\nimport { filterVisibleIdsBySearch } from './utils/search';\nimport { resolveInternalItemIndex } from './utils/idResolution';\nimport { useCardSelection } from './hooks/useCardSelection';\nimport { useDetailPanelClose } from './hooks/useDetailPanelClose';\nimport { useScrollSync } from './hooks/useScrollSync';\nimport { useAnimationModeTracking } from './hooks/useAnimationModeTracking';\nimport { useViewModeScrollHandling } from './hooks/useViewModeScrollHandling';\n\n/**\n * A faceted, zoomable card-grid visualization inspired by Microsoft's PivotViewer.\n * Renders a large set of items as cards that can be grouped by any of a set of\n * declared dimensions, filtered through faceted panels, searched by text, and\n * zoomed/panned around freely. A detail pane shows the selected card's full\n * information.\n *\n * Backed by PIXI.js for high-performance rendering, so it gracefully handles\n * thousands of items. Consumers supply their own `cardRenderer` and\n * `detailRenderer` to control card and detail content; the component handles\n * grouping, filtering, panning, zooming, and selection internally.\n *\n * Use this for exploratory data analysis UIs over large collections (catalogs,\n * inventories, telemetry samples). For tabular display, use {@link DataPage}\n * or {@link DataTableForQuery}.\n *\n * @typeParam TItem - The item type contained in {@link PivotViewerProps.data}.\n * @param props - {@link PivotViewerProps}.\n */\nexport function PivotViewer<TItem extends object>({\n data,\n dimensions,\n filters,\n defaultDimensionKey,\n cardRenderer,\n detailRenderer,\n getItemId,\n searchFields,\n title,\n className,\n emptyContent,\n isLoading = false,\n loadingLabel,\n labels,\n colors,\n}: PivotViewerProps<TItem>) {\n // Refs\n const containerRef = useRef<HTMLDivElement>(null!);\n const filterButtonRef = useRef<HTMLButtonElement>(null!);\n const axisLabelsRef = useRef<HTMLDivElement>(null!);\n const spacerRef = useRef<HTMLDivElement>(null!);\n\n // State\n const [search, setSearch] = useState('');\n const [viewMode, setViewMode] = useState<ViewMode>('collection');\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [selectedItem, setSelectedItem] = useState<TItem | null>(null);\n const [isZooming, setIsZooming] = useState(false);\n const [visibleIds, setVisibleIds] = useState<Uint32Array>(new Uint32Array(0));\n const [rawGrouping, setRawGrouping] = useState<GroupingResult>({ groups: [] });\n const [hoveredGroupIndex, setHoveredGroupIndex] = useState<number | null>(null);\n const [preSelectionState, setPreSelectionState] = useState<{\n zoom: number;\n scrollLeft: number;\n scrollTop: number;\n } | null>(null);\n const [, setAnimationMode] = useState<'layout' | 'filter'>('layout');\n const [scrollPosition, setScrollPosition] = useState({ x: 0, y: 0 });\n\n // Filter hooks\n const {\n filterState,\n rangeFilterState,\n expandedFilterKey,\n setExpandedFilterKey,\n handleToggleFilter,\n handleClearFilter,\n handleRangeChange,\n } = useFilterState(filters);\n\n // Dimension hooks\n const {\n activeDimensionKey,\n setActiveDimensionKey,\n activeDimension,\n dimensionFilter,\n handleAxisLabelClick,\n } = useDimensionState(dimensions, defaultDimensionKey);\n\n // Zoom and pan hooks\n const {\n zoomLevel,\n setZoomLevel,\n handleZoomIn,\n handleZoomOut,\n handleZoomSlider,\n handleZoomReset,\n handleZoomChange,\n } = useZoomState(1);\n\n const { isPanning, handlePanStart, handlePanMove, handlePanEnd } = usePanning(\n containerRef,\n undefined,\n setScrollPosition,\n );\n\n useWheelZoom(containerRef, zoomLevel, setZoomLevel);\n useZoomScrollAnchor(containerRef, spacerRef, viewMode);\n\n // Track container dimensions for responsive layout\n const containerDimensions = useContainerDimensions(containerRef, isLoading);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n setScrollPosition({\n x: container.scrollLeft,\n y: container.scrollTop,\n });\n };\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, []);\n\n // Build field extractors for the columnar store\n const { fieldExtractors, indexFields } = useFieldExtractors(dimensions, filters);\n\n // Initialize the Web Worker engine\n const {\n ready,\n applyFilters: engineApplyFilters,\n computeGrouping,\n sortIds,\n } = usePivotEngine({\n data,\n fieldExtractors,\n indexFields,\n });\n\n // Build filter specs from UI state\n const currentFilters = useCurrentFilters(\n filters,\n filterState,\n rangeFilterState,\n dimensionFilter,\n activeDimension,\n );\n\n const currentGroupBy = useCurrentGroupBy(activeDimensionKey, dimensions);\n\n // Apply filters, then narrow the result by search - a post-filter step over the visible\n // Uint32 ids so it applies identically whether the engine result came from the worker or\n // its synchronous fallback.\n useEffect(() => {\n if (!ready) return;\n\n let cancelled = false;\n void engineApplyFilters(currentFilters).then((result) => {\n if (cancelled) return;\n let ids = result.visibleIds;\n\n // If the engine failed to return any IDs while no filters are active,\n // fall back to showing the full dataset so the canvas never renders empty.\n if (ids.length === 0 && currentFilters.length === 0 && data.length > 0) {\n const fallbackIds = new Uint32Array(data.length);\n for (let i = 0; i < data.length; i++) {\n fallbackIds[i] = i;\n }\n ids = fallbackIds;\n }\n\n setVisibleIds(filterVisibleIdsBySearch(data, ids, search, searchFields));\n });\n return () => {\n cancelled = true;\n };\n }, [ready, currentFilters, engineApplyFilters, data, search, searchFields]);\n\n // Compute grouping. Every async branch ignores a result after its dependencies change, so an\n // older worker response can never overwrite a newer filter/search/view selection.\n useEffect(() => {\n if (!ready || visibleIds.length === 0) {\n setRawGrouping({ groups: [] });\n return;\n }\n\n let cancelled = false;\n if (viewMode === 'collection') {\n // In collection mode, create a single group with all items.\n if (activeDimensionKey) {\n void sortIds(visibleIds, activeDimensionKey).then((sortedIds) => {\n if (cancelled) return;\n setRawGrouping({\n groups: [\n {\n key: 'all',\n label: 'All Items',\n value: 'all',\n ids: sortedIds,\n count: sortedIds.length,\n },\n ],\n });\n });\n } else {\n setRawGrouping({\n groups: [\n {\n key: 'all',\n label: 'All Items',\n value: 'all',\n ids: visibleIds,\n count: visibleIds.length,\n },\n ],\n });\n }\n } else {\n void computeGrouping(visibleIds, currentGroupBy).then((result) => {\n if (!cancelled) setRawGrouping(result);\n });\n }\n\n return () => {\n cancelled = true;\n };\n }, [\n ready,\n visibleIds,\n currentGroupBy,\n viewMode,\n computeGrouping,\n sortIds,\n activeDimensionKey,\n ]);\n\n const grouping = useMemo(\n () => viewMode === 'grouped' ? presentGrouping(rawGrouping, activeDimension, data) : rawGrouping,\n [viewMode, rawGrouping, activeDimension, data],\n );\n\n // Compute layout\n const layout = useMemo(() => {\n // Calculate layout at base dimensions (zoom is applied as transform)\n const cardWidth = BASE_CARD_WIDTH;\n const cardHeight = BASE_CARD_HEIGHT;\n const containerWidth = containerDimensions.width / zoomLevel;\n // For grouped mode, use fixed container height to ensure stable layout during zoom\n const containerHeight =\n viewMode === 'collection'\n ? containerDimensions.height / zoomLevel\n : containerDimensions.height;\n\n const result = computeLayout(grouping, {\n viewMode,\n cardWidth,\n cardHeight,\n cardsPerColumn: CARDS_PER_COLUMN,\n groupSpacing: GROUP_SPACING,\n containerWidth,\n containerHeight,\n });\n\n return result;\n }, [\n grouping,\n viewMode,\n zoomLevel,\n containerDimensions.width,\n containerDimensions.height,\n ]);\n\n const resolveId = useCallback(\n (item: TItem) => resolveInternalItemIndex(data, item, getItemId),\n [data, getItemId],\n );\n\n // Track animation mode changes\n useAnimationModeTracking(\n filterState,\n rangeFilterState,\n search,\n activeDimensionKey,\n viewMode,\n setAnimationMode,\n );\n\n // Sync axis labels scroll with container scroll\n useScrollSync(containerRef, axisLabelsRef, viewMode);\n\n // Handle scroll positioning when switching view modes or grouping changes\n useViewModeScrollHandling({\n containerRef,\n viewMode,\n grouping,\n layout,\n selectedItem,\n zoomLevel,\n resolveId,\n data,\n setPreSelectionState,\n });\n\n // Handle card selection (click)\n const handleCardClick = useCardSelection({\n data,\n isPanning,\n selectedItem,\n zoomLevel,\n viewMode,\n layout,\n containerRef,\n spacerRef,\n containerDimensions,\n scrollPosition,\n preSelectionState,\n grouping,\n getItemId,\n resolveId,\n setZoomLevel,\n setIsZooming,\n setSelectedItem,\n setPreSelectionState,\n });\n\n // Handle detail panel close\n const closeDetail = useDetailPanelClose({\n selectedItem,\n preSelectionState,\n zoomLevel,\n viewMode,\n layout,\n containerRef,\n containerDimensions,\n grouping,\n data,\n resolveId,\n setZoomLevel,\n setIsZooming,\n setSelectedItem,\n setPreSelectionState,\n });\n\n // Use base card dimensions - zoom is applied as transform in canvas\n const cardWidth = BASE_CARD_WIDTH;\n const cardHeight = BASE_CARD_HEIGHT;\n\n // Calculate filter options\n const filterOptions = useFilterOptions(data, filters, filterState, rangeFilterState);\n\n const hasFilters = Boolean(filters && filters.length > 0);\n const activeFilterCount =\n Object.values(filterState).reduce(\n (sum: number, vals) => sum + (vals as Set<string>).size,\n 0,\n ) + Object.values(rangeFilterState).filter((r) => r !== null).length;\n\n const viewerClassName = [\n 'pivot-viewer',\n className,\n hasFilters ? (filtersOpen ? 'filters-open' : 'filters-closed') : 'no-filters',\n viewMode === 'grouped' ? 'grouped-mode' : 'collection-mode',\n ]\n .filter(Boolean)\n .join(' ');\n\n // Deselect any selected card when switching between view modes\n useEffect(() => {\n setSelectedItem(null);\n }, [viewMode]);\n\n // Map provided color overrides to CSS variables understood by the component.\n const cssVariables = useMemo(() => {\n const vars: Record<string, string> = {};\n if (!colors) return vars;\n if (colors.primaryColor) vars['--cratis-primary-color'] = colors.primaryColor;\n if (colors.primaryColorText)\n vars['--cratis-primary-color-text'] = colors.primaryColorText;\n if (colors.primary500) vars['--cratis-primary-500'] = colors.primary500;\n if (colors.surfaceGround) vars['--cratis-surface-ground'] = colors.surfaceGround;\n if (colors.surfaceCard) vars['--cratis-surface-card'] = colors.surfaceCard;\n if (colors.surfaceSection)\n vars['--cratis-surface-section'] = colors.surfaceSection;\n if (colors.surfaceOverlay)\n vars['--cratis-surface-overlay'] = colors.surfaceOverlay;\n if (colors.surfaceBorder) vars['--cratis-surface-border'] = colors.surfaceBorder;\n if (colors.textColor) vars['--cratis-text-color'] = colors.textColor;\n if (colors.textColorSecondary)\n vars['--cratis-text-color-secondary'] = colors.textColorSecondary;\n if (colors.highlightBg) vars['--cratis-highlight-bg'] = colors.highlightBg;\n if (colors.maskbg) vars['--cratis-maskbg'] = colors.maskbg;\n if (colors.focusRing) vars['--cratis-focus-ring'] = colors.focusRing;\n return vars;\n }, [colors]);\n\n return (\n <div className={viewerClassName} style={cssVariables as React.CSSProperties}>\n <FilterPanelContainer\n isOpen={filtersOpen && hasFilters}\n filterLabel={labels?.filters}\n searchPlaceholder={labels?.search}\n searchGroup={labels?.searchGroup}\n search={search}\n filterState={filterState}\n rangeFilterState={rangeFilterState}\n expandedFilterKey={expandedFilterKey}\n filterOptions={filterOptions}\n anchorRef={filterButtonRef}\n onClose={() => setFiltersOpen(false)}\n onSearchChange={setSearch}\n onFilterToggle={handleToggleFilter}\n onFilterClear={handleClearFilter}\n onRangeChange={handleRangeChange}\n onExpandedFilterChange={setExpandedFilterKey}\n />\n\n <main className='pv-main'>\n <ToolbarContainer\n hasFilters={hasFilters}\n filtersOpen={filtersOpen}\n filteredCount={visibleIds.length}\n viewMode={viewMode}\n zoomLevel={zoomLevel}\n activeDimensionKey={activeDimensionKey}\n dimensions={dimensions}\n activeFilterCount={activeFilterCount}\n title={title}\n labels={labels}\n onFiltersToggle={() => setFiltersOpen((prev) => !prev)}\n onViewModeChange={setViewMode}\n onZoomIn={handleZoomIn}\n onZoomOut={handleZoomOut}\n onZoomSlider={handleZoomSlider}\n onZoomReset={handleZoomReset}\n onZoomChange={handleZoomChange}\n onDimensionChange={setActiveDimensionKey}\n filterButtonRef={filterButtonRef}\n />\n\n <PivotViewerMain\n data={data}\n ready={ready}\n isLoading={isLoading}\n loadingLabel={loadingLabel ?? labels?.loading ?? 'Loading…'}\n viewportLabel={labels?.viewport ?? 'Card area'}\n visibleIds={visibleIds}\n grouping={grouping}\n layout={layout}\n cardWidth={cardWidth}\n cardHeight={cardHeight}\n zoomLevel={zoomLevel}\n scrollPosition={scrollPosition}\n containerDimensions={containerDimensions}\n selectedItem={selectedItem}\n hoveredGroupIndex={hoveredGroupIndex}\n isZooming={isZooming}\n viewMode={viewMode}\n cardRenderer={cardRenderer}\n colorOverrides={colors}\n detailRenderer={detailRenderer}\n resolveId={resolveId}\n emptyContent={emptyContent}\n dimensionFilter={dimensionFilter}\n onCardClick={handleCardClick}\n onPanStart={handlePanStart as (e: React.MouseEvent) => void}\n onPanMove={handlePanMove as (e: React.MouseEvent) => void}\n onPanEnd={handlePanEnd}\n onGroupHover={setHoveredGroupIndex}\n onAxisLabelClick={handleAxisLabelClick}\n onCloseDetail={closeDetail}\n containerRef={containerRef}\n axisLabelsRef={axisLabelsRef}\n spacerRef={spacerRef}\n />\n </main>\n </div>\n );\n}\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"PivotViewer.js","sources":["../../../PivotViewer/PivotViewer.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { PivotViewerProps } from './types';\nimport { useFilterState } from './hooks/useFilterState';\nimport { useDimensionState } from './hooks/useDimensionState';\nimport { useZoomState } from './hooks/useZoomState';\nimport { BASE_CARD_WIDTH, BASE_CARD_HEIGHT } from './constants';\nimport { PivotViewerMain } from './components/PivotViewerMain';\nimport { FilterPanelContainer } from './components/FilterPanelContainer';\nimport { ToolbarContainer } from './components/ToolbarContainer';\nimport { usePanning, useWheelZoom, useZoomScrollAnchor, useFilterOptions } from './hooks';\nimport { useContainerDimensions } from './hooks/useContainerDimensions';\nimport type { ViewMode } from './components/Toolbar';\nimport { useColorCssVariables } from './hooks/useColorCssVariables';\nimport { useViewerLayout } from './hooks/useViewerLayout';\nimport { useScrollPositionTracking } from './hooks/useScrollPositionTracking';\nimport { usePivotViewerGrouping } from './hooks/usePivotViewerGrouping';\nimport { usePivotViewerInteractions } from './hooks/usePivotViewerInteractions';\n\nfunction countActiveFilters(\n filterState: Record<string, unknown>,\n rangeFilterState: Record<string, unknown>,\n): number {\n const selectionCount = Object.values(filterState).reduce(\n (sum: number, vals) => sum + (vals as Set<string>).size,\n 0,\n );\n return selectionCount + Object.values(rangeFilterState).filter((r) => r !== null).length;\n}\n\nfunction filtersClassName(hasFilters: boolean, filtersOpen: boolean): string {\n if (!hasFilters) return 'no-filters';\n return filtersOpen ? 'filters-open' : 'filters-closed';\n}\n\nfunction buildViewerClassName(\n className: string | undefined,\n hasFilters: boolean,\n filtersOpen: boolean,\n viewMode: ViewMode,\n): string {\n return [\n 'pivot-viewer',\n className,\n filtersClassName(hasFilters, filtersOpen),\n viewMode === 'grouped' ? 'grouped-mode' : 'collection-mode',\n ]\n .filter(Boolean)\n .join(' ');\n}\n\n/**\n * A faceted, zoomable card-grid visualization inspired by Microsoft's PivotViewer.\n * Renders a large set of items as cards that can be grouped by any of a set of\n * declared dimensions, filtered through faceted panels, searched by text, and\n * zoomed/panned around freely. A detail pane shows the selected card's full\n * information.\n *\n * Backed by PIXI.js for high-performance rendering, so it gracefully handles\n * thousands of items. Consumers supply their own `cardRenderer` and\n * `detailRenderer` to control card and detail content; the component handles\n * grouping, filtering, panning, zooming, and selection internally.\n *\n * Use this for exploratory data analysis UIs over large collections (catalogs,\n * inventories, telemetry samples). For tabular display, use {@link DataPage}\n * or {@link DataTableForQuery}.\n *\n * @typeParam TItem - The item type contained in {@link PivotViewerProps.data}.\n * @param props - {@link PivotViewerProps}.\n */\nexport function PivotViewer<TItem extends object>({\n data,\n dimensions,\n filters,\n defaultDimensionKey,\n cardRenderer,\n detailRenderer,\n getItemId,\n searchFields,\n title,\n className,\n emptyContent,\n isLoading = false,\n loadingLabel,\n labels,\n colors,\n}: PivotViewerProps<TItem>) {\n // Refs\n const containerRef = useRef<HTMLDivElement>(null!);\n const filterButtonRef = useRef<HTMLButtonElement>(null!);\n const axisLabelsRef = useRef<HTMLDivElement>(null!);\n const spacerRef = useRef<HTMLDivElement>(null!);\n\n // State\n const [search, setSearch] = useState('');\n const [viewMode, setViewMode] = useState<ViewMode>('collection');\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [selectedItem, setSelectedItem] = useState<TItem | null>(null);\n const [isZooming, setIsZooming] = useState(false);\n const [hoveredGroupIndex, setHoveredGroupIndex] = useState<number | null>(null);\n const [preSelectionState, setPreSelectionState] = useState<{\n zoom: number;\n scrollLeft: number;\n scrollTop: number;\n } | null>(null);\n const [, setAnimationMode] = useState<'layout' | 'filter'>('layout');\n const [scrollPosition, setScrollPosition] = useState({ x: 0, y: 0 });\n\n // Filter hooks\n const {\n filterState,\n rangeFilterState,\n expandedFilterKey,\n setExpandedFilterKey,\n handleToggleFilter,\n handleClearFilter,\n handleRangeChange,\n } = useFilterState(filters);\n\n // Dimension hooks\n const {\n activeDimensionKey,\n setActiveDimensionKey,\n activeDimension,\n dimensionFilter,\n handleAxisLabelClick,\n } = useDimensionState(dimensions, defaultDimensionKey);\n\n // Zoom and pan hooks\n const {\n zoomLevel,\n setZoomLevel,\n handleZoomIn,\n handleZoomOut,\n handleZoomSlider,\n handleZoomReset,\n handleZoomChange,\n } = useZoomState(1);\n\n const { isPanning, handlePanStart, handlePanMove, handlePanEnd } = usePanning(\n containerRef,\n undefined,\n setScrollPosition,\n );\n\n useWheelZoom(containerRef, zoomLevel, setZoomLevel);\n useZoomScrollAnchor(containerRef, spacerRef, viewMode);\n\n // Track container dimensions for responsive layout\n const containerDimensions = useContainerDimensions(containerRef, isLoading);\n\n useScrollPositionTracking(containerRef, setScrollPosition);\n\n const { ready, visibleIds, grouping } = usePivotViewerGrouping({\n data,\n dimensions,\n filters,\n filterState,\n rangeFilterState,\n dimensionFilter,\n activeDimension,\n activeDimensionKey,\n searchFields,\n search,\n viewMode,\n });\n\n const layout = useViewerLayout(grouping, viewMode, zoomLevel, containerDimensions);\n\n const { resolveId, handleCardClick, closeDetail } = usePivotViewerInteractions({\n data,\n isPanning,\n selectedItem,\n zoomLevel,\n viewMode,\n layout,\n containerRef,\n axisLabelsRef,\n spacerRef,\n containerDimensions,\n scrollPosition,\n preSelectionState,\n grouping,\n getItemId,\n filterState,\n rangeFilterState,\n search,\n activeDimensionKey,\n setAnimationMode,\n setZoomLevel,\n setIsZooming,\n setSelectedItem,\n setPreSelectionState,\n });\n\n // Use base card dimensions - zoom is applied as transform in canvas\n const cardWidth = BASE_CARD_WIDTH;\n const cardHeight = BASE_CARD_HEIGHT;\n\n // Calculate filter options\n const filterOptions = useFilterOptions(data, filters, filterState, rangeFilterState);\n\n const hasFilters = Boolean(filters && filters.length > 0);\n const activeFilterCount = countActiveFilters(filterState, rangeFilterState);\n const viewerClassName = buildViewerClassName(className, hasFilters, filtersOpen, viewMode);\n\n // Deselect any selected card when switching between view modes\n useEffect(() => {\n setSelectedItem(null);\n }, [viewMode]);\n\n const cssVariables = useColorCssVariables(colors);\n\n return (\n <div className={viewerClassName} style={cssVariables as React.CSSProperties}>\n <FilterPanelContainer\n isOpen={filtersOpen && hasFilters}\n filterLabel={labels?.filters}\n searchPlaceholder={labels?.search}\n searchGroup={labels?.searchGroup}\n search={search}\n filterState={filterState}\n rangeFilterState={rangeFilterState}\n expandedFilterKey={expandedFilterKey}\n filterOptions={filterOptions}\n anchorRef={filterButtonRef}\n onClose={() => setFiltersOpen(false)}\n onSearchChange={setSearch}\n onFilterToggle={handleToggleFilter}\n onFilterClear={handleClearFilter}\n onRangeChange={handleRangeChange}\n onExpandedFilterChange={setExpandedFilterKey}\n />\n\n <main className='pv-main'>\n <ToolbarContainer\n hasFilters={hasFilters}\n filtersOpen={filtersOpen}\n filteredCount={visibleIds.length}\n viewMode={viewMode}\n zoomLevel={zoomLevel}\n activeDimensionKey={activeDimensionKey}\n dimensions={dimensions}\n activeFilterCount={activeFilterCount}\n title={title}\n labels={labels}\n onFiltersToggle={() => setFiltersOpen((prev) => !prev)}\n onViewModeChange={setViewMode}\n onZoomIn={handleZoomIn}\n onZoomOut={handleZoomOut}\n onZoomSlider={handleZoomSlider}\n onZoomReset={handleZoomReset}\n onZoomChange={handleZoomChange}\n onDimensionChange={setActiveDimensionKey}\n filterButtonRef={filterButtonRef}\n />\n\n <PivotViewerMain\n data={data}\n ready={ready}\n isLoading={isLoading}\n loadingLabel={loadingLabel ?? labels?.loading ?? 'Loading…'}\n viewportLabel={labels?.viewport ?? 'Card area'}\n visibleIds={visibleIds}\n grouping={grouping}\n layout={layout}\n cardWidth={cardWidth}\n cardHeight={cardHeight}\n zoomLevel={zoomLevel}\n scrollPosition={scrollPosition}\n containerDimensions={containerDimensions}\n selectedItem={selectedItem}\n hoveredGroupIndex={hoveredGroupIndex}\n isZooming={isZooming}\n viewMode={viewMode}\n cardRenderer={cardRenderer}\n colorOverrides={colors}\n detailRenderer={detailRenderer}\n resolveId={resolveId}\n emptyContent={emptyContent}\n dimensionFilter={dimensionFilter}\n onCardClick={handleCardClick}\n onPanStart={handlePanStart as (e: React.MouseEvent) => void}\n onPanMove={handlePanMove as (e: React.MouseEvent) => void}\n onPanEnd={handlePanEnd}\n onGroupHover={setHoveredGroupIndex}\n onAxisLabelClick={handleAxisLabelClick}\n onCloseDetail={closeDetail}\n containerRef={containerRef}\n axisLabelsRef={axisLabelsRef}\n spacerRef={spacerRef}\n />\n </main>\n </div>\n );\n}\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import * as PIXI from 'pixi.js';
1
+ import type * as PIXI from 'pixi.js';
2
2
  import type { CardSprite } from './constants.js';
3
3
  import type { LayoutResult } from '../../engine/types.js';
4
4
  export interface SyncParams<TItem> {
@@ -1 +1 @@
1
- {"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../../../../PivotViewer/components/pivot/visibility.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAa,CAAC;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAoB,CAAC;AAGvD,MAAM,WAAW,UAAU,CAAC,KAAK;IAC7B,IAAI,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,cAAc,GAAG,IAAI,CAAC;IACjC,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,UAAU,CAAC,CAAC;IAC1C,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,WAAW,CAAC;IACxB,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;IAC5E,iBAAiB,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACxC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACvB,4GAA4G;IAC5G,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC,KAAK,CAAC,cAIrF;AAiED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,GAAG,UAAU,CAkTlF"}
1
+ {"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../../../../PivotViewer/components/pivot/visibility.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,IAAI,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAoB,CAAC;AAgBvD,MAAM,WAAW,UAAU,CAAC,KAAK;IAC7B,IAAI,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,cAAc,GAAG,IAAI,CAAC;IACjC,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,UAAU,CAAC,CAAC;IAC1C,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,WAAW,CAAC;IACxB,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;IAC5E,iBAAiB,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACxC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACvB,4GAA4G;IAC5G,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC,KAAK,CAAC,cAIrF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,GAAG,UAAU,CA0ElF"}