@cratis/components 0.1.16 → 0.1.17
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 +16 -16
- package/dist/cjs/PivotViewer/PivotViewer.js +10 -3
- package/dist/cjs/PivotViewer/PivotViewer.js.map +1 -1
- package/dist/cjs/PivotViewer/components/PivotCanvas.js +32 -49
- package/dist/cjs/PivotViewer/components/PivotCanvas.js.map +1 -1
- package/dist/cjs/PivotViewer/components/Toolbar.js +1 -1
- package/dist/cjs/PivotViewer/components/Toolbar.js.map +1 -1
- package/dist/cjs/PivotViewer/components/pivot/animation.js +4 -3
- package/dist/cjs/PivotViewer/components/pivot/animation.js.map +1 -1
- package/dist/cjs/PivotViewer/components/pivot/groups.js +151 -0
- package/dist/cjs/PivotViewer/components/pivot/groups.js.map +1 -0
- package/dist/cjs/PivotViewer/components/pivot/sprites.js +1 -15
- package/dist/cjs/PivotViewer/components/pivot/sprites.js.map +1 -1
- package/dist/cjs/PivotViewer/components/pivot/visibility.js +50 -7
- package/dist/cjs/PivotViewer/components/pivot/visibility.js.map +1 -1
- package/dist/cjs/PivotViewer/engine/layout.js +11 -7
- package/dist/cjs/PivotViewer/engine/layout.js.map +1 -1
- package/dist/cjs/PivotViewer/hooks/useCurrentFilters.js.map +1 -1
- package/dist/cjs/PivotViewer/hooks/usePanning.js +8 -4
- package/dist/cjs/PivotViewer/hooks/usePanning.js.map +1 -1
- package/dist/cjs/PivotViewer/hooks/useViewModeScrollHandling.js +4 -3
- package/dist/cjs/PivotViewer/hooks/useViewModeScrollHandling.js.map +1 -1
- package/dist/cjs/PivotViewer/utils/animations.js +11 -3
- package/dist/cjs/PivotViewer/utils/animations.js.map +1 -1
- package/dist/cjs/PivotViewer/utils/cardPosition.js +0 -3
- package/dist/cjs/PivotViewer/utils/cardPosition.js.map +1 -1
- package/dist/cjs/PivotViewer/utils/constants.js +2 -2
- package/dist/cjs/PivotViewer/utils/constants.js.map +1 -1
- package/dist/esm/PivotViewer/PivotViewer.css +16 -16
- package/dist/esm/PivotViewer/PivotViewer.d.ts.map +1 -1
- package/dist/esm/PivotViewer/PivotViewer.js +11 -4
- package/dist/esm/PivotViewer/PivotViewer.js.map +1 -1
- package/dist/esm/PivotViewer/components/PivotCanvas.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/PivotCanvas.js +33 -50
- package/dist/esm/PivotViewer/components/PivotCanvas.js.map +1 -1
- package/dist/esm/PivotViewer/components/Toolbar.js +1 -1
- package/dist/esm/PivotViewer/components/Toolbar.js.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/animation.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/animation.js +4 -3
- package/dist/esm/PivotViewer/components/pivot/animation.js.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/groups.d.ts +6 -0
- package/dist/esm/PivotViewer/components/pivot/groups.d.ts.map +1 -0
- package/dist/esm/PivotViewer/components/pivot/groups.js +129 -0
- package/dist/esm/PivotViewer/components/pivot/groups.js.map +1 -0
- package/dist/esm/PivotViewer/components/pivot/sprites.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/sprites.js +2 -15
- package/dist/esm/PivotViewer/components/pivot/sprites.js.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/visibility.d.ts +4 -0
- package/dist/esm/PivotViewer/components/pivot/visibility.d.ts.map +1 -1
- package/dist/esm/PivotViewer/components/pivot/visibility.js +50 -7
- package/dist/esm/PivotViewer/components/pivot/visibility.js.map +1 -1
- package/dist/esm/PivotViewer/engine/layout.js +11 -7
- package/dist/esm/PivotViewer/engine/layout.js.map +1 -1
- package/dist/esm/PivotViewer/engine/types.d.ts +1 -0
- package/dist/esm/PivotViewer/engine/types.d.ts.map +1 -1
- package/dist/esm/PivotViewer/hooks/useCurrentFilters.js.map +1 -1
- package/dist/esm/PivotViewer/hooks/useFilteredData.d.ts +1 -1
- package/dist/esm/PivotViewer/hooks/useFilteredData.js +4 -4
- package/dist/esm/PivotViewer/hooks/useFilteredData.js.map +1 -1
- package/dist/esm/PivotViewer/hooks/usePanning.d.ts.map +1 -1
- package/dist/esm/PivotViewer/hooks/usePanning.js +8 -4
- package/dist/esm/PivotViewer/hooks/usePanning.js.map +1 -1
- package/dist/esm/PivotViewer/hooks/useViewModeScrollHandling.d.ts.map +1 -1
- package/dist/esm/PivotViewer/hooks/useViewModeScrollHandling.js +4 -3
- package/dist/esm/PivotViewer/hooks/useViewModeScrollHandling.js.map +1 -1
- package/dist/esm/PivotViewer/utils/animations.d.ts.map +1 -1
- package/dist/esm/PivotViewer/utils/animations.js +11 -3
- package/dist/esm/PivotViewer/utils/animations.js.map +1 -1
- package/dist/esm/PivotViewer/utils/cardPosition.js +1 -4
- package/dist/esm/PivotViewer/utils/cardPosition.js.map +1 -1
- package/dist/esm/PivotViewer/utils/constants.d.ts +4 -4
- package/dist/esm/PivotViewer/utils/constants.d.ts.map +1 -1
- package/dist/esm/PivotViewer/utils/constants.js +2 -2
- package/dist/esm/PivotViewer/utils/constants.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/dist/cjs/PivotViewer/components/pivot/buckets.js +0 -124
- package/dist/cjs/PivotViewer/components/pivot/buckets.js.map +0 -1
- package/dist/esm/PivotViewer/components/pivot/buckets.d.ts +0 -6
- package/dist/esm/PivotViewer/components/pivot/buckets.d.ts.map +0 -1
- package/dist/esm/PivotViewer/components/pivot/buckets.js +0 -102
- package/dist/esm/PivotViewer/components/pivot/buckets.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useRef, useState, useMemo, useEffect } from 'react';
|
|
2
2
|
import * as PIXI from 'pixi.js';
|
|
3
3
|
import { createCssColorResolver, resolveCardColors } from './pivot/colorResolver.js';
|
|
4
|
-
import {
|
|
4
|
+
import { updateCardContent, createCardSprite } from './pivot/sprites.js';
|
|
5
5
|
import { syncSpritesToViewport } from './pivot/visibility.js';
|
|
6
|
-
import {
|
|
6
|
+
import { updateGroupBackgrounds, updateHighlight } from './pivot/groups.js';
|
|
7
7
|
import { startAnimationLoop } from './pivot/animation.js';
|
|
8
8
|
import { DEFAULT_COLORS } from './pivot/constants.js';
|
|
9
9
|
|
|
@@ -13,7 +13,7 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
13
13
|
const spacerRef = useRef(null);
|
|
14
14
|
const appRef = useRef(null);
|
|
15
15
|
const rootRef = useRef(null);
|
|
16
|
-
const
|
|
16
|
+
const groupsContainerRef = useRef(null);
|
|
17
17
|
const spritesRef = useRef(new Map());
|
|
18
18
|
const animationFrameRef = useRef(0);
|
|
19
19
|
const mountedRef = useRef(true);
|
|
@@ -26,6 +26,8 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
26
26
|
const previousViewModeRef = useRef(viewMode);
|
|
27
27
|
const prevLayoutRef = useRef(null);
|
|
28
28
|
const prevGroupingRef = useRef(null);
|
|
29
|
+
const prevScrollTopRef = useRef(0);
|
|
30
|
+
const prevScrollLeftRef = useRef(0);
|
|
29
31
|
const cardColorsRef = useRef(DEFAULT_COLORS);
|
|
30
32
|
const cssColorResolver = useMemo(() => createCssColorResolver(), []);
|
|
31
33
|
const onPanStartRef = useRef(onPanStart);
|
|
@@ -77,9 +79,9 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
77
79
|
return;
|
|
78
80
|
}
|
|
79
81
|
appRef.current = app;
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
app.stage.addChild(
|
|
82
|
+
const groupsContainer = new PIXI.Container();
|
|
83
|
+
groupsContainerRef.current = groupsContainer;
|
|
84
|
+
app.stage.addChild(groupsContainer);
|
|
83
85
|
const root = new PIXI.Container();
|
|
84
86
|
rootRef.current = root;
|
|
85
87
|
app.stage.addChild(root);
|
|
@@ -100,6 +102,9 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
100
102
|
overlayParent.appendChild(c);
|
|
101
103
|
canvasRef.current = c;
|
|
102
104
|
}
|
|
105
|
+
else {
|
|
106
|
+
console.error('PivotCanvas: Could not find canvas element from Pixi application');
|
|
107
|
+
}
|
|
103
108
|
if (canvasRef.current && parentContainerRef.current) {
|
|
104
109
|
const parentBounds = parentContainerRef.current.getBoundingClientRect();
|
|
105
110
|
void parentBounds;
|
|
@@ -153,7 +158,7 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
153
158
|
appRef.current = null;
|
|
154
159
|
rootRef.current = null;
|
|
155
160
|
}
|
|
156
|
-
|
|
161
|
+
spritesRef.current.clear();
|
|
157
162
|
try {
|
|
158
163
|
const parentEl = parentContainerRef.current;
|
|
159
164
|
if (parentEl) {
|
|
@@ -201,9 +206,9 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
201
206
|
};
|
|
202
207
|
}, [pixiReady, viewportWidth, viewportHeight]);
|
|
203
208
|
useEffect(() => {
|
|
204
|
-
if (!
|
|
209
|
+
if (!groupsContainerRef.current || !parentContainerRef.current || !pixiReady)
|
|
205
210
|
return;
|
|
206
|
-
|
|
211
|
+
updateGroupBackgrounds(groupsContainerRef.current, parentContainerRef.current, grouping, layout, zoomLevel, cardColorsRef.current, viewMode);
|
|
207
212
|
needsRenderRef.current = true;
|
|
208
213
|
appRef.current?.renderer?.render(appRef.current.stage);
|
|
209
214
|
}, [grouping, layout, zoomLevel, viewMode, pixiReady]);
|
|
@@ -213,21 +218,12 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
213
218
|
}
|
|
214
219
|
const viewModeChanged = previousViewModeRef.current !== viewMode;
|
|
215
220
|
const groupingChanged = prevGroupingRef.current !== grouping;
|
|
216
|
-
|
|
221
|
+
const layoutChanged = prevLayoutRef.current !== layout;
|
|
222
|
+
if (viewModeChanged || groupingChanged || layoutChanged) {
|
|
217
223
|
isViewTransitionRef.current = true;
|
|
218
224
|
lastViewChangeTimeRef.current = Date.now();
|
|
219
225
|
previousViewModeRef.current = viewMode;
|
|
220
226
|
prevGroupingRef.current = grouping;
|
|
221
|
-
for (const sprite of spritesRef.current.values()) {
|
|
222
|
-
try {
|
|
223
|
-
if (sprite.container) {
|
|
224
|
-
sprite.container.visible = false;
|
|
225
|
-
}
|
|
226
|
-
sprite.__lastHiddenAt = Date.now();
|
|
227
|
-
}
|
|
228
|
-
catch (e) {
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
227
|
}
|
|
232
228
|
if (spacerRef.current) {
|
|
233
229
|
const spacer = spacerRef.current;
|
|
@@ -242,8 +238,11 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
242
238
|
const panDeltaX = panX - prevPanRef.current.x;
|
|
243
239
|
const panDeltaY = panY - prevPanRef.current.y;
|
|
244
240
|
prevPanRef.current = { x: panX, y: panY };
|
|
241
|
+
const currentScrollTop = parentContainerRef.current?.scrollTop || 0;
|
|
242
|
+
const currentScrollLeft = parentContainerRef.current?.scrollLeft || 0;
|
|
245
243
|
syncSpritesToViewport({
|
|
246
244
|
root: rootRef.current,
|
|
245
|
+
groupsContainer: groupsContainerRef.current,
|
|
247
246
|
container: parentContainerRef.current,
|
|
248
247
|
sprites: spritesRef.current,
|
|
249
248
|
layout,
|
|
@@ -258,11 +257,16 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
258
257
|
zoomLevel,
|
|
259
258
|
viewportWidth,
|
|
260
259
|
viewportHeight,
|
|
260
|
+
viewMode,
|
|
261
261
|
createCardSprite: (id, x, y) => createCardSprite(id, x, y, items, (item, e, id) => (onCardClickRef.current)(item, e, id), (e) => (onPanStart)(e), cardWidth, cardHeight, cardColorsRef.current),
|
|
262
262
|
updateCardContent: (sprite, item) => updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current),
|
|
263
|
-
isViewTransition: isViewTransitionRef.current
|
|
263
|
+
isViewTransition: isViewTransitionRef.current,
|
|
264
264
|
prevLayout: prevLayoutRef.current,
|
|
265
|
+
prevScrollTop: prevScrollTopRef.current,
|
|
266
|
+
prevScrollLeft: prevScrollLeftRef.current,
|
|
265
267
|
});
|
|
268
|
+
prevScrollTopRef.current = currentScrollTop;
|
|
269
|
+
prevScrollLeftRef.current = currentScrollLeft;
|
|
266
270
|
needsRenderRef.current = true;
|
|
267
271
|
if (appRef.current?.renderer && rootRef.current) {
|
|
268
272
|
appRef.current.renderer.render(appRef.current.stage);
|
|
@@ -281,21 +285,6 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
281
285
|
useEffect(() => {
|
|
282
286
|
prevLayoutRef.current = layout;
|
|
283
287
|
}, [layout]);
|
|
284
|
-
useEffect(() => {
|
|
285
|
-
if (!rootRef.current || !bucketsContainerRef.current)
|
|
286
|
-
return;
|
|
287
|
-
const effectivePanX = parentContainerRef.current ? parentContainerRef.current.scrollLeft : panX;
|
|
288
|
-
const effectivePanY = parentContainerRef.current ? parentContainerRef.current.scrollTop : panY;
|
|
289
|
-
if (rootRef.current.scale && bucketsContainerRef.current.scale) {
|
|
290
|
-
rootRef.current.scale.set(zoomLevel);
|
|
291
|
-
bucketsContainerRef.current.scale.set(zoomLevel);
|
|
292
|
-
}
|
|
293
|
-
if (rootRef.current.position && bucketsContainerRef.current.position) {
|
|
294
|
-
rootRef.current.position.set(-effectivePanX, -effectivePanY);
|
|
295
|
-
bucketsContainerRef.current.position.set(-effectivePanX, -effectivePanY);
|
|
296
|
-
}
|
|
297
|
-
appRef.current?.renderer?.render(appRef.current.stage);
|
|
298
|
-
}, [zoomLevel, panX, panY]);
|
|
299
288
|
useEffect(() => {
|
|
300
289
|
if (!rootRef.current)
|
|
301
290
|
return;
|
|
@@ -324,20 +313,9 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
324
313
|
const effectivePanY = container.scrollTop;
|
|
325
314
|
lastScroll.x = effectivePanX;
|
|
326
315
|
lastScroll.y = effectivePanY;
|
|
327
|
-
if (rootRef.current && bucketsContainerRef.current) {
|
|
328
|
-
if (rootRef.current.scale && bucketsContainerRef.current.scale) {
|
|
329
|
-
rootRef.current.scale.set(zoomLevel);
|
|
330
|
-
bucketsContainerRef.current.scale.set(zoomLevel);
|
|
331
|
-
}
|
|
332
|
-
const invScale = zoomLevel && zoomLevel !== 0 ? 1 / zoomLevel : 1;
|
|
333
|
-
void invScale;
|
|
334
|
-
if (rootRef.current.position && bucketsContainerRef.current.position) {
|
|
335
|
-
rootRef.current.position.set(-effectivePanX, -effectivePanY);
|
|
336
|
-
bucketsContainerRef.current.position.set(-effectivePanX, -effectivePanY);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
316
|
syncSpritesToViewport({
|
|
340
317
|
root: rootRef.current,
|
|
318
|
+
groupsContainer: groupsContainerRef.current,
|
|
341
319
|
container: parentContainerRef.current,
|
|
342
320
|
sprites: spritesRef.current,
|
|
343
321
|
layout,
|
|
@@ -352,8 +330,13 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
352
330
|
viewportHeight,
|
|
353
331
|
createCardSprite: (id, x, y) => createCardSprite(id, x, y, items, (item, e, id) => (onCardClickRef.current)(item, e, id), (e) => (onPanStartRef.current)(e), cardWidth, cardHeight, cardColorsRef.current),
|
|
354
332
|
updateCardContent: (sprite, item) => updateCardContent(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current),
|
|
355
|
-
isViewTransition: isViewTransitionRef.current
|
|
333
|
+
isViewTransition: isViewTransitionRef.current,
|
|
334
|
+
viewMode,
|
|
335
|
+
prevScrollTop: prevScrollTopRef.current,
|
|
336
|
+
prevScrollLeft: prevScrollLeftRef.current,
|
|
356
337
|
});
|
|
338
|
+
prevScrollTopRef.current = container.scrollTop || 0;
|
|
339
|
+
prevScrollLeftRef.current = container.scrollLeft || 0;
|
|
357
340
|
needsRenderRef.current = true;
|
|
358
341
|
app.renderer?.render(app.stage);
|
|
359
342
|
}
|
|
@@ -385,7 +368,7 @@ function PivotCanvas({ items, layout, grouping, visibleIds, cardWidth, cardHeigh
|
|
|
385
368
|
}
|
|
386
369
|
}
|
|
387
370
|
function updateHighlight$1() {
|
|
388
|
-
updateHighlight(
|
|
371
|
+
updateHighlight(groupsContainerRef.current, parentContainerRef.current, grouping, layout, hoveredGroupIndex, cardWidth, zoomLevel);
|
|
389
372
|
}
|
|
390
373
|
return null;
|
|
391
374
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PivotCanvas.js","sources":["../../../../PivotViewer/components/PivotCanvas.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, useMemo, useRef, useState, type ReactNode } from 'react';\nimport * as PIXI from 'pixi.js';\nimport type { ItemId, LayoutResult, GroupingResult } from '../engine/types';\nimport type { ViewMode } from './Toolbar';\nimport { createCssColorResolver, resolveCardColors } from './pivot/colorResolver';\nimport { createCardSprite as createCardSpriteExternal, updateCardContent as updateCardContentExternal, clearSpritePool } from './pivot/sprites';\nimport { syncSpritesToViewport } from './pivot/visibility';\nimport { updateBucketBackgrounds as updateBucketBackgroundsExternal, updateHighlight as updateHighlightExternal } from './pivot/buckets';\nimport { startAnimationLoop as startAnimationLoopExternal, updatePositions as updatePositionsExternal } from './pivot/animation';\nimport { ANIMATION_SPEED, DEFAULT_COLORS, type CardSprite, type CardColors } from './pivot/constants';\n\nexport interface PivotCanvasProps<TItem extends object> {\n /** Original items array */\n items: TItem[];\n\n /** Layout positions */\n layout: LayoutResult;\n\n /** Grouping information */\n grouping: GroupingResult;\n\n /** Visible item IDs */\n visibleIds: Uint32Array;\n\n /** Card dimensions */\n cardWidth: number;\n cardHeight: number;\n\n /** Zoom level */\n zoomLevel: number;\n\n /** Pan offset */\n panX: number;\n panY: number;\n\n /** Viewport dimensions (visible area) */\n viewportWidth: number;\n viewportHeight: number;\n\n /** Selected item ID */\n selectedId: ItemId | null;\n\n /** Hovered group index */\n hoveredGroupIndex: number | null;\n\n /** Current view mode */\n viewMode: ViewMode;\n\n /** Is zooming animation in progress */\n isZooming?: boolean;\n\n /** Card renderer function */\n cardRenderer?: (item: TItem) => ReactNode;\n\n /** ID resolver */\n resolveId: (item: TItem, index: number) => string | number;\n\n /** Click handler */\n onCardClick: (item: TItem, e: MouseEvent, id: number | string) => void;\n\n /** Pan handlers */\n onPanStart: (e: React.MouseEvent) => void;\n onPanMove: (e: React.MouseEvent) => void;\n onPanEnd: () => void;\n containerRef: React.RefObject<HTMLDivElement | null>;\n}\n\n// `CardSprite` type moved to ./pivot/constants and imported above\n\n// constants and CardColors type moved to ./pivot/constants\n\nexport function PivotCanvas<TItem extends object>({\n items,\n layout,\n grouping,\n visibleIds,\n cardWidth,\n cardHeight,\n zoomLevel,\n panX,\n panY,\n viewportWidth,\n viewportHeight,\n selectedId,\n hoveredGroupIndex,\n isZooming: _isZooming = false,\n resolveId: _resolveId,\n onCardClick,\n onPanStart,\n onPanMove,\n onPanEnd,\n viewMode,\n cardRenderer,\n containerRef,\n}: PivotCanvasProps<TItem>) {\n // Use the containerRef passed from the parent viewport so we append the Pixi\n // canvas and spacer into the actual scrollable element.\n const parentContainerRef = containerRef;\n // Mark intentionally-unused destructured props as used to satisfy lint\n void _isZooming;\n void _resolveId;\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const spacerRef = useRef<HTMLDivElement | null>(null);\n const appRef = useRef<PIXI.Application | null>(null);\n const rootRef = useRef<PIXI.Container | null>(null);\n const bucketsContainerRef = useRef<PIXI.Container | null>(null);\n const spritesRef = useRef<Map<ItemId, CardSprite>>(new Map());\n const animationFrameRef = useRef<number>(0);\n const mountedRef = useRef(true);\n const [pixiReady, setPixiReady] = useState(false);\n const isAnimatingRef = useRef(false);\n const needsRenderRef = useRef(false);\n const initializingRef = useRef(false);\n const isViewTransitionRef = useRef(false);\n const lastViewChangeTimeRef = useRef(0);\n const previousViewModeRef = useRef<ViewMode>(viewMode);\n const prevLayoutRef = useRef<LayoutResult | null>(null);\n const prevGroupingRef = useRef<GroupingResult | null>(null);\n const cardColorsRef = useRef<CardColors>(DEFAULT_COLORS);\n void cardRenderer; // unused in Pixi renderer but keep prop compatibility\n\n const cssColorResolver = useMemo(() => createCssColorResolver(), []);\n\n const onPanStartRef = useRef(onPanStart);\n const onPanMoveRef = useRef(onPanMove);\n const onPanEndRef = useRef(onPanEnd);\n const onCardClickRef = useRef(onCardClick);\n const prevPanRef = useRef({ x: panX, y: panY });\n\n // Initialize Pixi Application\n useEffect(() => {\n // ... existing code ...\n onPanMoveRef.current = onPanMove;\n onPanEndRef.current = onPanEnd;\n onCardClickRef.current = onCardClick;\n }, [onPanStart, onPanMove, onPanEnd, onCardClick]);\n\n useEffect(() => {\n cardColorsRef.current = resolveCardColors(cssColorResolver);\n }, [cssColorResolver]);\n\n useEffect(() => {\n // Reset mounted flag\n mountedRef.current = true;\n\n if (!parentContainerRef || !parentContainerRef.current) {\n return;\n }\n\n // Prevent multiple simultaneous initializations\n if (initializingRef.current || appRef.current) {\n return;\n }\n\n initializingRef.current = true;\n let app: PIXI.Application | null = null;\n // Handler references declared here so cleanup can remove them later.\n\n (async () => {\n try {\n // Prefer the new init API (v8+) to avoid deprecation issues. Fall back\n // to the constructor options when `init` is not available.\n const options = {\n backgroundAlpha: 0,\n antialias: false,\n autoStart: false,\n autoDensity: true,\n resolution: window.devicePixelRatio || 1,\n width: viewportWidth > 0 ? viewportWidth : 800,\n height: viewportHeight > 0 ? viewportHeight : 600,\n } as PIXI.ApplicationOptions;\n\n app = new PIXI.Application();\n if ((app as unknown as { init?: unknown }).init && typeof (app as unknown as { init: (...args: unknown[]) => unknown }).init === 'function') {\n // init may return a promise in some builds\n \n // @ts-ignore\n await app.init(options);\n } else {\n // Fall back to constructor that accepts options\n app.destroy?.();\n app = new PIXI.Application(options);\n }\n\n if (!mountedRef.current || !parentContainerRef.current) {\n // Component unmounted during initialization\n if (app && typeof app.destroy === 'function') app.destroy(true, { children: true });\n initializingRef.current = false;\n return;\n }\n\n appRef.current = app;\n\n const bucketsContainer = new PIXI.Container();\n bucketsContainerRef.current = bucketsContainer;\n app.stage.addChild(bucketsContainer);\n\n const root = new PIXI.Container();\n rootRef.current = root;\n app.stage.addChild(root);\n\n // Resolve canvas element (different Pixi builds expose it as `view` or\n // `canvas`).\n const canvasEl = (app.view ?? (app as unknown as { canvas?: HTMLCanvasElement }).canvas ?? app.renderer?.view) as HTMLCanvasElement | undefined;\n\n // Place canvas outside the scrollable content so native scrolling\n // doesn't move the canvas DOM element itself. We overlay the canvas\n // on top of the scroll area by inserting it into the parent element\n // (or the container itself if parent is not available). This ensures\n // the Pixi canvas remains stable while we move the Pixi world inside\n // it to represent camera pan.\n const overlayParent = parentContainerRef.current.parentElement ?? parentContainerRef.current;\n if (canvasEl) {\n if (canvasEl.parentElement) {\n canvasEl.parentElement.removeChild(canvasEl);\n }\n overlayParent.appendChild(canvasEl);\n canvasRef.current = canvasEl;\n } else if ((app as unknown as { canvas?: HTMLCanvasElement }).canvas) {\n const c = (app as unknown as { canvas: HTMLCanvasElement }).canvas;\n if (c.parentElement) {\n c.parentElement.removeChild(c);\n }\n overlayParent.appendChild(c);\n canvasRef.current = c;\n }\n\n // Position the canvas to overlay the scrollable container area.\n if (canvasRef.current && parentContainerRef.current) {\n const parentBounds = parentContainerRef.current.getBoundingClientRect();\n void parentBounds;\n canvasRef.current.style.position = 'absolute';\n // Place canvas relative to the overlayParent's coordinate space.\n // If overlayParent is the immediate parent, top/left 0 aligns it.\n const offsetLeft = parentContainerRef.current.offsetLeft;\n const offsetTop = parentContainerRef.current.offsetTop;\n canvasRef.current.style.left = `${offsetLeft}px`;\n canvasRef.current.style.top = `${offsetTop}px`;\n canvasRef.current.style.width = `${parentContainerRef.current.clientWidth}px`;\n canvasRef.current.style.height = `${parentContainerRef.current.clientHeight}px`;\n // Place canvas behind the scrollable container (which has z-index 1)\n // so scrollbars appear on top.\n canvasRef.current.style.zIndex = '0';\n // Disable pointer events on canvas so they pass through to the viewport if needed,\n // though viewport is on top anyway.\n canvasRef.current.style.pointerEvents = 'none';\n }\n\n // We handle clicks and interactions manually in PivotViewerMain now,\n // so we don't need to configure Pixi events on the container.\n // This avoids z-index conflicts and event propagation issues.\n\n // Make canvas fill container with absolute positioning\n if (canvasRef.current) {\n canvasRef.current.style.display = 'block';\n // Ensure canvas does not capture events so they pass through to the viewport\n canvasRef.current.style.pointerEvents = 'none';\n }\n\n // Setup stage events for background panning\n app.stage.eventMode = 'static';\n app.stage.hitArea = new PIXI.Rectangle(0, 0, viewportWidth, viewportHeight);\n\n app.stage.on('pointerdown', (e) => {\n // Only handle if it reached the stage (background)\n // Sprites stop propagation, so this is safe\n onPanStartRef.current(e.nativeEvent as unknown as React.MouseEvent);\n });\n\n app.stage.on('globalpointermove', (e) => {\n onPanMoveRef.current(e.nativeEvent as unknown as React.MouseEvent);\n });\n\n app.stage.on('globalpointerup', () => {\n onPanEndRef.current();\n });\n\n // We no longer need manual event listeners on parentEl because Pixi\n // is now listening to events on parentEl directly via setTargetElement.\n // This allows Pixi to handle hit testing through the transparent container.\n const parentEl = parentContainerRef.current;\n if (parentEl) {\n // handleMouseDown = (e: Event) => onPanStartRef.current(e as unknown);\n // handleMouseMove = (e: Event) => onPanMoveRef.current(e as unknown);\n // handleMouseUp = () => onPanEndRef.current();\n // parentEl.addEventListener('mousedown', handleMouseDown);\n // parentEl.addEventListener('mousemove', handleMouseMove);\n // parentEl.addEventListener('mouseup', handleMouseUp);\n // parentEl.addEventListener('mouseleave', handleMouseUp);\n // window.addEventListener('mouseup', handleMouseUp);\n // window.addEventListener('pointerup', handleMouseUp);\n }\n\n // Immediately size to container to avoid delay\n if (viewportWidth > 0 && viewportHeight > 0) {\n app.renderer?.resize(viewportWidth, viewportHeight);\n }\n\n setPixiReady(true);\n initializingRef.current = false;\n\n // Trigger initial render\n needsRenderRef.current = true;\n app.renderer?.render(app.stage);\n } catch (error) {\n console.error('Failed to initialize Pixi.js:', error);\n initializingRef.current = false;\n }\n })();\n\n return () => {\n mountedRef.current = false;\n setPixiReady(false);\n cancelAnimationFrame(animationFrameRef.current);\n\n if (appRef.current && typeof appRef.current.destroy === 'function') {\n appRef.current.destroy(true, { children: true });\n appRef.current = null;\n rootRef.current = null;\n }\n\n // Clear sprite pool to avoid holding onto destroyed textures\n clearSpritePool();\n\n // Remove any event listeners we attached to the parent container\n try {\n const parentEl = parentContainerRef.current;\n if (parentEl) {\n // if (handleMouseDown) parentEl.removeEventListener('mousedown', handleMouseDown);\n // if (handleMouseMove) parentEl.removeEventListener('mousemove', handleMouseMove);\n // if (handleMouseUp) parentEl.removeEventListener('mouseup', handleMouseUp);\n // if (handleMouseUp) parentEl.removeEventListener('mouseleave', handleMouseUp);\n // if (handleMouseUp) {\n // window.removeEventListener('mouseup', handleMouseUp);\n // window.removeEventListener('pointerup', handleMouseUp);\n // }\n }\n } catch (e) {\n void e;\n }\n // Remove DOM nodes we appended\n try {\n if (canvasRef.current && canvasRef.current.parentElement) {\n canvasRef.current.parentElement.removeChild(canvasRef.current);\n }\n } catch (e) {\n void e;\n }\n };\n }, [viewportWidth, viewportHeight]);\n\n // Handle canvas resize\n useEffect(() => {\n if (!parentContainerRef || !parentContainerRef.current || !appRef.current || !pixiReady) return;\n\n const container = parentContainerRef.current;\n const app = appRef.current;\n\n let resizeTimeout: ReturnType<typeof setTimeout>;\n\n const handleResize = () => {\n // Size canvas to viewport dimensions from props\n if (viewportWidth > 0 && viewportHeight > 0) {\n app.renderer?.resize(viewportWidth, viewportHeight);\n app.stage.hitArea = new PIXI.Rectangle(0, 0, viewportWidth, viewportHeight);\n\n // Keep canvas DOM size in sync with container\n if (canvasRef.current && parentContainerRef.current) {\n canvasRef.current.style.width = `${parentContainerRef.current.clientWidth}px`;\n canvasRef.current.style.height = `${parentContainerRef.current.clientHeight}px`;\n // Also update left/top in case the container moved\n canvasRef.current.style.left = `${parentContainerRef.current.offsetLeft}px`;\n canvasRef.current.style.top = `${parentContainerRef.current.offsetTop}px`;\n }\n }\n };\n\n const debouncedResize = () => {\n clearTimeout(resizeTimeout);\n resizeTimeout = setTimeout(handleResize, 150);\n };\n\n // Initial resize (immediate)\n handleResize();\n\n // Watch for size changes (debounced)\n const resizeObserver = new ResizeObserver(debouncedResize);\n resizeObserver.observe(container);\n\n return () => {\n clearTimeout(resizeTimeout);\n resizeObserver.disconnect();\n };\n }, [pixiReady, viewportWidth, viewportHeight]);\n\n // Update bucket backgrounds only when layout/grouping changes\n useEffect(() => {\n if (!bucketsContainerRef.current || !parentContainerRef.current || !pixiReady) return;\n updateBucketBackgroundsExternal(bucketsContainerRef.current, parentContainerRef.current, grouping, layout, zoomLevel, cardColorsRef.current, viewMode);\n needsRenderRef.current = true;\n appRef.current?.renderer?.render(appRef.current.stage);\n }, [grouping, layout, zoomLevel, viewMode, pixiReady]);\n\n useEffect(() => {\n if (!rootRef.current || !parentContainerRef.current || !pixiReady) {\n return;\n }\n\n // Check if this is a view mode change (not just pan/scroll)\n const viewModeChanged = previousViewModeRef.current !== viewMode;\n const groupingChanged = prevGroupingRef.current !== grouping;\n\n if (viewModeChanged || groupingChanged) {\n isViewTransitionRef.current = true;\n lastViewChangeTimeRef.current = Date.now();\n previousViewModeRef.current = viewMode;\n prevGroupingRef.current = grouping;\n \n // When switching modes, mark all sprites for cleanup by hiding them\n // The normal sweep logic will remove them after SWEEP_MS delay\n for (const sprite of spritesRef.current.values()) {\n try {\n if (sprite.container) {\n sprite.container.visible = false;\n }\n (sprite as unknown as { __lastHiddenAt?: number }).__lastHiddenAt = Date.now();\n } catch (e) {\n void e;\n }\n }\n }\n\n // Update spacer dimensions to match scaled world size\n if (spacerRef.current) {\n const spacer = spacerRef.current;\n const worldWidth = (layout.totalWidth || viewportWidth) * zoomLevel;\n const worldHeight = (layout.totalHeight || viewportHeight) * zoomLevel;\n spacer.style.width = `${Math.max(worldWidth, viewportWidth)}px`;\n spacer.style.height = `${Math.max(worldHeight, viewportHeight)}px`;\n }\n\n // Ensure scroll spacer matches layout so the container becomes scrollable and\n // native scrollLeft/scrollTop reflect the camera position.\n if (parentContainerRef.current) {\n const spacer = spacerRef.current;\n if (spacer) {\n // Debug: log spacer and layout values to detect mismatches\n }\n }\n\n const panDeltaX = panX - prevPanRef.current.x;\n const panDeltaY = panY - prevPanRef.current.y;\n prevPanRef.current = { x: panX, y: panY };\n\n // Sync sprites into viewport and create/remove as needed\n // Provide wrappers for sprite creation and content update so helpers have required context\n syncSpritesToViewport({\n root: rootRef.current,\n container: parentContainerRef.current,\n sprites: spritesRef.current,\n layout,\n visibleIds,\n items,\n cardWidth,\n cardHeight,\n panX,\n panY,\n panDeltaX,\n panDeltaY,\n zoomLevel,\n viewportWidth,\n viewportHeight,\n createCardSprite: (id: string | number, x: number, y: number) => createCardSpriteExternal(\n id,\n x,\n y,\n items as TItem[],\n (item: TItem, e: MouseEvent, id: string | number) => (onCardClickRef.current)(item, e, id),\n (e: MouseEvent) => (onPanStart)(e as unknown as React.MouseEvent),\n cardWidth,\n cardHeight,\n cardColorsRef.current\n ),\n updateCardContent: (sprite: CardSprite, item: TItem) => updateCardContentExternal(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current),\n isViewTransition: isViewTransitionRef.current || (Date.now() - lastViewChangeTimeRef.current < 1000),\n prevLayout: prevLayoutRef.current,\n });\n needsRenderRef.current = true;\n \n // Force an immediate render after syncing sprites to ensure cards appear\n if (appRef.current?.renderer && rootRef.current) {\n appRef.current.renderer.render(appRef.current.stage);\n needsRenderRef.current = false;\n }\n \n startAnimationLoopExternal({\n mountedRef,\n appRef,\n animationFrameRef,\n isAnimatingRef,\n needsRenderRef,\n spritesRef,\n isViewTransitionRef,\n });\n }, [layout, visibleIds, items, cardWidth, cardHeight, pixiReady, zoomLevel, panX, panY, grouping, viewMode]);\n\n // Update prevLayoutRef after processing layout changes\n useEffect(() => {\n prevLayoutRef.current = layout;\n }, [layout]);\n\n useEffect(() => {\n if (!rootRef.current || !bucketsContainerRef.current) return;\n\n // Camera transform: move world opposite to camera position. Prefer the\n // native container scroll positions where available (they are authoritative\n // during user scrolls) and fall back to the passed pan props.\n const effectivePanX = parentContainerRef.current ? parentContainerRef.current.scrollLeft : panX;\n const effectivePanY = parentContainerRef.current ? parentContainerRef.current.scrollTop : panY;\n\n // Apply zoom and position to root and buckets.\n if (rootRef.current.scale && bucketsContainerRef.current.scale) {\n rootRef.current.scale.set(zoomLevel);\n bucketsContainerRef.current.scale.set(zoomLevel);\n }\n if (rootRef.current.position && bucketsContainerRef.current.position) {\n rootRef.current.position.set(-effectivePanX, -effectivePanY);\n bucketsContainerRef.current.position.set(-effectivePanX, -effectivePanY);\n }\n appRef.current?.renderer?.render(appRef.current.stage);\n }, [zoomLevel, panX, panY]);\n\n useEffect(() => {\n if (!rootRef.current) return;\n updateSelection();\n needsRenderRef.current = true;\n appRef.current?.renderer.render(appRef.current.stage);\n }, [selectedId, items]);\n\n useEffect(() => {\n if (!rootRef.current) return;\n updateHighlight();\n needsRenderRef.current = true;\n appRef.current?.renderer.render(appRef.current.stage);\n }, [hoveredGroupIndex, layout, grouping]);\n\n // Note: animation loop and bucket background updates are delegated to\n // external helpers (`startAnimationLoopExternal` and\n // `updateBucketBackgroundsExternal`) and invoked where needed. We don't\n // expose local wrappers to avoid unused-function lint warnings.\n\n // Listen to native scroll events on the parent container so we update the\n // Pixi world immediately when the user scrolls (native scrollbar or\n // programmatic). This ensures `syncSpritesToViewport` runs on scroll and\n // creates/destroys sprites as the viewport moves.\n useEffect(() => {\n if (!pixiReady || !parentContainerRef || !parentContainerRef.current || !appRef.current || !rootRef.current) return;\n\n const container = parentContainerRef.current;\n const app = appRef.current;\n\n // rAF-batched scroll handling: store the latest scroll values and process\n // them once per animation frame to avoid heavy synchronous work inside\n // the scroll event which causes jank and de-synchronisation between the\n // compositor and Pixi render updates.\n const lastScroll = { x: container.scrollLeft, y: container.scrollTop };\n const pendingRef = { scheduled: false } as { scheduled: boolean };\n\n const processScroll = () => {\n pendingRef.scheduled = false;\n try {\n // Read directly from container to ensure consistency with visibility logic\n // and to handle cases where scroll changes without event (e.g. resize clamping)\n const effectivePanX = container.scrollLeft;\n const effectivePanY = container.scrollTop;\n\n // Update lastScroll to keep it in sync\n lastScroll.x = effectivePanX;\n lastScroll.y = effectivePanY;\n\n if (rootRef.current && bucketsContainerRef.current) {\n if (rootRef.current.scale && bucketsContainerRef.current.scale) {\n rootRef.current.scale.set(zoomLevel);\n bucketsContainerRef.current.scale.set(zoomLevel);\n }\n const invScale = zoomLevel && zoomLevel !== 0 ? 1 / zoomLevel : 1;\n void invScale;\n if (rootRef.current.position && bucketsContainerRef.current.position) {\n rootRef.current.position.set(-effectivePanX, -effectivePanY);\n bucketsContainerRef.current.position.set(-effectivePanX, -effectivePanY);\n }\n }\n\n syncSpritesToViewport({\n root: rootRef.current,\n container: parentContainerRef.current,\n sprites: spritesRef.current,\n layout,\n visibleIds,\n items,\n cardWidth,\n cardHeight,\n panX,\n panY,\n zoomLevel,\n viewportWidth,\n viewportHeight,\n createCardSprite: (id: string | number, x: number, y: number) => createCardSpriteExternal(\n id, x, y, items as TItem[],\n (item, e, id) => (onCardClickRef.current)(item, e, id),\n (e) => (onPanStartRef.current)(e as unknown as React.MouseEvent), // Pixi events to React events\n cardWidth, cardHeight, cardColorsRef.current\n ),\n updateCardContent: (sprite: CardSprite, item: TItem) => updateCardContentExternal(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current),\n isViewTransition: isViewTransitionRef.current || (Date.now() - lastViewChangeTimeRef.current < 1000),\n });\n needsRenderRef.current = true;\n app.renderer?.render(app.stage);\n } catch (e) {\n console.error('[PivotCanvas] processScroll error', e);\n }\n };\n\n const onScroll = () => {\n // capture latest scroll positions quickly and schedule work\n lastScroll.x = container.scrollLeft;\n lastScroll.y = container.scrollTop;\n if (!pendingRef.scheduled) {\n pendingRef.scheduled = true;\n requestAnimationFrame(processScroll);\n }\n };\n\n container.addEventListener('scroll', onScroll, { passive: true });\n\n return () => {\n container.removeEventListener('scroll', onScroll);\n };\n }, [pixiReady, layout, visibleIds, items, cardWidth, cardHeight, zoomLevel, viewportWidth, viewportHeight, panX, panY, grouping, viewMode, selectedId, onCardClick, onPanStart]);\n\n function createCardSprite(id: ItemId, x: number, y: number): CardSprite {\n return createCardSpriteExternal(\n id, x, y, items as TItem[],\n (item, e, id) => (onCardClickRef.current)(item, e, id),\n (e) => (onPanStartRef.current)(e as unknown as React.MouseEvent),\n cardWidth, cardHeight, cardColorsRef.current\n );\n }\n // Mark these helpers as used (they may be referenced externally or via callbacks)\n void createCardSprite;\n\n function updateCardContent(sprite: CardSprite, item: TItem) {\n return updateCardContentExternal(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current);\n }\n\n function updatePositions(): boolean {\n return updatePositionsExternal(spritesRef.current, isViewTransitionRef, ANIMATION_SPEED);\n }\n\n void updatePositions;\n\n function updateSelection() {\n const sprites = spritesRef.current;\n\n for (const sprite of sprites.values()) {\n const val = (items as TItem[])[Number(sprite.itemId)];\n updateCardContent(sprite, val);\n }\n }\n\n function updateHighlight() {\n updateHighlightExternal(bucketsContainerRef.current, parentContainerRef.current, grouping, layout, hoveredGroupIndex, cardWidth, zoomLevel);\n }\n\n void updateHighlight;\n\n // This component renders into the parent `containerRef` (we append Pixi canvas\n // and spacer directly into that DOM node). Return null so we don't replace or\n // reassign the parent's ref which must remain the scrollable viewport element.\n return null;\n}\n"],"names":["updateBucketBackgroundsExternal","createCardSpriteExternal","updateCardContentExternal","startAnimationLoopExternal","updateHighlight","updateCardContent","updateHighlightExternal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PivotCanvas.js","sources":["../../../../PivotViewer/components/PivotCanvas.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, useMemo, useRef, useState, type ReactNode } from 'react';\nimport * as PIXI from 'pixi.js';\nimport type { ItemId, LayoutResult, GroupingResult } from '../engine/types';\nimport type { ViewMode } from './Toolbar';\nimport { createCssColorResolver, resolveCardColors } from './pivot/colorResolver';\nimport { createCardSprite as createCardSpriteExternal, updateCardContent as updateCardContentExternal } from './pivot/sprites';\nimport { syncSpritesToViewport } from './pivot/visibility';\nimport { updateGroupBackgrounds as updateGroupBackgroundsExternal, updateHighlight as updateHighlightExternal } from './pivot/groups';\nimport { startAnimationLoop as startAnimationLoopExternal, updatePositions as updatePositionsExternal } from './pivot/animation';\nimport { ANIMATION_SPEED, DEFAULT_COLORS, type CardSprite, type CardColors } from './pivot/constants';\n\nexport interface PivotCanvasProps<TItem extends object> {\n /** Original items array */\n items: TItem[];\n\n /** Layout positions */\n layout: LayoutResult;\n\n /** Grouping information */\n grouping: GroupingResult;\n\n /** Visible item IDs */\n visibleIds: Uint32Array;\n\n /** Card dimensions */\n cardWidth: number;\n cardHeight: number;\n\n /** Zoom level */\n zoomLevel: number;\n\n /** Pan offset */\n panX: number;\n panY: number;\n\n /** Viewport dimensions (visible area) */\n viewportWidth: number;\n viewportHeight: number;\n\n /** Selected item ID */\n selectedId: ItemId | null;\n\n /** Hovered group index */\n hoveredGroupIndex: number | null;\n\n /** Current view mode */\n viewMode: ViewMode;\n\n /** Is zooming animation in progress */\n isZooming?: boolean;\n\n /** Card renderer function */\n cardRenderer?: (item: TItem) => ReactNode;\n\n /** ID resolver */\n resolveId: (item: TItem, index: number) => string | number;\n\n /** Click handler */\n onCardClick: (item: TItem, e: MouseEvent, id: number | string) => void;\n\n /** Pan handlers */\n onPanStart: (e: React.MouseEvent) => void;\n onPanMove: (e: React.MouseEvent) => void;\n onPanEnd: () => void;\n containerRef: React.RefObject<HTMLDivElement | null>;\n}\n\n// `CardSprite` type moved to ./pivot/constants and imported above\n\n// constants and CardColors type moved to ./pivot/constants\n\nexport function PivotCanvas<TItem extends object>({\n items,\n layout,\n grouping,\n visibleIds,\n cardWidth,\n cardHeight,\n zoomLevel,\n panX,\n panY,\n viewportWidth,\n viewportHeight,\n selectedId,\n hoveredGroupIndex,\n isZooming: _isZooming = false,\n resolveId: _resolveId,\n onCardClick,\n onPanStart,\n onPanMove,\n onPanEnd,\n viewMode,\n cardRenderer,\n containerRef,\n}: PivotCanvasProps<TItem>) {\n // Use the containerRef passed from the parent viewport so we append the Pixi\n // canvas and spacer into the actual scrollable element.\n const parentContainerRef = containerRef;\n // Mark intentionally-unused destructured props as used to satisfy lint\n void _isZooming;\n void _resolveId;\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const spacerRef = useRef<HTMLDivElement | null>(null);\n const appRef = useRef<PIXI.Application | null>(null);\n const rootRef = useRef<PIXI.Container | null>(null);\n const groupsContainerRef = useRef<PIXI.Container | null>(null);\n const spritesRef = useRef<Map<ItemId, CardSprite>>(new Map());\n const animationFrameRef = useRef<number>(0);\n const mountedRef = useRef(true);\n const [pixiReady, setPixiReady] = useState(false);\n const isAnimatingRef = useRef(false);\n const needsRenderRef = useRef(false);\n const initializingRef = useRef(false);\n const isViewTransitionRef = useRef(false);\n const lastViewChangeTimeRef = useRef(0);\n const previousViewModeRef = useRef<ViewMode>(viewMode);\n const prevLayoutRef = useRef<LayoutResult | null>(null);\n const prevGroupingRef = useRef<GroupingResult | null>(null);\n const prevScrollTopRef = useRef<number>(0);\n const prevScrollLeftRef = useRef<number>(0);\n const cardColorsRef = useRef<CardColors>(DEFAULT_COLORS);\n void cardRenderer; // unused in Pixi renderer but keep prop compatibility\n\n const cssColorResolver = useMemo(() => createCssColorResolver(), []);\n\n const onPanStartRef = useRef(onPanStart);\n const onPanMoveRef = useRef(onPanMove);\n const onPanEndRef = useRef(onPanEnd);\n const onCardClickRef = useRef(onCardClick);\n const prevPanRef = useRef({ x: panX, y: panY });\n\n // Initialize Pixi Application\n useEffect(() => {\n // ... existing code ...\n onPanMoveRef.current = onPanMove;\n onPanEndRef.current = onPanEnd;\n onCardClickRef.current = onCardClick;\n }, [onPanStart, onPanMove, onPanEnd, onCardClick]);\n\n useEffect(() => {\n cardColorsRef.current = resolveCardColors(cssColorResolver);\n }, [cssColorResolver]);\n\n useEffect(() => {\n // Reset mounted flag\n mountedRef.current = true;\n\n if (!parentContainerRef || !parentContainerRef.current) {\n return;\n }\n\n // Prevent multiple simultaneous initializations\n if (initializingRef.current || appRef.current) {\n return;\n }\n\n initializingRef.current = true;\n let app: PIXI.Application | null = null;\n // Handler references declared here so cleanup can remove them later.\n\n (async () => {\n try {\n // Prefer the new init API (v8+) to avoid deprecation issues. Fall back\n // to the constructor options when `init` is not available.\n const options = {\n backgroundAlpha: 0,\n antialias: false,\n autoStart: false,\n autoDensity: true,\n resolution: window.devicePixelRatio || 1,\n width: viewportWidth > 0 ? viewportWidth : 800,\n height: viewportHeight > 0 ? viewportHeight : 600,\n } as PIXI.ApplicationOptions;\n\n app = new PIXI.Application();\n if ((app as unknown as { init?: unknown }).init && typeof (app as unknown as { init: (...args: unknown[]) => unknown }).init === 'function') {\n // init may return a promise in some builds\n \n // @ts-ignore\n await app.init(options);\n } else {\n // Fall back to constructor that accepts options\n app.destroy?.();\n app = new PIXI.Application(options);\n }\n\n if (!mountedRef.current || !parentContainerRef.current) {\n // Component unmounted during initialization\n if (app && typeof app.destroy === 'function') app.destroy(true, { children: true });\n initializingRef.current = false;\n return;\n }\n\n appRef.current = app;\n\n const groupsContainer = new PIXI.Container();\n groupsContainerRef.current = groupsContainer;\n app.stage.addChild(groupsContainer);\n\n const root = new PIXI.Container();\n rootRef.current = root;\n app.stage.addChild(root);\n\n // Resolve canvas element (different Pixi builds expose it as `view` or\n // `canvas`).\n const canvasEl = (app.view ?? (app as unknown as { canvas?: HTMLCanvasElement }).canvas ?? app.renderer?.view) as HTMLCanvasElement | undefined;\n\n // Place canvas outside the scrollable content so native scrolling\n // doesn't move the canvas DOM element itself. We overlay the canvas\n // on top of the scroll area by inserting it into the parent element\n // (or the container itself if parent is not available). This ensures\n // the Pixi canvas remains stable while we move the Pixi world inside\n // it to represent camera pan.\n const overlayParent = parentContainerRef.current.parentElement ?? parentContainerRef.current;\n\n if (canvasEl) {\n if (canvasEl.parentElement) {\n canvasEl.parentElement.removeChild(canvasEl);\n }\n overlayParent.appendChild(canvasEl);\n canvasRef.current = canvasEl;\n } else if ((app as unknown as { canvas?: HTMLCanvasElement }).canvas) {\n const c = (app as unknown as { canvas: HTMLCanvasElement }).canvas;\n if (c.parentElement) {\n c.parentElement.removeChild(c);\n }\n overlayParent.appendChild(c);\n canvasRef.current = c;\n } else {\n console.error('PivotCanvas: Could not find canvas element from Pixi application');\n }\n\n // Position the canvas to overlay the scrollable container area.\n if (canvasRef.current && parentContainerRef.current) {\n const parentBounds = parentContainerRef.current.getBoundingClientRect();\n void parentBounds;\n canvasRef.current.style.position = 'absolute';\n // Place canvas relative to the overlayParent's coordinate space.\n // If overlayParent is the immediate parent, top/left 0 aligns it.\n const offsetLeft = parentContainerRef.current.offsetLeft;\n const offsetTop = parentContainerRef.current.offsetTop;\n canvasRef.current.style.left = `${offsetLeft}px`;\n canvasRef.current.style.top = `${offsetTop}px`;\n canvasRef.current.style.width = `${parentContainerRef.current.clientWidth}px`;\n canvasRef.current.style.height = `${parentContainerRef.current.clientHeight}px`;\n // Place canvas behind the scrollable container (which has z-index 1)\n // so scrollbars appear on top.\n canvasRef.current.style.zIndex = '0';\n // Disable pointer events on canvas so they pass through to the viewport if needed,\n // though viewport is on top anyway.\n canvasRef.current.style.pointerEvents = 'none';\n }\n\n // We handle clicks and interactions manually in PivotViewerMain now,\n // so we don't need to configure Pixi events on the container.\n // This avoids z-index conflicts and event propagation issues.\n\n // Make canvas fill container with absolute positioning\n if (canvasRef.current) {\n canvasRef.current.style.display = 'block';\n // Ensure canvas does not capture events so they pass through to the viewport\n canvasRef.current.style.pointerEvents = 'none';\n }\n\n // Setup stage events for background panning\n app.stage.eventMode = 'static';\n app.stage.hitArea = new PIXI.Rectangle(0, 0, viewportWidth, viewportHeight);\n\n app.stage.on('pointerdown', (e) => {\n // Only handle if it reached the stage (background)\n // Sprites stop propagation, so this is safe\n onPanStartRef.current(e.nativeEvent as unknown as React.MouseEvent);\n });\n\n app.stage.on('globalpointermove', (e) => {\n onPanMoveRef.current(e.nativeEvent as unknown as React.MouseEvent);\n });\n\n app.stage.on('globalpointerup', () => {\n onPanEndRef.current();\n });\n\n // We no longer need manual event listeners on parentEl because Pixi\n // is now listening to events on parentEl directly via setTargetElement.\n // This allows Pixi to handle hit testing through the transparent container.\n const parentEl = parentContainerRef.current;\n if (parentEl) {\n // handleMouseDown = (e: Event) => onPanStartRef.current(e as unknown);\n // handleMouseMove = (e: Event) => onPanMoveRef.current(e as unknown);\n // handleMouseUp = () => onPanEndRef.current();\n // parentEl.addEventListener('mousedown', handleMouseDown);\n // parentEl.addEventListener('mousemove', handleMouseMove);\n // parentEl.addEventListener('mouseup', handleMouseUp);\n // parentEl.addEventListener('mouseleave', handleMouseUp);\n // window.addEventListener('mouseup', handleMouseUp);\n // window.addEventListener('pointerup', handleMouseUp);\n }\n\n // Immediately size to container to avoid delay\n if (viewportWidth > 0 && viewportHeight > 0) {\n app.renderer?.resize(viewportWidth, viewportHeight);\n }\n\n setPixiReady(true);\n initializingRef.current = false;\n\n // Trigger initial render\n needsRenderRef.current = true;\n app.renderer?.render(app.stage);\n } catch (error) {\n console.error('Failed to initialize Pixi.js:', error);\n initializingRef.current = false;\n }\n })();\n\n return () => {\n mountedRef.current = false;\n setPixiReady(false);\n cancelAnimationFrame(animationFrameRef.current);\n\n if (appRef.current && typeof appRef.current.destroy === 'function') {\n appRef.current.destroy(true, { children: true });\n appRef.current = null;\n rootRef.current = null;\n }\n\n // Clear local sprite references to prevent re-use of destroyed sprites\n spritesRef.current.clear();\n\n // Clear sprite pool to avoid holding onto destroyed textures\n // clearSpritePool();\n\n // Remove any event listeners we attached to the parent container\n try {\n const parentEl = parentContainerRef.current;\n if (parentEl) {\n // if (handleMouseDown) parentEl.removeEventListener('mousedown', handleMouseDown);\n // if (handleMouseMove) parentEl.removeEventListener('mousemove', handleMouseMove);\n // if (handleMouseUp) parentEl.removeEventListener('mouseup', handleMouseUp);\n // if (handleMouseUp) parentEl.removeEventListener('mouseleave', handleMouseUp);\n // if (handleMouseUp) {\n // window.removeEventListener('mouseup', handleMouseUp);\n // window.removeEventListener('pointerup', handleMouseUp);\n // }\n }\n } catch (e) {\n void e;\n }\n // Remove DOM nodes we appended\n try {\n if (canvasRef.current && canvasRef.current.parentElement) {\n canvasRef.current.parentElement.removeChild(canvasRef.current);\n }\n } catch (e) {\n void e;\n }\n };\n }, [viewportWidth, viewportHeight]);\n\n // Handle canvas resize\n useEffect(() => {\n if (!parentContainerRef || !parentContainerRef.current || !appRef.current || !pixiReady) return;\n\n const container = parentContainerRef.current;\n const app = appRef.current;\n\n let resizeTimeout: ReturnType<typeof setTimeout>;\n\n const handleResize = () => {\n // Size canvas to viewport dimensions from props\n if (viewportWidth > 0 && viewportHeight > 0) {\n app.renderer?.resize(viewportWidth, viewportHeight);\n app.stage.hitArea = new PIXI.Rectangle(0, 0, viewportWidth, viewportHeight);\n\n // Keep canvas DOM size in sync with container\n if (canvasRef.current && parentContainerRef.current) {\n canvasRef.current.style.width = `${parentContainerRef.current.clientWidth}px`;\n canvasRef.current.style.height = `${parentContainerRef.current.clientHeight}px`;\n // Also update left/top in case the container moved\n canvasRef.current.style.left = `${parentContainerRef.current.offsetLeft}px`;\n canvasRef.current.style.top = `${parentContainerRef.current.offsetTop}px`;\n }\n }\n };\n\n const debouncedResize = () => {\n clearTimeout(resizeTimeout);\n resizeTimeout = setTimeout(handleResize, 150);\n };\n\n // Initial resize (immediate)\n handleResize();\n\n // Watch for size changes (debounced)\n const resizeObserver = new ResizeObserver(debouncedResize);\n resizeObserver.observe(container);\n\n return () => {\n clearTimeout(resizeTimeout);\n resizeObserver.disconnect();\n };\n }, [pixiReady, viewportWidth, viewportHeight]);\n\n // Update group backgrounds only when layout/grouping changes\n useEffect(() => {\n if (!groupsContainerRef.current || !parentContainerRef.current || !pixiReady) return;\n updateGroupBackgroundsExternal(groupsContainerRef.current, parentContainerRef.current, grouping, layout, zoomLevel, cardColorsRef.current, viewMode);\n needsRenderRef.current = true;\n appRef.current?.renderer?.render(appRef.current.stage);\n }, [grouping, layout, zoomLevel, viewMode, pixiReady]);\n\n useEffect(() => {\n if (!rootRef.current || !parentContainerRef.current || !pixiReady) {\n return;\n }\n\n // Check if this is a view mode change (not just pan/scroll)\n const viewModeChanged = previousViewModeRef.current !== viewMode;\n const groupingChanged = prevGroupingRef.current !== grouping;\n const layoutChanged = prevLayoutRef.current !== layout;\n\n if (viewModeChanged || groupingChanged || layoutChanged) {\n isViewTransitionRef.current = true;\n lastViewChangeTimeRef.current = Date.now();\n previousViewModeRef.current = viewMode;\n prevGroupingRef.current = grouping;\n \n // Don't hide sprites here - let visibility.ts handle the transition\n // The syncSpritesToViewport function will properly animate sprites to new positions\n // during view transitions (isViewTransitionRef.current = true), and visibility.ts\n // will handle cleanup of sprites that no longer have positions in the layout.\n // Previously, hiding sprites here caused sorting/transitions to not work because\n // sprites were destroyed before they could animate.\n }\n\n // Update spacer dimensions to match scaled world size\n if (spacerRef.current) {\n const spacer = spacerRef.current;\n const worldWidth = (layout.totalWidth || viewportWidth) * zoomLevel;\n const worldHeight = (layout.totalHeight || viewportHeight) * zoomLevel;\n spacer.style.width = `${Math.max(worldWidth, viewportWidth)}px`;\n spacer.style.height = `${Math.max(worldHeight, viewportHeight)}px`;\n }\n\n // Ensure scroll spacer matches layout so the container becomes scrollable and\n // native scrollLeft/scrollTop reflect the camera position.\n if (parentContainerRef.current) {\n const spacer = spacerRef.current;\n if (spacer) {\n // Debug: log spacer and layout values to detect mismatches\n }\n }\n\n const panDeltaX = panX - prevPanRef.current.x;\n const panDeltaY = panY - prevPanRef.current.y;\n prevPanRef.current = { x: panX, y: panY };\n\n // Sync sprites into viewport and create/remove as needed\n // Provide wrappers for sprite creation and content update so helpers have required context\n const currentScrollTop = parentContainerRef.current?.scrollTop || 0;\n const currentScrollLeft = parentContainerRef.current?.scrollLeft || 0;\n \n syncSpritesToViewport({\n root: rootRef.current,\n groupsContainer: groupsContainerRef.current,\n container: parentContainerRef.current,\n sprites: spritesRef.current,\n layout,\n visibleIds,\n items,\n cardWidth,\n cardHeight,\n panX,\n panY,\n panDeltaX,\n panDeltaY,\n zoomLevel,\n viewportWidth,\n viewportHeight,\n viewMode,\n createCardSprite: (id: string | number, x: number, y: number) => createCardSpriteExternal(\n id,\n x,\n y,\n items as TItem[],\n (item: TItem, e: MouseEvent, id: string | number) => (onCardClickRef.current)(item, e, id),\n (e: MouseEvent) => (onPanStart)(e as unknown as React.MouseEvent),\n cardWidth,\n cardHeight,\n cardColorsRef.current\n ),\n updateCardContent: (sprite: CardSprite, item: TItem) => updateCardContentExternal(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current),\n isViewTransition: isViewTransitionRef.current,\n prevLayout: prevLayoutRef.current,\n prevScrollTop: prevScrollTopRef.current,\n prevScrollLeft: prevScrollLeftRef.current,\n });\n \n // Update previous scroll position for next frame\n prevScrollTopRef.current = currentScrollTop;\n prevScrollLeftRef.current = currentScrollLeft;\n needsRenderRef.current = true;\n \n // Force an immediate render after syncing sprites to ensure cards appear\n if (appRef.current?.renderer && rootRef.current) {\n appRef.current.renderer.render(appRef.current.stage);\n needsRenderRef.current = false;\n }\n \n startAnimationLoopExternal({\n mountedRef,\n appRef,\n animationFrameRef,\n isAnimatingRef,\n needsRenderRef,\n spritesRef,\n isViewTransitionRef,\n });\n }, [layout, visibleIds, items, cardWidth, cardHeight, pixiReady, zoomLevel, panX, panY, grouping, viewMode]);\n\n // Update prevLayoutRef after processing layout changes\n useEffect(() => {\n prevLayoutRef.current = layout;\n }, [layout]);\n\n // Duplicate camera position effect removed -- syncSpritesToViewport handles this with correct offsetY logic logic\n /*\n useEffect(() => {\n if (!rootRef.current || !groupsContainerRef.current) return;\n\n // Camera transform: move world opposite to camera position. Prefer the\n // native container scroll positions where available (they are authoritative\n // during user scrolls) and fall back to the passed pan props.\n const effectivePanX = parentContainerRef.current ? parentContainerRef.current.scrollLeft : panX;\n const effectivePanY = parentContainerRef.current ? parentContainerRef.current.scrollTop : panY;\n\n // Apply zoom and position to root and groups.\n if (rootRef.current.scale && groupsContainerRef.current.scale) {\n rootRef.current.scale.set(zoomLevel);\n groupsContainerRef.current.scale.set(zoomLevel);\n }\n if (rootRef.current.position && groupsContainerRef.current.position) {\n rootRef.current.position.set(-effectivePanX, -effectivePanY);\n groupsContainerRef.current.position.set(-effectivePanX, -effectivePanY);\n }\n appRef.current?.renderer?.render(appRef.current.stage);\n }, [zoomLevel, panX, panY]);\n */\n\n useEffect(() => {\n if (!rootRef.current) return;\n updateSelection();\n needsRenderRef.current = true;\n appRef.current?.renderer.render(appRef.current.stage);\n }, [selectedId, items]);\n\n useEffect(() => {\n if (!rootRef.current) return;\n updateHighlight();\n needsRenderRef.current = true;\n appRef.current?.renderer.render(appRef.current.stage);\n }, [hoveredGroupIndex, layout, grouping]);\n\n // Note: animation loop and group background updates are delegated to\n // external helpers (`startAnimationLoopExternal` and\n // `updateGroupBackgroundsExternal`) and invoked where needed. We don't\n // expose local wrappers to avoid unused-function lint warnings.\n\n // Listen to native scroll events on the parent container so we update the\n // Pixi world immediately when the user scrolls (native scrollbar or\n // programmatic). This ensures `syncSpritesToViewport` runs on scroll and\n // creates/destroys sprites as the viewport moves.\n useEffect(() => {\n if (!pixiReady || !parentContainerRef || !parentContainerRef.current || !appRef.current || !rootRef.current) return;\n\n const container = parentContainerRef.current;\n const app = appRef.current;\n\n // rAF-batched scroll handling: store the latest scroll values and process\n // them once per animation frame to avoid heavy synchronous work inside\n // the scroll event which causes jank and de-synchronisation between the\n // compositor and Pixi render updates.\n const lastScroll = { x: container.scrollLeft, y: container.scrollTop };\n const pendingRef = { scheduled: false } as { scheduled: boolean };\n\n const processScroll = () => {\n pendingRef.scheduled = false;\n try {\n // Read directly from container to ensure consistency with visibility logic\n // and to handle cases where scroll changes without event (e.g. resize clamping)\n const effectivePanX = container.scrollLeft;\n const effectivePanY = container.scrollTop;\n\n // Update lastScroll to keep it in sync\n lastScroll.x = effectivePanX;\n lastScroll.y = effectivePanY;\n\n // Note: We delegate root/groups container positioning to syncSpritesToViewport\n // because it encapsulates the logic for conditional vertical alignment (offsetY)\n // in different view modes. Manually setting position here would overwrite that logic.\n\n syncSpritesToViewport({\n root: rootRef.current,\n groupsContainer: groupsContainerRef.current,\n container: parentContainerRef.current,\n sprites: spritesRef.current,\n layout,\n visibleIds,\n items,\n cardWidth,\n cardHeight,\n panX,\n panY,\n zoomLevel,\n viewportWidth,\n viewportHeight,\n createCardSprite: (id: string | number, x: number, y: number) => createCardSpriteExternal(\n id, x, y, items as TItem[],\n (item, e, id) => (onCardClickRef.current)(item, e, id),\n (e) => (onPanStartRef.current)(e as unknown as React.MouseEvent), // Pixi events to React events\n cardWidth, cardHeight, cardColorsRef.current\n ),\n updateCardContent: (sprite: CardSprite, item: TItem) => updateCardContentExternal(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current),\n isViewTransition: isViewTransitionRef.current,\n viewMode,\n prevScrollTop: prevScrollTopRef.current,\n prevScrollLeft: prevScrollLeftRef.current,\n });\n \n // Update previous scroll position for next frame\n prevScrollTopRef.current = container.scrollTop || 0;\n prevScrollLeftRef.current = container.scrollLeft || 0;\n needsRenderRef.current = true;\n app.renderer?.render(app.stage);\n } catch (e) {\n console.error('[PivotCanvas] processScroll error', e);\n }\n };\n\n const onScroll = () => {\n // capture latest scroll positions quickly and schedule work\n lastScroll.x = container.scrollLeft;\n lastScroll.y = container.scrollTop;\n if (!pendingRef.scheduled) {\n pendingRef.scheduled = true;\n requestAnimationFrame(processScroll);\n }\n };\n\n container.addEventListener('scroll', onScroll, { passive: true });\n\n return () => {\n container.removeEventListener('scroll', onScroll);\n };\n }, [pixiReady, layout, visibleIds, items, cardWidth, cardHeight, zoomLevel, viewportWidth, viewportHeight, panX, panY, grouping, viewMode, selectedId, onCardClick, onPanStart]);\n\n function createCardSprite(id: ItemId, x: number, y: number): CardSprite {\n return createCardSpriteExternal(\n id, x, y, items as TItem[],\n (item, e, id) => (onCardClickRef.current)(item, e, id),\n (e) => (onPanStartRef.current)(e as unknown as React.MouseEvent),\n cardWidth, cardHeight, cardColorsRef.current\n );\n }\n // Mark these helpers as used (they may be referenced externally or via callbacks)\n void createCardSprite;\n\n function updateCardContent(sprite: CardSprite, item: TItem) {\n return updateCardContentExternal(sprite, item, selectedId, cardWidth, cardHeight, cardColorsRef.current);\n }\n\n function updatePositions(): boolean {\n return updatePositionsExternal(spritesRef.current, isViewTransitionRef, ANIMATION_SPEED);\n }\n\n void updatePositions;\n\n function updateSelection() {\n const sprites = spritesRef.current;\n\n for (const sprite of sprites.values()) {\n const val = (items as TItem[])[Number(sprite.itemId)];\n updateCardContent(sprite, val);\n }\n }\n\n function updateHighlight() {\n updateHighlightExternal(groupsContainerRef.current, parentContainerRef.current, grouping, layout, hoveredGroupIndex, cardWidth, zoomLevel);\n }\n\n void updateHighlight;\n\n // This component renders into the parent `containerRef` (we append Pixi canvas\n // and spacer directly into that DOM node). Return null so we don't replace or\n // reassign the parent's ref which must remain the scrollable viewport element.\n return null;\n}\n"],"names":["updateGroupBackgroundsExternal","createCardSpriteExternal","updateCardContentExternal","startAnimationLoopExternal","updateHighlight","updateCardContent","updateHighlightExternal"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { ZOOM_MIN, ZOOM_STEP, ZOOM_MAX } from '../utils/utils.js';
|
|
|
3
3
|
|
|
4
4
|
function Toolbar({ hasFilters, filtersOpen, filteredCount, viewMode, zoomLevel, activeDimensionKey, dimensions, activeFilterCount, onFiltersToggle, onViewModeChange, onZoomIn, onZoomOut, onZoomSlider, onDimensionChange, filterButtonRef, }) {
|
|
5
5
|
const labelText = 'Sort by';
|
|
6
|
-
return (jsxs("header", { className: "pv-toolbar", children: [jsxs("div", { className: "pv-toolbar-left", children: [hasFilters && (jsxs("button", { ref: filterButtonRef, type: "button", className: `pv-filter-icon-button ${filtersOpen ? 'active' : ''}`, onClick: onFiltersToggle, title: "Filters", children: [jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polygon", { points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" }) }), activeFilterCount > 0 && (jsx("span", { className: "pv-filter-badge", children: activeFilterCount }))] })), jsx("h1", { children: "Pivot Viewer" }), jsxs("span", { className: "pv-count", children: [filteredCount, " events"] })] }), jsxs("div", { className: "pv-toolbar-right", children: [jsxs("div", { className: "pv-zoom-controls", children: [jsx("button", { type: "button", onClick: onZoomOut, disabled: zoomLevel <= ZOOM_MIN, title: "Zoom out", children: "\u2212" }), jsx("input", { type: "range", className: "pv-zoom-slider", min: ZOOM_MIN, max: ZOOM_MAX, step: ZOOM_STEP, value: zoomLevel, onChange: onZoomSlider, title: `Zoom: ${Math.round(zoomLevel * 100)}%` }), jsxs("span", { className: "pv-zoom-level", children: [Math.round(zoomLevel * 100), "%"] }), jsx("button", { type: "button", onClick: onZoomIn, disabled: zoomLevel >= ZOOM_MAX, title: "Zoom in", children: "+" })] }), jsxs("div", { className: "pv-view-toggle", children: [jsx("button", { type: "button", className: viewMode === 'collection' ? 'active' : '', onClick: () => onViewModeChange('collection'), children: "Collection" }), jsx("button", { type: "button", className: viewMode === 'grouped' ? 'active' : '', onClick: () => onViewModeChange('grouped'), children: "
|
|
6
|
+
return (jsxs("header", { className: "pv-toolbar", children: [jsxs("div", { className: "pv-toolbar-left", children: [hasFilters && (jsxs("button", { ref: filterButtonRef, type: "button", className: `pv-filter-icon-button ${filtersOpen ? 'active' : ''}`, onClick: onFiltersToggle, title: "Filters", children: [jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polygon", { points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" }) }), activeFilterCount > 0 && (jsx("span", { className: "pv-filter-badge", children: activeFilterCount }))] })), jsx("h1", { children: "Pivot Viewer" }), jsxs("span", { className: "pv-count", children: [filteredCount, " events"] })] }), jsxs("div", { className: "pv-toolbar-right", children: [jsxs("div", { className: "pv-zoom-controls", children: [jsx("button", { type: "button", onClick: onZoomOut, disabled: zoomLevel <= ZOOM_MIN, title: "Zoom out", children: "\u2212" }), jsx("input", { type: "range", className: "pv-zoom-slider", min: ZOOM_MIN, max: ZOOM_MAX, step: ZOOM_STEP, value: zoomLevel, onChange: onZoomSlider, title: `Zoom: ${Math.round(zoomLevel * 100)}%` }), jsxs("span", { className: "pv-zoom-level", children: [Math.round(zoomLevel * 100), "%"] }), jsx("button", { type: "button", onClick: onZoomIn, disabled: zoomLevel >= ZOOM_MAX, title: "Zoom in", children: "+" })] }), jsxs("div", { className: "pv-view-toggle", children: [jsx("button", { type: "button", className: viewMode === 'collection' ? 'active' : '', onClick: () => onViewModeChange('collection'), children: "Collection" }), jsx("button", { type: "button", className: viewMode === 'grouped' ? 'active' : '', onClick: () => onViewModeChange('grouped'), children: "Grouped" })] }), jsxs("label", { className: "pv-dimension-select", children: [jsx("span", { children: labelText }), jsx("select", { value: activeDimensionKey, onChange: (event) => onDimensionChange(event.target.value), children: dimensions.map((dimension) => (jsx("option", { value: dimension.key, children: dimension.label }, dimension.key))) })] })] })] }));
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export { Toolbar };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.js","sources":["../../../../PivotViewer/components/Toolbar.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 { PivotDimension } from '../types';\nimport { ZOOM_MIN, ZOOM_MAX, ZOOM_STEP } from '../utils/utils';\n\nexport type ViewMode = 'collection' | 'grouped';\n\nexport interface ToolbarProps<TItem extends object> {\n hasFilters: boolean;\n filtersOpen: boolean;\n filteredCount: number;\n viewMode: ViewMode;\n zoomLevel: number;\n activeDimensionKey: string;\n dimensions: PivotDimension<TItem>[];\n activeFilterCount: number;\n onFiltersToggle: () => void;\n onViewModeChange: (mode: ViewMode) => void;\n onZoomIn: () => void;\n onZoomOut: () => void;\n onZoomSlider: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onDimensionChange: (key: string) => void;\n filterButtonRef: React.RefObject<HTMLButtonElement | null>;\n}\n\nexport function Toolbar<TItem extends object>({\n hasFilters,\n filtersOpen,\n filteredCount,\n viewMode,\n zoomLevel,\n activeDimensionKey,\n dimensions,\n activeFilterCount,\n onFiltersToggle,\n onViewModeChange,\n onZoomIn,\n onZoomOut,\n onZoomSlider,\n onDimensionChange,\n filterButtonRef,\n}: ToolbarProps<TItem>) {\n const labelText = 'Sort by';\n\n return (\n <header className=\"pv-toolbar\">\n <div className=\"pv-toolbar-left\">\n {hasFilters && (\n <button\n ref={filterButtonRef}\n type=\"button\"\n className={`pv-filter-icon-button ${filtersOpen ? 'active' : ''}`}\n onClick={onFiltersToggle}\n title=\"Filters\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\" />\n </svg>\n {activeFilterCount > 0 && (\n <span className=\"pv-filter-badge\">{activeFilterCount}</span>\n )}\n </button>\n )}\n <h1>Pivot Viewer</h1>\n <span className=\"pv-count\">{filteredCount} events</span>\n </div>\n <div className=\"pv-toolbar-right\">\n <div className=\"pv-zoom-controls\">\n <button\n type=\"button\"\n onClick={onZoomOut}\n disabled={zoomLevel <= ZOOM_MIN}\n title=\"Zoom out\"\n >\n −\n </button>\n <input\n type=\"range\"\n className=\"pv-zoom-slider\"\n min={ZOOM_MIN}\n max={ZOOM_MAX}\n step={ZOOM_STEP}\n value={zoomLevel}\n onChange={onZoomSlider}\n title={`Zoom: ${Math.round(zoomLevel * 100)}%`}\n />\n <span className=\"pv-zoom-level\">{Math.round(zoomLevel * 100)}%</span>\n <button\n type=\"button\"\n onClick={onZoomIn}\n disabled={zoomLevel >= ZOOM_MAX}\n title=\"Zoom in\"\n >\n +\n </button>\n </div>\n <div className=\"pv-view-toggle\">\n <button\n type=\"button\"\n className={viewMode === 'collection' ? 'active' : ''}\n onClick={() => onViewModeChange('collection')}\n >\n Collection\n </button>\n <button\n type=\"button\"\n className={viewMode === 'grouped' ? 'active' : ''}\n onClick={() => onViewModeChange('grouped')}\n >\n
|
|
1
|
+
{"version":3,"file":"Toolbar.js","sources":["../../../../PivotViewer/components/Toolbar.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 { PivotDimension } from '../types';\nimport { ZOOM_MIN, ZOOM_MAX, ZOOM_STEP } from '../utils/utils';\n\nexport type ViewMode = 'collection' | 'grouped';\n\nexport interface ToolbarProps<TItem extends object> {\n hasFilters: boolean;\n filtersOpen: boolean;\n filteredCount: number;\n viewMode: ViewMode;\n zoomLevel: number;\n activeDimensionKey: string;\n dimensions: PivotDimension<TItem>[];\n activeFilterCount: number;\n onFiltersToggle: () => void;\n onViewModeChange: (mode: ViewMode) => void;\n onZoomIn: () => void;\n onZoomOut: () => void;\n onZoomSlider: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onDimensionChange: (key: string) => void;\n filterButtonRef: React.RefObject<HTMLButtonElement | null>;\n}\n\nexport function Toolbar<TItem extends object>({\n hasFilters,\n filtersOpen,\n filteredCount,\n viewMode,\n zoomLevel,\n activeDimensionKey,\n dimensions,\n activeFilterCount,\n onFiltersToggle,\n onViewModeChange,\n onZoomIn,\n onZoomOut,\n onZoomSlider,\n onDimensionChange,\n filterButtonRef,\n}: ToolbarProps<TItem>) {\n const labelText = 'Sort by';\n\n return (\n <header className=\"pv-toolbar\">\n <div className=\"pv-toolbar-left\">\n {hasFilters && (\n <button\n ref={filterButtonRef}\n type=\"button\"\n className={`pv-filter-icon-button ${filtersOpen ? 'active' : ''}`}\n onClick={onFiltersToggle}\n title=\"Filters\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\" />\n </svg>\n {activeFilterCount > 0 && (\n <span className=\"pv-filter-badge\">{activeFilterCount}</span>\n )}\n </button>\n )}\n <h1>Pivot Viewer</h1>\n <span className=\"pv-count\">{filteredCount} events</span>\n </div>\n <div className=\"pv-toolbar-right\">\n <div className=\"pv-zoom-controls\">\n <button\n type=\"button\"\n onClick={onZoomOut}\n disabled={zoomLevel <= ZOOM_MIN}\n title=\"Zoom out\"\n >\n −\n </button>\n <input\n type=\"range\"\n className=\"pv-zoom-slider\"\n min={ZOOM_MIN}\n max={ZOOM_MAX}\n step={ZOOM_STEP}\n value={zoomLevel}\n onChange={onZoomSlider}\n title={`Zoom: ${Math.round(zoomLevel * 100)}%`}\n />\n <span className=\"pv-zoom-level\">{Math.round(zoomLevel * 100)}%</span>\n <button\n type=\"button\"\n onClick={onZoomIn}\n disabled={zoomLevel >= ZOOM_MAX}\n title=\"Zoom in\"\n >\n +\n </button>\n </div>\n <div className=\"pv-view-toggle\">\n <button\n type=\"button\"\n className={viewMode === 'collection' ? 'active' : ''}\n onClick={() => onViewModeChange('collection')}\n >\n Collection\n </button>\n <button\n type=\"button\"\n className={viewMode === 'grouped' ? 'active' : ''}\n onClick={() => onViewModeChange('grouped')}\n >\n Grouped\n </button>\n </div>\n <label className=\"pv-dimension-select\">\n <span>{labelText}</span>\n <select\n value={activeDimensionKey}\n onChange={(event) => onDimensionChange(event.target.value)}\n >\n {dimensions.map((dimension) => (\n <option key={dimension.key} value={dimension.key}>\n {dimension.label}\n </option>\n ))}\n </select>\n </label>\n </div>\n </header>\n );\n}\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animation.d.ts","sourceRoot":"","sources":["../../../../../PivotViewer/components/pivot/animation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,KAAK,IAAI,MAAM,SAAS,CAAC;AAErC,wBAAgB,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,mBAAmB,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,cAAc,SAAO,WAgElI;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE;IACJ,UAAU,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACjC,MAAM,EAAE;QAAE,OAAO,EAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;KAAE,CAAC;IAC7C,iBAAiB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,cAAc,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,cAAc,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,UAAU,EAAE;QAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;KAAE,CAAC;IAClD,mBAAmB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3C,EACD,cAAc,SAAO,
|
|
1
|
+
{"version":3,"file":"animation.d.ts","sourceRoot":"","sources":["../../../../../PivotViewer/components/pivot/animation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,KAAK,IAAI,MAAM,SAAS,CAAC;AAErC,wBAAgB,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,mBAAmB,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,cAAc,SAAO,WAgElI;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE;IACJ,UAAU,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACjC,MAAM,EAAE;QAAE,OAAO,EAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;KAAE,CAAC;IAC7C,iBAAiB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,cAAc,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,cAAc,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,UAAU,EAAE;QAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;KAAE,CAAC;IAClD,mBAAmB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3C,EACD,cAAc,SAAO,QA4BtB"}
|
|
@@ -69,10 +69,11 @@ function startAnimationLoop(refs, animationSpeed = 0.15) {
|
|
|
69
69
|
isAnimatingRef.current = false;
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
animate();
|
|
72
|
+
if (animationFrameRef.current) {
|
|
73
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
75
74
|
}
|
|
75
|
+
isAnimatingRef.current = true;
|
|
76
|
+
animate();
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
export { startAnimationLoop, updatePositions };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animation.js","sources":["../../../../../PivotViewer/components/pivot/animation.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport type { CardSprite } from './constants';\nimport type * as PIXI from 'pixi.js';\n\nexport function updatePositions(sprites: Map<unknown, CardSprite>, isViewTransitionRef: { current: boolean }, animationSpeed = 0.15) {\n let isAnimating = false;\n const threshold = 0.5;\n const shouldAnimate = isViewTransitionRef.current;\n const now = Date.now();\n const DURATION = 600; // ms\n\n for (const sprite of sprites.values()) {\n // Handle explicit time-based animation (view transitions)\n if (sprite.animationStartTime !== undefined) {\n const elapsed = now - sprite.animationStartTime;\n const delay = sprite.animationDelay || 0;\n\n if (elapsed < delay) {\n isAnimating = true;\n continue;\n }\n\n const progress = Math.min(1, (elapsed - delay) / DURATION);\n // Ease out cubic: 1 - (1-t)^3\n const t = 1 - Math.pow(1 - progress, 3);\n\n if (sprite.startX !== undefined && sprite.startY !== undefined) {\n sprite.currentX = sprite.startX + (sprite.targetX - sprite.startX) * t;\n sprite.currentY = sprite.startY + (sprite.targetY - sprite.startY) * t;\n }\n\n sprite.container.position.set(sprite.currentX, sprite.currentY);\n\n if (progress < 1) {\n isAnimating = true;\n } else {\n // Animation finished, clean up\n sprite.currentX = sprite.targetX;\n sprite.currentY = sprite.targetY;\n delete sprite.animationStartTime;\n delete sprite.animationDelay;\n delete sprite.startX;\n delete sprite.startY;\n }\n continue;\n }\n\n const dx = sprite.targetX - sprite.currentX;\n const dy = sprite.targetY - sprite.currentY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (shouldAnimate && distance > threshold) {\n sprite.currentX += dx * animationSpeed;\n sprite.currentY += dy * animationSpeed;\n sprite.container.position.set(sprite.currentX, sprite.currentY);\n isAnimating = true;\n } else if (distance > 0) {\n sprite.currentX = sprite.targetX;\n sprite.currentY = sprite.targetY;\n sprite.container.position.set(sprite.currentX, sprite.currentY);\n }\n }\n\n if (!isAnimating && isViewTransitionRef.current) {\n isViewTransitionRef.current = false;\n }\n\n return isAnimating;\n}\n\nexport function startAnimationLoop(\n refs: {\n mountedRef: { current: boolean };\n appRef: { current: PIXI.Application | null };\n animationFrameRef: { current: number };\n isAnimatingRef: { current: boolean };\n needsRenderRef: { current: boolean };\n spritesRef: { current: Map<unknown, CardSprite> };\n isViewTransitionRef: { current: boolean };\n },\n animationSpeed = 0.15,\n) {\n const { mountedRef, appRef, animationFrameRef, isAnimatingRef, needsRenderRef, spritesRef, isViewTransitionRef } = refs;\n\n const animate = () => {\n if (!mountedRef.current) return;\n\n const stillAnimating = updatePositions(spritesRef.current, isViewTransitionRef, animationSpeed);\n\n if (stillAnimating || needsRenderRef.current) {\n appRef.current?.renderer.render(appRef.current.stage);\n needsRenderRef.current = false;\n }\n\n if (stillAnimating) {\n animationFrameRef.current = requestAnimationFrame(animate);\n } else {\n isAnimatingRef.current = false;\n }\n };\n\n if (
|
|
1
|
+
{"version":3,"file":"animation.js","sources":["../../../../../PivotViewer/components/pivot/animation.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport type { CardSprite } from './constants';\nimport type * as PIXI from 'pixi.js';\n\nexport function updatePositions(sprites: Map<unknown, CardSprite>, isViewTransitionRef: { current: boolean }, animationSpeed = 0.15) {\n let isAnimating = false;\n const threshold = 0.5;\n const shouldAnimate = isViewTransitionRef.current;\n const now = Date.now();\n const DURATION = 600; // ms\n\n for (const sprite of sprites.values()) {\n // Handle explicit time-based animation (view transitions)\n if (sprite.animationStartTime !== undefined) {\n const elapsed = now - sprite.animationStartTime;\n const delay = sprite.animationDelay || 0;\n\n if (elapsed < delay) {\n isAnimating = true;\n continue;\n }\n\n const progress = Math.min(1, (elapsed - delay) / DURATION);\n // Ease out cubic: 1 - (1-t)^3\n const t = 1 - Math.pow(1 - progress, 3);\n\n if (sprite.startX !== undefined && sprite.startY !== undefined) {\n sprite.currentX = sprite.startX + (sprite.targetX - sprite.startX) * t;\n sprite.currentY = sprite.startY + (sprite.targetY - sprite.startY) * t;\n }\n\n sprite.container.position.set(sprite.currentX, sprite.currentY);\n\n if (progress < 1) {\n isAnimating = true;\n } else {\n // Animation finished, clean up\n sprite.currentX = sprite.targetX;\n sprite.currentY = sprite.targetY;\n delete sprite.animationStartTime;\n delete sprite.animationDelay;\n delete sprite.startX;\n delete sprite.startY;\n }\n continue;\n }\n\n const dx = sprite.targetX - sprite.currentX;\n const dy = sprite.targetY - sprite.currentY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (shouldAnimate && distance > threshold) {\n sprite.currentX += dx * animationSpeed;\n sprite.currentY += dy * animationSpeed;\n sprite.container.position.set(sprite.currentX, sprite.currentY);\n isAnimating = true;\n } else if (distance > 0) {\n sprite.currentX = sprite.targetX;\n sprite.currentY = sprite.targetY;\n sprite.container.position.set(sprite.currentX, sprite.currentY);\n }\n }\n\n if (!isAnimating && isViewTransitionRef.current) {\n isViewTransitionRef.current = false;\n }\n\n return isAnimating;\n}\n\nexport function startAnimationLoop(\n refs: {\n mountedRef: { current: boolean };\n appRef: { current: PIXI.Application | null };\n animationFrameRef: { current: number };\n isAnimatingRef: { current: boolean };\n needsRenderRef: { current: boolean };\n spritesRef: { current: Map<unknown, CardSprite> };\n isViewTransitionRef: { current: boolean };\n },\n animationSpeed = 0.15,\n) {\n const { mountedRef, appRef, animationFrameRef, isAnimatingRef, needsRenderRef, spritesRef, isViewTransitionRef } = refs;\n\n const animate = () => {\n if (!mountedRef.current) return;\n\n const stillAnimating = updatePositions(spritesRef.current, isViewTransitionRef, animationSpeed);\n\n if (stillAnimating || needsRenderRef.current) {\n appRef.current?.renderer.render(appRef.current.stage);\n needsRenderRef.current = false;\n }\n\n if (stillAnimating) {\n animationFrameRef.current = requestAnimationFrame(animate);\n } else {\n isAnimatingRef.current = false;\n }\n };\n\n // Always restart animation when called to ensure animations continue\n // Cancel any existing animation frame and start fresh\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n isAnimatingRef.current = true;\n animate();\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as PIXI from 'pixi.js';
|
|
2
|
+
import type { CardColors } from './constants';
|
|
3
|
+
import type { GroupingResult, LayoutResult } from '../../engine/types';
|
|
4
|
+
export declare function updateGroupBackgrounds(groupsContainer: PIXI.Container | null, container: HTMLDivElement | null, grouping: GroupingResult, layout: LayoutResult, zoomLevel: number, cardColors: CardColors, viewMode: string): void;
|
|
5
|
+
export declare function updateHighlight(groupsContainer: PIXI.Container | null, container: HTMLDivElement | null, grouping: GroupingResult, layout: LayoutResult, hoveredGroupIndex: number | null, cardWidth: number, zoomLevel: number): void;
|
|
6
|
+
//# sourceMappingURL=groups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../../../../PivotViewer/components/pivot/groups.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvE,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,EACtC,SAAS,EAAE,cAAc,GAAG,IAAI,EAChC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,QA2FjB;AAED,wBAAgB,eAAe,CAC7B,eAAe,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,EACtC,SAAS,EAAE,cAAc,GAAG,IAAI,EAChC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,YAAY,EACpB,iBAAiB,EAAE,MAAM,GAAG,IAAI,EAChC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,QA0ElB"}
|