@cratis/components 0.1.13 → 0.1.14
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.js +57 -378
- package/dist/cjs/PivotViewer/PivotViewer.js.map +1 -1
- package/dist/cjs/PivotViewer/hooks/useAnimationModeTracking.js +37 -0
- package/dist/cjs/PivotViewer/hooks/useAnimationModeTracking.js.map +1 -0
- package/dist/cjs/PivotViewer/hooks/useCardSelection.js +64 -0
- package/dist/cjs/PivotViewer/hooks/useCardSelection.js.map +1 -0
- package/dist/cjs/PivotViewer/hooks/useCurrentFilters.js +52 -0
- package/dist/cjs/PivotViewer/hooks/useCurrentFilters.js.map +1 -0
- package/dist/cjs/PivotViewer/hooks/useDetailPanelClose.js +63 -0
- package/dist/cjs/PivotViewer/hooks/useDetailPanelClose.js.map +1 -0
- package/dist/cjs/PivotViewer/hooks/useFieldExtractors.js +50 -0
- package/dist/cjs/PivotViewer/hooks/useFieldExtractors.js.map +1 -0
- package/dist/cjs/PivotViewer/hooks/useScrollSync.js +21 -0
- package/dist/cjs/PivotViewer/hooks/useScrollSync.js.map +1 -0
- package/dist/cjs/PivotViewer/hooks/useViewModeScrollHandling.js +42 -0
- package/dist/cjs/PivotViewer/hooks/useViewModeScrollHandling.js.map +1 -0
- package/dist/cjs/PivotViewer/utils/cardPosition.js +67 -0
- package/dist/cjs/PivotViewer/utils/cardPosition.js.map +1 -0
- package/dist/cjs/PivotViewer/utils/constants.js +4 -0
- package/dist/cjs/PivotViewer/utils/constants.js.map +1 -1
- package/dist/cjs/PivotViewer/utils/idResolution.js +34 -0
- package/dist/cjs/PivotViewer/utils/idResolution.js.map +1 -0
- package/dist/esm/PivotViewer/PivotViewer.d.ts.map +1 -1
- package/dist/esm/PivotViewer/PivotViewer.js +57 -378
- package/dist/esm/PivotViewer/PivotViewer.js.map +1 -1
- package/dist/esm/PivotViewer/hooks/index.d.ts +7 -0
- package/dist/esm/PivotViewer/hooks/index.d.ts.map +1 -1
- package/dist/esm/PivotViewer/hooks/index.js +7 -0
- package/dist/esm/PivotViewer/hooks/index.js.map +1 -1
- package/dist/esm/PivotViewer/hooks/useAnimationModeTracking.d.ts +2 -0
- package/dist/esm/PivotViewer/hooks/useAnimationModeTracking.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useAnimationModeTracking.js +35 -0
- package/dist/esm/PivotViewer/hooks/useAnimationModeTracking.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useCardSelection.d.ts +37 -0
- package/dist/esm/PivotViewer/hooks/useCardSelection.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useCardSelection.js +62 -0
- package/dist/esm/PivotViewer/hooks/useCardSelection.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useCurrentFilters.d.ts +5 -0
- package/dist/esm/PivotViewer/hooks/useCurrentFilters.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useCurrentFilters.js +49 -0
- package/dist/esm/PivotViewer/hooks/useCurrentFilters.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useDetailPanelClose.d.ts +27 -0
- package/dist/esm/PivotViewer/hooks/useDetailPanelClose.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useDetailPanelClose.js +61 -0
- package/dist/esm/PivotViewer/hooks/useDetailPanelClose.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useFieldExtractors.d.ts +7 -0
- package/dist/esm/PivotViewer/hooks/useFieldExtractors.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useFieldExtractors.js +48 -0
- package/dist/esm/PivotViewer/hooks/useFieldExtractors.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useScrollSync.d.ts +3 -0
- package/dist/esm/PivotViewer/hooks/useScrollSync.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useScrollSync.js +19 -0
- package/dist/esm/PivotViewer/hooks/useScrollSync.js.map +1 -0
- package/dist/esm/PivotViewer/hooks/useViewModeScrollHandling.d.ts +16 -0
- package/dist/esm/PivotViewer/hooks/useViewModeScrollHandling.d.ts.map +1 -0
- package/dist/esm/PivotViewer/hooks/useViewModeScrollHandling.js +40 -0
- package/dist/esm/PivotViewer/hooks/useViewModeScrollHandling.js.map +1 -0
- package/dist/esm/PivotViewer/utils/cardPosition.d.ts +18 -0
- package/dist/esm/PivotViewer/utils/cardPosition.d.ts.map +1 -0
- package/dist/esm/PivotViewer/utils/cardPosition.js +63 -0
- package/dist/esm/PivotViewer/utils/cardPosition.js.map +1 -0
- package/dist/esm/PivotViewer/utils/constants.js +3 -1
- package/dist/esm/PivotViewer/utils/constants.js.map +1 -1
- package/dist/esm/PivotViewer/utils/idResolution.d.ts +13 -0
- package/dist/esm/PivotViewer/utils/idResolution.d.ts.map +1 -0
- package/dist/esm/PivotViewer/utils/idResolution.js +31 -0
- package/dist/esm/PivotViewer/utils/idResolution.js.map +1 -0
- package/dist/esm/PivotViewer/utils/index.d.ts +2 -0
- package/dist/esm/PivotViewer/utils/index.d.ts.map +1 -1
- package/dist/esm/PivotViewer/utils/index.js +2 -0
- package/dist/esm/PivotViewer/utils/index.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var layout = require('../engine/layout.js');
|
|
4
|
+
var constants = require('../constants.js');
|
|
5
|
+
|
|
6
|
+
function getCardPositionAtZoom(zoom, itemId, grouping, viewMode, containerWidth, containerHeight) {
|
|
7
|
+
const scaledContainerWidth = containerWidth / zoom;
|
|
8
|
+
const scaledContainerHeight = viewMode === 'collection'
|
|
9
|
+
? containerHeight / zoom
|
|
10
|
+
: containerHeight;
|
|
11
|
+
const layout$1 = layout.computeLayout(grouping, {
|
|
12
|
+
viewMode,
|
|
13
|
+
cardWidth: constants.BASE_CARD_WIDTH,
|
|
14
|
+
cardHeight: constants.BASE_CARD_HEIGHT,
|
|
15
|
+
cardsPerColumn: constants.CARDS_PER_COLUMN,
|
|
16
|
+
groupSpacing: constants.GROUP_SPACING,
|
|
17
|
+
containerWidth: scaledContainerWidth,
|
|
18
|
+
containerHeight: scaledContainerHeight,
|
|
19
|
+
});
|
|
20
|
+
const position = layout$1.positions.get(itemId);
|
|
21
|
+
if (!position) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
x: position.x,
|
|
26
|
+
y: position.y,
|
|
27
|
+
width: constants.BASE_CARD_WIDTH,
|
|
28
|
+
height: constants.BASE_CARD_HEIGHT,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function getLayoutSizeAtZoom(zoom, grouping, viewMode, containerWidth, containerHeight) {
|
|
32
|
+
if (viewMode === 'collection') {
|
|
33
|
+
const layout$1 = layout.computeLayout(grouping, {
|
|
34
|
+
viewMode,
|
|
35
|
+
cardWidth: constants.BASE_CARD_WIDTH,
|
|
36
|
+
cardHeight: constants.BASE_CARD_HEIGHT,
|
|
37
|
+
cardsPerColumn: constants.CARDS_PER_COLUMN,
|
|
38
|
+
groupSpacing: constants.GROUP_SPACING,
|
|
39
|
+
containerWidth,
|
|
40
|
+
containerHeight,
|
|
41
|
+
});
|
|
42
|
+
return { width: layout$1.totalWidth, height: layout$1.totalHeight };
|
|
43
|
+
}
|
|
44
|
+
const scaledContainerWidth = containerWidth / zoom;
|
|
45
|
+
const scaledContainerHeight = containerHeight;
|
|
46
|
+
const layout$1 = layout.computeLayout(grouping, {
|
|
47
|
+
viewMode,
|
|
48
|
+
cardWidth: constants.BASE_CARD_WIDTH,
|
|
49
|
+
cardHeight: constants.BASE_CARD_HEIGHT,
|
|
50
|
+
cardsPerColumn: constants.CARDS_PER_COLUMN,
|
|
51
|
+
groupSpacing: constants.GROUP_SPACING,
|
|
52
|
+
containerWidth: scaledContainerWidth,
|
|
53
|
+
containerHeight: scaledContainerHeight,
|
|
54
|
+
});
|
|
55
|
+
return { width: layout$1.totalWidth, height: layout$1.totalHeight };
|
|
56
|
+
}
|
|
57
|
+
function createCardPositionCallbacks(itemId, grouping, viewMode, containerWidth, containerHeight) {
|
|
58
|
+
return {
|
|
59
|
+
getCardPositionAtZoom: (zoom) => getCardPositionAtZoom(zoom, itemId, grouping, viewMode, containerWidth, containerHeight),
|
|
60
|
+
getLayoutSizeAtZoom: (zoom) => getLayoutSizeAtZoom(zoom, grouping, viewMode, containerWidth, containerHeight),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
exports.createCardPositionCallbacks = createCardPositionCallbacks;
|
|
65
|
+
exports.getCardPositionAtZoom = getCardPositionAtZoom;
|
|
66
|
+
exports.getLayoutSizeAtZoom = getLayoutSizeAtZoom;
|
|
67
|
+
//# sourceMappingURL=cardPosition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cardPosition.js","sources":["../../../../PivotViewer/utils/cardPosition.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 { GroupingResult } from '../engine/types';\nimport { computeLayout } from '../engine/layout';\nimport {\n BASE_CARD_WIDTH,\n BASE_CARD_HEIGHT,\n CARDS_PER_COLUMN,\n GROUP_SPACING,\n} from '../constants';\nimport type { ViewMode } from '../components/Toolbar';\nimport type { LayoutResult } from '../engine/types';\nimport type { CardPosition } from './idResolution';\n\nexport type Layout = LayoutResult;\n\n/**\n * Computes the card position at a specific zoom level\n */\nexport function getCardPositionAtZoom(\n zoom: number,\n itemId: string | number,\n grouping: GroupingResult,\n viewMode: ViewMode,\n containerWidth: number,\n containerHeight: number,\n): CardPosition | null {\n const scaledContainerWidth = containerWidth / zoom;\n const scaledContainerHeight = viewMode === 'collection'\n ? containerHeight / zoom\n : containerHeight;\n\n const layout = computeLayout(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n grouping as unknown as any, {\n viewMode,\n cardWidth: BASE_CARD_WIDTH,\n cardHeight: BASE_CARD_HEIGHT,\n cardsPerColumn: CARDS_PER_COLUMN,\n groupSpacing: GROUP_SPACING,\n containerWidth: scaledContainerWidth,\n containerHeight: scaledContainerHeight,\n });\n\n const position = layout.positions.get(itemId);\n if (!position) {\n return null;\n }\n\n return {\n x: position.x,\n y: position.y,\n width: BASE_CARD_WIDTH,\n height: BASE_CARD_HEIGHT,\n };\n}\n\n/**\n * Computes layout size at a specific zoom level\n */\nexport function getLayoutSizeAtZoom(\n zoom: number,\n grouping: GroupingResult,\n viewMode: ViewMode,\n containerWidth: number,\n containerHeight: number,\n): { width: number; height: number } {\n if (viewMode === 'collection') {\n const layout = computeLayout(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n grouping as unknown as any, {\n viewMode,\n cardWidth: BASE_CARD_WIDTH,\n cardHeight: BASE_CARD_HEIGHT,\n cardsPerColumn: CARDS_PER_COLUMN,\n groupSpacing: GROUP_SPACING,\n containerWidth,\n containerHeight,\n });\n return { width: layout.totalWidth, height: layout.totalHeight };\n }\n\n const scaledContainerWidth = containerWidth / zoom;\n const scaledContainerHeight = containerHeight;\n\n const layout = computeLayout(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n grouping as unknown as any, {\n viewMode,\n cardWidth: BASE_CARD_WIDTH,\n cardHeight: BASE_CARD_HEIGHT,\n cardsPerColumn: CARDS_PER_COLUMN,\n groupSpacing: GROUP_SPACING,\n containerWidth: scaledContainerWidth,\n containerHeight: scaledContainerHeight,\n });\n\n return { width: layout.totalWidth, height: layout.totalHeight };\n}\n\n/**\n * Creates callback functions for card position calculations at various zoom levels\n * Used for smooth animations during zoom and pan operations\n */\nexport function createCardPositionCallbacks(\n itemId: string | number,\n grouping: GroupingResult,\n viewMode: ViewMode,\n containerWidth: number,\n containerHeight: number,\n) {\n return {\n getCardPositionAtZoom: (zoom: number) =>\n getCardPositionAtZoom(zoom, itemId, grouping, viewMode, containerWidth, containerHeight),\n \n getLayoutSizeAtZoom: (zoom: number) =>\n getLayoutSizeAtZoom(zoom, grouping, viewMode, containerWidth, containerHeight),\n };\n}\n"],"names":["layout","computeLayout","BASE_CARD_WIDTH","BASE_CARD_HEIGHT","CARDS_PER_COLUMN","GROUP_SPACING"],"mappings":";;;;;AAoBM,SAAU,qBAAqB,CACjC,IAAY,EACZ,MAAuB,EACvB,QAAwB,EACxB,QAAkB,EAClB,cAAsB,EACtB,eAAuB,EAAA;AAEvB,IAAA,MAAM,oBAAoB,GAAG,cAAc,GAAG,IAAI;AAClD,IAAA,MAAM,qBAAqB,GAAG,QAAQ,KAAK;UACrC,eAAe,GAAG;UAClB,eAAe;AAErB,IAAA,MAAMA,QAAM,GAAGC,oBAAa,CAExB,QAA0B,EAAE;QAC5B,QAAQ;AACR,QAAA,SAAS,EAAEC,yBAAe;AAC1B,QAAA,UAAU,EAAEC,0BAAgB;AAC5B,QAAA,cAAc,EAAEC,0BAAgB;AAChC,QAAA,YAAY,EAAEC,uBAAa;AAC3B,QAAA,cAAc,EAAE,oBAAoB;AACpC,QAAA,eAAe,EAAE,qBAAqB;AACzC,KAAA,CAAC;IAEF,MAAM,QAAQ,GAAGL,QAAM,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE;AACX,QAAA,OAAO,IAAI;IACf;IAEA,OAAO;QACH,CAAC,EAAE,QAAQ,CAAC,CAAC;QACb,CAAC,EAAE,QAAQ,CAAC,CAAC;AACb,QAAA,KAAK,EAAEE,yBAAe;AACtB,QAAA,MAAM,EAAEC,0BAAgB;KAC3B;AACL;AAKM,SAAU,mBAAmB,CAC/B,IAAY,EACZ,QAAwB,EACxB,QAAkB,EAClB,cAAsB,EACtB,eAAuB,EAAA;AAEvB,IAAA,IAAI,QAAQ,KAAK,YAAY,EAAE;AAC3B,QAAA,MAAMH,QAAM,GAAGC,oBAAa,CAExB,QAA0B,EAAE;YAC5B,QAAQ;AACR,YAAA,SAAS,EAAEC,yBAAe;AAC1B,YAAA,UAAU,EAAEC,0BAAgB;AAC5B,YAAA,cAAc,EAAEC,0BAAgB;AAChC,YAAA,YAAY,EAAEC,uBAAa;YAC3B,cAAc;YACd,eAAe;AAClB,SAAA,CAAC;AACF,QAAA,OAAO,EAAE,KAAK,EAAEL,QAAM,CAAC,UAAU,EAAE,MAAM,EAAEA,QAAM,CAAC,WAAW,EAAE;IACnE;AAEA,IAAA,MAAM,oBAAoB,GAAG,cAAc,GAAG,IAAI;IAClD,MAAM,qBAAqB,GAAG,eAAe;AAE7C,IAAA,MAAMA,QAAM,GAAGC,oBAAa,CAExB,QAA0B,EAAE;QAC5B,QAAQ;AACR,QAAA,SAAS,EAAEC,yBAAe;AAC1B,QAAA,UAAU,EAAEC,0BAAgB;AAC5B,QAAA,cAAc,EAAEC,0BAAgB;AAChC,QAAA,YAAY,EAAEC,uBAAa;AAC3B,QAAA,cAAc,EAAE,oBAAoB;AACpC,QAAA,eAAe,EAAE,qBAAqB;AACzC,KAAA,CAAC;AAEF,IAAA,OAAO,EAAE,KAAK,EAAEL,QAAM,CAAC,UAAU,EAAE,MAAM,EAAEA,QAAM,CAAC,WAAW,EAAE;AACnE;AAMM,SAAU,2BAA2B,CACvC,MAAuB,EACvB,QAAwB,EACxB,QAAkB,EAClB,cAAsB,EACtB,eAAuB,EAAA;IAEvB,OAAO;AACH,QAAA,qBAAqB,EAAE,CAAC,IAAY,KAChC,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,CAAC;AAE5F,QAAA,mBAAmB,EAAE,CAAC,IAAY,KAC9B,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,CAAC;KACrF;AACL;;;;;;"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const ZOOM_MAX = 3;
|
|
4
|
+
const BASE_CARD_WIDTH = 180;
|
|
5
|
+
const BASE_CARD_HEIGHT = 140;
|
|
4
6
|
const DETAIL_PANEL_WIDTH = 380;
|
|
5
7
|
const ZOOM_MULTIPLIER = 1.15;
|
|
6
8
|
const MIN_ZOOM_ON_SELECT = 1.2;
|
|
7
9
|
|
|
10
|
+
exports.BASE_CARD_HEIGHT = BASE_CARD_HEIGHT;
|
|
11
|
+
exports.BASE_CARD_WIDTH = BASE_CARD_WIDTH;
|
|
8
12
|
exports.DETAIL_PANEL_WIDTH = DETAIL_PANEL_WIDTH;
|
|
9
13
|
exports.MIN_ZOOM_ON_SELECT = MIN_ZOOM_ON_SELECT;
|
|
10
14
|
exports.ZOOM_MAX = ZOOM_MAX;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sources":["../../../../PivotViewer/utils/constants.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n// Zoom constants\nexport const ZOOM_MIN = 0.1;\nexport const ZOOM_MAX = 3;\nexport const ZOOM_STEP = 0.05;\n\n// Layout constants\nexport const GROUP_SPACING = 40;\nexport const CARD_GAP = 8;\nexport const CARDS_PER_COLUMN = 5;\nexport const BASE_CARD_WIDTH = 180;\nexport const BASE_CARD_HEIGHT = 140;\nexport const DETAIL_PANEL_WIDTH = 380;\n\n// Animation constants\nexport const ZOOM_ANIMATION_DURATION = 300;\nexport const ZOOM_MULTIPLIER = 1.15;\nexport const MIN_ZOOM_ON_SELECT = 1.2;\n"],"names":[],"mappings":";;AAKO,MAAM,QAAQ,GAAG;
|
|
1
|
+
{"version":3,"file":"constants.js","sources":["../../../../PivotViewer/utils/constants.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n// Zoom constants\nexport const ZOOM_MIN = 0.1;\nexport const ZOOM_MAX = 3;\nexport const ZOOM_STEP = 0.05;\n\n// Layout constants\nexport const GROUP_SPACING = 40;\nexport const CARD_GAP = 8;\nexport const CARDS_PER_COLUMN = 5;\nexport const BASE_CARD_WIDTH = 180;\nexport const BASE_CARD_HEIGHT = 140;\nexport const DETAIL_PANEL_WIDTH = 380;\n\n// Animation constants\nexport const ZOOM_ANIMATION_DURATION = 300;\nexport const ZOOM_MULTIPLIER = 1.15;\nexport const MIN_ZOOM_ON_SELECT = 1.2;\n"],"names":[],"mappings":";;AAKO,MAAM,QAAQ,GAAG;AAOjB,MAAM,eAAe,GAAG;AACxB,MAAM,gBAAgB,GAAG;AACzB,MAAM,kBAAkB,GAAG;AAI3B,MAAM,eAAe,GAAG;AACxB,MAAM,kBAAkB,GAAG;;;;;;;;;"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function normalizeIdToLayoutKey(itemId, layout) {
|
|
4
|
+
if (layout.positions.has(itemId)) {
|
|
5
|
+
return itemId;
|
|
6
|
+
}
|
|
7
|
+
if (typeof itemId === 'number' && layout.positions.has(String(itemId))) {
|
|
8
|
+
return String(itemId);
|
|
9
|
+
}
|
|
10
|
+
if (typeof itemId === 'string') {
|
|
11
|
+
const numId = Number(itemId);
|
|
12
|
+
if (!isNaN(numId) && layout.positions.has(numId)) {
|
|
13
|
+
return numId;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return itemId;
|
|
17
|
+
}
|
|
18
|
+
function getCardPositionFromLayout(itemId, layout, cardWidth, cardHeight) {
|
|
19
|
+
const normalizedId = normalizeIdToLayoutKey(itemId, layout);
|
|
20
|
+
const position = layout.positions.get(normalizedId);
|
|
21
|
+
if (!position) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
x: position.x,
|
|
26
|
+
y: position.y,
|
|
27
|
+
width: cardWidth,
|
|
28
|
+
height: cardHeight,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
exports.getCardPositionFromLayout = getCardPositionFromLayout;
|
|
33
|
+
exports.normalizeIdToLayoutKey = normalizeIdToLayoutKey;
|
|
34
|
+
//# sourceMappingURL=idResolution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idResolution.js","sources":["../../../../PivotViewer/utils/idResolution.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 { LayoutResult } from '../engine/types';\n\ntype Layout = LayoutResult;\n\nexport interface CardPosition {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Resolves the ID for an item, handling type conversions and consistency with layout keys\n */\nexport function resolveItemId<TItem extends object>(\n item: TItem,\n index: number,\n getItemId?: (item: TItem, index: number) => string | number,\n): string | number {\n if (getItemId) {\n const id = getItemId(item, index);\n return typeof id === 'number' ? id : id;\n }\n const id = (item as Record<string, unknown>)['id'];\n return typeof id === 'number' ? id : index;\n}\n\n/**\n * Ensures the item ID matches the layout's key type (number vs string)\n * by attempting type conversion if needed\n */\nexport function normalizeIdToLayoutKey(\n itemId: string | number,\n layout: Layout,\n): string | number {\n // If already in layout, return as-is\n if (layout.positions.has(itemId)) {\n return itemId;\n }\n\n // Try converting number to string\n if (typeof itemId === 'number' && layout.positions.has(String(itemId))) {\n return String(itemId);\n }\n\n // Try converting string to number\n if (typeof itemId === 'string') {\n const numId = Number(itemId);\n if (!isNaN(numId) && layout.positions.has(numId)) {\n return numId;\n }\n }\n\n // Return original if no match found (will likely result in null position)\n return itemId;\n}\n\n/**\n * Gets the card position from the layout, handling ID type mismatches\n */\nexport function getCardPositionFromLayout(\n itemId: string | number,\n layout: Layout,\n cardWidth: number,\n cardHeight: number,\n): CardPosition | null {\n const normalizedId = normalizeIdToLayoutKey(itemId, layout);\n const position = layout.positions.get(normalizedId);\n\n if (!position) {\n return null;\n }\n\n return {\n x: position.x,\n y: position.y,\n width: cardWidth,\n height: cardHeight,\n };\n}\n"],"names":[],"mappings":";;AAkCM,SAAU,sBAAsB,CAClC,MAAuB,EACvB,MAAc,EAAA;IAGd,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;AAC9B,QAAA,OAAO,MAAM;IACjB;AAGA,IAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE;AACpE,QAAA,OAAO,MAAM,CAAC,MAAM,CAAC;IACzB;AAGA,IAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC5B,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;AAC5B,QAAA,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;AAC9C,YAAA,OAAO,KAAK;QAChB;IACJ;AAGA,IAAA,OAAO,MAAM;AACjB;AAKM,SAAU,yBAAyB,CACrC,MAAuB,EACvB,MAAc,EACd,SAAiB,EACjB,UAAkB,EAAA;IAElB,MAAM,YAAY,GAAG,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC;IAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC;IAEnD,IAAI,CAAC,QAAQ,EAAE;AACX,QAAA,OAAO,IAAI;IACf;IAEA,OAAO;QACH,CAAC,EAAE,QAAQ,CAAC,CAAC;QACb,CAAC,EAAE,QAAQ,CAAC,CAAC;AACb,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,MAAM,EAAE,UAAU;KACrB;AACL;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PivotViewer.d.ts","sourceRoot":"","sources":["../../../PivotViewer/PivotViewer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"PivotViewer.d.ts","sourceRoot":"","sources":["../../../PivotViewer/PivotViewer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAQhD,OAAO,mBAAmB,CAAC;AAe3B,wBAAgB,WAAW,CAAC,KAAK,SAAS,MAAM,EAAE,EAC9C,IAAI,EACJ,UAAU,EACV,OAAO,EACP,mBAAmB,EACnB,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,SAAiB,GACpB,EAAE,gBAAgB,CAAC,KAAK,CAAC,2CA6VzB"}
|
|
@@ -5,10 +5,7 @@ import { computeLayout } from './engine/layout.js';
|
|
|
5
5
|
import { useFilterState } from './hooks/useFilterState.js';
|
|
6
6
|
import { useDimensionState } from './hooks/useDimensionState.js';
|
|
7
7
|
import { useZoomState } from './hooks/useZoomState.js';
|
|
8
|
-
import { handleCardSelection } from './utils/selection.js';
|
|
9
|
-
import { calculateCenterScrollPosition, smoothScrollTo, animateZoomAndScroll } from './utils/animations.js';
|
|
10
8
|
import { BASE_CARD_HEIGHT, BASE_CARD_WIDTH, GROUP_SPACING, CARDS_PER_COLUMN } from './constants.js';
|
|
11
|
-
import { DETAIL_PANEL_WIDTH, ZOOM_MAX, MIN_ZOOM_ON_SELECT, ZOOM_MULTIPLIER } from './utils/constants.js';
|
|
12
9
|
import './PivotViewer.css';
|
|
13
10
|
import { PivotViewerMain } from './components/PivotViewerMain.js';
|
|
14
11
|
import { FilterPanelContainer } from './components/FilterPanelContainer.js';
|
|
@@ -17,6 +14,13 @@ import { useFilterOptions } from './hooks/useFilterOptions.js';
|
|
|
17
14
|
import { usePanning } from './hooks/usePanning.js';
|
|
18
15
|
import { useWheelZoom } from './hooks/useWheelZoom.js';
|
|
19
16
|
import 'react-dom';
|
|
17
|
+
import { useFieldExtractors } from './hooks/useFieldExtractors.js';
|
|
18
|
+
import { useCurrentFilters, useCurrentGroupBy } from './hooks/useCurrentFilters.js';
|
|
19
|
+
import { useCardSelection } from './hooks/useCardSelection.js';
|
|
20
|
+
import { useDetailPanelClose } from './hooks/useDetailPanelClose.js';
|
|
21
|
+
import { useScrollSync } from './hooks/useScrollSync.js';
|
|
22
|
+
import { useAnimationModeTracking } from './hooks/useAnimationModeTracking.js';
|
|
23
|
+
import { useViewModeScrollHandling } from './hooks/useViewModeScrollHandling.js';
|
|
20
24
|
import { useContainerDimensions } from './hooks/useContainerDimensions.js';
|
|
21
25
|
|
|
22
26
|
function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRenderer, getItemId, searchFields, className, emptyContent, isLoading = false, }) {
|
|
@@ -37,12 +41,6 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
|
|
|
37
41
|
const [scrollPosition, setScrollPosition] = useState({ x: 0, y: 0 });
|
|
38
42
|
const { filterState, rangeFilterState, expandedFilterKey, setExpandedFilterKey, handleToggleFilter, handleClearFilter, handleRangeChange, } = useFilterState(filters);
|
|
39
43
|
const { activeDimensionKey, setActiveDimensionKey, activeDimension, dimensionFilter, handleAxisLabelClick, } = useDimensionState(dimensions, defaultDimensionKey);
|
|
40
|
-
const prevFilterStateRef = useRef(filterState);
|
|
41
|
-
const prevRangeFilterStateRef = useRef(rangeFilterState);
|
|
42
|
-
const prevSearchRef = useRef(search);
|
|
43
|
-
const prevDimensionRef = useRef(activeDimensionKey);
|
|
44
|
-
const prevViewModeRef = useRef(viewMode);
|
|
45
|
-
const isFirstRenderRef = useRef(true);
|
|
46
44
|
const { zoomLevel, setZoomLevel, handleZoomIn, handleZoomOut, handleZoomSlider, } = useZoomState(1);
|
|
47
45
|
const { isPanning, handlePanStart, handlePanMove, handlePanEnd, } = usePanning(containerRef, undefined, setScrollPosition);
|
|
48
46
|
useWheelZoom(containerRef, zoomLevel, setZoomLevel);
|
|
@@ -60,125 +58,14 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
|
|
|
60
58
|
container.addEventListener('scroll', handleScroll);
|
|
61
59
|
return () => container.removeEventListener('scroll', handleScroll);
|
|
62
60
|
}, []);
|
|
63
|
-
|
|
64
|
-
if (isFirstRenderRef.current) {
|
|
65
|
-
isFirstRenderRef.current = false;
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
const filterChanged = prevFilterStateRef.current !== filterState;
|
|
69
|
-
const rangeChanged = prevRangeFilterStateRef.current !== rangeFilterState;
|
|
70
|
-
const searchChanged = prevSearchRef.current !== search;
|
|
71
|
-
const dimensionChanged = prevDimensionRef.current !== activeDimensionKey;
|
|
72
|
-
const viewModeChanged = prevViewModeRef.current !== viewMode;
|
|
73
|
-
if (filterChanged || rangeChanged || searchChanged) {
|
|
74
|
-
setAnimationMode('filter');
|
|
75
|
-
}
|
|
76
|
-
else if (dimensionChanged || viewModeChanged) {
|
|
77
|
-
setAnimationMode('layout');
|
|
78
|
-
}
|
|
79
|
-
prevFilterStateRef.current = filterState;
|
|
80
|
-
prevRangeFilterStateRef.current = rangeFilterState;
|
|
81
|
-
prevSearchRef.current = search;
|
|
82
|
-
prevDimensionRef.current = activeDimensionKey;
|
|
83
|
-
prevViewModeRef.current = viewMode;
|
|
84
|
-
}, [filterState, rangeFilterState, search, activeDimensionKey, viewMode]);
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
const container = containerRef.current;
|
|
87
|
-
const axisLabels = axisLabelsRef.current;
|
|
88
|
-
if (!container || !axisLabels || viewMode !== 'grouped')
|
|
89
|
-
return;
|
|
90
|
-
const handleScroll = () => {
|
|
91
|
-
axisLabels.scrollLeft = container.scrollLeft;
|
|
92
|
-
};
|
|
93
|
-
handleScroll();
|
|
94
|
-
container.addEventListener('scroll', handleScroll);
|
|
95
|
-
return () => container.removeEventListener('scroll', handleScroll);
|
|
96
|
-
}, [viewMode]);
|
|
97
|
-
const fieldExtractors = useMemo(() => {
|
|
98
|
-
const extractors = new Map();
|
|
99
|
-
for (const dim of dimensions) {
|
|
100
|
-
extractors.set(dim.key, (item) => {
|
|
101
|
-
const val = dim.getValue(item);
|
|
102
|
-
if (val instanceof Date)
|
|
103
|
-
return val.getTime();
|
|
104
|
-
if (typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean' || val === null) {
|
|
105
|
-
return val;
|
|
106
|
-
}
|
|
107
|
-
return String(val);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
if (filters) {
|
|
111
|
-
for (const filter of filters) {
|
|
112
|
-
extractors.set(filter.key, (item) => {
|
|
113
|
-
const val = filter.getValue(item);
|
|
114
|
-
if (val instanceof Date)
|
|
115
|
-
return val.getTime();
|
|
116
|
-
if (typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean' || val === null) {
|
|
117
|
-
return val;
|
|
118
|
-
}
|
|
119
|
-
return String(val);
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return extractors;
|
|
124
|
-
}, [dimensions, filters]);
|
|
125
|
-
const indexFields = useMemo(() => {
|
|
126
|
-
const fields = new Set();
|
|
127
|
-
for (const dim of dimensions) {
|
|
128
|
-
fields.add(dim.key);
|
|
129
|
-
}
|
|
130
|
-
if (filters) {
|
|
131
|
-
for (const filter of filters) {
|
|
132
|
-
fields.add(filter.key);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return Array.from(fields);
|
|
136
|
-
}, [dimensions, filters]);
|
|
61
|
+
const { fieldExtractors, indexFields } = useFieldExtractors(dimensions, filters);
|
|
137
62
|
const { ready, applyFilters: engineApplyFilters, computeGrouping, sortIds } = usePivotEngine({
|
|
138
63
|
data,
|
|
139
64
|
fieldExtractors,
|
|
140
65
|
indexFields,
|
|
141
66
|
});
|
|
142
|
-
const currentFilters =
|
|
143
|
-
|
|
144
|
-
const searchTerm = search.trim().toLowerCase();
|
|
145
|
-
if (searchTerm && searchFields && searchFields.length > 0) ;
|
|
146
|
-
for (const [key, values] of Object.entries(filterState)) {
|
|
147
|
-
const valueSet = values;
|
|
148
|
-
if (valueSet.size > 0) {
|
|
149
|
-
specs.push({
|
|
150
|
-
field: key,
|
|
151
|
-
type: 'categorical',
|
|
152
|
-
values: valueSet,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
for (const [key, range] of Object.entries(rangeFilterState)) {
|
|
157
|
-
if (range && (range[0] !== null || range[1] !== null)) {
|
|
158
|
-
const min = range[0] ?? -Infinity;
|
|
159
|
-
const max = range[1] ?? Infinity;
|
|
160
|
-
specs.push({
|
|
161
|
-
field: key,
|
|
162
|
-
type: 'numeric',
|
|
163
|
-
range: { min, max },
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (dimensionFilter && activeDimension) {
|
|
168
|
-
specs.push({
|
|
169
|
-
field: activeDimension.key,
|
|
170
|
-
type: 'categorical',
|
|
171
|
-
values: new Set([dimensionFilter]),
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
return specs;
|
|
175
|
-
}, [filterState, rangeFilterState, search, searchFields, dimensionFilter, activeDimension]);
|
|
176
|
-
const currentGroupBy = useMemo(() => {
|
|
177
|
-
return {
|
|
178
|
-
field: activeDimensionKey || dimensions[0]?.key || '',
|
|
179
|
-
buckets: 10,
|
|
180
|
-
};
|
|
181
|
-
}, [activeDimensionKey, dimensions]);
|
|
67
|
+
const currentFilters = useCurrentFilters(filters, filterState, rangeFilterState, search, searchFields, dimensionFilter, activeDimension);
|
|
68
|
+
const currentGroupBy = useCurrentGroupBy(activeDimensionKey, dimensions);
|
|
182
69
|
useEffect(() => {
|
|
183
70
|
if (!ready)
|
|
184
71
|
return;
|
|
@@ -224,7 +111,7 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
|
|
|
224
111
|
const lastRequest = lastGroupingRequest.current;
|
|
225
112
|
if (lastRequest &&
|
|
226
113
|
lastRequest.viewMode === viewMode &&
|
|
227
|
-
lastRequest.groupBy
|
|
114
|
+
lastRequest.groupBy?.field === currentGroupBy.field &&
|
|
228
115
|
lastRequest.visibleIds === visibleIds) {
|
|
229
116
|
console.log('[PivotViewer] Skipping duplicate grouping request');
|
|
230
117
|
return;
|
|
@@ -262,260 +149,52 @@ function PivotViewer({ data, dimensions, filters, defaultDimensionKey, cardRende
|
|
|
262
149
|
const id = item['id'];
|
|
263
150
|
return typeof id === 'number' ? id : index;
|
|
264
151
|
}, [getItemId]);
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
if (isPanning)
|
|
312
|
-
return;
|
|
313
|
-
const container = containerRef.current;
|
|
314
|
-
if (!container)
|
|
315
|
-
return;
|
|
316
|
-
let itemId = (id !== undefined && id !== null) ? id : resolveId(item, 0);
|
|
317
|
-
if (typeof itemId === 'string' && !layout.positions.has(itemId)) {
|
|
318
|
-
const numId = Number(itemId);
|
|
319
|
-
if (!isNaN(numId) && layout.positions.has(numId)) {
|
|
320
|
-
itemId = numId;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
else if (typeof itemId === 'number' && !layout.positions.has(itemId)) {
|
|
324
|
-
const strId = String(itemId);
|
|
325
|
-
if (layout.positions.has(strId)) {
|
|
326
|
-
itemId = strId;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
const selectedId = selectedItem ? (data.indexOf(selectedItem) !== -1 ? data.indexOf(selectedItem) : resolveId(selectedItem, 0)) : null;
|
|
330
|
-
const position = layout.positions.get(itemId);
|
|
331
|
-
const cardPosition = position ? {
|
|
332
|
-
x: position.x,
|
|
333
|
-
y: position.y,
|
|
334
|
-
width: BASE_CARD_WIDTH,
|
|
335
|
-
height: BASE_CARD_HEIGHT
|
|
336
|
-
} : null;
|
|
337
|
-
let targetCardPosition = null;
|
|
338
|
-
let getCardPositionAtZoom = undefined;
|
|
339
|
-
let targetTotalHeight = layout.totalHeight;
|
|
340
|
-
if (viewMode === 'grouped' && cardPosition) {
|
|
341
|
-
const targetZoom = Math.min(ZOOM_MAX, Math.max(MIN_ZOOM_ON_SELECT, zoomLevel * ZOOM_MULTIPLIER));
|
|
342
|
-
const targetContainerWidth = containerDimensions.width / targetZoom;
|
|
343
|
-
const targetContainerHeight = containerDimensions.height;
|
|
344
|
-
const targetLayout = computeLayout(grouping, {
|
|
345
|
-
viewMode,
|
|
346
|
-
cardWidth: BASE_CARD_WIDTH,
|
|
347
|
-
cardHeight: BASE_CARD_HEIGHT,
|
|
348
|
-
cardsPerColumn: CARDS_PER_COLUMN,
|
|
349
|
-
groupSpacing: GROUP_SPACING,
|
|
350
|
-
containerWidth: targetContainerWidth,
|
|
351
|
-
containerHeight: targetContainerHeight,
|
|
352
|
-
});
|
|
353
|
-
targetTotalHeight = targetLayout.totalHeight;
|
|
354
|
-
const targetPos = targetLayout.positions.get(itemId);
|
|
355
|
-
if (targetPos) {
|
|
356
|
-
targetCardPosition = {
|
|
357
|
-
x: targetPos.x,
|
|
358
|
-
y: targetPos.y,
|
|
359
|
-
width: BASE_CARD_WIDTH,
|
|
360
|
-
height: BASE_CARD_HEIGHT
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
getCardPositionAtZoom = (zoom) => {
|
|
364
|
-
const currentContainerWidth = containerDimensions.width / zoom;
|
|
365
|
-
const currentContainerHeight = containerDimensions.height;
|
|
366
|
-
const currentLayout = computeLayout(grouping, {
|
|
367
|
-
viewMode,
|
|
368
|
-
cardWidth: BASE_CARD_WIDTH,
|
|
369
|
-
cardHeight: BASE_CARD_HEIGHT,
|
|
370
|
-
cardsPerColumn: CARDS_PER_COLUMN,
|
|
371
|
-
groupSpacing: GROUP_SPACING,
|
|
372
|
-
containerWidth: currentContainerWidth,
|
|
373
|
-
containerHeight: currentContainerHeight,
|
|
374
|
-
});
|
|
375
|
-
const pos = currentLayout.positions.get(itemId);
|
|
376
|
-
return pos ? { x: pos.x, y: pos.y, width: BASE_CARD_WIDTH, height: BASE_CARD_HEIGHT } : null;
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
const getLayoutSizeAtZoom = (zoom) => {
|
|
380
|
-
if (viewMode === 'collection') {
|
|
381
|
-
return { width: layout.totalWidth, height: layout.totalHeight };
|
|
382
|
-
}
|
|
383
|
-
const currentContainerWidth = containerDimensions.width / zoom;
|
|
384
|
-
const currentContainerHeight = containerDimensions.height;
|
|
385
|
-
const currentLayout = computeLayout(grouping, {
|
|
386
|
-
viewMode,
|
|
387
|
-
cardWidth: BASE_CARD_WIDTH,
|
|
388
|
-
cardHeight: BASE_CARD_HEIGHT,
|
|
389
|
-
cardsPerColumn: CARDS_PER_COLUMN,
|
|
390
|
-
groupSpacing: GROUP_SPACING,
|
|
391
|
-
containerWidth: currentContainerWidth,
|
|
392
|
-
containerHeight: currentContainerHeight,
|
|
393
|
-
});
|
|
394
|
-
return { width: currentLayout.totalWidth, height: currentLayout.totalHeight };
|
|
395
|
-
};
|
|
396
|
-
handleCardSelection({
|
|
397
|
-
item,
|
|
398
|
-
itemId,
|
|
399
|
-
selectedItemId: selectedId,
|
|
400
|
-
container,
|
|
401
|
-
cardPosition,
|
|
402
|
-
targetCardPosition,
|
|
403
|
-
getCardPositionAtZoom,
|
|
404
|
-
getLayoutSizeAtZoom,
|
|
405
|
-
spacer: spacerRef.current,
|
|
406
|
-
preSelectionState,
|
|
407
|
-
startScrollPosition: { x: scrollPosition.x, y: scrollPosition.y },
|
|
408
|
-
setZoomLevel,
|
|
409
|
-
setIsZooming,
|
|
410
|
-
setSelectedItem,
|
|
411
|
-
setPreSelectionState,
|
|
412
|
-
viewMode,
|
|
413
|
-
zoomLevel,
|
|
414
|
-
totalHeight: targetTotalHeight,
|
|
415
|
-
});
|
|
416
|
-
}, [isPanning, selectedItem, zoomLevel, preSelectionState, viewMode, resolveId, setZoomLevel, layout, grouping, containerDimensions, scrollPosition]);
|
|
417
|
-
const closeDetail = useCallback(() => {
|
|
418
|
-
const container = containerRef.current;
|
|
419
|
-
if (!container || !selectedItem) {
|
|
420
|
-
setSelectedItem(null);
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
const index = data.indexOf(selectedItem);
|
|
424
|
-
let itemId = index !== -1 ? index : resolveId(selectedItem, 0);
|
|
425
|
-
if (typeof itemId === 'string' && !layout.positions.has(itemId)) {
|
|
426
|
-
const numId = Number(itemId);
|
|
427
|
-
if (!isNaN(numId) && layout.positions.has(numId)) {
|
|
428
|
-
itemId = numId;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
else if (typeof itemId === 'number' && !layout.positions.has(itemId)) {
|
|
432
|
-
const strId = String(itemId);
|
|
433
|
-
if (layout.positions.has(strId)) {
|
|
434
|
-
itemId = strId;
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
const position = layout.positions.get(itemId);
|
|
438
|
-
const cardPosition = position ? {
|
|
439
|
-
x: position.x,
|
|
440
|
-
y: position.y,
|
|
441
|
-
width: BASE_CARD_WIDTH,
|
|
442
|
-
height: BASE_CARD_HEIGHT
|
|
443
|
-
} : null;
|
|
444
|
-
if (!preSelectionState) {
|
|
445
|
-
setSelectedItem(null);
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
if (viewMode === 'collection') {
|
|
449
|
-
setSelectedItem(null);
|
|
450
|
-
smoothScrollTo(container, preSelectionState.scrollLeft, preSelectionState.scrollTop, true);
|
|
451
|
-
setPreSelectionState(null);
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
const zoomChanged = Math.abs(preSelectionState.zoom - zoomLevel) > 0.001;
|
|
455
|
-
if (!zoomChanged || !cardPosition) {
|
|
456
|
-
setSelectedItem(null);
|
|
457
|
-
smoothScrollTo(container, preSelectionState.scrollLeft, preSelectionState.scrollTop, true);
|
|
458
|
-
setPreSelectionState(null);
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
let targetCardPosition = null;
|
|
462
|
-
let getCardPositionAtZoom = undefined;
|
|
463
|
-
if (viewMode === 'grouped') {
|
|
464
|
-
const targetZoom = preSelectionState.zoom;
|
|
465
|
-
const targetContainerWidth = containerDimensions.width / targetZoom;
|
|
466
|
-
const targetContainerHeight = containerDimensions.height;
|
|
467
|
-
const targetLayout = computeLayout(grouping, {
|
|
468
|
-
viewMode,
|
|
469
|
-
cardWidth: BASE_CARD_WIDTH,
|
|
470
|
-
cardHeight: BASE_CARD_HEIGHT,
|
|
471
|
-
cardsPerColumn: CARDS_PER_COLUMN,
|
|
472
|
-
groupSpacing: GROUP_SPACING,
|
|
473
|
-
containerWidth: targetContainerWidth,
|
|
474
|
-
containerHeight: targetContainerHeight,
|
|
475
|
-
});
|
|
476
|
-
const targetPos = targetLayout.positions.get(itemId);
|
|
477
|
-
if (targetPos) {
|
|
478
|
-
targetCardPosition = {
|
|
479
|
-
x: targetPos.x,
|
|
480
|
-
y: targetPos.y,
|
|
481
|
-
width: BASE_CARD_WIDTH,
|
|
482
|
-
height: BASE_CARD_HEIGHT
|
|
483
|
-
};
|
|
484
|
-
}
|
|
485
|
-
getCardPositionAtZoom = (zoom) => {
|
|
486
|
-
const currentContainerWidth = containerDimensions.width / zoom;
|
|
487
|
-
const currentContainerHeight = containerDimensions.height;
|
|
488
|
-
const currentLayout = computeLayout(grouping, {
|
|
489
|
-
viewMode,
|
|
490
|
-
cardWidth: BASE_CARD_WIDTH,
|
|
491
|
-
cardHeight: BASE_CARD_HEIGHT,
|
|
492
|
-
cardsPerColumn: CARDS_PER_COLUMN,
|
|
493
|
-
groupSpacing: GROUP_SPACING,
|
|
494
|
-
containerWidth: currentContainerWidth,
|
|
495
|
-
containerHeight: currentContainerHeight,
|
|
496
|
-
});
|
|
497
|
-
const pos = currentLayout.positions.get(itemId);
|
|
498
|
-
return pos ? { x: pos.x, y: pos.y, width: BASE_CARD_WIDTH, height: BASE_CARD_HEIGHT } : null;
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
setIsZooming(true);
|
|
502
|
-
animateZoomAndScroll({
|
|
503
|
-
container,
|
|
504
|
-
cardPosition,
|
|
505
|
-
targetCardPosition,
|
|
506
|
-
getCardPositionAtZoom,
|
|
507
|
-
startZoom: zoomLevel,
|
|
508
|
-
targetZoom: preSelectionState.zoom,
|
|
509
|
-
targetScrollLeft: preSelectionState.scrollLeft,
|
|
510
|
-
targetScrollTop: preSelectionState.scrollTop,
|
|
511
|
-
onUpdate: setZoomLevel,
|
|
512
|
-
onComplete: () => {
|
|
513
|
-
setIsZooming(false);
|
|
514
|
-
setSelectedItem(null);
|
|
515
|
-
setPreSelectionState(null);
|
|
516
|
-
},
|
|
517
|
-
});
|
|
518
|
-
}, [preSelectionState, selectedItem, zoomLevel, viewMode, resolveId, setZoomLevel, layout, grouping, containerDimensions]);
|
|
152
|
+
useAnimationModeTracking(filterState, rangeFilterState, search, activeDimensionKey, viewMode, setAnimationMode);
|
|
153
|
+
useScrollSync(containerRef, axisLabelsRef, viewMode);
|
|
154
|
+
useViewModeScrollHandling({
|
|
155
|
+
containerRef,
|
|
156
|
+
viewMode,
|
|
157
|
+
grouping,
|
|
158
|
+
layout,
|
|
159
|
+
selectedItem,
|
|
160
|
+
zoomLevel,
|
|
161
|
+
resolveId,
|
|
162
|
+
data,
|
|
163
|
+
setPreSelectionState,
|
|
164
|
+
});
|
|
165
|
+
const handleCardClick = useCardSelection({
|
|
166
|
+
data,
|
|
167
|
+
isPanning,
|
|
168
|
+
selectedItem,
|
|
169
|
+
zoomLevel,
|
|
170
|
+
viewMode,
|
|
171
|
+
layout,
|
|
172
|
+
containerDimensions,
|
|
173
|
+
scrollPosition,
|
|
174
|
+
preSelectionState,
|
|
175
|
+
grouping,
|
|
176
|
+
getItemId,
|
|
177
|
+
resolveId,
|
|
178
|
+
setZoomLevel,
|
|
179
|
+
setIsZooming,
|
|
180
|
+
setSelectedItem,
|
|
181
|
+
setPreSelectionState,
|
|
182
|
+
});
|
|
183
|
+
const closeDetail = useDetailPanelClose({
|
|
184
|
+
selectedItem,
|
|
185
|
+
preSelectionState,
|
|
186
|
+
zoomLevel,
|
|
187
|
+
viewMode,
|
|
188
|
+
layout,
|
|
189
|
+
containerDimensions,
|
|
190
|
+
grouping,
|
|
191
|
+
data,
|
|
192
|
+
resolveId,
|
|
193
|
+
setZoomLevel,
|
|
194
|
+
setIsZooming,
|
|
195
|
+
setSelectedItem,
|
|
196
|
+
setPreSelectionState,
|
|
197
|
+
});
|
|
519
198
|
const cardWidth = BASE_CARD_WIDTH;
|
|
520
199
|
const cardHeight = BASE_CARD_HEIGHT;
|
|
521
200
|
const filterOptions = useFilterOptions(data, filters, filterState, rangeFilterState);
|