@vitessce/vit-s 3.6.0 → 3.6.1
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/index.js +2444 -2806
- package/dist-tsc/CallbackPublisher.d.ts.map +1 -1
- package/dist-tsc/CallbackPublisher.js +4 -4
- package/dist-tsc/DebugWindow.d.ts +1 -1
- package/dist-tsc/DebugWindow.d.ts.map +1 -1
- package/dist-tsc/Warning.d.ts +1 -1
- package/dist-tsc/Warning.d.ts.map +1 -1
- package/dist-tsc/state/hooks.d.ts +8 -18
- package/dist-tsc/state/hooks.d.ts.map +1 -1
- package/dist-tsc/state/hooks.js +92 -36
- package/package.json +13 -13
- package/src/CallbackPublisher.js +4 -3
- package/src/state/hooks.js +119 -43
package/src/state/hooks.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/* eslint-disable max-len */
|
|
2
2
|
/* eslint-disable react-refresh/only-export-components */
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import React, {
|
|
4
|
+
useCallback,
|
|
5
|
+
useRef,
|
|
6
|
+
useMemo,
|
|
7
|
+
createContext,
|
|
8
|
+
useContext,
|
|
9
|
+
} from 'react';
|
|
10
|
+
import { create, useStore } from 'zustand';
|
|
11
|
+
import { useShallow } from 'zustand/shallow';
|
|
12
|
+
import { subscribeWithSelector } from 'zustand/middleware';
|
|
7
13
|
import { isMatch, cloneDeep } from 'lodash-es';
|
|
8
14
|
import { CoordinationType } from '@vitessce/constants-internal';
|
|
9
15
|
import { capitalize } from '@vitessce/utils';
|
|
@@ -13,25 +19,95 @@ import {
|
|
|
13
19
|
addImageChannelInMetaCoordinationScopesHelper,
|
|
14
20
|
} from './spatial-reducers.js';
|
|
15
21
|
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
// References for Zustand v3:
|
|
23
|
+
// - https://github.com/pmndrs/zustand#react-context
|
|
24
|
+
// - https://github.com/pmndrs/zustand/blob/e47ea03/tests/context.test.tsx#L60
|
|
25
|
+
// References for Zustand v4:
|
|
26
|
+
// - https://github.com/pmndrs/zustand/discussions/1180#discussioncomment-3354713
|
|
27
|
+
// - https://zustand.docs.pmnd.rs/previous-versions/zustand-v3-create-context#migration
|
|
28
|
+
const ViewConfigStoreContext = createContext(null);
|
|
29
|
+
const AuxiliaryStoreContext = createContext(null);
|
|
30
|
+
|
|
31
|
+
export function ViewConfigProvider(props) {
|
|
32
|
+
const {
|
|
33
|
+
createStore,
|
|
34
|
+
children,
|
|
35
|
+
} = props;
|
|
36
|
+
|
|
37
|
+
// Reference: https://github.com/pmndrs/zustand/discussions/1180
|
|
38
|
+
const storeRef = useRef();
|
|
39
|
+
if (!storeRef.current) {
|
|
40
|
+
storeRef.current = createStore();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<ViewConfigStoreContext.Provider value={storeRef.current}>
|
|
45
|
+
{children}
|
|
46
|
+
</ViewConfigStoreContext.Provider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function useViewConfigStoreApi() {
|
|
51
|
+
const store = useContext(ViewConfigStoreContext);
|
|
52
|
+
if (!store) {
|
|
53
|
+
throw new Error('Missing StoreProvider');
|
|
54
|
+
}
|
|
55
|
+
return store;
|
|
56
|
+
}
|
|
57
|
+
export function useViewConfigStore(selector) {
|
|
58
|
+
const store = useViewConfigStoreApi();
|
|
59
|
+
if (!store) {
|
|
60
|
+
throw new Error('Missing StoreProvider');
|
|
61
|
+
}
|
|
62
|
+
const slice = useStore(store, selector);
|
|
63
|
+
return slice;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function useViewConfigStoreShallow(selector) {
|
|
67
|
+
return useViewConfigStore(useShallow(selector));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Begin auxiliary store things */
|
|
71
|
+
export function AuxiliaryProvider(props) {
|
|
72
|
+
const {
|
|
73
|
+
createStore,
|
|
74
|
+
children,
|
|
75
|
+
} = props;
|
|
76
|
+
|
|
77
|
+
// Reference: https://github.com/pmndrs/zustand/discussions/1180
|
|
78
|
+
const storeRef = useRef();
|
|
79
|
+
if (!storeRef.current) {
|
|
80
|
+
storeRef.current = createStore();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<AuxiliaryStoreContext.Provider value={storeRef.current}>
|
|
85
|
+
{children}
|
|
86
|
+
</AuxiliaryStoreContext.Provider>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
23
89
|
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
|
|
90
|
+
export function useAuxiliaryStoreApi() {
|
|
91
|
+
const store = useContext(AuxiliaryStoreContext);
|
|
92
|
+
if (!store) {
|
|
93
|
+
throw new Error('Missing StoreProvider');
|
|
94
|
+
}
|
|
95
|
+
return store;
|
|
96
|
+
}
|
|
97
|
+
export function useAuxiliaryStore(selector) {
|
|
98
|
+
const store = useAuxiliaryStoreApi();
|
|
99
|
+
if (!store) {
|
|
100
|
+
throw new Error('Missing StoreProvider');
|
|
101
|
+
}
|
|
102
|
+
const slice = useStore(store, selector);
|
|
103
|
+
return slice;
|
|
104
|
+
}
|
|
27
105
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
106
|
+
export function useAuxiliaryStoreShallow(selector) {
|
|
107
|
+
return useAuxiliaryStore(useShallow(selector));
|
|
108
|
+
}
|
|
109
|
+
/* end auxiliary store things */
|
|
32
110
|
|
|
33
|
-
export const AuxiliaryProvider = AuxiliaryProviderLocal;
|
|
34
|
-
export const useAuxiliaryStore = useAuxiliaryStoreLocal;
|
|
35
111
|
|
|
36
112
|
/**
|
|
37
113
|
* Get the "computed" coordinationScopes after accounting for
|
|
@@ -160,7 +236,7 @@ export function getParameterScopeBy(
|
|
|
160
236
|
* - https://github.com/pmndrs/zustand#using-subscribe-with-selector
|
|
161
237
|
* @returns {function} The useStore hook.
|
|
162
238
|
*/
|
|
163
|
-
export const createViewConfigStore = (initialLoaders, initialConfig) => create(set => ({
|
|
239
|
+
export const createViewConfigStore = (initialLoaders, initialConfig) => create()(subscribeWithSelector(set => ({
|
|
164
240
|
// State:
|
|
165
241
|
// The viewConfig is an object which must conform to the schema
|
|
166
242
|
// found in src/schemas/config.schema.json.
|
|
@@ -348,14 +424,14 @@ export const createViewConfigStore = (initialLoaders, initialConfig) => create(s
|
|
|
348
424
|
mostRecentConfigSource: 'internal',
|
|
349
425
|
};
|
|
350
426
|
}),
|
|
351
|
-
}));
|
|
427
|
+
})));
|
|
352
428
|
|
|
353
429
|
/**
|
|
354
430
|
* Hook for getting components' layout from the view config based on
|
|
355
431
|
* matching all coordination scopes.
|
|
356
432
|
* @returns {Object} The components' layout.
|
|
357
433
|
*/
|
|
358
|
-
export const useComponentLayout = (component, scopes, coordinationScopes) =>
|
|
434
|
+
export const useComponentLayout = (component, scopes, coordinationScopes) => useViewConfigStoreShallow(
|
|
359
435
|
state => state.viewConfig.layout.filter(l => l.component === component).filter(
|
|
360
436
|
l => scopes.every(scope => l.coordinationScopes[scope]
|
|
361
437
|
=== coordinationScopes[scope]),
|
|
@@ -455,7 +531,7 @@ const useGridSizeStore = create(set => ({
|
|
|
455
531
|
* @returns {object} Object containing all coordination values.
|
|
456
532
|
*/
|
|
457
533
|
export function useInitialCoordination(parameters, coordinationScopes) {
|
|
458
|
-
const values =
|
|
534
|
+
const values = useViewConfigStoreShallow((state) => {
|
|
459
535
|
const { coordinationSpace } = state.initialViewConfig;
|
|
460
536
|
return Object.fromEntries(parameters.map((parameter) => {
|
|
461
537
|
if (coordinationSpace && coordinationSpace[parameter]) {
|
|
@@ -464,7 +540,7 @@ export function useInitialCoordination(parameters, coordinationScopes) {
|
|
|
464
540
|
}
|
|
465
541
|
return [parameter, undefined];
|
|
466
542
|
}));
|
|
467
|
-
}
|
|
543
|
+
});
|
|
468
544
|
return values;
|
|
469
545
|
}
|
|
470
546
|
|
|
@@ -487,7 +563,7 @@ export function useInitialCoordination(parameters, coordinationScopes) {
|
|
|
487
563
|
export function useCoordination(parameters, coordinationScopes) {
|
|
488
564
|
const setCoordinationValue = useViewConfigStore(state => state.setCoordinationValue);
|
|
489
565
|
|
|
490
|
-
const values =
|
|
566
|
+
const values = useViewConfigStoreShallow((state) => {
|
|
491
567
|
const { coordinationSpace } = state.viewConfig;
|
|
492
568
|
return Object.fromEntries(parameters.map((parameter) => {
|
|
493
569
|
if (coordinationSpace) {
|
|
@@ -499,7 +575,7 @@ export function useCoordination(parameters, coordinationScopes) {
|
|
|
499
575
|
}
|
|
500
576
|
return [parameter, undefined];
|
|
501
577
|
}));
|
|
502
|
-
}
|
|
578
|
+
});
|
|
503
579
|
|
|
504
580
|
const setters = useMemo(() => Object.fromEntries(parameters.map((parameter) => {
|
|
505
581
|
const setterName = `set${capitalize(parameter)}`;
|
|
@@ -527,10 +603,10 @@ export function useMultiCoordinationScopesNonNull(parameter, coordinationScopes)
|
|
|
527
603
|
|
|
528
604
|
// Return array of coordination scopes,
|
|
529
605
|
// but filter out any whose value is null / falsey.
|
|
530
|
-
const parameterSpace =
|
|
606
|
+
const parameterSpace = useViewConfigStoreShallow((state) => {
|
|
531
607
|
const { coordinationSpace } = state.viewConfig;
|
|
532
608
|
return coordinationSpace?.[parameter];
|
|
533
|
-
}
|
|
609
|
+
});
|
|
534
610
|
const nonNullScopes = useMemo(() => {
|
|
535
611
|
// Convert a single scope to an array of scopes to be consistent.
|
|
536
612
|
const scopesArr = Array.isArray(scopes) ? scopes : [scopes];
|
|
@@ -580,14 +656,14 @@ export function useMultiCoordinationScopesSecondaryNonNull(
|
|
|
580
656
|
) {
|
|
581
657
|
const scopes = getParameterScope(byType, coordinationScopes);
|
|
582
658
|
|
|
583
|
-
const parameterSpace =
|
|
659
|
+
const parameterSpace = useViewConfigStoreShallow((state) => {
|
|
584
660
|
const { coordinationSpace } = state.viewConfig;
|
|
585
661
|
return coordinationSpace?.[parameter];
|
|
586
|
-
}
|
|
587
|
-
const byTypeSpace =
|
|
662
|
+
});
|
|
663
|
+
const byTypeSpace = useViewConfigStoreShallow((state) => {
|
|
588
664
|
const { coordinationSpace } = state.viewConfig;
|
|
589
665
|
return coordinationSpace?.[byType];
|
|
590
|
-
}
|
|
666
|
+
});
|
|
591
667
|
|
|
592
668
|
return useMemo(() => {
|
|
593
669
|
if (scopes && coordinationScopesBy?.[byType]?.[parameter]) {
|
|
@@ -647,7 +723,7 @@ export function useMultiCoordinationValues(parameter, coordinationScopes) {
|
|
|
647
723
|
const scopes = getParameterScope(parameter, coordinationScopes);
|
|
648
724
|
|
|
649
725
|
// Mapping from dataset coordination scope name to dataset uid
|
|
650
|
-
const vals =
|
|
726
|
+
const vals = useViewConfigStoreShallow((state) => {
|
|
651
727
|
const { coordinationSpace } = state.viewConfig;
|
|
652
728
|
// Convert a single scope to an array of scopes to be consistent.
|
|
653
729
|
const scopesArr = Array.isArray(scopes) ? scopes : [scopes];
|
|
@@ -659,7 +735,7 @@ export function useMultiCoordinationValues(parameter, coordinationScopes) {
|
|
|
659
735
|
return [scope, undefined];
|
|
660
736
|
// eslint-disable-next-line no-unused-vars
|
|
661
737
|
}).filter(([k, v]) => v !== undefined));
|
|
662
|
-
}
|
|
738
|
+
});
|
|
663
739
|
|
|
664
740
|
return vals;
|
|
665
741
|
}
|
|
@@ -692,10 +768,10 @@ export function useComplexCoordination(
|
|
|
692
768
|
) {
|
|
693
769
|
const setCoordinationValue = useViewConfigStore(state => state.setCoordinationValue);
|
|
694
770
|
|
|
695
|
-
const parameterSpaces =
|
|
771
|
+
const parameterSpaces = useViewConfigStoreShallow((state) => {
|
|
696
772
|
const { coordinationSpace } = state.viewConfig;
|
|
697
773
|
return parameters.map(parameter => coordinationSpace[parameter]);
|
|
698
|
-
}
|
|
774
|
+
});
|
|
699
775
|
|
|
700
776
|
const values = useMemo(() => {
|
|
701
777
|
const typeScopes = getParameterScope(byType, coordinationScopes);
|
|
@@ -766,10 +842,10 @@ export function useComplexCoordination(
|
|
|
766
842
|
* @returns {object} The coordinationScopes after filling in with meta-coordinationScopes.
|
|
767
843
|
*/
|
|
768
844
|
export function useCoordinationScopes(coordinationScopes) {
|
|
769
|
-
const metaSpace =
|
|
845
|
+
const metaSpace = useViewConfigStoreShallow((state) => {
|
|
770
846
|
const { coordinationSpace } = state.viewConfig;
|
|
771
847
|
return coordinationSpace?.[CoordinationType.META_COORDINATION_SCOPES];
|
|
772
|
-
}
|
|
848
|
+
});
|
|
773
849
|
const vals = useMemo(() => {
|
|
774
850
|
const scopes = getScopes(
|
|
775
851
|
coordinationScopes,
|
|
@@ -790,10 +866,10 @@ export function useCoordinationScopes(coordinationScopes) {
|
|
|
790
866
|
* @returns {object} The coordinationScopesBy after filling in with meta-coordinationScopesBy.
|
|
791
867
|
*/
|
|
792
868
|
export function useCoordinationScopesBy(coordinationScopes, coordinationScopesBy) {
|
|
793
|
-
const metaSpaceBy =
|
|
869
|
+
const metaSpaceBy = useViewConfigStoreShallow((state) => {
|
|
794
870
|
const { coordinationSpace } = state.viewConfig;
|
|
795
871
|
return coordinationSpace?.[CoordinationType.META_COORDINATION_SCOPES_BY];
|
|
796
|
-
}
|
|
872
|
+
});
|
|
797
873
|
const vals = useMemo(() => {
|
|
798
874
|
const scopesBy = getScopesBy(
|
|
799
875
|
coordinationScopes,
|
|
@@ -950,7 +1026,7 @@ export function useAuxiliaryCoordination(parameters, coordinationScopes) {
|
|
|
950
1026
|
const setCoordinationValue = useAuxiliaryStore(state => state.setCoordinationValue);
|
|
951
1027
|
const mappedCoordinationScopes = mapCoordinationScopes(coordinationScopes);
|
|
952
1028
|
const mappedParameters = mapParameters(parameters);
|
|
953
|
-
const values =
|
|
1029
|
+
const values = useAuxiliaryStoreShallow((state) => {
|
|
954
1030
|
const { auxiliaryStore } = state;
|
|
955
1031
|
return Object.fromEntries(mappedParameters.map((parameter) => {
|
|
956
1032
|
if (auxiliaryStore && auxiliaryStore[parameter]) {
|
|
@@ -959,7 +1035,7 @@ export function useAuxiliaryCoordination(parameters, coordinationScopes) {
|
|
|
959
1035
|
}
|
|
960
1036
|
return [parameter, undefined];
|
|
961
1037
|
}));
|
|
962
|
-
}
|
|
1038
|
+
});
|
|
963
1039
|
const setters = useMemo(() => Object.fromEntries(mappedParameters.map((parameter) => {
|
|
964
1040
|
const setterName = `set${capitalize(parameter)}`;
|
|
965
1041
|
const setterFunc = value => setCoordinationValue({
|