@cratis/components 0.1.17 → 0.1.18
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/dist/cjs/PivotViewer/PivotViewer.css +54 -5
- package/dist/cjs/PivotViewer/PivotViewer.js +5 -2
- package/dist/cjs/PivotViewer/PivotViewer.js.map +1 -1
- package/dist/cjs/PivotViewer/components/AxisLabels.js +5 -8
- package/dist/cjs/PivotViewer/components/AxisLabels.js.map +1 -1
- package/dist/cjs/PivotViewer/components/DetailPanel.js +9 -2
- package/dist/cjs/PivotViewer/components/DetailPanel.js.map +1 -1
- package/dist/cjs/PivotViewer/components/PivotCanvas.js +30 -6
- package/dist/cjs/PivotViewer/components/PivotCanvas.js.map +1 -1
- package/dist/cjs/PivotViewer/components/PivotViewerMain.js +16 -5
- package/dist/cjs/PivotViewer/components/PivotViewerMain.js.map +1 -1
- package/dist/cjs/PivotViewer/components/Toolbar.js +34 -2
- package/dist/cjs/PivotViewer/components/Toolbar.js.map +1 -1
- package/dist/cjs/PivotViewer/components/pivot/constants.js +5 -5
- package/dist/cjs/PivotViewer/components/pivot/constants.js.map +1 -1
- package/dist/cjs/PivotViewer/components/pivot/sprites.js +10 -27
- package/dist/cjs/PivotViewer/components/pivot/sprites.js.map +1 -1
- package/dist/cjs/PivotViewer/components/pivot/visibility.js +8 -20
- package/dist/cjs/PivotViewer/components/pivot/visibility.js.map +1 -1
- package/dist/cjs/PivotViewer/constants.js +0 -2
- package/dist/cjs/PivotViewer/constants.js.map +1 -1
- package/dist/cjs/PivotViewer/engine/layout.js +1 -1
- package/dist/cjs/PivotViewer/engine/layout.js.map +1 -1
- package/dist/cjs/PivotViewer/hooks/useCardSelection.js +2 -1
- package/dist/cjs/PivotViewer/hooks/useCardSelection.js.map +1 -1
- package/dist/cjs/PivotViewer/hooks/useZoomState.js +4 -0
- package/dist/cjs/PivotViewer/hooks/useZoomState.js.map +1 -1
- package/dist/cjs/PivotViewer/types.js.map +1 -1
- package/dist/cjs/PivotViewer/utils/animations.js +1 -1
- package/dist/cjs/PivotViewer/utils/animations.js.map +1 -1
- package/dist/cjs/PivotViewer/utils/constants.js +1 -1
- package/dist/cjs/PivotViewer/utils/constants.js.map +1 -1
- package/dist/cjs/PivotViewer/utils/selection.js +8 -1
- package/dist/cjs/PivotViewer/utils/selection.js.map +1 -1
- package/dist/esm/PivotViewer/PivotViewer.css +54 -5
- package/dist/esm/PivotViewer/PivotViewer.d.ts.map +1 -1
- package/dist/esm/PivotViewer/PivotViewer.js +5 -2
- package/dist/esm/PivotViewer/PivotViewer.js.map +1 -1
- package/dist/esm/PivotViewer/PivotViewer.stories.d.ts +0 -1
- package/dist/esm/PivotViewer/PivotViewer.stories.d.ts.map +1 -1
- package/dist/esm/PivotViewer/PivotViewer.stories.js +10 -9
- package/dist/esm/PivotViewer/PivotViewer.stories.js.map +1 -1
- package/dist/esm/PivotViewer/components/AxisLabels.d.ts +2 -1
- package/dist/esm/PivotViewer/components/AxisLabels.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/AxisLabels.js +6 -9
- package/dist/esm/PivotViewer/components/AxisLabels.js.map +1 -1
- package/dist/esm/PivotViewer/components/DetailPanel.d.ts +3 -1
- package/dist/esm/PivotViewer/components/DetailPanel.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/DetailPanel.js +10 -3
- package/dist/esm/PivotViewer/components/DetailPanel.js.map +1 -1
- package/dist/esm/PivotViewer/components/PivotCanvas.d.ts +5 -2
- package/dist/esm/PivotViewer/components/PivotCanvas.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/PivotCanvas.js +30 -6
- package/dist/esm/PivotViewer/components/PivotCanvas.js.map +1 -1
- package/dist/esm/PivotViewer/components/PivotViewerMain.d.ts +5 -1
- package/dist/esm/PivotViewer/components/PivotViewerMain.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/PivotViewerMain.js +16 -5
- package/dist/esm/PivotViewer/components/PivotViewerMain.js.map +1 -1
- package/dist/esm/PivotViewer/components/Toolbar.d.ts +3 -1
- package/dist/esm/PivotViewer/components/Toolbar.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/Toolbar.js +34 -2
- package/dist/esm/PivotViewer/components/Toolbar.js.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/constants.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/constants.js +5 -5
- package/dist/esm/PivotViewer/components/pivot/constants.js.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/sprites.d.ts +10 -2
- package/dist/esm/PivotViewer/components/pivot/sprites.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/sprites.js +10 -27
- package/dist/esm/PivotViewer/components/pivot/sprites.js.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/visibility.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/visibility.js +8 -20
- package/dist/esm/PivotViewer/components/pivot/visibility.js.map +1 -1
- package/dist/esm/PivotViewer/constants.js +1 -2
- package/dist/esm/PivotViewer/constants.js.map +1 -1
- package/dist/esm/PivotViewer/engine/layout.js +1 -1
- package/dist/esm/PivotViewer/engine/layout.js.map +1 -1
- package/dist/esm/PivotViewer/hooks/useCardSelection.d.ts.map +1 -1
- package/dist/esm/PivotViewer/hooks/useCardSelection.js +2 -1
- package/dist/esm/PivotViewer/hooks/useCardSelection.js.map +1 -1
- package/dist/esm/PivotViewer/hooks/useZoomState.d.ts +1 -0
- package/dist/esm/PivotViewer/hooks/useZoomState.d.ts.map +1 -1
- package/dist/esm/PivotViewer/hooks/useZoomState.js +4 -0
- package/dist/esm/PivotViewer/hooks/useZoomState.js.map +1 -1
- package/dist/esm/PivotViewer/types.d.ts +5 -1
- package/dist/esm/PivotViewer/types.d.ts.map +1 -1
- package/dist/esm/PivotViewer/types.js.map +1 -1
- package/dist/esm/PivotViewer/utils/animations.js +1 -1
- package/dist/esm/PivotViewer/utils/animations.js.map +1 -1
- package/dist/esm/PivotViewer/utils/constants.d.ts +1 -1
- package/dist/esm/PivotViewer/utils/constants.d.ts.map +1 -1
- package/dist/esm/PivotViewer/utils/constants.js +1 -1
- package/dist/esm/PivotViewer/utils/constants.js.map +1 -1
- package/dist/esm/PivotViewer/utils/selection.d.ts.map +1 -1
- package/dist/esm/PivotViewer/utils/selection.js +8 -1
- package/dist/esm/PivotViewer/utils/selection.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -530,6 +530,33 @@
|
|
|
530
530
|
min-width: 3rem;
|
|
531
531
|
text-align: center;
|
|
532
532
|
font-variant-numeric: tabular-nums;
|
|
533
|
+
cursor: pointer;
|
|
534
|
+
padding: 0.25rem 0.5rem;
|
|
535
|
+
border-radius: 0.4rem;
|
|
536
|
+
transition: background 120ms ease;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.pv-zoom-controls span:hover {
|
|
540
|
+
background: var(--surface-hover);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.pv-zoom-level-input {
|
|
544
|
+
width: 3rem;
|
|
545
|
+
font-size: 0.75rem;
|
|
546
|
+
text-align: center;
|
|
547
|
+
background: var(--surface-ground);
|
|
548
|
+
border: 1px solid var(--primary-color);
|
|
549
|
+
border-radius: 0.4rem;
|
|
550
|
+
color: var(--text-color);
|
|
551
|
+
padding: 0.25rem 0.5rem;
|
|
552
|
+
font-variant-numeric: tabular-nums;
|
|
553
|
+
outline: none;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
.pv-zoom-reset {
|
|
557
|
+
display: flex;
|
|
558
|
+
align-items: center;
|
|
559
|
+
justify-content: center;
|
|
533
560
|
}
|
|
534
561
|
|
|
535
562
|
.pv-dimension-select {
|
|
@@ -688,7 +715,7 @@
|
|
|
688
715
|
}
|
|
689
716
|
|
|
690
717
|
.pv-cards-grouped .pv-card {
|
|
691
|
-
|
|
718
|
+
transform: none;
|
|
692
719
|
}
|
|
693
720
|
|
|
694
721
|
/* Empty placeholder cells in grouped grid */
|
|
@@ -704,9 +731,8 @@
|
|
|
704
731
|
align-items: stretch;
|
|
705
732
|
background: var(--surface-section);
|
|
706
733
|
border-top: 1px solid var(--surface-border);
|
|
707
|
-
padding: 0.5rem
|
|
708
|
-
|
|
709
|
-
gap: 0.25rem; /* Match gap between groups */
|
|
734
|
+
padding: 0.5rem 0; /* padding-left set dynamically from JS; no right padding to prevent skew */
|
|
735
|
+
gap: 0; /* No extra gap to avoid skew */
|
|
710
736
|
overflow-x: hidden; /* Disable independent scroll - synced via JS */
|
|
711
737
|
flex-shrink: 0;
|
|
712
738
|
}
|
|
@@ -719,6 +745,7 @@
|
|
|
719
745
|
padding: 0.5rem 0;
|
|
720
746
|
text-align: center;
|
|
721
747
|
cursor: pointer;
|
|
748
|
+
/* Note: opacity transition added later in the file for filter effects */
|
|
722
749
|
transition: background 180ms ease, border-color 180ms ease;
|
|
723
750
|
flex: 0 0 auto;
|
|
724
751
|
border-radius: 0.5rem;
|
|
@@ -772,6 +799,28 @@
|
|
|
772
799
|
font-variant-numeric: tabular-nums;
|
|
773
800
|
}
|
|
774
801
|
|
|
802
|
+
/* Fade axis labels when switching views - matched to sprite animation duration (600ms) */
|
|
803
|
+
.pivot-viewer .pv-axis-labels {
|
|
804
|
+
transition: opacity 600ms ease;
|
|
805
|
+
}
|
|
806
|
+
.pivot-viewer .pv-axis-labels.hidden {
|
|
807
|
+
opacity: 0;
|
|
808
|
+
pointer-events: none;
|
|
809
|
+
}
|
|
810
|
+
.pivot-viewer .pv-axis-labels.visible {
|
|
811
|
+
opacity: 1;
|
|
812
|
+
pointer-events: auto;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/* Fade individual axis labels when filtering groups */
|
|
816
|
+
.pv-axis-label {
|
|
817
|
+
transition: opacity 600ms ease, background 180ms ease, border-color 180ms ease;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
.pv-axis-label.filtered-out {
|
|
821
|
+
opacity: 0.3;
|
|
822
|
+
}
|
|
823
|
+
|
|
775
824
|
.pv-groups.pv-groups-collection {
|
|
776
825
|
display: flex;
|
|
777
826
|
flex-wrap: wrap;
|
|
@@ -784,7 +833,7 @@
|
|
|
784
833
|
|
|
785
834
|
/* Pause flex reflow during zoom animation for smoother effect */
|
|
786
835
|
.pv-groups.pv-zooming {
|
|
787
|
-
|
|
836
|
+
pointer-events: none;
|
|
788
837
|
}
|
|
789
838
|
|
|
790
839
|
/* CRITICAL: Freeze collection layout during zoom - prevent any reflow */
|
|
@@ -43,7 +43,7 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
|
|
|
43
43
|
const [scrollPosition, setScrollPosition] = React.useState({ x: 0, y: 0 });
|
|
44
44
|
const { filterState, rangeFilterState, expandedFilterKey, setExpandedFilterKey, handleToggleFilter, handleClearFilter, handleRangeChange, } = useFilterState.useFilterState(filters);
|
|
45
45
|
const { activeDimensionKey, setActiveDimensionKey, activeDimension, dimensionFilter, handleAxisLabelClick, } = useDimensionState.useDimensionState(dimensions, defaultDimensionKey);
|
|
46
|
-
const { zoomLevel, setZoomLevel, handleZoomIn, handleZoomOut, handleZoomSlider, } = useZoomState.useZoomState(1);
|
|
46
|
+
const { zoomLevel, setZoomLevel, handleZoomIn, handleZoomOut, handleZoomSlider, handleZoomReset, handleZoomChange, } = useZoomState.useZoomState(1);
|
|
47
47
|
const { isPanning, handlePanStart, handlePanMove, handlePanEnd, } = usePanning.usePanning(containerRef, undefined, setScrollPosition);
|
|
48
48
|
useWheelZoom.useWheelZoom(containerRef, zoomLevel, setZoomLevel);
|
|
49
49
|
const containerDimensions = useContainerDimensions.useContainerDimensions(containerRef, isLoading);
|
|
@@ -215,6 +215,9 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
|
|
|
215
215
|
]
|
|
216
216
|
.filter(Boolean)
|
|
217
217
|
.join(' ');
|
|
218
|
+
React.useEffect(() => {
|
|
219
|
+
setSelectedItem(null);
|
|
220
|
+
}, [viewMode]);
|
|
218
221
|
const cssVariables = React.useMemo(() => {
|
|
219
222
|
const vars = {};
|
|
220
223
|
if (!colors)
|
|
@@ -247,7 +250,7 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
|
|
|
247
250
|
vars['--focus-ring'] = colors.focusRing;
|
|
248
251
|
return vars;
|
|
249
252
|
}, [colors]);
|
|
250
|
-
return (jsxRuntime.jsxs("div", { className: viewerClassName, style: cssVariables, children: [jsxRuntime.jsx(FilterPanelContainer.FilterPanelContainer, { isOpen: filtersOpen && hasFilters, 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 }), jsxRuntime.jsxs("main", { className: "pv-main", children: [jsxRuntime.jsx(ToolbarContainer.ToolbarContainer, { hasFilters: hasFilters, filtersOpen: filtersOpen, filteredCount: visibleIds.length, viewMode: viewMode, zoomLevel: zoomLevel, activeDimensionKey: activeDimensionKey, dimensions: dimensions, activeFilterCount: activeFilterCount, onFiltersToggle: () => setFiltersOpen((prev) => !prev), onViewModeChange: setViewMode, onZoomIn: handleZoomIn, onZoomOut: handleZoomOut, onZoomSlider: handleZoomSlider, onDimensionChange: setActiveDimensionKey, filterButtonRef: filterButtonRef }), jsxRuntime.jsx(PivotViewerMain.PivotViewerMain, { data: data, ready: ready, isLoading: isLoading, visibleIds: visibleIds, grouping: grouping, layout: layout$1, cardWidth: cardWidth, cardHeight: cardHeight, zoomLevel: zoomLevel, scrollPosition: scrollPosition, containerDimensions: containerDimensions, selectedItem: selectedItem, hoveredGroupIndex: hoveredGroupIndex, isZooming: isZooming, viewMode: viewMode, cardRenderer: cardRenderer, 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 })] })] }));
|
|
253
|
+
return (jsxRuntime.jsxs("div", { className: viewerClassName, style: cssVariables, children: [jsxRuntime.jsx(FilterPanelContainer.FilterPanelContainer, { isOpen: filtersOpen && hasFilters, 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 }), jsxRuntime.jsxs("main", { className: "pv-main", children: [jsxRuntime.jsx(ToolbarContainer.ToolbarContainer, { hasFilters: hasFilters, filtersOpen: filtersOpen, filteredCount: visibleIds.length, viewMode: viewMode, zoomLevel: zoomLevel, activeDimensionKey: activeDimensionKey, dimensions: dimensions, activeFilterCount: activeFilterCount, onFiltersToggle: () => setFiltersOpen((prev) => !prev), onViewModeChange: setViewMode, onZoomIn: handleZoomIn, onZoomOut: handleZoomOut, onZoomSlider: handleZoomSlider, onZoomReset: handleZoomReset, onZoomChange: handleZoomChange, onDimensionChange: setActiveDimensionKey, filterButtonRef: filterButtonRef }), jsxRuntime.jsx(PivotViewerMain.PivotViewerMain, { data: data, ready: ready, isLoading: isLoading, visibleIds: visibleIds, grouping: grouping, layout: layout$1, cardWidth: cardWidth, cardHeight: cardHeight, zoomLevel: zoomLevel, scrollPosition: scrollPosition, containerDimensions: containerDimensions, selectedItem: selectedItem, hoveredGroupIndex: hoveredGroupIndex, isZooming: isZooming, viewMode: viewMode, cardRenderer: cardRenderer, 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 })] })] }));
|
|
251
254
|
}
|
|
252
255
|
|
|
253
256
|
exports.PivotViewer = PivotViewer;
|
|
@@ -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 { BASE_CARD_WIDTH, BASE_CARD_HEIGHT, CARDS_PER_COLUMN, GROUP_SPACING } from './constants';\nimport './PivotViewer.css';\nimport { PivotViewerMain } from './components/PivotViewerMain';\nimport { FilterPanelContainer } from './components/FilterPanelContainer';\nimport { ToolbarContainer } from './components/ToolbarContainer';\nimport { usePanning, useWheelZoom, useFilterOptions } from './hooks';\nimport { useContainerDimensions } from './hooks/useContainerDimensions';\nimport type { ViewMode } from './components/Toolbar';\nimport { useFieldExtractors } from './hooks/useFieldExtractors';\nimport { useCurrentFilters, useCurrentGroupBy } from './hooks/useCurrentFilters';\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\nexport function PivotViewer<TItem extends object>({\n data,\n dimensions,\n filters,\n defaultDimensionKey,\n cardRenderer,\n detailRenderer,\n getItemId,\n searchFields,\n className,\n emptyContent,\n isLoading = false,\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 [grouping, setGrouping] = useState<GroupingResult>({ groups: [] });\n const [hoveredGroupIndex, setHoveredGroupIndex] = useState<number | null>(null);\n const [preSelectionState, setPreSelectionState] = useState<{ zoom: number; scrollLeft: number; scrollTop: number } | 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 } = useZoomState(1);\n\n const {\n isPanning,\n handlePanStart,\n handlePanMove,\n handlePanEnd,\n } = usePanning(containerRef, undefined, setScrollPosition);\n\n useWheelZoom(containerRef, zoomLevel, setZoomLevel);\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 { ready, applyFilters: engineApplyFilters, computeGrouping, sortIds } = 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 search,\n searchFields,\n dimensionFilter,\n activeDimension,\n );\n\n const currentGroupBy = useCurrentGroupBy(activeDimensionKey, dimensions);\n\n // Apply filters\n useEffect(() => {\n if (!ready) return;\n\n engineApplyFilters(currentFilters).then((result) => {\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 (result.visibleIds.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 setVisibleIds(fallbackIds);\n return;\n }\n\n setVisibleIds(result.visibleIds);\n });\n }, [ready, currentFilters, engineApplyFilters, data.length]);\n\n // Compute grouping\n const lastGroupingRequest = useRef<{ viewMode: ViewMode; groupBy: unknown; visibleIds: Uint32Array } | null>(null);\n \n useEffect(() => {\n if (!ready || visibleIds.length === 0) {\n setGrouping({ groups: [] });\n lastGroupingRequest.current = null;\n return;\n }\n\n if (viewMode === 'collection') {\n // In collection mode, create a single group with all items\n // Sort items if activeDimensionKey is set\n if (activeDimensionKey) {\n sortIds(visibleIds, activeDimensionKey).then((sortedIds) => {\n setGrouping({\n groups: [{\n key: 'all',\n label: 'All Items',\n value: 'all',\n ids: sortedIds,\n count: sortedIds.length\n }]\n });\n });\n } else {\n setGrouping({\n groups: [{\n key: 'all',\n label: 'All Items',\n value: 'all',\n ids: visibleIds,\n count: visibleIds.length\n }]\n });\n }\n lastGroupingRequest.current = null;\n return;\n }\n\n // Check if this is the same request as last time to prevent duplicate computations\n const lastRequest = lastGroupingRequest.current;\n if (\n lastRequest &&\n lastRequest.viewMode === viewMode &&\n (lastRequest.groupBy as unknown as typeof currentGroupBy)?.field === currentGroupBy.field &&\n lastRequest.visibleIds === visibleIds\n ) {\n return;\n }\n\n lastGroupingRequest.current = { viewMode, groupBy: currentGroupBy, visibleIds };\n \n computeGrouping(visibleIds, currentGroupBy).then((result) => {\n setGrouping(result);\n });\n }, [ready, visibleIds, currentGroupBy, viewMode, computeGrouping, sortIds, activeDimensionKey]);\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 = 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 }, [grouping, viewMode, zoomLevel, containerDimensions.width, containerDimensions.height]);\n\n const resolveId = useCallback((item: TItem, index: number) => {\n if (getItemId) {\n const id = getItemId(item, index);\n return typeof id === 'number' ? id : index;\n }\n const id = (item as Record<string, unknown>)['id'];\n return typeof id === 'number' ? id : index;\n }, [getItemId]);\n\n // Track animation mode changes\n useAnimationModeTracking(filterState, rangeFilterState, search, activeDimensionKey, viewMode, setAnimationMode);\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 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 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 = Object.values(filterState).reduce((sum: number, vals) => sum + (vals as Set<string>).size, 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 // 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['--primary-color'] = colors.primaryColor;\n if (colors.primaryColorText) vars['--primary-color-text'] = colors.primaryColorText;\n if (colors.primary500) vars['--primary-500'] = colors.primary500;\n if (colors.surfaceGround) vars['--surface-ground'] = colors.surfaceGround;\n if (colors.surfaceCard) vars['--surface-card'] = colors.surfaceCard;\n if (colors.surfaceSection) vars['--surface-section'] = colors.surfaceSection;\n if (colors.surfaceOverlay) vars['--surface-overlay'] = colors.surfaceOverlay;\n if (colors.surfaceBorder) vars['--surface-border'] = colors.surfaceBorder;\n if (colors.textColor) vars['--text-color'] = colors.textColor;\n if (colors.textColorSecondary) vars['--text-color-secondary'] = colors.textColorSecondary;\n if (colors.highlightBg) vars['--highlight-bg'] = colors.highlightBg;\n if (colors.maskbg) vars['--maskbg'] = colors.maskbg;\n if (colors.focusRing) vars['--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 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 onFiltersToggle={() => setFiltersOpen((prev) => !prev)}\n onViewModeChange={setViewMode}\n onZoomIn={handleZoomIn}\n onZoomOut={handleZoomOut}\n onZoomSlider={handleZoomSlider}\n onDimensionChange={setActiveDimensionKey}\n filterButtonRef={filterButtonRef}\n />\n\n <PivotViewerMain\n data={data}\n ready={ready}\n isLoading={isLoading}\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 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":["useRef","useState","useFilterState","useDimensionState","useZoomState","usePanning","useWheelZoom","useContainerDimensions","useEffect","useFieldExtractors","usePivotEngine","useCurrentFilters","useCurrentGroupBy","layout","useMemo","BASE_CARD_WIDTH","BASE_CARD_HEIGHT","computeLayout","CARDS_PER_COLUMN","useCallback","useAnimationModeTracking","useScrollSync","useViewModeScrollHandling","useCardSelection","useDetailPanelClose","useFilterOptions","_jsxs","_jsx","FilterPanelContainer","ToolbarContainer","PivotViewerMain"],"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 { 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 { BASE_CARD_WIDTH, BASE_CARD_HEIGHT, CARDS_PER_COLUMN, GROUP_SPACING } from './constants';\nimport './PivotViewer.css';\nimport { PivotViewerMain } from './components/PivotViewerMain';\nimport { FilterPanelContainer } from './components/FilterPanelContainer';\nimport { ToolbarContainer } from './components/ToolbarContainer';\nimport { usePanning, useWheelZoom, useFilterOptions } from './hooks';\nimport { useContainerDimensions } from './hooks/useContainerDimensions';\nimport type { ViewMode } from './components/Toolbar';\nimport { useFieldExtractors } from './hooks/useFieldExtractors';\nimport { useCurrentFilters, useCurrentGroupBy } from './hooks/useCurrentFilters';\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\nexport function PivotViewer<TItem extends object>({\n data,\n dimensions,\n filters,\n defaultDimensionKey,\n cardRenderer,\n detailRenderer,\n getItemId,\n searchFields,\n className,\n emptyContent,\n isLoading = false,\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 [grouping, setGrouping] = useState<GroupingResult>({ groups: [] });\n const [hoveredGroupIndex, setHoveredGroupIndex] = useState<number | null>(null);\n const [preSelectionState, setPreSelectionState] = useState<{ zoom: number; scrollLeft: number; scrollTop: number } | 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 {\n isPanning,\n handlePanStart,\n handlePanMove,\n handlePanEnd,\n } = usePanning(containerRef, undefined, setScrollPosition);\n\n useWheelZoom(containerRef, zoomLevel, setZoomLevel);\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 { ready, applyFilters: engineApplyFilters, computeGrouping, sortIds } = 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 search,\n searchFields,\n dimensionFilter,\n activeDimension,\n );\n\n const currentGroupBy = useCurrentGroupBy(activeDimensionKey, dimensions);\n\n // Apply filters\n useEffect(() => {\n if (!ready) return;\n\n engineApplyFilters(currentFilters).then((result) => {\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 (result.visibleIds.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 setVisibleIds(fallbackIds);\n return;\n }\n\n setVisibleIds(result.visibleIds);\n });\n }, [ready, currentFilters, engineApplyFilters, data.length]);\n\n // Compute grouping\n const lastGroupingRequest = useRef<{ viewMode: ViewMode; groupBy: unknown; visibleIds: Uint32Array } | null>(null);\n \n useEffect(() => {\n if (!ready || visibleIds.length === 0) {\n setGrouping({ groups: [] });\n lastGroupingRequest.current = null;\n return;\n }\n\n if (viewMode === 'collection') {\n // In collection mode, create a single group with all items\n // Sort items if activeDimensionKey is set\n if (activeDimensionKey) {\n sortIds(visibleIds, activeDimensionKey).then((sortedIds) => {\n setGrouping({\n groups: [{\n key: 'all',\n label: 'All Items',\n value: 'all',\n ids: sortedIds,\n count: sortedIds.length\n }]\n });\n });\n } else {\n setGrouping({\n groups: [{\n key: 'all',\n label: 'All Items',\n value: 'all',\n ids: visibleIds,\n count: visibleIds.length\n }]\n });\n }\n lastGroupingRequest.current = null;\n return;\n }\n\n // Check if this is the same request as last time to prevent duplicate computations\n const lastRequest = lastGroupingRequest.current;\n if (\n lastRequest &&\n lastRequest.viewMode === viewMode &&\n (lastRequest.groupBy as unknown as typeof currentGroupBy)?.field === currentGroupBy.field &&\n lastRequest.visibleIds === visibleIds\n ) {\n return;\n }\n\n lastGroupingRequest.current = { viewMode, groupBy: currentGroupBy, visibleIds };\n \n computeGrouping(visibleIds, currentGroupBy).then((result) => {\n setGrouping(result);\n });\n }, [ready, visibleIds, currentGroupBy, viewMode, computeGrouping, sortIds, activeDimensionKey]);\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 = 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 }, [grouping, viewMode, zoomLevel, containerDimensions.width, containerDimensions.height]);\n\n const resolveId = useCallback((item: TItem, index: number) => {\n if (getItemId) {\n const id = getItemId(item, index);\n return typeof id === 'number' ? id : index;\n }\n const id = (item as Record<string, unknown>)['id'];\n return typeof id === 'number' ? id : index;\n }, [getItemId]);\n\n // Track animation mode changes\n useAnimationModeTracking(filterState, rangeFilterState, search, activeDimensionKey, viewMode, setAnimationMode);\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 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 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 = Object.values(filterState).reduce((sum: number, vals) => sum + (vals as Set<string>).size, 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['--primary-color'] = colors.primaryColor;\n if (colors.primaryColorText) vars['--primary-color-text'] = colors.primaryColorText;\n if (colors.primary500) vars['--primary-500'] = colors.primary500;\n if (colors.surfaceGround) vars['--surface-ground'] = colors.surfaceGround;\n if (colors.surfaceCard) vars['--surface-card'] = colors.surfaceCard;\n if (colors.surfaceSection) vars['--surface-section'] = colors.surfaceSection;\n if (colors.surfaceOverlay) vars['--surface-overlay'] = colors.surfaceOverlay;\n if (colors.surfaceBorder) vars['--surface-border'] = colors.surfaceBorder;\n if (colors.textColor) vars['--text-color'] = colors.textColor;\n if (colors.textColorSecondary) vars['--text-color-secondary'] = colors.textColorSecondary;\n if (colors.highlightBg) vars['--highlight-bg'] = colors.highlightBg;\n if (colors.maskbg) vars['--maskbg'] = colors.maskbg;\n if (colors.focusRing) vars['--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 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 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 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 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":["useRef","useState","useFilterState","useDimensionState","useZoomState","usePanning","useWheelZoom","useContainerDimensions","useEffect","useFieldExtractors","usePivotEngine","useCurrentFilters","useCurrentGroupBy","layout","useMemo","BASE_CARD_WIDTH","BASE_CARD_HEIGHT","computeLayout","CARDS_PER_COLUMN","useCallback","useAnimationModeTracking","useScrollSync","useViewModeScrollHandling","useCardSelection","useDetailPanelClose","useFilterOptions","_jsxs","_jsx","FilterPanelContainer","ToolbarContainer","PivotViewerMain"],"mappings":"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"}
|
|
@@ -3,12 +3,9 @@
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var constants = require('../constants.js');
|
|
5
5
|
|
|
6
|
-
function AxisLabels({ groups, bucketWidths, dimensionFilter, hoveredGroup, zoomLevel, onHover, onClick, containerRef, }) {
|
|
7
|
-
return (jsxRuntime.jsx("div", { className:
|
|
8
|
-
|
|
9
|
-
gap: `${constants.GROUP_SPACING * zoomLevel}px`,
|
|
10
|
-
paddingLeft: 0,
|
|
11
|
-
paddingRight: 0,
|
|
6
|
+
function AxisLabels({ groups, bucketWidths, dimensionFilter, hoveredGroup, zoomLevel, visible, onHover, onClick, containerRef, }) {
|
|
7
|
+
return (jsxRuntime.jsx("div", { className: `pv-axis-labels ${visible ? 'visible' : 'hidden'}`, ref: containerRef, style: {
|
|
8
|
+
paddingLeft: `${(constants.CANVAS_PADDING * zoomLevel) - (20 * zoomLevel)}px`,
|
|
12
9
|
overflowX: 'hidden',
|
|
13
10
|
whiteSpace: 'nowrap',
|
|
14
11
|
}, children: groups.map((group, index) => {
|
|
@@ -16,9 +13,9 @@ function AxisLabels({ groups, bucketWidths, dimensionFilter, hoveredGroup, zoomL
|
|
|
16
13
|
const baseBucketWidth = bucketWidths[index] || 0;
|
|
17
14
|
const bucketWidth = baseBucketWidth * zoomLevel;
|
|
18
15
|
const width = bucketWidth;
|
|
19
|
-
|
|
16
|
+
const isFilteredOut = dimensionFilter !== null && !isSelected;
|
|
17
|
+
return (jsxRuntime.jsxs("button", { type: "button", className: `pv-axis-label ${hoveredGroup === group.key ? 'highlighted' : ''} ${isSelected ? 'selected' : ''} ${isFilteredOut ? 'filtered-out' : ''}`, style: {
|
|
20
18
|
width,
|
|
21
|
-
pointerEvents: 'auto'
|
|
22
19
|
}, onMouseEnter: () => onHover(group.key), onMouseLeave: () => onHover(null), onClick: () => onClick(group.key), children: [jsxRuntime.jsx("span", { className: "pv-axis-label-text", children: group.label }), jsxRuntime.jsx("span", { className: "pv-axis-label-count", children: group.count ?? group.items.length })] }, group.key));
|
|
23
20
|
}) }));
|
|
24
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AxisLabels.js","sources":["../../../../PivotViewer/components/AxisLabels.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 type { PivotGroup } from '../types';\nimport {
|
|
1
|
+
{"version":3,"file":"AxisLabels.js","sources":["../../../../PivotViewer/components/AxisLabels.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 type { PivotGroup } from '../types';\nimport { CANVAS_PADDING } from '../constants';\n\nexport interface AxisLabelsProps<TItem extends object> {\n groups: PivotGroup<TItem>[];\n bucketWidths: number[];\n dimensionFilter: string | null;\n hoveredGroup: string | null;\n zoomLevel: number;\n visible: boolean;\n onHover: (key: string | null) => void;\n onClick: (key: string) => void;\n containerRef: React.RefObject<HTMLDivElement | null>;\n}\n\nexport function AxisLabels<TItem extends object>({\n groups,\n bucketWidths,\n dimensionFilter,\n hoveredGroup,\n zoomLevel,\n visible,\n onHover,\n onClick,\n containerRef,\n}: AxisLabelsProps<TItem>) {\n return (\n <div\n className={`pv-axis-labels ${visible ? 'visible' : 'hidden'}`}\n ref={containerRef}\n style={{\n // Align labels start with grouped buckets using canvas padding scaled by zoom\n paddingLeft: `${(CANVAS_PADDING * zoomLevel)-(20*zoomLevel)}px`,\n overflowX: 'hidden',\n whiteSpace: 'nowrap',\n }}\n >\n {groups.map((group, index) => {\n const isSelected = dimensionFilter === group.key;\n const baseBucketWidth = bucketWidths[index] || 0;\n // Apply zoom to bucket width\n const bucketWidth = baseBucketWidth * zoomLevel;\n // Width is just the bucket width - spacing is handled by CSS gap\n const width = bucketWidth;\n\n // When a dimension filter is active, mark non-selected groups as filtered-out\n const isFilteredOut = dimensionFilter !== null && !isSelected;\n\n return (\n <button\n key={group.key}\n type=\"button\"\n className={`pv-axis-label ${hoveredGroup === group.key ? 'highlighted' : ''} ${isSelected ? 'selected' : ''} ${isFilteredOut ? 'filtered-out' : ''}`}\n style={{\n width,\n }}\n onMouseEnter={() => onHover(group.key)}\n onMouseLeave={() => onHover(null)}\n onClick={() => onClick(group.key)}\n >\n <span className=\"pv-axis-label-text\">{group.label}</span>\n <span className=\"pv-axis-label-count\">{group.count ?? group.items.length}</span>\n </button>\n );\n })}\n </div>\n );\n}\n"],"names":["_jsx","CANVAS_PADDING","_jsxs"],"mappings":";;;;;AAkBM,SAAU,UAAU,CAAuB,EAC/C,MAAM,EACN,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,SAAS,EACT,OAAO,EACP,OAAO,EACP,OAAO,EACP,YAAY,GACW,EAAA;IACvB,QACEA,wBACE,SAAS,EAAE,kBAAkB,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAA,CAAE,EAC7D,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE;AAEL,YAAA,WAAW,EAAE,CAAA,EAAG,CAACC,wBAAc,GAAG,SAAS,KAAG,EAAE,GAAC,SAAS,CAAC,CAAA,EAAA,CAAI;AAC/D,YAAA,SAAS,EAAE,QAAQ;AACnB,YAAA,UAAU,EAAE,QAAQ;SACrB,EAAA,QAAA,EAEA,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAI;AAC3B,YAAA,MAAM,UAAU,GAAG,eAAe,KAAK,KAAK,CAAC,GAAG;YAChD,MAAM,eAAe,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC;AAEhD,YAAA,MAAM,WAAW,GAAG,eAAe,GAAG,SAAS;YAE/C,MAAM,KAAK,GAAG,WAAW;YAGzB,MAAM,aAAa,GAAG,eAAe,KAAK,IAAI,IAAI,CAAC,UAAU;YAE7D,QACEC,4BAEE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,CAAA,cAAA,EAAiB,YAAY,KAAK,KAAK,CAAC,GAAG,GAAG,aAAa,GAAG,EAAE,IAAI,UAAU,GAAG,UAAU,GAAG,EAAE,CAAA,CAAA,EAAI,aAAa,GAAG,cAAc,GAAG,EAAE,CAAA,CAAE,EACpJ,KAAK,EAAE;oBACL,KAAK;AACN,iBAAA,EACD,YAAY,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EACtC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACjC,OAAO,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAA,QAAA,EAAA,CAEjCF,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,oBAAoB,EAAA,QAAA,EAAE,KAAK,CAAC,KAAK,EAAA,CAAQ,EACzDA,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,qBAAqB,EAAA,QAAA,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAA,CAAQ,CAAA,EAAA,EAX3E,KAAK,CAAC,GAAG,CAYP;QAEb,CAAC,CAAC,EAAA,CACE;AAEV;;;;"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var framerMotion = require('framer-motion');
|
|
5
5
|
|
|
6
|
-
function DetailPanel({ selectedItem, onClose, }) {
|
|
6
|
+
function DetailPanel({ selectedItem, onClose, contentRenderer, }) {
|
|
7
7
|
const selectedRecord = selectedItem;
|
|
8
8
|
const selectedContent = selectedRecord
|
|
9
9
|
? (selectedRecord['content'] ?? {})
|
|
@@ -28,7 +28,14 @@ function DetailPanel({ selectedItem, onClose, }) {
|
|
|
28
28
|
const causation = Array.isArray(selectedRecord?.['causation'])
|
|
29
29
|
? selectedRecord?.['causation']
|
|
30
30
|
: [];
|
|
31
|
-
|
|
31
|
+
const defaultContent = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [metadataEntries.length > 0 && (jsxRuntime.jsxs("section", { className: "pv-detail-meta", children: [jsxRuntime.jsx("h3", { children: "Metadata" }), jsxRuntime.jsx("dl", { children: metadataEntries.map(([key, value]) => (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("dt", { children: key }), jsxRuntime.jsx("dd", { children: String(value) })] }, key))) })] })), causation.length > 0 && (jsxRuntime.jsxs("section", { className: "pv-detail-causation", children: [jsxRuntime.jsx("h3", { children: "Causation" }), jsxRuntime.jsx("div", { className: "pv-pill-row", children: causation.map((value, index) => (jsxRuntime.jsx("span", { className: "pv-pill", children: String(value) }, `${value}-${index}`))) })] })), jsxRuntime.jsxs("section", { className: "pv-detail-content", children: [jsxRuntime.jsx("h3", { children: "Content" }), jsxRuntime.jsx("dl", { children: Object.entries(selectedContent).map(([key, value]) => (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("dt", { children: key }), jsxRuntime.jsx("dd", { children: typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value) })] }, key))) })] })] }));
|
|
32
|
+
const customContent = contentRenderer && selectedRecord ? contentRenderer(selectedRecord, onClose) : null;
|
|
33
|
+
return (jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: selectedRecord && (jsxRuntime.jsxs(framerMotion.motion.aside, { className: "pv-detail-panel", initial: { x: '100%' }, animate: { x: 0 }, exit: { x: '100%' }, transition: {
|
|
34
|
+
type: 'spring',
|
|
35
|
+
stiffness: 120,
|
|
36
|
+
damping: 20,
|
|
37
|
+
mass: 1,
|
|
38
|
+
}, children: [jsxRuntime.jsxs("header", { children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("h2", { children: String(selectedRecord['name'] ?? selectedRecord['type'] ?? 'Event') }), selectedRecord['type'] ? jsxRuntime.jsx("p", { children: String(selectedRecord['type']) }) : null] }), jsxRuntime.jsx("button", { type: "button", onClick: onClose, title: "Close", children: "\u00D7" })] }), jsxRuntime.jsx("div", { className: "pv-detail-panel-content", children: customContent ?? defaultContent })] })) }));
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
exports.DetailPanel = DetailPanel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetailPanel.js","sources":["../../../../PivotViewer/components/DetailPanel.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 { AnimatePresence, motion } from 'framer-motion';\n\ntype WithRecord<TItem> = TItem extends Record<string, unknown> ? TItem : never;\n\nexport interface DetailPanelProps<TItem extends object> {\n selectedItem: TItem | null;\n onClose: () => void;\n}\n\nexport function DetailPanel<TItem extends object>({\n selectedItem,\n onClose,\n}: DetailPanelProps<TItem>) {\n const selectedRecord = selectedItem as WithRecord<TItem> | null;\n\n const selectedContent = selectedRecord\n ? ((selectedRecord['content'] as Record<string, unknown> | undefined) ?? {})\n : {};\n\n const metadataEntries = selectedRecord\n ? (\n [\n ['Type', selectedRecord['type']],\n [\n 'Occurred',\n selectedRecord['occurred'] instanceof Date\n ? (selectedRecord['occurred'] as Date).toLocaleString()\n : selectedRecord['occurred']\n ? new Date(String(selectedRecord['occurred'])).toLocaleString()\n : undefined,\n ],\n ['Service', selectedRecord['service']],\n ['Environment', selectedRecord['environment']],\n ['Tenant', selectedRecord['tenant']],\n ['Correlation Id', selectedRecord['correlationId']],\n ] as Array<[string, unknown]>\n ).filter(([, value]) => value !== undefined && value !== null)\n : [];\n\n const causation = Array.isArray(selectedRecord?.['causation'])\n ? (selectedRecord?.['causation'] as unknown[])\n : [];\n\n
|
|
1
|
+
{"version":3,"file":"DetailPanel.js","sources":["../../../../PivotViewer/components/DetailPanel.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 { AnimatePresence, motion } from 'framer-motion';\nimport type { ReactNode } from 'react';\n\ntype WithRecord<TItem> = TItem extends Record<string, unknown> ? TItem : never;\n\nexport interface DetailPanelProps<TItem extends object> {\n selectedItem: TItem | null;\n onClose: () => void;\n /** Custom renderer for the detail content area. The drawer shell (header, close button, layout) remains owned by the component. */\n contentRenderer?: (item: TItem, onClose: () => void) => ReactNode;\n}\n\nexport function DetailPanel<TItem extends object>({\n selectedItem,\n onClose,\n contentRenderer,\n}: DetailPanelProps<TItem>) {\n const selectedRecord = selectedItem as WithRecord<TItem> | null;\n\n const selectedContent = selectedRecord\n ? ((selectedRecord['content'] as Record<string, unknown> | undefined) ?? {})\n : {};\n\n const metadataEntries = selectedRecord\n ? (\n [\n ['Type', selectedRecord['type']],\n [\n 'Occurred',\n selectedRecord['occurred'] instanceof Date\n ? (selectedRecord['occurred'] as Date).toLocaleString()\n : selectedRecord['occurred']\n ? new Date(String(selectedRecord['occurred'])).toLocaleString()\n : undefined,\n ],\n ['Service', selectedRecord['service']],\n ['Environment', selectedRecord['environment']],\n ['Tenant', selectedRecord['tenant']],\n ['Correlation Id', selectedRecord['correlationId']],\n ] as Array<[string, unknown]>\n ).filter(([, value]) => value !== undefined && value !== null)\n : [];\n\n const causation = Array.isArray(selectedRecord?.['causation'])\n ? (selectedRecord?.['causation'] as unknown[])\n : [];\n\n const defaultContent = (\n <>\n {metadataEntries.length > 0 && (\n <section className=\"pv-detail-meta\">\n <h3>Metadata</h3>\n <dl>\n {metadataEntries.map(([key, value]) => (\n <div key={key}>\n <dt>{key}</dt>\n <dd>{String(value)}</dd>\n </div>\n ))}\n </dl>\n </section>\n )}\n {causation.length > 0 && (\n <section className=\"pv-detail-causation\">\n <h3>Causation</h3>\n <div className=\"pv-pill-row\">\n {causation.map((value, index) => (\n <span key={`${value}-${index}`} className=\"pv-pill\">\n {String(value)}\n </span>\n ))}\n </div>\n </section>\n )}\n <section className=\"pv-detail-content\">\n <h3>Content</h3>\n <dl>\n {Object.entries(selectedContent).map(([key, value]) => (\n <div key={key}>\n <dt>{key}</dt>\n <dd>{typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value)}</dd>\n </div>\n ))}\n </dl>\n </section>\n </>\n );\n\n const customContent = contentRenderer && selectedRecord ? contentRenderer(selectedRecord, onClose) : null;\n\n return (\n <AnimatePresence mode=\"wait\">\n {selectedRecord && (\n <motion.aside\n className=\"pv-detail-panel\"\n initial={{ x: '100%' }}\n animate={{ x: 0 }}\n exit={{ x: '100%' }}\n transition={{\n type: 'spring',\n stiffness: 120,\n damping: 20,\n mass: 1,\n }}\n >\n <header>\n <div>\n <h2>{String(selectedRecord['name'] ?? selectedRecord['type'] ?? 'Event')}</h2>\n {selectedRecord['type'] ? <p>{String(selectedRecord['type'])}</p> : null}\n </div>\n <button type=\"button\" onClick={onClose} title=\"Close\">\n ×\n </button>\n </header>\n <div className=\"pv-detail-panel-content\">\n {customContent ?? defaultContent}\n </div>\n </motion.aside>\n )}\n </AnimatePresence>\n );\n}\n"],"names":["_jsxs","_jsx","AnimatePresence","motion"],"mappings":"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"}
|
|
@@ -30,6 +30,7 @@ var PIXI__namespace = /*#__PURE__*/_interopNamespaceDefault(PIXI);
|
|
|
30
30
|
|
|
31
31
|
function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeight, zoomLevel, panX, panY, viewportWidth, viewportHeight, selectedId, hoveredGroupIndex, isZooming: _isZooming = false, resolveId: _resolveId, onCardClick, onPanStart, onPanMove, onPanEnd, viewMode, cardRenderer, containerRef, }) {
|
|
32
32
|
const parentContainerRef = containerRef;
|
|
33
|
+
const resolveId = _resolveId;
|
|
33
34
|
const canvasRef = React.useRef(null);
|
|
34
35
|
const spacerRef = React.useRef(null);
|
|
35
36
|
const appRef = React.useRef(null);
|
|
@@ -195,7 +196,7 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
195
196
|
catch (e) {
|
|
196
197
|
}
|
|
197
198
|
};
|
|
198
|
-
}, [
|
|
199
|
+
}, []);
|
|
199
200
|
React.useEffect(() => {
|
|
200
201
|
if (!parentContainerRef || !parentContainerRef.current || !appRef.current || !pixiReady)
|
|
201
202
|
return;
|
|
@@ -233,6 +234,29 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
233
234
|
needsRenderRef.current = true;
|
|
234
235
|
appRef.current?.renderer?.render(appRef.current.stage);
|
|
235
236
|
}, [grouping, layout, zoomLevel, viewMode, pixiReady]);
|
|
237
|
+
React.useEffect(() => {
|
|
238
|
+
const gc = groupsContainerRef.current;
|
|
239
|
+
const app = appRef.current;
|
|
240
|
+
if (!gc || !app)
|
|
241
|
+
return;
|
|
242
|
+
const target = viewMode === 'grouped' ? 1 : 0;
|
|
243
|
+
const start = typeof gc.alpha === 'number' ? gc.alpha : 1;
|
|
244
|
+
const duration = 200;
|
|
245
|
+
if (Math.abs(start - target) < 0.01) {
|
|
246
|
+
gc.alpha = target;
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const t0 = performance.now();
|
|
250
|
+
const step = () => {
|
|
251
|
+
const u = Math.min(1, (performance.now() - t0) / duration);
|
|
252
|
+
const eased = u * (2 - u);
|
|
253
|
+
gc.alpha = start + (target - start) * eased;
|
|
254
|
+
app.renderer?.render(app.stage);
|
|
255
|
+
if (u < 1)
|
|
256
|
+
requestAnimationFrame(step);
|
|
257
|
+
};
|
|
258
|
+
requestAnimationFrame(step);
|
|
259
|
+
}, [viewMode]);
|
|
236
260
|
React.useEffect(() => {
|
|
237
261
|
if (!rootRef.current || !parentContainerRef.current || !pixiReady) {
|
|
238
262
|
return;
|
|
@@ -279,8 +303,8 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
279
303
|
viewportWidth,
|
|
280
304
|
viewportHeight,
|
|
281
305
|
viewMode,
|
|
282
|
-
createCardSprite: (id, x, y) => sprites.createCardSprite(id, x, y, items, (item, e, id) => (onCardClickRef.current)(item, e, id), (e) => (onPanStart)(e), cardWidth, cardHeight, cardColorsRef.current),
|
|
283
|
-
updateCardContent: (sprite, item) => sprites.updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current),
|
|
306
|
+
createCardSprite: (id, x, y) => sprites.createCardSprite(id, x, y, items, (item, e, id) => (onCardClickRef.current)(item, e, id), (e) => (onPanStart)(e), cardWidth, cardHeight, cardColorsRef.current, cardRenderer, resolveId),
|
|
307
|
+
updateCardContent: (sprite, item) => sprites.updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current, cardRenderer),
|
|
284
308
|
isViewTransition: isViewTransitionRef.current,
|
|
285
309
|
prevLayout: prevLayoutRef.current,
|
|
286
310
|
prevScrollTop: prevScrollTopRef.current,
|
|
@@ -349,8 +373,8 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
349
373
|
zoomLevel,
|
|
350
374
|
viewportWidth,
|
|
351
375
|
viewportHeight,
|
|
352
|
-
createCardSprite: (id, x, y) => sprites.createCardSprite(id, x, y, items, (item, e, id) => (onCardClickRef.current)(item, e, id), (e) => (onPanStartRef.current)(e), cardWidth, cardHeight, cardColorsRef.current),
|
|
353
|
-
updateCardContent: (sprite, item) => sprites.updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current),
|
|
376
|
+
createCardSprite: (id, x, y) => sprites.createCardSprite(id, x, y, items, (item, e, id) => (onCardClickRef.current)(item, e, id), (e) => (onPanStartRef.current)(e), cardWidth, cardHeight, cardColorsRef.current, cardRenderer, resolveId),
|
|
377
|
+
updateCardContent: (sprite, item) => sprites.updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current, cardRenderer),
|
|
354
378
|
isViewTransition: isViewTransitionRef.current,
|
|
355
379
|
viewMode,
|
|
356
380
|
prevScrollTop: prevScrollTopRef.current,
|
|
@@ -379,7 +403,7 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
379
403
|
};
|
|
380
404
|
}, [pixiReady, layout, visibleIds, items, cardWidth, cardHeight, zoomLevel, viewportWidth, viewportHeight, panX, panY, grouping, viewMode, selectedId, onCardClick, onPanStart]);
|
|
381
405
|
function updateCardContent(sprite, item) {
|
|
382
|
-
return sprites.updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current);
|
|
406
|
+
return sprites.updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current, cardRenderer);
|
|
383
407
|
}
|
|
384
408
|
function updateSelection() {
|
|
385
409
|
const sprites = spritesRef.current;
|