@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.
- package/compat-manifest.json +11 -11
- package/dist/esm/Common/CratisComponentsProvider.d.ts +4 -0
- package/dist/esm/Common/CratisComponentsProvider.d.ts.map +1 -1
- package/dist/esm/Common/CratisComponentsProvider.js +1 -0
- package/dist/esm/Common/CratisComponentsProvider.js.map +1 -1
- package/dist/esm/DataPage/DataPage.d.ts +2 -0
- package/dist/esm/DataPage/DataPage.d.ts.map +1 -1
- package/dist/esm/DataPage/DataPage.js.map +1 -1
- package/dist/esm/DataTables/DataTableForObservableQuery.d.ts +2 -0
- package/dist/esm/DataTables/DataTableForObservableQuery.d.ts.map +1 -1
- package/dist/esm/DataTables/DataTableForObservableQuery.js +1 -1
- package/dist/esm/DataTables/DataTableForObservableQuery.js.map +1 -1
- package/dist/esm/DataTables/DataTableForQuery.d.ts +2 -0
- package/dist/esm/DataTables/DataTableForQuery.d.ts.map +1 -1
- package/dist/esm/DataTables/DataTableForQuery.js +1 -1
- package/dist/esm/DataTables/DataTableForQuery.js.map +1 -1
- package/dist/esm/DataTables/PaginatorPageItem.d.ts +13 -0
- package/dist/esm/DataTables/PaginatorPageItem.d.ts.map +1 -0
- package/dist/esm/DataTables/PaginatorPageItem.js +4 -0
- package/dist/esm/DataTables/PaginatorPageItem.js.map +1 -0
- package/dist/esm/DataTables/TablePaginator.d.ts +22 -2
- package/dist/esm/DataTables/TablePaginator.d.ts.map +1 -1
- package/dist/esm/DataTables/TablePaginator.js.map +1 -1
- package/dist/esm/DataTables/TablePaginatorImplementation.d.ts +1 -1
- package/dist/esm/DataTables/TablePaginatorImplementation.d.ts.map +1 -1
- package/dist/esm/DataTables/TablePaginatorImplementation.js +8 -3
- package/dist/esm/DataTables/TablePaginatorImplementation.js.map +1 -1
- package/dist/esm/DataTables/TablePaginatorPages.d.ts +9 -0
- package/dist/esm/DataTables/TablePaginatorPages.d.ts.map +1 -0
- package/dist/esm/DataTables/TablePaginatorPages.js +20 -0
- package/dist/esm/DataTables/TablePaginatorPages.js.map +1 -0
- package/dist/esm/DataTables/index.d.ts +2 -0
- package/dist/esm/DataTables/index.d.ts.map +1 -1
- package/dist/esm/DataTables/index.js +1 -0
- package/dist/esm/DataTables/index.js.map +1 -1
- package/dist/esm/DataTables/paginatorPages.d.ts +15 -0
- package/dist/esm/DataTables/paginatorPages.d.ts.map +1 -0
- package/dist/esm/DataTables/paginatorPages.js +40 -0
- package/dist/esm/DataTables/paginatorPages.js.map +1 -0
- package/dist/esm/Filter/FilterGroup.d.ts +23 -0
- package/dist/esm/Filter/FilterGroup.d.ts.map +1 -0
- package/dist/esm/Filter/FilterGroup.js +51 -0
- package/dist/esm/Filter/FilterGroup.js.map +1 -0
- package/dist/esm/Filter/FilterPanel.d.ts.map +1 -1
- package/dist/esm/Filter/FilterPanel.js +24 -257
- package/dist/esm/Filter/FilterPanel.js.map +1 -1
- package/dist/esm/Filter/FilterSearchBox.d.ts +10 -0
- package/dist/esm/Filter/FilterSearchBox.d.ts.map +1 -0
- package/dist/esm/Filter/FilterSearchBox.js +10 -0
- package/dist/esm/Filter/FilterSearchBox.js.map +1 -0
- package/dist/esm/Filter/measurePanelPlacement.d.ts +31 -0
- package/dist/esm/Filter/measurePanelPlacement.d.ts.map +1 -0
- package/dist/esm/Filter/measurePanelPlacement.js +132 -0
- package/dist/esm/Filter/measurePanelPlacement.js.map +1 -0
- package/dist/esm/Filter/usePanelDismissal.d.ts +32 -0
- package/dist/esm/Filter/usePanelDismissal.d.ts.map +1 -0
- package/dist/esm/Filter/usePanelDismissal.js +63 -0
- package/dist/esm/Filter/usePanelDismissal.js.map +1 -0
- package/dist/esm/Filter/usePanelPosition.d.ts +24 -0
- package/dist/esm/Filter/usePanelPosition.d.ts.map +1 -0
- package/dist/esm/Filter/usePanelPosition.js +85 -0
- package/dist/esm/Filter/usePanelPosition.js.map +1 -0
- package/dist/esm/Filter/useResolvedAnchor.d.ts +17 -0
- package/dist/esm/Filter/useResolvedAnchor.d.ts.map +1 -0
- package/dist/esm/Filter/useResolvedAnchor.js +16 -0
- package/dist/esm/Filter/useResolvedAnchor.js.map +1 -0
- package/dist/esm/PivotViewer/PivotViewer.d.ts.map +1 -1
- package/dist/esm/PivotViewer/PivotViewer.js +47 -207
- package/dist/esm/PivotViewer/PivotViewer.js.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/visibility.d.ts +1 -1
- package/dist/esm/PivotViewer/components/pivot/visibility.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/visibility.js +24 -222
- package/dist/esm/PivotViewer/components/pivot/visibility.js.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/visibilityHelpers.d.ts +114 -0
- package/dist/esm/PivotViewer/components/pivot/visibilityHelpers.d.ts.map +1 -0
- package/dist/esm/PivotViewer/components/pivot/visibilityHelpers.js +306 -0
- package/dist/esm/PivotViewer/components/pivot/visibilityHelpers.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useColorCssVariables.d.ts +9 -0
- package/dist/esm/PivotViewer/hooks/useColorCssVariables.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useColorCssVariables.js +32 -0
- package/dist/esm/PivotViewer/hooks/useColorCssVariables.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/usePivotViewerGrouping.d.ts +27 -0
- package/dist/esm/PivotViewer/hooks/usePivotViewerGrouping.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/usePivotViewerGrouping.js +40 -0
- package/dist/esm/PivotViewer/hooks/usePivotViewerGrouping.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/usePivotViewerInteractions.d.ts +27 -0
- package/dist/esm/PivotViewer/hooks/usePivotViewerInteractions.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/usePivotViewerInteractions.js +46 -0
- package/dist/esm/PivotViewer/hooks/usePivotViewerInteractions.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useRawGrouping.d.ts +22 -0
- package/dist/esm/PivotViewer/hooks/useRawGrouping.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useRawGrouping.js +56 -0
- package/dist/esm/PivotViewer/hooks/useRawGrouping.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useScrollPositionTracking.d.ts +12 -0
- package/dist/esm/PivotViewer/hooks/useScrollPositionTracking.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useScrollPositionTracking.js +20 -0
- package/dist/esm/PivotViewer/hooks/useScrollPositionTracking.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useViewerLayout.d.ts +16 -0
- package/dist/esm/PivotViewer/hooks/useViewerLayout.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useViewerLayout.js +29 -0
- package/dist/esm/PivotViewer/hooks/useViewerLayout.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useVisibleIds.d.ts +21 -0
- package/dist/esm/PivotViewer/hooks/useVisibleIds.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useVisibleIds.js +34 -0
- package/dist/esm/PivotViewer/hooks/useVisibleIds.js.map +1 -0
- package/dist/esm/SchemaEditor/SchemaEditor.d.ts +4 -1
- package/dist/esm/SchemaEditor/SchemaEditor.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/SchemaEditor.js.map +1 -1
- package/dist/esm/SchemaEditor/SchemaEditorLabels.d.ts +6 -0
- package/dist/esm/SchemaEditor/SchemaEditorLabels.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/SchemaEditorLabels.js.map +1 -1
- package/dist/esm/SchemaEditor/Tree/GeneratedToggle.d.ts +11 -0
- package/dist/esm/SchemaEditor/Tree/GeneratedToggle.d.ts.map +1 -0
- package/dist/esm/SchemaEditor/Tree/GeneratedToggle.js +24 -0
- package/dist/esm/SchemaEditor/Tree/GeneratedToggle.js.map +1 -0
- package/dist/esm/SchemaEditor/Tree/Property.d.ts +6 -0
- package/dist/esm/SchemaEditor/Tree/Property.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/Tree/Property.js.map +1 -1
- package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.d.ts +2 -0
- package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.js.map +1 -1
- package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.d.ts +2 -0
- package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.js.map +1 -1
- package/dist/esm/SchemaEditor/Tree/SchemaOrderedProperty.d.ts +12 -0
- package/dist/esm/SchemaEditor/Tree/SchemaOrderedProperty.d.ts.map +1 -0
- package/dist/esm/SchemaEditor/Tree/SchemaOrderedProperty.js +13 -0
- package/dist/esm/SchemaEditor/Tree/SchemaOrderedProperty.js.map +1 -0
- package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.js +2 -2
- package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.js.map +1 -1
- package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.d.ts +8 -1
- package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.js +15 -11
- package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.js.map +1 -1
- package/dist/esm/SchemaEditor/Tree/schemaConversion.d.ts +15 -3
- package/dist/esm/SchemaEditor/Tree/schemaConversion.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/Tree/schemaConversion.js +83 -27
- package/dist/esm/SchemaEditor/Tree/schemaConversion.js.map +1 -1
- package/dist/esm/SchemaEditor/Tree/schemaInOriginalOrder.d.ts +3 -0
- package/dist/esm/SchemaEditor/Tree/schemaInOriginalOrder.d.ts.map +1 -0
- package/dist/esm/SchemaEditor/Tree/schemaInOriginalOrder.js +7 -0
- package/dist/esm/SchemaEditor/Tree/schemaInOriginalOrder.js.map +1 -0
- package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.js +3 -0
- package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.js.map +1 -1
- package/dist/esm/SchemaEditor/index.d.ts +1 -1
- package/dist/esm/SchemaEditor/index.d.ts.map +1 -1
- package/dist/esm/SchemaEditor/index.js +1 -1
- package/dist/esm/configuration/CratisComponentsDefaults.d.ts.map +1 -1
- package/dist/esm/configuration/CratisComponentsDefaults.js +2 -0
- package/dist/esm/configuration/CratisComponentsDefaults.js.map +1 -1
- package/dist/esm/styles.DataPage.css +51 -6
- package/dist/esm/styles.DataTables.css +51 -6
- package/dist/esm/styles.SchemaEditor.css +58 -16
- package/dist/esm/styles.css +58 -16
- package/dist/esm/styles.renderer.builtin.css +51 -6
- package/dist/esm/types/parts.d.ts +6 -2
- package/dist/esm/types/parts.d.ts.map +1 -1
- package/dist/esm/types/parts.js +6 -2
- package/dist/esm/types/parts.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { useRef, useState, useEffect
|
|
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
|
|
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 {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
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
|
-
|
|
53
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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 =
|
|
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 =
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../../../../PivotViewer/components/pivot/visibility.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;
|
|
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"}
|