@vitessce/vit-s 2.0.2 → 2.0.3

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.
Files changed (172) hide show
  1. package/dist/index.mjs +84801 -0
  2. package/{dist → dist-tsc}/index.js +2 -2
  3. package/package.json +7 -7
  4. package/src/CallbackPublisher.js +81 -0
  5. package/src/LoadingIndicator.js +34 -0
  6. package/src/TitleInfo.js +240 -0
  7. package/src/VitS.js +180 -0
  8. package/src/VitessceGrid.js +110 -0
  9. package/src/VitessceGrid.test.jsx +48 -0
  10. package/src/Warning.js +62 -0
  11. package/{dist → src}/classNames.js +0 -0
  12. package/src/component-registry.js +21 -0
  13. package/src/data/AbstractLoader.js +46 -0
  14. package/{dist → src}/data/AbstractTwoStepLoader.js +5 -4
  15. package/src/data/LoaderResult.js +8 -0
  16. package/{dist → src}/data/index.js +0 -0
  17. package/src/data/loader-registry.js +19 -0
  18. package/src/data-hook-utils.js +197 -0
  19. package/src/data-hooks.js +354 -0
  20. package/src/errors/AbstractLoaderError.js +14 -0
  21. package/src/errors/DataSourceFetchError.js +15 -0
  22. package/src/errors/DatasetNotFoundError.js +23 -0
  23. package/src/errors/LoaderNotFoundError.js +24 -0
  24. package/src/errors/LoaderValidationError.js +23 -0
  25. package/src/errors/OptionsValidationError.js +25 -0
  26. package/{dist → src}/errors/index.js +0 -0
  27. package/src/file-options-schemas-legacy.js +139 -0
  28. package/src/file-options-schemas-legacy.test.js +138 -0
  29. package/src/file-options-schemas.js +327 -0
  30. package/src/file-options-schemas.test.js +26 -0
  31. package/src/hooks.js +252 -0
  32. package/src/index.js +101 -0
  33. package/src/joint-file-types-legacy.js +298 -0
  34. package/src/joint-file-types-legacy.test.js +412 -0
  35. package/src/joint-file-types.js +171 -0
  36. package/src/joint-file-types.test.js +144 -0
  37. package/{dist/schemas.js → src/json-schemas.js} +6 -1
  38. package/{dist → src}/plugins.js +102 -70
  39. package/src/plugins.test.fixtures.js +78 -0
  40. package/src/plugins.test.js +42 -0
  41. package/src/schemas/config-0.1.0.schema.json +85 -0
  42. package/src/schemas/config-1.0.0.schema.json +733 -0
  43. package/src/schemas/config-1.0.1.schema.json +909 -0
  44. package/src/schemas/config-1.0.10.schema.json +969 -0
  45. package/src/schemas/config-1.0.11.schema.json +990 -0
  46. package/src/schemas/config-1.0.12.schema.json +997 -0
  47. package/src/schemas/config-1.0.13.schema.json +1013 -0
  48. package/src/schemas/config-1.0.14.schema.json +1048 -0
  49. package/src/schemas/config-1.0.15.schema.json +1048 -0
  50. package/src/schemas/config-1.0.16.schema.json +1069 -0
  51. package/src/schemas/config-1.0.16.schema.test.js +32 -0
  52. package/src/schemas/config-1.0.2.schema.json +911 -0
  53. package/src/schemas/config-1.0.3.schema.json +911 -0
  54. package/src/schemas/config-1.0.4.schema.json +949 -0
  55. package/src/schemas/config-1.0.5.schema.json +949 -0
  56. package/src/schemas/config-1.0.6.schema.json +950 -0
  57. package/src/schemas/config-1.0.7.schema.json +950 -0
  58. package/src/schemas/config-1.0.8.schema.json +966 -0
  59. package/src/schemas/config-1.0.9.schema.json +965 -0
  60. package/src/schemas/fixtures/cellSets.good.json +16 -0
  61. package/src/schemas/fixtures/config-1.0.1.bad.json +1 -0
  62. package/src/schemas/fixtures/config-1.0.1.bad.message.json +11 -0
  63. package/src/schemas/fixtures/config-1.0.1.good.json +37 -0
  64. package/src/schemas/fixtures/config-1.0.2.bad.json +1 -0
  65. package/src/schemas/fixtures/config-1.0.2.bad.message.json +11 -0
  66. package/src/schemas/fixtures/config-1.0.2.good.json +38 -0
  67. package/src/schemas/fixtures/config-1.0.3.bad.json +1 -0
  68. package/src/schemas/fixtures/config-1.0.3.bad.message.json +11 -0
  69. package/src/schemas/fixtures/config-1.0.3.good.json +38 -0
  70. package/src/schemas/fixtures/obsSets.bad.json +1 -0
  71. package/src/schemas/fixtures/obsSets.bad.message.json +11 -0
  72. package/src/schemas/fixtures/obsSets.good.json +16 -0
  73. package/src/schemas/fixtures/obsSetsTabular.bad.json +1 -0
  74. package/src/schemas/fixtures/obsSetsTabular.bad.message.json +11 -0
  75. package/src/schemas/fixtures/obsSetsTabular.good.json +26 -0
  76. package/src/schemas/fixtures/raster.bad.json +1 -0
  77. package/src/schemas/fixtures/raster.bad.message.json +11 -0
  78. package/src/schemas/fixtures/raster.good.json +39 -0
  79. package/src/schemas/obsSets.schema.js +195 -0
  80. package/src/schemas/obsSetsTabular.schema.js +39 -0
  81. package/src/schemas/raster.schema.js +121 -0
  82. package/src/schemas/schema-schema.sh +34 -0
  83. package/{dist → src}/schemas/schema.test-old.js +0 -1
  84. package/src/shared-mui/components.js +79 -0
  85. package/src/shared-mui/container.js +212 -0
  86. package/src/shared-mui/styles.js +110 -0
  87. package/src/shared-plot-options/CellColorEncodingOption.js +43 -0
  88. package/src/shared-plot-options/OptionSelect.js +19 -0
  89. package/src/shared-plot-options/OptionsContainer.js +26 -0
  90. package/{dist → src}/shared-plot-options/index.js +0 -0
  91. package/src/shared-plot-options/styles.js +49 -0
  92. package/src/state/hooks.js +633 -0
  93. package/src/view-config-upgraders.js +628 -0
  94. package/src/view-config-utils.js +315 -0
  95. package/src/view-config-utils.test.fixtures.js +893 -0
  96. package/src/view-config-utils.test.js +95 -0
  97. package/src/view-config-versions.js +68 -0
  98. package/src/vitessce-grid-layout/VitessceGridLayout.js +158 -0
  99. package/src/vitessce-grid-layout/VitessceGridLayout.test.jsx +56 -0
  100. package/{dist → src}/vitessce-grid-layout/index.js +0 -0
  101. package/src/vitessce-grid-layout/layout-utils.js +76 -0
  102. package/src/vitessce-grid-layout/layout-utils.test.js +167 -0
  103. package/src/vitessce-grid-utils.js +160 -0
  104. package/dist/CallbackPublisher.js +0 -68
  105. package/dist/LoadingIndicator.js +0 -27
  106. package/dist/TitleInfo.js +0 -151
  107. package/dist/VitS.js +0 -112
  108. package/dist/VitessceGrid.js +0 -59
  109. package/dist/VitessceGrid.test.js +0 -36
  110. package/dist/Warning.js +0 -45
  111. package/dist/component-registry.js +0 -16
  112. package/dist/data/AbstractLoader.js +0 -35
  113. package/dist/data/LoaderResult.js +0 -7
  114. package/dist/data/loader-registry.js +0 -15
  115. package/dist/data-hook-utils.js +0 -175
  116. package/dist/data-hooks.js +0 -241
  117. package/dist/errors/AbstractLoaderError.js +0 -13
  118. package/dist/errors/DataSourceFetchError.js +0 -13
  119. package/dist/errors/DatasetNotFoundError.js +0 -17
  120. package/dist/errors/LoaderNotFoundError.js +0 -17
  121. package/dist/errors/LoaderValidationError.js +0 -15
  122. package/dist/errors/OptionsValidationError.js +0 -15
  123. package/dist/file-options-schemas-legacy.js +0 -136
  124. package/dist/file-options-schemas-legacy.test.js +0 -126
  125. package/dist/file-options-schemas.js +0 -322
  126. package/dist/file-options-schemas.test.js +0 -23
  127. package/dist/hooks.js +0 -215
  128. package/dist/joint-file-types-legacy.js +0 -278
  129. package/dist/joint-file-types-legacy.test.js +0 -400
  130. package/dist/joint-file-types.js +0 -148
  131. package/dist/joint-file-types.test.js +0 -139
  132. package/dist/plugins.test.fixtures.js +0 -76
  133. package/dist/plugins.test.js +0 -30
  134. package/dist/schemas/config-0.1.0.schema.json +0 -84
  135. package/dist/schemas/config-1.0.0.schema.json +0 -733
  136. package/dist/schemas/config-1.0.1.schema.json +0 -909
  137. package/dist/schemas/config-1.0.10.schema.json +0 -969
  138. package/dist/schemas/config-1.0.11.schema.json +0 -990
  139. package/dist/schemas/config-1.0.12.schema.json +0 -997
  140. package/dist/schemas/config-1.0.13.schema.json +0 -1013
  141. package/dist/schemas/config-1.0.14.schema.json +0 -1048
  142. package/dist/schemas/config-1.0.15.schema.json +0 -1048
  143. package/dist/schemas/config-1.0.15.schema.test.js +0 -22
  144. package/dist/schemas/config-1.0.2.schema.json +0 -910
  145. package/dist/schemas/config-1.0.3.schema.json +0 -910
  146. package/dist/schemas/config-1.0.4.schema.json +0 -949
  147. package/dist/schemas/config-1.0.5.schema.json +0 -949
  148. package/dist/schemas/config-1.0.6.schema.json +0 -949
  149. package/dist/schemas/config-1.0.7.schema.json +0 -949
  150. package/dist/schemas/config-1.0.8.schema.json +0 -965
  151. package/dist/schemas/config-1.0.9.schema.json +0 -965
  152. package/dist/schemas/obsSets.schema.js +0 -195
  153. package/dist/schemas/obsSetsTabular.schema.js +0 -38
  154. package/dist/schemas/raster.schema.js +0 -120
  155. package/dist/shared-mui/components.js +0 -35
  156. package/dist/shared-mui/container.js +0 -211
  157. package/dist/shared-mui/styles.js +0 -73
  158. package/dist/shared-plot-options/CellColorEncodingOption.js +0 -18
  159. package/dist/shared-plot-options/OptionSelect.js +0 -12
  160. package/dist/shared-plot-options/OptionsContainer.js +0 -12
  161. package/dist/shared-plot-options/styles.js +0 -48
  162. package/dist/state/hooks.js +0 -549
  163. package/dist/view-config-upgraders.js +0 -525
  164. package/dist/view-config-utils.js +0 -286
  165. package/dist/view-config-utils.test.fixtures.js +0 -765
  166. package/dist/view-config-utils.test.js +0 -66
  167. package/dist/view-config-versions.js +0 -47
  168. package/dist/vitessce-grid-layout/VitessceGridLayout.js +0 -95
  169. package/dist/vitessce-grid-layout/VitessceGridLayout.test.js +0 -40
  170. package/dist/vitessce-grid-layout/layout-utils.js +0 -60
  171. package/dist/vitessce-grid-layout/layout-utils.test.js +0 -146
  172. package/dist/vitessce-grid-utils.js +0 -140
@@ -1,18 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import React from 'react';
3
- import TableCell from '@material-ui/core/TableCell';
4
- import TableRow from '@material-ui/core/TableRow';
5
- import { capitalize } from '@vitessce/utils';
6
- import OptionSelect from './OptionSelect';
7
- import { useStyles } from './styles';
8
- export default function CellColorEncodingOption(props) {
9
- const { observationsLabel, cellColorEncoding, setCellColorEncoding, } = props;
10
- const classes = useStyles();
11
- const observationsLabelNice = capitalize(observationsLabel);
12
- function handleColorEncodingChange(event) {
13
- setCellColorEncoding(event.target.value);
14
- }
15
- return (_jsxs(TableRow, { children: [_jsxs(TableCell, { className: classes.labelCell, htmlFor: "cell-color-encoding-select", children: [observationsLabelNice, " Color Encoding"] }), _jsx(TableCell, { className: classes.inputCell, children: _jsxs(OptionSelect, { className: classes.select, value: cellColorEncoding, onChange: handleColorEncodingChange, inputProps: {
16
- id: 'cell-color-encoding-select',
17
- }, children: [_jsx("option", { value: "cellSetSelection", children: "Cell Sets" }), _jsx("option", { value: "geneSelection", children: "Gene Expression" })] }) })] }));
18
- }
@@ -1,12 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from 'react';
3
- import Select from '@material-ui/core/Select';
4
- import { useStyles } from './styles';
5
- export default function OptionSelect(props) {
6
- const { classes: classesProp = {} } = props;
7
- const classes = useStyles();
8
- return (_jsx(Select, { native: true, disableUnderline: true, ...props, classes: {
9
- root: classes.selectRoot,
10
- ...classesProp,
11
- } }));
12
- }
@@ -1,12 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from 'react';
3
- import Box from '@material-ui/core/Box';
4
- import Table from '@material-ui/core/Table';
5
- import TableBody from '@material-ui/core/TableBody';
6
- import TableContainer from '@material-ui/core/TableContainer';
7
- import { useStyles } from './styles';
8
- export default function OptionsContainer(props) {
9
- const { children, } = props;
10
- const classes = useStyles();
11
- return (_jsx(Box, { className: classes.box, children: _jsx(TableContainer, { className: classes.tableContainer, children: _jsx(Table, { className: classes.table, size: "small", children: _jsx(TableBody, { children: children }) }) }) }));
12
- }
@@ -1,48 +0,0 @@
1
- import { makeStyles } from '@material-ui/core/styles';
2
- export const useStyles = makeStyles(theme => ({
3
- box: {
4
- boxSizing: 'border-box',
5
- },
6
- checkbox: {
7
- padding: '3px',
8
- color: theme.palette.primaryForeground,
9
- '&:checked': {
10
- color: theme.palette.primaryForeground,
11
- },
12
- '& input': {
13
- height: '100%',
14
- },
15
- },
16
- slider: {
17
- color: theme.palette.primaryForeground,
18
- minWidth: '60px',
19
- padding: '10px 0 10px 0',
20
- },
21
- sliderValueLabel: {
22
- '& span': {
23
- '& span': {
24
- color: theme.palette.primaryBackground,
25
- },
26
- },
27
- },
28
- tableContainer: {
29
- overflow: 'hidden',
30
- overflowX: 'hidden !important',
31
- },
32
- labelCell: {
33
- padding: '2px 8px 2px 16px',
34
- },
35
- inputCell: {
36
- padding: '2px 16px 2px 8px',
37
- overflow: 'visible',
38
- },
39
- select: {
40
- '& select': {
41
- fontSize: '.875rem',
42
- },
43
- },
44
- selectRoot: {
45
- padding: 0,
46
- height: 'auto',
47
- },
48
- }));
@@ -1,549 +0,0 @@
1
- import { useRef, useCallback, useMemo } from 'react';
2
- import create from 'zustand';
3
- import createContext from 'zustand/context';
4
- import shallow from 'zustand/shallow';
5
- import isMatch from 'lodash/isMatch';
6
- import { CoordinationType } from '@vitessce/constants-internal';
7
- import { fromEntries, capitalize } from '@vitessce/utils';
8
- // Reference: https://github.com/pmndrs/zustand#react-context
9
- // Reference: https://github.com/pmndrs/zustand/blob/e47ea03/tests/context.test.tsx#L60
10
- const { Provider: ViewConfigProviderLocal, useStore: useViewConfigStoreLocal, useStoreApi: useViewConfigStoreApiLocal, } = createContext();
11
- export const ViewConfigProvider = ViewConfigProviderLocal;
12
- export const useViewConfigStore = useViewConfigStoreLocal;
13
- export const useViewConfigStoreApi = useViewConfigStoreApiLocal;
14
- const { Provider: AuxiliaryProviderLocal, useStore: useAuxiliaryStoreLocal, } = createContext();
15
- export const AuxiliaryProvider = AuxiliaryProviderLocal;
16
- export const useAuxiliaryStore = useAuxiliaryStoreLocal;
17
- /**
18
- * The useViewConfigStore hook is initialized via the zustand
19
- * create() function, which sets up both the state variables
20
- * and the reducer-type functions.
21
- * Reference: https://github.com/react-spring/zustand
22
- * @returns {function} The useStore hook.
23
- */
24
- export const createViewConfigStore = () => create(set => ({
25
- // State:
26
- // The viewConfig is an object which must conform to the schema
27
- // found in src/schemas/config.schema.json.
28
- viewConfig: null,
29
- // The loaders object is a mapping from dataset ID to
30
- // data type to loader object instance.
31
- loaders: null,
32
- // Reducer functions which update the state
33
- // (although technically also part of state):
34
- setViewConfig: viewConfig => set({ viewConfig }),
35
- setLoaders: loaders => set({ loaders }),
36
- setCoordinationValue: ({ parameter, scope, value }) => set(state => ({
37
- viewConfig: {
38
- ...state.viewConfig,
39
- coordinationSpace: {
40
- ...state.viewConfig.coordinationSpace,
41
- [parameter]: {
42
- ...state.viewConfig.coordinationSpace[parameter],
43
- [scope]: value,
44
- },
45
- },
46
- },
47
- })),
48
- removeComponent: uid => set((state) => {
49
- const newLayout = state.viewConfig.layout.filter(c => c.uid !== uid);
50
- return {
51
- viewConfig: {
52
- ...state.viewConfig,
53
- layout: newLayout,
54
- },
55
- };
56
- }),
57
- changeLayout: newComponentProps => set((state) => {
58
- const newLayout = state.viewConfig.layout
59
- .slice()
60
- .map(componentProps => ({
61
- ...componentProps,
62
- ...newComponentProps[componentProps.uid],
63
- }));
64
- return {
65
- viewConfig: {
66
- ...state.viewConfig,
67
- layout: newLayout,
68
- },
69
- };
70
- }),
71
- }));
72
- /**
73
- * Hook for getting components' layout from the view config based on
74
- * matching all coordination scopes.
75
- * @returns {Object} The components' layout.
76
- */
77
- export const useComponentLayout = (component, scopes, coordinationScopes) => useViewConfigStore(state => state.viewConfig.layout.filter(l => l.component === component).filter(l => scopes.every(scope => l.coordinationScopes[scope]
78
- === coordinationScopes[scope])));
79
- /**
80
- * The useAuxiliaryStore hook is initialized via the zustand
81
- * create() function, which sets up both the state variables
82
- * and the reducer-type functions.
83
- * Reference: https://github.com/react-spring/zustand
84
- * It is meant to be used for non-viewconfig-based coordination between components.
85
- * For example, as currently happens, the layer controller can coordinate
86
- * on-load callbacks with spatial view based on whether or not they are
87
- * coordinated via `spatialImageLayer` - the callbacks are not part of the view config
88
- * though so they live here.
89
- * @returns {function} The useStore hook.
90
- */
91
- export const createAuxiliaryStore = () => create(set => ({
92
- auxiliaryStore: null,
93
- setCoordinationValue: ({ parameter, scope, value }) => set(state => ({
94
- auxiliaryStore: {
95
- ...state.auxiliaryStore,
96
- [parameter]: {
97
- [scope]: value,
98
- },
99
- },
100
- })),
101
- }));
102
- /**
103
- * The hover store can be used to store global state
104
- * related to which component is currently hovered,
105
- * which is required for tooltip / crossover elements.
106
- * @returns {function} The useStore hook.
107
- */
108
- const useHoverStore = create(set => ({
109
- // Components may need to know if they are the "hover source"
110
- // for tooltip interactions. This value should be a unique
111
- // component ID, such as its index in the view config layout.
112
- componentHover: null,
113
- setComponentHover: componentHover => set({ componentHover }),
114
- }));
115
- /**
116
- * The warning store can be used to store global state
117
- * related to app warning messages.
118
- * @returns {function} The useStore hook.
119
- */
120
- const useWarnStore = create(set => ({
121
- // Want a global state to collect warning messages
122
- // that occur anywhere in the app.
123
- warning: null,
124
- setWarning: warning => set({ warning }),
125
- }));
126
- /**
127
- * The view info store can be used to store component-level
128
- * viewInfo objects,
129
- * which are required for tooltip / crossover elements.
130
- * @returns {function} The useStore hook.
131
- */
132
- const useViewInfoStore = create(set => ({
133
- // The viewInfo object is a mapping from
134
- // component IDs to component view info objects.
135
- // Each view info object must have a project() function.
136
- viewInfo: {},
137
- setComponentViewInfo: (uuid, viewInfo) => set(state => ({
138
- viewInfo: {
139
- ...state.viewInfo,
140
- [uuid]: viewInfo,
141
- },
142
- })),
143
- }));
144
- /**
145
- * The grid size store can be used to store a
146
- * counter which updates on each window or react-grid-layout
147
- * resize event.
148
- * @returns {function} The useStore hook.
149
- */
150
- const useGridSizeStore = create(set => ({
151
- resizeCount: {},
152
- incrementResizeCount: () => set(state => ({
153
- resizeCount: state.resizeCount + 1,
154
- })),
155
- }));
156
- /**
157
- * The useCoordination hook returns both the
158
- * values and setter functions for the coordination objects
159
- * in a particular coordination scope mapping.
160
- * This hook is intended to be used within the ___Subscriber
161
- * components to allow them to "hook into" only those coordination
162
- * objects and setter functions of relevance.
163
- * @param {string[]} parameters Array of coordination types.
164
- * @param {object} coordinationScopes Mapping of coordination types
165
- * to scope names.
166
- * @returns {array} Returns a tuple [values, setters]
167
- * where values is an object containing all coordination values,
168
- * and setters is an object containing all coordination setter
169
- * functions for the values in `values`, named with a "set"
170
- * prefix.
171
- */
172
- export function useCoordination(parameters, coordinationScopes) {
173
- const setCoordinationValue = useViewConfigStore(state => state.setCoordinationValue);
174
- const values = useViewConfigStore((state) => {
175
- const { coordinationSpace } = state.viewConfig;
176
- return fromEntries(parameters.map((parameter) => {
177
- if (coordinationSpace && coordinationSpace[parameter]) {
178
- const value = coordinationSpace[parameter][coordinationScopes[parameter]];
179
- return [parameter, value];
180
- }
181
- return [parameter, undefined];
182
- }));
183
- }, shallow);
184
- const setters = useMemo(() => fromEntries(parameters.map((parameter) => {
185
- const setterName = `set${capitalize(parameter)}`;
186
- const setterFunc = value => setCoordinationValue({
187
- parameter,
188
- scope: coordinationScopes[parameter],
189
- value,
190
- });
191
- return [setterName, setterFunc];
192
- // eslint-disable-next-line react-hooks/exhaustive-deps
193
- })), [parameters, coordinationScopes]);
194
- return [values, setters];
195
- }
196
- export function useMultiCoordinationValues(parameter, coordinationScopes) {
197
- const scopes = coordinationScopes[parameter];
198
- // Mapping from dataset coordination scope name to dataset uid
199
- const vals = useViewConfigStore((state) => {
200
- const { coordinationSpace } = state.viewConfig;
201
- // Convert a single scope to an array of scopes to be consistent.
202
- const scopesArr = Array.isArray(scopes) ? scopes : [scopes];
203
- return fromEntries(scopesArr.map((scope) => {
204
- if (coordinationSpace && coordinationSpace[parameter]) {
205
- const value = coordinationSpace[parameter][scope];
206
- return [scope, value];
207
- }
208
- return [scope, undefined];
209
- // eslint-disable-next-line no-unused-vars
210
- }).filter(([k, v]) => v !== undefined));
211
- }, shallow);
212
- return vals;
213
- }
214
- /**
215
- * Get a mapping from dataset coordination scopes to dataset UIDs.
216
- * @param {object} coordinationScopes The coordination scope mapping object for a view.
217
- * @returns {object} Mapping from dataset coordination scope names to dataset UIDs.
218
- */
219
- export function useDatasetUids(coordinationScopes) {
220
- return useMultiCoordinationValues(CoordinationType.DATASET, coordinationScopes);
221
- }
222
- /**
223
- * Use coordination values and coordination setter functions corresponding to
224
- * dataset-specific coordination scopes for each coordination type.
225
- * @param {string[]} parameters An array of coordination types supported by a view.
226
- * @param {object} coordinationScopes The coordination scope mapping object for a view.
227
- * @returns {array} [cValues, cSetters] where
228
- * cValues is a mapping from coordination scope name to { coordinationType: coordinationValue },
229
- * and cSetters is a mapping from coordination scope name to { setCoordinationType }
230
- * setter functions.
231
- */
232
- export function useMultiDatasetCoordination(parameters, coordinationScopes) {
233
- const setCoordinationValue = useViewConfigStore(state => state.setCoordinationValue);
234
- const datasetScopes = coordinationScopes[CoordinationType.DATASET];
235
- // Convert a single scope to an array of scopes to be consistent.
236
- const datasetScopesArr = Array.isArray(datasetScopes) ? datasetScopes : [datasetScopes];
237
- const values = useViewConfigStore((state) => {
238
- const { coordinationSpace } = state.viewConfig;
239
- return fromEntries(datasetScopesArr.map((datasetScope) => {
240
- const datasetValues = fromEntries(parameters.map((parameter) => {
241
- if (coordinationSpace && coordinationSpace[parameter]) {
242
- let value;
243
- const parameterSpace = coordinationSpace[parameter];
244
- const parameterScope = coordinationScopes[parameter];
245
- if (typeof parameterScope === 'object') {
246
- value = parameterSpace[parameterScope[datasetScope]];
247
- }
248
- else if (typeof parameterScope === 'string') {
249
- value = parameterSpace[parameterScope];
250
- }
251
- else {
252
- console.error(`coordination scope for ${parameter} must be of type string or object.`);
253
- }
254
- return [parameter, value];
255
- }
256
- return [parameter, undefined];
257
- }));
258
- return [datasetScope, datasetValues];
259
- }));
260
- }, shallow);
261
- const setters = useMemo(() => fromEntries(datasetScopesArr.map((datasetScope) => {
262
- const datasetSetters = fromEntries(parameters.map((parameter) => {
263
- const setterName = `set${capitalize(parameter)}`;
264
- let setterFunc;
265
- const parameterScope = coordinationScopes[parameter];
266
- if (typeof parameterScope === 'object') {
267
- setterFunc = value => setCoordinationValue({
268
- parameter,
269
- scope: parameterScope[datasetScope],
270
- value,
271
- });
272
- }
273
- else if (typeof parameterScope === 'string') {
274
- setterFunc = value => setCoordinationValue({
275
- parameter,
276
- scope: parameterScope,
277
- value,
278
- });
279
- }
280
- else {
281
- console.error(`coordination scope for ${parameter} must be of type string or object.`);
282
- }
283
- return [setterName, setterFunc];
284
- }));
285
- return [datasetScope, datasetSetters];
286
- // eslint-disable-next-line react-hooks/exhaustive-deps
287
- })), [parameters, coordinationScopes]);
288
- return [values, setters];
289
- }
290
- const AUXILIARY_COORDINATION_TYPES_MAP = {
291
- spatialImageLayer: ['imageLayerCallbacks', 'areLoadingImageChannels'],
292
- spatialSegmentationLayer: ['segmentationLayerCallbacks', 'areLoadingSegmentationChannels'],
293
- };
294
- /**
295
- * The maps the coordination types of incoming scopes to new types
296
- * for the auxiliary store.
297
- * @param {object} coordinationScopes Mapping of coordination types
298
- * to scope names.
299
- * @returns {object} Mapping of coordination types
300
- * to new scope names for the auxiliary store.
301
- */
302
- const mapCoordinationScopes = (coordinationScopes) => {
303
- const newCoordinationScopes = {};
304
- Object.keys(coordinationScopes).forEach((key) => {
305
- const newCoordinationTypes = AUXILIARY_COORDINATION_TYPES_MAP[key] || [];
306
- newCoordinationTypes.forEach((coordinationType) => {
307
- newCoordinationScopes[coordinationType || key] = coordinationScopes[key];
308
- });
309
- });
310
- return newCoordinationScopes;
311
- };
312
- const mapParameters = parameters => parameters
313
- .map(parameter => AUXILIARY_COORDINATION_TYPES_MAP[parameter]).filter(Boolean).flat();
314
- /**
315
- * The useAuxiliaryCoordination hook returns both the
316
- * values and setter functions for the auxiliary coordination objects
317
- * in a particular coordination scope mapping.
318
- * This hook is intended to be used within the ___Subscriber
319
- * components to allow them to "hook into" only those auxiliary coordination
320
- * objects and setter functions of relevance, for example "on load" callbacks.
321
- * @param {string[]} parameters Array of coordination types.
322
- * @param {object} coordinationScopes Mapping of coordination types
323
- * to scope names.
324
- * @returns {array} Returns a tuple [values, setters]
325
- * where values is an object containing all coordination values,
326
- * and setters is an object containing all coordination setter
327
- * functions for the values in `values`, named with a "set"
328
- * prefix.
329
- */
330
- export function useAuxiliaryCoordination(parameters, coordinationScopes) {
331
- const setCoordinationValue = useAuxiliaryStore(state => state.setCoordinationValue);
332
- const mappedCoordinationScopes = mapCoordinationScopes(coordinationScopes);
333
- const mappedParameters = mapParameters(parameters);
334
- const values = useAuxiliaryStore((state) => {
335
- const { auxiliaryStore } = state;
336
- return fromEntries(mappedParameters.map((parameter) => {
337
- if (auxiliaryStore && auxiliaryStore[parameter]) {
338
- const value = auxiliaryStore[parameter][mappedCoordinationScopes[parameter]];
339
- return [parameter, value];
340
- }
341
- return [parameter, undefined];
342
- }));
343
- }, shallow);
344
- const setters = useMemo(() => fromEntries(mappedParameters.map((parameter) => {
345
- const setterName = `set${capitalize(parameter)}`;
346
- const setterFunc = value => setCoordinationValue({
347
- parameter,
348
- scope: mappedCoordinationScopes[parameter],
349
- value,
350
- });
351
- return [setterName, setterFunc];
352
- // eslint-disable-next-line react-hooks/exhaustive-deps
353
- })), [parameters, coordinationScopes]);
354
- return [values, setters];
355
- }
356
- /**
357
- * Obtain the loaders object from
358
- * the global app state.
359
- * @returns {object} The loaders object
360
- * in the `useViewConfigStore` store.
361
- */
362
- export function useLoaders() {
363
- return useViewConfigStore(state => state.loaders);
364
- }
365
- /**
366
- * Find a specific loader instance for a particular dataset, data type, and view
367
- * coordination values (mapping from coordination types to coordination values).
368
- * Uses lodash/isMatch to perform matching against the file definition's
369
- * coordination value mapping.
370
- * @param {object} loaders The value returned by useLoaders.
371
- * @param {string} dataset The dataset UID.
372
- * @param {string} dataType The data type for the matching file.
373
- * @param {object} viewCoordinationValues Current coordination values
374
- * from the view. Match these against a subset of file definition coordination
375
- * values.
376
- * @returns The matching loader instance or `null`.
377
- */
378
- export function useMatchingLoader(loaders, dataset, dataType, viewCoordinationValues) {
379
- return useMemo(() => {
380
- if (!loaders[dataset]) {
381
- return null;
382
- }
383
- const loaderInternMap = loaders[dataset].loaders[dataType];
384
- if (!loaderInternMap) {
385
- return null;
386
- }
387
- const loaderKeys = Array.from(loaderInternMap.keys());
388
- const matchingKey = loaderKeys
389
- .find(fileCoordinationValues => isMatch(fileCoordinationValues, viewCoordinationValues));
390
- if (!matchingKey) {
391
- return null;
392
- }
393
- return loaderInternMap.get(matchingKey);
394
- }, [loaders, dataset, dataType, viewCoordinationValues]);
395
- }
396
- /**
397
- * Find a specific loader instance for a particular dataset, data type, and view
398
- * coordination values (mapping from coordination types to coordination values).
399
- * Uses lodash/isMatch to perform matching against the file definition's
400
- * coordination value mapping.
401
- * @param {object} loaders The value returned by useLoaders.
402
- * @param {string} dataset The dataset UID.
403
- * @param {string} dataType The data type for the matching file.
404
- * @param {object} viewCoordinationValues Current coordination values
405
- * from the view. Match these against a subset of file definition coordination
406
- * values.
407
- * @returns The matching loader instance or `null`.
408
- */
409
- export function useMatchingLoaders(loaders, dataset, dataType, viewCoordinationValuesObj) {
410
- return useMemo(() => {
411
- if (!loaders[dataset]) {
412
- return null;
413
- }
414
- const loaderInternMap = loaders[dataset].loaders[dataType];
415
- if (!loaderInternMap) {
416
- return null;
417
- }
418
- const loaderKeys = Array.from(loaderInternMap.keys());
419
- function getLoader(viewCoordinationValues) {
420
- const matchingKey = loaderKeys
421
- .find(fileCoordinationValues => isMatch(fileCoordinationValues, viewCoordinationValues));
422
- return loaderInternMap.get(matchingKey);
423
- }
424
- return fromEntries(Object.entries(viewCoordinationValuesObj).map(([key, viewCoordinationValues]) => ([
425
- key,
426
- getLoader(viewCoordinationValues),
427
- ])));
428
- }, [loaders, dataset, dataType, viewCoordinationValuesObj]);
429
- }
430
- /**
431
- * Obtain the view config layout array from
432
- * the global app state.
433
- * @returns {object[]} The layout array
434
- * in the `useViewConfigStore` store.
435
- */
436
- export function useLayout() {
437
- return useViewConfigStore(state => state.viewConfig?.layout);
438
- }
439
- /**
440
- * Obtain the component removal function from
441
- * the global app state.
442
- * @returns {function} The remove component function
443
- * in the `useViewInfoStore` store.
444
- */
445
- export function useRemoveComponent() {
446
- return useViewConfigStore(state => state.removeComponent);
447
- }
448
- /**
449
- * Obtain the component prop setter function from
450
- * the global app state.
451
- * @returns {function} The set component props function
452
- * in the `useViewInfoStore` store.
453
- */
454
- export function useChangeLayout() {
455
- return useViewConfigStore(state => state.changeLayout);
456
- }
457
- /**
458
- * Obtain the loaders setter function from
459
- * the global app state.
460
- * @returns {function} The loaders setter function
461
- * in the `useViewConfigStore` store.
462
- */
463
- export function useSetLoaders() {
464
- return useViewConfigStore(state => state.setLoaders);
465
- }
466
- /**
467
- * Obtain the view config setter function from
468
- * the global app state.
469
- * @returns {function} The view config setter function
470
- * in the `useViewConfigStore` store.
471
- */
472
- export function useSetViewConfig(viewConfigStoreApi) {
473
- const setViewConfigRef = useRef(viewConfigStoreApi.getState().setViewConfig);
474
- const setViewConfig = setViewConfigRef.current;
475
- return setViewConfig;
476
- }
477
- /**
478
- * Obtain the component hover value from
479
- * the global app state.
480
- * @returns {number} The hovered component ID
481
- * in the `useHoverStore` store.
482
- */
483
- export function useComponentHover() {
484
- return useHoverStore(state => state.componentHover);
485
- }
486
- /**
487
- * Obtain the component hover setter function from
488
- * the global app state.
489
- * @returns {function} The component hover setter function
490
- * in the `useHoverStore` store.
491
- */
492
- export function useSetComponentHover() {
493
- return useHoverStore(state => state.setComponentHover);
494
- }
495
- /**
496
- * Obtain the warning message from
497
- * the global app state.
498
- * @returns {string} The warning message
499
- * in the `useWarnStore` store.
500
- */
501
- export function useWarning() {
502
- return useWarnStore(state => state.warning);
503
- }
504
- /**
505
- * Obtain the warning setter function from
506
- * the global app state.
507
- * @returns {function} The warning setter function
508
- * in the `useWarnStore` store.
509
- */
510
- export function useSetWarning() {
511
- return useWarnStore(state => state.setWarning);
512
- }
513
- /**
514
- * Obtain the component view info value from
515
- * the global app state.
516
- * @returns {object} The view info object for the component
517
- * in the `useViewInfoStore` store.
518
- */
519
- export function useComponentViewInfo(uuid) {
520
- return useViewInfoStore(useCallback(state => state.viewInfo[uuid], [uuid]));
521
- }
522
- /**
523
- * Obtain the component view info setter function from
524
- * the global app state.
525
- * @returns {function} The component view info setter function
526
- * in the `useViewInfoStore` store.
527
- */
528
- export function useSetComponentViewInfo(uuid) {
529
- const setViewInfoRef = useRef(useViewInfoStore.getState().setComponentViewInfo);
530
- const setComponentViewInfo = viewInfo => setViewInfoRef.current(uuid, viewInfo);
531
- return setComponentViewInfo;
532
- }
533
- /**
534
- * Obtain the grid resize count value
535
- * from the global app state.
536
- * @returns {number} The grid resize increment value.
537
- */
538
- export function useGridResize() {
539
- return useGridSizeStore(state => state.resizeCount);
540
- }
541
- /**
542
- * Obtain the grid resize count increment function
543
- * from the global app state.
544
- * @returns {function} The grid resize count increment
545
- * function.
546
- */
547
- export function useEmitGridResize() {
548
- return useGridSizeStore(state => state.incrementResizeCount);
549
- }