@cratis/components 0.1.13 → 0.1.15
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/usePivotEngine.js +99 -65
- package/dist/cjs/PivotViewer/hooks/usePivotEngine.js.map +1 -1
- 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/usePivotEngine.d.ts.map +1 -1
- package/dist/esm/PivotViewer/hooks/usePivotEngine.js +100 -66
- package/dist/esm/PivotViewer/hooks/usePivotEngine.js.map +1 -1
- 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
|
@@ -6,87 +6,121 @@ var store = require('../engine/store.js');
|
|
|
6
6
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
7
7
|
function usePivotEngine({ data, fieldExtractors, indexFields, }) {
|
|
8
8
|
const [ready, setReady] = React.useState(false);
|
|
9
|
+
const [workerAvailable, setWorkerAvailable] = React.useState(false);
|
|
9
10
|
const workerRef = React.useRef(null);
|
|
10
11
|
const indexesRef = React.useRef(null);
|
|
11
12
|
const fallbackRef = React.useRef(false);
|
|
12
13
|
const storeRef = React.useRef(null);
|
|
13
14
|
const pendingCallbacksRef = React.useRef(new Map());
|
|
14
15
|
React.useEffect(() => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
16
|
+
if (typeof window === 'undefined' || typeof Worker === 'undefined') {
|
|
17
|
+
console.warn('[PivotEngine] Worker not supported in this environment, using main thread');
|
|
18
|
+
fallbackRef.current = true;
|
|
19
|
+
setWorkerAvailable(false);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const workerUrl = new URL('../engine/pivot.worker.js', (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('PivotViewer/hooks/usePivotEngine.js', document.baseURI).href)));
|
|
23
|
+
let disposed = false;
|
|
24
|
+
const enableFallback = () => {
|
|
25
|
+
fallbackRef.current = true;
|
|
26
|
+
workerRef.current = null;
|
|
27
|
+
setWorkerAvailable(false);
|
|
28
|
+
};
|
|
29
|
+
const setupWorker = async () => {
|
|
30
|
+
try {
|
|
31
|
+
if (typeof fetch === 'function') {
|
|
32
|
+
const response = await fetch(workerUrl, { method: 'HEAD' });
|
|
33
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
34
|
+
if (!response.ok || !contentType.includes('javascript')) {
|
|
35
|
+
console.warn('[PivotEngine] Worker asset not reachable, using main thread');
|
|
36
|
+
enableFallback();
|
|
37
|
+
return;
|
|
36
38
|
}
|
|
37
|
-
break;
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.warn('[PivotEngine] Worker preflight failed, using main thread', error);
|
|
43
|
+
enableFallback();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (disposed) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
console.log('[PivotEngine] Creating worker');
|
|
50
|
+
const worker = new Worker(workerUrl, { type: 'module' });
|
|
51
|
+
workerRef.current = worker;
|
|
52
|
+
setWorkerAvailable(true);
|
|
53
|
+
console.log('[PivotEngine] Worker created, setting up message handlers');
|
|
54
|
+
worker.onmessage = (e) => {
|
|
55
|
+
const message = e.data;
|
|
56
|
+
console.log('[PivotEngine] Received message from worker:', message.type);
|
|
57
|
+
switch (message.type) {
|
|
58
|
+
case 'indexesReady':
|
|
59
|
+
console.log('[PivotEngine] Indexes ready');
|
|
60
|
+
setReady(true);
|
|
61
|
+
break;
|
|
62
|
+
case 'filterResult': {
|
|
63
|
+
const callback = pendingCallbacksRef.current.get('filter');
|
|
64
|
+
if (callback) {
|
|
65
|
+
console.log('[PivotEngine] Calling filter callback and deleting');
|
|
66
|
+
callback(message.result);
|
|
67
|
+
pendingCallbacksRef.current.delete('filter');
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.warn('[PivotEngine] No callback registered for filter result - ignoring duplicate message');
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case 'groupingResult': {
|
|
75
|
+
console.log('[PivotEngine] Received groupingResult:', message.result);
|
|
76
|
+
const callback = pendingCallbacksRef.current.get('grouping');
|
|
77
|
+
if (callback) {
|
|
78
|
+
console.log('[PivotEngine] Calling grouping callback and deleting');
|
|
79
|
+
callback(message.result);
|
|
80
|
+
pendingCallbacksRef.current.delete('grouping');
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.warn('[PivotEngine] No callback registered for grouping result - ignoring duplicate message');
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
46
86
|
}
|
|
47
|
-
|
|
48
|
-
|
|
87
|
+
case 'sortResult': {
|
|
88
|
+
const callback = pendingCallbacksRef.current.get('sort');
|
|
89
|
+
if (callback) {
|
|
90
|
+
console.log('[PivotEngine] Calling sort callback and deleting');
|
|
91
|
+
callback(message.result);
|
|
92
|
+
pendingCallbacksRef.current.delete('sort');
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
console.warn('[PivotEngine] No callback registered for sort result - ignoring duplicate message');
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
49
98
|
}
|
|
50
|
-
break;
|
|
51
99
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
100
|
+
};
|
|
101
|
+
worker.onerror = (error) => {
|
|
102
|
+
console.error('[PivotEngine] Worker error:', error);
|
|
103
|
+
enableFallback();
|
|
104
|
+
if (storeRef.current) {
|
|
105
|
+
try {
|
|
106
|
+
indexesRef.current = store.buildIndexes(storeRef.current, indexFields);
|
|
58
107
|
}
|
|
59
|
-
|
|
60
|
-
console.
|
|
108
|
+
catch (e) {
|
|
109
|
+
console.error('[PivotEngine] Failed to build indexes in fallback:', e);
|
|
110
|
+
indexesRef.current = null;
|
|
61
111
|
}
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
worker.onerror = (error) => {
|
|
67
|
-
console.error('[PivotEngine] Worker error:', error);
|
|
68
|
-
fallbackRef.current = true;
|
|
69
|
-
workerRef.current = null;
|
|
70
|
-
if (storeRef.current) {
|
|
71
|
-
try {
|
|
72
|
-
indexesRef.current = store.buildIndexes(storeRef.current, indexFields);
|
|
73
|
-
}
|
|
74
|
-
catch (e) {
|
|
75
|
-
console.error('[PivotEngine] Failed to build indexes in fallback:', e);
|
|
76
|
-
indexesRef.current = null;
|
|
112
|
+
setReady(true);
|
|
77
113
|
}
|
|
78
|
-
|
|
79
|
-
}
|
|
114
|
+
};
|
|
80
115
|
};
|
|
116
|
+
void setupWorker();
|
|
81
117
|
return () => {
|
|
82
|
-
|
|
118
|
+
disposed = true;
|
|
119
|
+
workerRef.current?.terminate();
|
|
120
|
+
workerRef.current = null;
|
|
83
121
|
};
|
|
84
|
-
}, []);
|
|
122
|
+
}, [indexFields]);
|
|
85
123
|
React.useEffect(() => {
|
|
86
|
-
if (!workerRef.current) {
|
|
87
|
-
console.warn('[PivotEngine] Worker not available in data effect');
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
124
|
console.log('[PivotEngine] Building indexes for', data.length, 'items');
|
|
91
125
|
setReady(false);
|
|
92
126
|
const store$1 = store.buildStore(data, fieldExtractors);
|
|
@@ -99,7 +133,7 @@ function usePivotEngine({ data, fieldExtractors, indexFields, }) {
|
|
|
99
133
|
console.error('[PivotEngine] buildIndexes failed:', e);
|
|
100
134
|
indexesRef.current = null;
|
|
101
135
|
}
|
|
102
|
-
if (workerRef.current) {
|
|
136
|
+
if (workerRef.current && !fallbackRef.current) {
|
|
103
137
|
const fieldsArray = Array.from(store$1.fields.entries());
|
|
104
138
|
const serializableStore = {
|
|
105
139
|
...store$1,
|
|
@@ -116,7 +150,7 @@ function usePivotEngine({ data, fieldExtractors, indexFields, }) {
|
|
|
116
150
|
else {
|
|
117
151
|
setReady(true);
|
|
118
152
|
}
|
|
119
|
-
}, [data, fieldExtractors, indexFields]);
|
|
153
|
+
}, [data, fieldExtractors, indexFields, workerAvailable]);
|
|
120
154
|
const applyFiltersCallback = React.useCallback((filters) => {
|
|
121
155
|
return new Promise((resolve) => {
|
|
122
156
|
if (!workerRef.current || fallbackRef.current) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePivotEngine.js","sources":["../../../../PivotViewer/hooks/usePivotEngine.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 { useEffect, useRef, useState, useCallback } from 'react';\nimport type {\n PivotStore,\n PivotIndexes,\n FilterSpec,\n FilterResult,\n GroupSpec,\n GroupingResult,\n WorkerInMessage,\n WorkerOutMessage,\n FieldValue,\n} from '../engine/types';\nimport { buildStore, buildIndexes, applyFilters, computeGrouping, sortIds } from '../engine/store';\n\nexport interface UsePivotEngineOptions<TItem extends object> {\n data: TItem[];\n fieldExtractors: Map<string, (item: TItem) => FieldValue>;\n indexFields: string[];\n}\n\nexport interface UsePivotEngineResult {\n ready: boolean;\n applyFilters: (filters: FilterSpec[]) => Promise<FilterResult>;\n computeGrouping: (visibleIds: Uint32Array, groupBy: GroupSpec) => Promise<GroupingResult>;\n sortIds: (visibleIds: Uint32Array, sortBy: string) => Promise<Uint32Array>;\n}\n\nexport function usePivotEngine<TItem extends object>({\n data,\n fieldExtractors,\n indexFields,\n}: UsePivotEngineOptions<TItem>): UsePivotEngineResult {\n const [ready, setReady] = useState(false);\n const workerRef = useRef<Worker | null>(null);\n const indexesRef = useRef<PivotIndexes | null>(null);\n const fallbackRef = useRef(false);\n const storeRef = useRef<PivotStore | null>(null);\n const pendingCallbacksRef = useRef<Map<string, (result: unknown) => void>>(new Map());\n\n useEffect(() => {\n console.log('[PivotEngine] Creating worker');\n const worker = new Worker(\n new URL('../engine/pivot.worker.ts', import.meta.url),\n { type: 'module' }\n );\n\n workerRef.current = worker;\n console.log('[PivotEngine] Worker created, setting up message handlers');\n\n worker.onmessage = (e: MessageEvent<WorkerOutMessage>) => {\n const message = e.data;\n console.log('[PivotEngine] Received message from worker:', message.type);\n\n switch (message.type) {\n case 'indexesReady':\n console.log('[PivotEngine] Indexes ready');\n setReady(true);\n break;\n\n case 'filterResult': {\n const callback = pendingCallbacksRef.current.get('filter');\n if (callback) {\n console.log('[PivotEngine] Calling filter callback and deleting');\n callback(message.result);\n pendingCallbacksRef.current.delete('filter');\n } else {\n console.warn('[PivotEngine] No callback registered for filter result - ignoring duplicate message');\n }\n break;\n }\n\n case 'groupingResult': {\n console.log('[PivotEngine] Received groupingResult:', message.result);\n const callback = pendingCallbacksRef.current.get('grouping');\n if (callback) {\n console.log('[PivotEngine] Calling grouping callback and deleting');\n callback(message.result);\n pendingCallbacksRef.current.delete('grouping');\n } else {\n console.warn('[PivotEngine] No callback registered for grouping result - ignoring duplicate message');\n }\n break;\n }\n\n case 'sortResult': {\n const callback = pendingCallbacksRef.current.get('sort');\n if (callback) {\n console.log('[PivotEngine] Calling sort callback and deleting');\n callback(message.result);\n pendingCallbacksRef.current.delete('sort');\n } else {\n console.warn('[PivotEngine] No callback registered for sort result - ignoring duplicate message');\n }\n break;\n }\n }\n };\n\n worker.onerror = (error) => {\n console.error('[PivotEngine] Worker error:', error);\n // enable synchronous fallback so UI can still function without worker\n fallbackRef.current = true;\n workerRef.current = null;\n // if we already built store/indexes, mark ready so UI can use fallback\n if (storeRef.current) {\n try {\n indexesRef.current = buildIndexes(storeRef.current, indexFields);\n } catch (e) {\n console.error('[PivotEngine] Failed to build indexes in fallback:', e);\n indexesRef.current = null;\n }\n setReady(true);\n }\n };\n\n return () => {\n worker.terminate();\n };\n }, []);\n\n useEffect(() => {\n if (!workerRef.current) {\n console.warn('[PivotEngine] Worker not available in data effect');\n return;\n }\n\n console.log('[PivotEngine] Building indexes for', data.length, 'items');\n setReady(false);\n\n const store = buildStore(data, fieldExtractors);\n storeRef.current = store;\n console.log('[PivotEngine] Store built with', store.items.length, 'items and', store.fields.size, 'fields');\n\n // compute indexes locally for immediate fallback and cache\n try {\n indexesRef.current = buildIndexes(store, indexFields);\n } catch (e) {\n console.error('[PivotEngine] buildIndexes failed:', e);\n indexesRef.current = null;\n }\n\n if (workerRef.current) {\n // Convert Map to array for serialization\n const fieldsArray = Array.from(store.fields.entries());\n const serializableStore = {\n ...store,\n fields: fieldsArray,\n };\n\n const message: WorkerInMessage = {\n type: 'buildIndexes',\n store: serializableStore as unknown as PivotStore,\n fields: indexFields,\n };\n\n console.log('[PivotEngine] Posting buildIndexes with', fieldsArray.length, 'fields');\n workerRef.current.postMessage(message);\n } else {\n // no worker available, mark ready to allow fallback synchronous usage\n setReady(true);\n }\n }, [data, fieldExtractors, indexFields]);\n\n const applyFiltersCallback = useCallback(\n (filters: FilterSpec[]): Promise<FilterResult> => {\n return new Promise((resolve) => {\n // If worker is not available, use synchronous fallback using local indexes\n if (!workerRef.current || fallbackRef.current) {\n try {\n const store = storeRef.current;\n const indexes = indexesRef.current;\n if (store && indexes) {\n const result = applyFilters(store, indexes, filters);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback applyFilters error:', e);\n }\n\n // if fallback not possible, return empty result\n resolve({ visibleIds: new Uint32Array(0), count: 0 });\n return;\n }\n\n pendingCallbacksRef.current.set('filter', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'applyFilters',\n filters,\n };\n\n workerRef.current.postMessage(message);\n });\n },\n [ready]\n );\n\n const computeGroupingCallback = useCallback(\n (visibleIds: Uint32Array, groupBy: GroupSpec): Promise<GroupingResult> => {\n console.log('[PivotEngine] computeGroupingCallback called with', visibleIds.length, 'visibleIds');\n \n // Check if there's already a pending grouping request\n if (pendingCallbacksRef.current.has('grouping')) {\n console.warn('[PivotEngine] Grouping already in progress, ignoring duplicate request');\n return Promise.resolve({ groups: [] });\n }\n \n return new Promise((resolve) => {\n // synchronous fallback if worker unavailable\n if (!workerRef.current || fallbackRef.current) {\n console.log('[PivotEngine] Using synchronous fallback for grouping');\n try {\n const store = storeRef.current;\n const indexes = indexesRef.current;\n if (store && indexes) {\n const result = computeGrouping(store, indexes, visibleIds, groupBy);\n console.log('[PivotEngine] Fallback grouping result:', result);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback computeGrouping error:', e);\n }\n\n console.warn('[PivotEngine] No store/indexes for fallback, returning empty');\n resolve({ groups: [] });\n return;\n }\n\n console.log('[PivotEngine] Setting grouping callback and posting to worker');\n pendingCallbacksRef.current.set('grouping', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'computeGrouping',\n visibleIds,\n groupBy,\n };\n\n workerRef.current.postMessage(message);\n console.log('[PivotEngine] Message posted to worker');\n });\n },\n [ready]\n );\n\n const sortIdsCallback = useCallback(\n (visibleIds: Uint32Array, sortBy: string): Promise<Uint32Array> => {\n return new Promise((resolve) => {\n // synchronous fallback if worker unavailable\n if (!workerRef.current || fallbackRef.current) {\n try {\n const store = storeRef.current;\n if (store) {\n const result = sortIds(store, visibleIds, sortBy);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback sortIds error:', e);\n }\n\n resolve(visibleIds);\n return;\n }\n\n pendingCallbacksRef.current.set('sort', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'sort',\n ids: visibleIds,\n sortBy,\n };\n\n workerRef.current.postMessage(message);\n });\n },\n [ready]\n );\n\n return {\n ready,\n applyFilters: applyFiltersCallback,\n computeGrouping: computeGroupingCallback,\n sortIds: sortIdsCallback,\n };\n}\n"],"names":["useState","useRef","useEffect","buildIndexes","store","buildStore","useCallback","applyFilters","computeGrouping","sortIds"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"usePivotEngine.js","sources":["../../../../PivotViewer/hooks/usePivotEngine.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 { useEffect, useRef, useState, useCallback } from 'react';\nimport type {\n PivotStore,\n PivotIndexes,\n FilterSpec,\n FilterResult,\n GroupSpec,\n GroupingResult,\n WorkerInMessage,\n WorkerOutMessage,\n FieldValue,\n} from '../engine/types';\nimport { buildStore, buildIndexes, applyFilters, computeGrouping, sortIds } from '../engine/store';\n\nexport interface UsePivotEngineOptions<TItem extends object> {\n data: TItem[];\n fieldExtractors: Map<string, (item: TItem) => FieldValue>;\n indexFields: string[];\n}\n\nexport interface UsePivotEngineResult {\n ready: boolean;\n applyFilters: (filters: FilterSpec[]) => Promise<FilterResult>;\n computeGrouping: (visibleIds: Uint32Array, groupBy: GroupSpec) => Promise<GroupingResult>;\n sortIds: (visibleIds: Uint32Array, sortBy: string) => Promise<Uint32Array>;\n}\n\nexport function usePivotEngine<TItem extends object>({\n data,\n fieldExtractors,\n indexFields,\n}: UsePivotEngineOptions<TItem>): UsePivotEngineResult {\n const [ready, setReady] = useState(false);\n const [workerAvailable, setWorkerAvailable] = useState(false);\n const workerRef = useRef<Worker | null>(null);\n const indexesRef = useRef<PivotIndexes | null>(null);\n const fallbackRef = useRef(false);\n const storeRef = useRef<PivotStore | null>(null);\n const pendingCallbacksRef = useRef<Map<string, (result: unknown) => void>>(new Map());\n\n useEffect(() => {\n if (typeof window === 'undefined' || typeof Worker === 'undefined') {\n console.warn('[PivotEngine] Worker not supported in this environment, using main thread');\n fallbackRef.current = true;\n setWorkerAvailable(false);\n return;\n }\n\n const workerUrl = new URL('../engine/pivot.worker.js', import.meta.url);\n let disposed = false;\n\n const enableFallback = () => {\n fallbackRef.current = true;\n workerRef.current = null;\n setWorkerAvailable(false);\n };\n\n const setupWorker = async () => {\n try {\n if (typeof fetch === 'function') {\n const response = await fetch(workerUrl, { method: 'HEAD' });\n const contentType = response.headers.get('content-type') ?? '';\n\n if (!response.ok || !contentType.includes('javascript')) {\n console.warn('[PivotEngine] Worker asset not reachable, using main thread');\n enableFallback();\n return;\n }\n }\n } catch (error) {\n console.warn('[PivotEngine] Worker preflight failed, using main thread', error);\n enableFallback();\n return;\n }\n\n if (disposed) {\n return;\n }\n\n console.log('[PivotEngine] Creating worker');\n const worker = new Worker(workerUrl, { type: 'module' });\n\n workerRef.current = worker;\n setWorkerAvailable(true);\n console.log('[PivotEngine] Worker created, setting up message handlers');\n\n worker.onmessage = (e: MessageEvent<WorkerOutMessage>) => {\n const message = e.data;\n console.log('[PivotEngine] Received message from worker:', message.type);\n\n switch (message.type) {\n case 'indexesReady':\n console.log('[PivotEngine] Indexes ready');\n setReady(true);\n break;\n\n case 'filterResult': {\n const callback = pendingCallbacksRef.current.get('filter');\n if (callback) {\n console.log('[PivotEngine] Calling filter callback and deleting');\n callback(message.result);\n pendingCallbacksRef.current.delete('filter');\n } else {\n console.warn('[PivotEngine] No callback registered for filter result - ignoring duplicate message');\n }\n break;\n }\n\n case 'groupingResult': {\n console.log('[PivotEngine] Received groupingResult:', message.result);\n const callback = pendingCallbacksRef.current.get('grouping');\n if (callback) {\n console.log('[PivotEngine] Calling grouping callback and deleting');\n callback(message.result);\n pendingCallbacksRef.current.delete('grouping');\n } else {\n console.warn('[PivotEngine] No callback registered for grouping result - ignoring duplicate message');\n }\n break;\n }\n\n case 'sortResult': {\n const callback = pendingCallbacksRef.current.get('sort');\n if (callback) {\n console.log('[PivotEngine] Calling sort callback and deleting');\n callback(message.result);\n pendingCallbacksRef.current.delete('sort');\n } else {\n console.warn('[PivotEngine] No callback registered for sort result - ignoring duplicate message');\n }\n break;\n }\n }\n };\n\n worker.onerror = (error) => {\n console.error('[PivotEngine] Worker error:', error);\n enableFallback();\n if (storeRef.current) {\n try {\n indexesRef.current = buildIndexes(storeRef.current, indexFields);\n } catch (e) {\n console.error('[PivotEngine] Failed to build indexes in fallback:', e);\n indexesRef.current = null;\n }\n setReady(true);\n }\n };\n };\n\n void setupWorker();\n\n return () => {\n disposed = true;\n workerRef.current?.terminate();\n workerRef.current = null;\n };\n }, [indexFields]);\n\n useEffect(() => {\n console.log('[PivotEngine] Building indexes for', data.length, 'items');\n setReady(false);\n\n const store = buildStore(data, fieldExtractors);\n storeRef.current = store;\n console.log('[PivotEngine] Store built with', store.items.length, 'items and', store.fields.size, 'fields');\n\n try {\n indexesRef.current = buildIndexes(store, indexFields);\n } catch (e) {\n console.error('[PivotEngine] buildIndexes failed:', e);\n indexesRef.current = null;\n }\n\n if (workerRef.current && !fallbackRef.current) {\n const fieldsArray = Array.from(store.fields.entries());\n const serializableStore = {\n ...store,\n fields: fieldsArray,\n };\n\n const message: WorkerInMessage = {\n type: 'buildIndexes',\n store: serializableStore as unknown as PivotStore,\n fields: indexFields,\n };\n\n console.log('[PivotEngine] Posting buildIndexes with', fieldsArray.length, 'fields');\n workerRef.current.postMessage(message);\n } else {\n setReady(true);\n }\n }, [data, fieldExtractors, indexFields, workerAvailable]);\n\n const applyFiltersCallback = useCallback(\n (filters: FilterSpec[]): Promise<FilterResult> => {\n return new Promise((resolve) => {\n // If worker is not available, use synchronous fallback using local indexes\n if (!workerRef.current || fallbackRef.current) {\n try {\n const store = storeRef.current;\n const indexes = indexesRef.current;\n if (store && indexes) {\n const result = applyFilters(store, indexes, filters);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback applyFilters error:', e);\n }\n\n // if fallback not possible, return empty result\n resolve({ visibleIds: new Uint32Array(0), count: 0 });\n return;\n }\n\n pendingCallbacksRef.current.set('filter', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'applyFilters',\n filters,\n };\n\n workerRef.current.postMessage(message);\n });\n },\n [ready]\n );\n\n const computeGroupingCallback = useCallback(\n (visibleIds: Uint32Array, groupBy: GroupSpec): Promise<GroupingResult> => {\n console.log('[PivotEngine] computeGroupingCallback called with', visibleIds.length, 'visibleIds');\n \n // Check if there's already a pending grouping request\n if (pendingCallbacksRef.current.has('grouping')) {\n console.warn('[PivotEngine] Grouping already in progress, ignoring duplicate request');\n return Promise.resolve({ groups: [] });\n }\n \n return new Promise((resolve) => {\n // synchronous fallback if worker unavailable\n if (!workerRef.current || fallbackRef.current) {\n console.log('[PivotEngine] Using synchronous fallback for grouping');\n try {\n const store = storeRef.current;\n const indexes = indexesRef.current;\n if (store && indexes) {\n const result = computeGrouping(store, indexes, visibleIds, groupBy);\n console.log('[PivotEngine] Fallback grouping result:', result);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback computeGrouping error:', e);\n }\n\n console.warn('[PivotEngine] No store/indexes for fallback, returning empty');\n resolve({ groups: [] });\n return;\n }\n\n console.log('[PivotEngine] Setting grouping callback and posting to worker');\n pendingCallbacksRef.current.set('grouping', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'computeGrouping',\n visibleIds,\n groupBy,\n };\n\n workerRef.current.postMessage(message);\n console.log('[PivotEngine] Message posted to worker');\n });\n },\n [ready]\n );\n\n const sortIdsCallback = useCallback(\n (visibleIds: Uint32Array, sortBy: string): Promise<Uint32Array> => {\n return new Promise((resolve) => {\n // synchronous fallback if worker unavailable\n if (!workerRef.current || fallbackRef.current) {\n try {\n const store = storeRef.current;\n if (store) {\n const result = sortIds(store, visibleIds, sortBy);\n resolve(result);\n return;\n }\n } catch (e) {\n console.error('[PivotEngine] fallback sortIds error:', e);\n }\n\n resolve(visibleIds);\n return;\n }\n\n pendingCallbacksRef.current.set('sort', resolve as (result: unknown) => void);\n\n const message: WorkerInMessage = {\n type: 'sort',\n ids: visibleIds,\n sortBy,\n };\n\n workerRef.current.postMessage(message);\n });\n },\n [ready]\n );\n\n return {\n ready,\n applyFilters: applyFiltersCallback,\n computeGrouping: computeGroupingCallback,\n sortIds: sortIdsCallback,\n };\n}\n"],"names":["useState","useRef","useEffect","buildIndexes","store","buildStore","useCallback","applyFilters","computeGrouping","sortIds"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
|
|
5
|
+
function useScrollSync(containerRef, axisLabelsRef, viewMode) {
|
|
6
|
+
React.useEffect(() => {
|
|
7
|
+
const container = containerRef.current;
|
|
8
|
+
const axisLabels = axisLabelsRef.current;
|
|
9
|
+
if (!container || !axisLabels || viewMode !== 'grouped')
|
|
10
|
+
return;
|
|
11
|
+
const handleScroll = () => {
|
|
12
|
+
axisLabels.scrollLeft = container.scrollLeft;
|
|
13
|
+
};
|
|
14
|
+
handleScroll();
|
|
15
|
+
container.addEventListener('scroll', handleScroll);
|
|
16
|
+
return () => container.removeEventListener('scroll', handleScroll);
|
|
17
|
+
}, [viewMode, containerRef, axisLabelsRef]);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.useScrollSync = useScrollSync;
|
|
21
|
+
//# sourceMappingURL=useScrollSync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScrollSync.js","sources":["../../../../PivotViewer/hooks/useScrollSync.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 { useEffect } from 'react';\nimport type { ViewMode } from '../components/Toolbar';\n\n/**\n * Synchronizes axis labels scroll with container scroll\n */\nexport function useScrollSync(\n containerRef: React.RefObject<HTMLDivElement>,\n axisLabelsRef: React.RefObject<HTMLDivElement>,\n viewMode: ViewMode,\n) {\n useEffect(() => {\n const container = containerRef.current;\n const axisLabels = axisLabelsRef.current;\n\n if (!container || !axisLabels || viewMode !== 'grouped') return;\n\n const handleScroll = () => {\n axisLabels.scrollLeft = container.scrollLeft;\n };\n\n // Sync immediately\n handleScroll();\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, [viewMode, containerRef, axisLabelsRef]);\n}\n"],"names":["useEffect"],"mappings":";;;;SASgB,aAAa,CACzB,YAA6C,EAC7C,aAA8C,EAC9C,QAAkB,EAAA;IAElBA,eAAS,CAAC,MAAK;AACX,QAAA,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO;AACtC,QAAA,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO;QAExC,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,IAAI,QAAQ,KAAK,SAAS;YAAE;QAEzD,MAAM,YAAY,GAAG,MAAK;AACtB,YAAA,UAAU,CAAC,UAAU,GAAG,SAAS,CAAC,UAAU;AAChD,QAAA,CAAC;AAGD,QAAA,YAAY,EAAE;AAEd,QAAA,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC;QAClD,OAAO,MAAM,SAAS,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC;IACtE,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;AAC/C;;;;"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var animations = require('../utils/animations.js');
|
|
5
|
+
var constants = require('../utils/constants.js');
|
|
6
|
+
var idResolution = require('../utils/idResolution.js');
|
|
7
|
+
|
|
8
|
+
function useViewModeScrollHandling({ containerRef, viewMode, grouping, layout, selectedItem, zoomLevel, resolveId, data, setPreSelectionState, }) {
|
|
9
|
+
const lastProcessedViewMode = React.useRef(viewMode);
|
|
10
|
+
const lastProcessedGrouping = React.useRef(grouping);
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
const viewModeChanged = lastProcessedViewMode.current !== viewMode;
|
|
13
|
+
const groupingChanged = lastProcessedGrouping.current !== grouping;
|
|
14
|
+
if (!viewModeChanged && !groupingChanged)
|
|
15
|
+
return;
|
|
16
|
+
lastProcessedViewMode.current = viewMode;
|
|
17
|
+
lastProcessedGrouping.current = grouping;
|
|
18
|
+
const container = containerRef.current;
|
|
19
|
+
if (!container)
|
|
20
|
+
return;
|
|
21
|
+
if (selectedItem) {
|
|
22
|
+
const index = data.indexOf(selectedItem);
|
|
23
|
+
let itemId = index !== -1 ? index : resolveId(selectedItem, 0);
|
|
24
|
+
itemId = idResolution.normalizeIdToLayoutKey(itemId, layout);
|
|
25
|
+
const cardPosition = idResolution.getCardPositionFromLayout(itemId, layout, constants.BASE_CARD_WIDTH, constants.BASE_CARD_HEIGHT);
|
|
26
|
+
if (cardPosition) {
|
|
27
|
+
const detailWidth = viewMode === 'collection' ? 0 : constants.DETAIL_PANEL_WIDTH;
|
|
28
|
+
const { scrollLeft, scrollTop } = animations.calculateCenterScrollPosition(container, cardPosition, zoomLevel, detailWidth, layout.totalHeight);
|
|
29
|
+
container.scrollTo({ left: scrollLeft, top: scrollTop });
|
|
30
|
+
setPreSelectionState(null);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if (viewMode === 'grouped') {
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
container.scrollTop = container.scrollHeight;
|
|
36
|
+
}, 0);
|
|
37
|
+
}
|
|
38
|
+
}, [viewMode, grouping, layout, selectedItem, resolveId, zoomLevel, containerRef, data, setPreSelectionState]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
exports.useViewModeScrollHandling = useViewModeScrollHandling;
|
|
42
|
+
//# sourceMappingURL=useViewModeScrollHandling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useViewModeScrollHandling.js","sources":["../../../../PivotViewer/hooks/useViewModeScrollHandling.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 { useEffect, useRef } from 'react';\nimport { calculateCenterScrollPosition } from '../utils/animations';\nimport type { Layout } from '../utils/cardPosition';\nimport type { ViewMode } from '../components/Toolbar';\nimport { BASE_CARD_WIDTH, BASE_CARD_HEIGHT, DETAIL_PANEL_WIDTH } from '../utils/constants';\nimport {\n getCardPositionFromLayout,\n normalizeIdToLayoutKey,\n} from '../utils/idResolution';\n\ninterface UseViewModeScrollHandlingParams<TItem extends object> {\n containerRef: React.RefObject<HTMLDivElement>;\n viewMode: ViewMode;\n grouping: unknown;\n layout: Layout;\n selectedItem: TItem | null;\n zoomLevel: number;\n resolveId: (item: TItem, index: number) => string | number;\n data: TItem[];\n setPreSelectionState: (state: null) => void;\n}\n\n/**\n * Handles scroll positioning when switching view modes or grouping changes\n */\nexport function useViewModeScrollHandling<TItem extends object>({\n containerRef,\n viewMode,\n grouping,\n layout,\n selectedItem,\n zoomLevel,\n resolveId,\n data,\n setPreSelectionState,\n}: UseViewModeScrollHandlingParams<TItem>) {\n const lastProcessedViewMode = useRef(viewMode);\n const lastProcessedGrouping = useRef(grouping);\n\n useEffect(() => {\n const viewModeChanged = lastProcessedViewMode.current !== viewMode;\n const groupingChanged = lastProcessedGrouping.current !== grouping;\n\n if (!viewModeChanged && !groupingChanged) return;\n\n lastProcessedViewMode.current = viewMode;\n lastProcessedGrouping.current = grouping;\n\n const container = containerRef.current;\n if (!container) return;\n\n // If we have a selected item, keep it centered in the new layout\n if (selectedItem) {\n const index = data.indexOf(selectedItem);\n let itemId: string | number = index !== -1 ? index : resolveId(selectedItem, 0);\n itemId = normalizeIdToLayoutKey(itemId, layout);\n\n const cardPosition = getCardPositionFromLayout(itemId, layout, BASE_CARD_WIDTH, BASE_CARD_HEIGHT);\n\n if (cardPosition) {\n const detailWidth = viewMode === 'collection' ? 0 : DETAIL_PANEL_WIDTH;\n\n const { scrollLeft, scrollTop } = calculateCenterScrollPosition(\n container,\n cardPosition,\n zoomLevel,\n detailWidth,\n layout.totalHeight,\n );\n\n container.scrollTo({ left: scrollLeft, top: scrollTop });\n setPreSelectionState(null);\n }\n } else if (viewMode === 'grouped') {\n // Default behavior for grouped view: scroll to bottom\n setTimeout(() => {\n container.scrollTop = container.scrollHeight;\n }, 0);\n }\n }, [viewMode, grouping, layout, selectedItem, resolveId, zoomLevel, containerRef, data, setPreSelectionState]);\n}\n"],"names":["useRef","useEffect","normalizeIdToLayoutKey","getCardPositionFromLayout","BASE_CARD_WIDTH","BASE_CARD_HEIGHT","DETAIL_PANEL_WIDTH","calculateCenterScrollPosition"],"mappings":";;;;;;;AA4BM,SAAU,yBAAyB,CAAuB,EAC5D,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,SAAS,EACT,SAAS,EACT,IAAI,EACJ,oBAAoB,GACiB,EAAA;AACrC,IAAA,MAAM,qBAAqB,GAAGA,YAAM,CAAC,QAAQ,CAAC;AAC9C,IAAA,MAAM,qBAAqB,GAAGA,YAAM,CAAC,QAAQ,CAAC;IAE9CC,eAAS,CAAC,MAAK;AACX,QAAA,MAAM,eAAe,GAAG,qBAAqB,CAAC,OAAO,KAAK,QAAQ;AAClE,QAAA,MAAM,eAAe,GAAG,qBAAqB,CAAC,OAAO,KAAK,QAAQ;AAElE,QAAA,IAAI,CAAC,eAAe,IAAI,CAAC,eAAe;YAAE;AAE1C,QAAA,qBAAqB,CAAC,OAAO,GAAG,QAAQ;AACxC,QAAA,qBAAqB,CAAC,OAAO,GAAG,QAAQ;AAExC,QAAA,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO;AACtC,QAAA,IAAI,CAAC,SAAS;YAAE;QAGhB,IAAI,YAAY,EAAE;YACd,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;AACxC,YAAA,IAAI,MAAM,GAAoB,KAAK,KAAK,EAAE,GAAG,KAAK,GAAG,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;AAC/E,YAAA,MAAM,GAAGC,mCAAsB,CAAC,MAAM,EAAE,MAAM,CAAC;AAE/C,YAAA,MAAM,YAAY,GAAGC,sCAAyB,CAAC,MAAM,EAAE,MAAM,EAAEC,yBAAe,EAAEC,0BAAgB,CAAC;YAEjG,IAAI,YAAY,EAAE;AACd,gBAAA,MAAM,WAAW,GAAG,QAAQ,KAAK,YAAY,GAAG,CAAC,GAAGC,4BAAkB;gBAEtE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAGC,wCAA6B,CAC3D,SAAS,EACT,YAAY,EACZ,SAAS,EACT,WAAW,EACX,MAAM,CAAC,WAAW,CACrB;AAED,gBAAA,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;gBACxD,oBAAoB,CAAC,IAAI,CAAC;YAC9B;QACJ;AAAO,aAAA,IAAI,QAAQ,KAAK,SAAS,EAAE;YAE/B,UAAU,CAAC,MAAK;AACZ,gBAAA,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC,YAAY;YAChD,CAAC,EAAE,CAAC,CAAC;QACT;IACJ,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,oBAAoB,CAAC,CAAC;AAClH;;;;"}
|
|
@@ -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"}
|