@aics/vole-app 2.15.0 → 3.1.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.
Files changed (79) hide show
  1. package/es/aics-image-viewer/components/App/ChannelUpdater.js +21 -3
  2. package/es/aics-image-viewer/components/App/index.js +156 -199
  3. package/es/aics-image-viewer/components/CellViewerCanvasWrapper/index.js +10 -9
  4. package/es/aics-image-viewer/components/ChannelsWidget.js +35 -22
  5. package/es/aics-image-viewer/components/ChannelsWidgetRow/index.js +27 -71
  6. package/es/aics-image-viewer/components/ChannelsWidgetRow/styles.css +0 -6
  7. package/es/aics-image-viewer/components/ColorPicker.js +1 -1
  8. package/es/aics-image-viewer/components/ControlPanel/index.js +5 -4
  9. package/es/aics-image-viewer/components/CustomizeWidget.js +12 -8
  10. package/es/aics-image-viewer/components/ErrorAlert/index.js +4 -4
  11. package/es/aics-image-viewer/components/GlobalVolumeControls.js +12 -10
  12. package/es/aics-image-viewer/components/StyleProvider/index.js +4 -2
  13. package/es/aics-image-viewer/components/TfEditor/index.js +304 -154
  14. package/es/aics-image-viewer/components/TfEditor/styles.css +53 -31
  15. package/es/aics-image-viewer/components/Toolbar/DownloadButton.js +1 -1
  16. package/es/aics-image-viewer/components/Toolbar/index.js +18 -16
  17. package/es/aics-image-viewer/components/shared/SharedCheckBox.js +1 -1
  18. package/es/aics-image-viewer/components/shared/SliderRow/styles.css +1 -0
  19. package/es/aics-image-viewer/components/shared/SmarterSlider.js +1 -1
  20. package/es/aics-image-viewer/components/shared/ViewerIcon.js +1 -1
  21. package/es/aics-image-viewer/components/useVolume.js +59 -58
  22. package/es/aics-image-viewer/shared/constants.js +2 -2
  23. package/es/aics-image-viewer/shared/utils/controlPointsToLut.js +57 -24
  24. package/es/aics-image-viewer/shared/utils/sceneStore.js +5 -3
  25. package/es/aics-image-viewer/shared/utils/storage.js +238 -0
  26. package/es/aics-image-viewer/shared/utils/test/storage.test.js +264 -0
  27. package/es/aics-image-viewer/shared/utils/test/urlParsing.test.js +240 -108
  28. package/es/aics-image-viewer/shared/utils/test/viewerChannelSettings.test.js +1 -1
  29. package/es/aics-image-viewer/shared/utils/urlParsing.js +278 -153
  30. package/es/aics-image-viewer/shared/utils/viewerState.js +4 -24
  31. package/es/aics-image-viewer/state/reset.js +111 -0
  32. package/es/aics-image-viewer/state/store.js +90 -0
  33. package/es/aics-image-viewer/state/subscribers.js +153 -0
  34. package/es/aics-image-viewer/state/test/reset.test.js +247 -0
  35. package/es/aics-image-viewer/state/util.js +71 -0
  36. package/es/index.js +3 -3
  37. package/package.json +18 -11
  38. package/type-declarations/aics-image-viewer/components/App/ChannelUpdater.d.ts +2 -4
  39. package/type-declarations/aics-image-viewer/components/App/types.d.ts +3 -3
  40. package/type-declarations/aics-image-viewer/components/AxisClipSliders/index.d.ts +6 -6
  41. package/type-declarations/aics-image-viewer/components/CellViewerCanvasWrapper/index.d.ts +5 -14
  42. package/type-declarations/aics-image-viewer/components/ChannelsWidget.d.ts +3 -6
  43. package/type-declarations/aics-image-viewer/components/ChannelsWidgetRow/index.d.ts +3 -6
  44. package/type-declarations/aics-image-viewer/components/ColorPicker.d.ts +1 -1
  45. package/type-declarations/aics-image-viewer/components/ControlPanel/index.d.ts +6 -7
  46. package/type-declarations/aics-image-viewer/components/CustomizeWidget.d.ts +2 -8
  47. package/type-declarations/aics-image-viewer/components/ErrorAlert/index.d.ts +4 -0
  48. package/type-declarations/aics-image-viewer/components/GlobalVolumeControls.d.ts +2 -9
  49. package/type-declarations/aics-image-viewer/components/MetadataViewer/index.d.ts +1 -1
  50. package/type-declarations/aics-image-viewer/components/StyleProvider/index.d.ts +1 -1
  51. package/type-declarations/aics-image-viewer/components/TfEditor/index.d.ts +10 -3
  52. package/type-declarations/aics-image-viewer/components/Toolbar/index.d.ts +3 -12
  53. package/type-declarations/aics-image-viewer/components/shared/SliderRow/index.d.ts +1 -1
  54. package/type-declarations/aics-image-viewer/components/shared/SmarterSlider.d.ts +1 -1
  55. package/type-declarations/aics-image-viewer/components/shared/ViewerIcon.d.ts +1 -1
  56. package/type-declarations/aics-image-viewer/components/useVolume.d.ts +7 -4
  57. package/type-declarations/aics-image-viewer/shared/constants.d.ts +5 -5
  58. package/type-declarations/aics-image-viewer/shared/types.d.ts +1 -1
  59. package/type-declarations/aics-image-viewer/shared/utils/controlPointsToLut.d.ts +9 -5
  60. package/type-declarations/aics-image-viewer/shared/utils/firebase/index.d.ts +1 -1
  61. package/type-declarations/aics-image-viewer/shared/utils/hooks.d.ts +1 -1
  62. package/type-declarations/aics-image-viewer/shared/utils/playControls.d.ts +1 -1
  63. package/type-declarations/aics-image-viewer/shared/utils/sceneStore.d.ts +8 -4
  64. package/type-declarations/aics-image-viewer/shared/utils/storage.d.ts +15 -0
  65. package/type-declarations/aics-image-viewer/shared/utils/urlParsing.d.ts +94 -31
  66. package/type-declarations/aics-image-viewer/shared/utils/viewerChannelSettings.d.ts +39 -1
  67. package/type-declarations/aics-image-viewer/shared/utils/viewerState.d.ts +3 -6
  68. package/type-declarations/aics-image-viewer/state/reset.d.ts +29 -0
  69. package/type-declarations/aics-image-viewer/state/store.d.ts +30 -0
  70. package/type-declarations/aics-image-viewer/state/subscribers.d.ts +4 -0
  71. package/type-declarations/aics-image-viewer/state/types.d.ts +46 -0
  72. package/type-declarations/aics-image-viewer/state/util.d.ts +8 -0
  73. package/type-declarations/index.d.ts +4 -4
  74. package/es/aics-image-viewer/components/ViewerStateProvider/ResetStateProvider.js +0 -163
  75. package/es/aics-image-viewer/components/ViewerStateProvider/index.js +0 -259
  76. package/type-declarations/aics-image-viewer/components/ViewerStateProvider/ResetStateProvider.d.ts +0 -34
  77. package/type-declarations/aics-image-viewer/components/ViewerStateProvider/index.d.ts +0 -33
  78. package/type-declarations/aics-image-viewer/components/ViewerStateProvider/types.d.ts +0 -107
  79. /package/es/aics-image-viewer/{components/ViewerStateProvider → state}/types.js +0 -0
@@ -1,23 +1,29 @@
1
- import { CameraState } from "@aics/vole-core";
2
- import { FirebaseFirestore } from "@firebase/firestore-types";
1
+ import type { CameraState } from "@aics/vole-core";
2
+ import type { FirebaseFirestore } from "@firebase/firestore-types";
3
3
  import type { AppProps } from "../../components/App/types";
4
- import type { ChannelState, ViewerState, ViewerStateContextType } from "../../components/ViewerStateProvider/types";
4
+ import type { ViewerStore } from "../../state/store";
5
+ import type { ChannelState, ViewerState } from "../../state/types";
5
6
  import { ViewMode } from "../enums";
6
7
  import type { MetadataRecord } from "../types";
7
- import { ColorArray } from "./colorRepresentations";
8
+ import type { ColorArray } from "./colorRepresentations";
8
9
  import type { ViewerChannelSetting } from "./viewerChannelSettings";
9
10
  export declare const ENCODED_COMMA_REGEX: RegExp;
10
11
  export declare const ENCODED_COLON_REGEX: RegExp;
11
12
  /**
12
13
  * LEGACY: Matches a COMMA-separated list of control points, where each control point is represented
13
14
  * by a triplet of `{x}:{opacity}:{hex color}`.
14
- * The hex color can be replaced with `w` to represent white (`ffffff`).
15
+ * The hex color can be replaced with `1` to represent white (`ffffff`).
15
16
  */
16
17
  export declare const LEGACY_CONTROL_POINTS_REGEX: RegExp;
17
18
  /**
18
- * Matches a COLON-separated list of control points, where each control point is represented
19
- * by a triplet of `{x}:{opacity}:{hex color}`.
20
- * The hex color can be replaced with `w` to represent white (`ffffff`).
19
+ * Matches a COLON-separated list of control points, where each control point is
20
+ * represented by a triplet of `{x}:{opacity}:{hex color}`.
21
+ * - `x` is a value that will either be parsed as a histogram bin index (legacy,
22
+ * for `ControlPointsLegacy`) or intensity value (for `ControlPoints`),
23
+ * depending on on which field is being parsed.
24
+ * - Opacity is a float in the [0, 1] range.
25
+ * - The hex color is a 6-digit hex color (e.g. `ffeecc`), and can be replaced
26
+ * with `1` to represent white (`ffffff`).
21
27
  */
22
28
  export declare const CONTROL_POINTS_REGEX: RegExp;
23
29
  /**
@@ -65,12 +71,15 @@ export declare enum ViewerChannelSettingKeys {
65
71
  ColorizeAlpha = "cza",
66
72
  IsosurfaceAlpha = "isa",
67
73
  Lut = "lut",
68
- Ramp = "rmp",
69
- ControlPoints = "cps",
74
+ ControlPoints = "cpt",
75
+ ControlPointsLegacy = "cps",
76
+ Ramp = "ram",
77
+ RampLegacy = "rmp",
70
78
  ControlPointsEnabled = "cpe",
71
79
  VolumeEnabled = "ven",
72
80
  SurfaceEnabled = "sen",
73
- IsosurfaceValue = "isv"
81
+ IsosurfaceValue = "isv",
82
+ KeepRange = "pin"
74
83
  }
75
84
  /**
76
85
  * The serialized form of a ViewerChannelSetting, as a dictionary object.
@@ -112,12 +121,24 @@ export declare class ViewerChannelSettingParams {
112
121
  */
113
122
  [ViewerChannelSettingKeys.Lut]?: string;
114
123
  /**
115
- * Control points for the transfer function. If provided, overrides the
116
- * `lut` field when calculating the control points. Should be a list
117
- * of `x:opacity:color` triplets, separated by colon.
124
+ * Legacy specifier for control points for the transfer function as a list of
125
+ * `x:opacity:color` triplets, separated by colon. Uses histogram bin indices
126
+ * instead of intensity values.
127
+ * - `x` is a histogram bin index in the [0, 255] range.
128
+ * - `opacity` is a float in the [0, 1] range.
129
+ * - `color` is a 6-digit hex color, e.g. `ff0000`.
130
+ *
131
+ * Will be overridden by the ControlPoints field (`cpt`) if provided.
132
+ */
133
+ [ViewerChannelSettingKeys.ControlPointsLegacy]?: string;
134
+ /**
135
+ * Control points for the transfer function, formatted as a list of
136
+ * `x:opacity:color` triplets, separated by colons.
118
137
  * - `x` is a numeric intensity value.
119
138
  * - `opacity` is a float in the [0, 1] range.
120
139
  * - `color` is a 6-digit hex color, e.g. `ff0000`.
140
+ *
141
+ * If provided, overrides the `lut` field when calculating the control points.
121
142
  */
122
143
  [ViewerChannelSettingKeys.ControlPoints]?: string;
123
144
  /**
@@ -126,8 +147,14 @@ export declare class ViewerChannelSettingParams {
126
147
  */
127
148
  [ViewerChannelSettingKeys.ControlPointsEnabled]?: "1" | "0";
128
149
  /**
129
- * Raw ramp values, which should be two numeric values separated by a colon.
130
- * If provided, overrides the `lut` field when calculating the ramp values.
150
+ * Legacy specifier for the transfer function ramp which uses histogram bin
151
+ * indices instead of intensity values, formatted as `min:max`. Will be
152
+ * overridden by the Ramp field (`ram`) if provided.
153
+ */
154
+ [ViewerChannelSettingKeys.RampLegacy]?: string;
155
+ /**
156
+ * Ramp min and max intensity values (`min:max`). If provided, overrides the
157
+ * `lut` field when calculating the ramp.
131
158
  */
132
159
  [ViewerChannelSettingKeys.Ramp]?: string;
133
160
  /** Volume enabled. "1" is enabled. Disabled by default. */
@@ -136,6 +163,11 @@ export declare class ViewerChannelSettingParams {
136
163
  [ViewerChannelSettingKeys.SurfaceEnabled]?: "1" | "0";
137
164
  /** Isosurface value, in the [0, 255] range. Set to `128` by default. */
138
165
  [ViewerChannelSettingKeys.IsosurfaceValue]?: string;
166
+ /**
167
+ * Whether to keep the current contrast settings when loading a new volume.
168
+ * "1" is enabled. Disabled by default.
169
+ */
170
+ [ViewerChannelSettingKeys.KeepRange]?: "1" | "0";
139
171
  }
140
172
  /**
141
173
  * Channels, matching the pattern `c0`, `c1`, etc. corresponding to the index of the channel being configured.
@@ -209,8 +241,15 @@ export declare class ViewerStateParams {
209
241
  /** URL parameters that define data sources when loading volumes. */
210
242
  declare class DataParams {
211
243
  /**
212
- * One or more volume URLs to load. If multiple URLs are provided, they should
213
- * be separated by commas.
244
+ * One or more volume URLs to load.
245
+ *
246
+ * This parameter may represent a single image with multiple data sources by delimiting each source URL with `,`.
247
+ * It may also represent multiple scenes by delimiting each scene URL (and/or each collection of multiple
248
+ * `,`-delimited source URLs) with `+`. E.g. `url1+url2,url3` represents a collection of two scenes, where the first
249
+ * scene comes from `url1` and the second is a combination of the channels from the images at `url2` and `url3`.
250
+ *
251
+ * When parsing, we do our best to account for `%`-encoding, including the possibility that each source/scene URL was
252
+ * encoded separately, then concatenated with the proper delimiters, then encoded again.
214
253
  */
215
254
  url?: string;
216
255
  /**
@@ -221,14 +260,24 @@ declare class DataParams {
221
260
  * See `ManifestJson` for the type definition.
222
261
  */
223
262
  manifest?: string;
224
- /**
225
- * The name of a dataset in the Cell Feature Explorer database. Used with `id`.
226
- */
263
+ /** The name of a dataset in the Cell Feature Explorer database. Used with `id`. */
227
264
  dataset?: string;
265
+ /** The ID of a cell within the loaded dataset. Used with `dataset`. */
266
+ id?: string;
267
+ /** The key of a collection of scenes stored in local storage. Overrides `url`. */
268
+ collectionid?: string;
228
269
  /**
229
- * The ID of a cell within the loaded dataset. Used with `dataset`.
270
+ * The origin of an opening window that wants to send a message to this window.
271
+ *
272
+ * The presence of this param implies that this window has just been opened by another app, and the opening app has
273
+ * more data to send. Until that message is received, we fall back to `url`. Once that message arrives, the scenes to
274
+ * open are written to local storage at a new `collectionid` and `msgorigin` is removed, allowing the window to
275
+ * switch to reading local storage.
276
+ *
277
+ * All this happens independently of URL parsing, so the only meaningful thing this parsing code does with this param
278
+ * is check whether it is present.
230
279
  */
231
- id?: string;
280
+ msgorigin?: string;
232
281
  }
233
282
  declare class DeprecatedParams {
234
283
  /** Deprecated query parameter for channel settings. */
@@ -239,6 +288,18 @@ declare class DeprecatedParams {
239
288
  colors?: string;
240
289
  }
241
290
  type AppParams = Partial<ViewerStateParams & DataParams & DeprecatedParams & ChannelParams>;
291
+ /**
292
+ * A message sent from an external application after this app was opened,
293
+ * containing data that was too large to pack into the URL.
294
+ */
295
+ type ViewerMessage = {
296
+ /** A (possibly very long) list of scene URLs. */
297
+ scenes?: string[];
298
+ /** A (likely very large) list of metadata records for each scene. */
299
+ meta?: Record<string, MetadataRecord>;
300
+ /** The scene to open once this message arrives. */
301
+ sceneIndex?: number;
302
+ };
242
303
  /**
243
304
  * Filters a set of URLSearchParams for only the keys that are valid parameters for the viewer.
244
305
  * Non-matching keys are discarded.
@@ -246,6 +307,8 @@ type AppParams = Partial<ViewerStateParams & DataParams & DeprecatedParams & Cha
246
307
  * @returns a dictionary object matching the type of `Params`.
247
308
  */
248
309
  export declare function getAllowedParams(searchParams: URLSearchParams): AppParams;
310
+ /** Parses the `url` query param into a 2D URL array: one or more scenes, with one or more sources per scene. */
311
+ export declare const parseImageURLParam: (urlParam: string) => string[][];
249
312
  /**
250
313
  * Parse a string list of comma-separated key:value pairs into
251
314
  * a key-value object.
@@ -319,26 +382,26 @@ export declare function loadFromManifest(manifestUrl: string): Promise<{
319
382
  }>;
320
383
  /**
321
384
  * Parses a set of URL search parameters into props for the viewer.
322
- * @param urlSearchParams The URLSearchParams object to parse.
323
- * @param firestore Optional Firestore instance. If provided, the function can
324
- * load data from a Firestore dataset if the `dataset` and `id` parameters are
325
- * provided.
385
+ * @param search The query string to parse, which must be valid in the `URLSearchParams constructor
386
+ * @param firestore Optional Firestore instance. If provided, the function can load data from a
387
+ * Firestore dataset if the `dataset` and `id` parameters are provided.
326
388
  * @returns An object containing:
327
389
  * - `args`: Partial AppProps object.
328
390
  * - `viewerSettings`: Partial ViewerState object.
329
391
  *
330
- * `args` can be passed as props to the `ImageViewerApp`, and `viewerSettings`
331
- * can be passed to `ViewerStateProvider`.
392
+ * `args` can be passed as props to the `ImageViewerApp`, and `viewerSettings` can be passed to `ViewerStateProvider`.
332
393
  */
333
- export declare function parseViewerUrlParams(urlSearchParams: URLSearchParams, firestore?: FirebaseFirestore): Promise<{
394
+ export declare function parseViewerUrlParams(search: string, firestore?: FirebaseFirestore): Promise<{
334
395
  args: Partial<AppProps>;
335
396
  viewerSettings: Partial<ViewerState>;
336
397
  }>;
398
+ /** Adds the data in a newly-arrived `ViewerMessage` to an existing stored `AppProps` instance. */
399
+ export declare function addViewerParamsFromMessage<P extends Pick<AppProps, "imageUrl" | "metadata">>(args: P, message: ViewerMessage): P;
337
400
  /**
338
401
  * Serializes the ViewerState and ChannelState of a ViewerStateContext into a URLSearchParams object.
339
402
  * @param state ViewerStateContext to serialize.
340
403
  * @param removeDefaults If true, shortens parameters by removing any properties that match the default state.
341
404
  * This includes the output of GET_DEFAULT_VIEWER_STATE and GET_DEFAULT_CHANNEL_STATE.
342
405
  */
343
- export declare function serializeViewerUrlParams(state: Partial<ViewerStateContextType>, removeDefaults?: boolean): AppParams;
406
+ export declare function serializeViewerUrlParams(state: Partial<ViewerStore>, removeDefaults?: boolean): AppParams;
344
407
  export {};
@@ -1,4 +1,28 @@
1
- import { ControlPoint } from "@aics/vole-core";
1
+ import type { ControlPoint } from "@aics/vole-core";
2
+ export type IntensitySettings = {
3
+ /**
4
+ * Defines a linear function for mapping from intensity values in the volume
5
+ * to opacity between two [min, max] intensity values.
6
+ */
7
+ ramp?: [number, number];
8
+ /**
9
+ * Defines a piecewise linear function for mapping from intensity values in
10
+ * the volume to opacity and color.
11
+ */
12
+ controlPoints?: ControlPoint[];
13
+ /**
14
+ * Min and max values for the intensity lookup table, which maps from raw intensity values
15
+ * in the volume to opacity and color. Defaults to [0, 255].
16
+ *
17
+ * - Plain numbers are indices of histogram bins, in the range [0, 255].
18
+ * - `v{n}` represents a raw intensity value, where `n` is an integer.
19
+ * - `p{n}` represents a percentile, where `n` is a percentile in the [0, 100] range.
20
+ * - `m{n}` represents the median multiplied by `n / 100`.
21
+ * - `autoij` in either the min or max fields will use the "auto" algorithm
22
+ * from ImageJ to select the min and max.
23
+ */
24
+ lut?: [string, string];
25
+ };
2
26
  /** Settings for a single channel, as passed in via props by App users */
3
27
  export interface ViewerChannelSetting {
4
28
  match: (string | number)[] | string | number;
@@ -16,6 +40,8 @@ export interface ViewerChannelSetting {
16
40
  * - `m{n}` represents the median multiplied by `n / 100`.
17
41
  * - `autoij` in either the min or max fields will use the "auto" algorithm
18
42
  * from ImageJ to select the min and max.
43
+ * @deprecated Will be removed in a future update. Specify via `intensity.lut`
44
+ * instead.
19
45
  */
20
46
  lut?: [string, string];
21
47
  /**
@@ -23,12 +49,24 @@ export interface ViewerChannelSetting {
23
49
  * Defaults to false.
24
50
  */
25
51
  controlPointsEnabled?: boolean;
52
+ /**
53
+ * Control points for the transfer function, as histogram bin values.
54
+ * @deprecated Will be removed in a future update. Specify via `intensity.controlPoints` instead.
55
+ */
26
56
  controlPoints?: ControlPoint[];
57
+ /**
58
+ * Min and max ramp values for the transfer function, as histogram bin values.
59
+ * @deprecated Will be removed in a future update. Specify via
60
+ * `intensity.ramp` instead.
61
+ */
27
62
  ramp?: [number, number];
63
+ intensity?: IntensitySettings;
28
64
  isovalue?: number;
29
65
  surfaceOpacity?: number;
30
66
  colorizeEnabled?: boolean;
31
67
  colorizeAlpha?: number;
68
+ /** Whether to keep the current contrast settings when switching volumes. */
69
+ keepIntensityRange?: boolean;
32
70
  }
33
71
  export interface ViewerChannelGroup {
34
72
  name: string;
@@ -1,9 +1,6 @@
1
- import { ChannelState, ViewerSettingUpdater, ViewerState } from "../../components/ViewerStateProvider/types";
2
- import { ColorArray } from "./colorRepresentations";
3
- import { ViewerChannelSettings } from "./viewerChannelSettings";
4
- /** Sets all fields of the viewer state to the values of the `newState`. */
5
- export declare function overrideViewerState(changeViewerSetting: ViewerSettingUpdater, newState: ViewerState): void;
6
- export declare function overrideChannelStates(setChannelSettings: (settings: ChannelState[]) => void, currentStates: ChannelState[], newStates: ChannelState[]): void;
1
+ import type { ChannelState } from "../../state/types";
2
+ import type { ColorArray } from "./colorRepresentations";
3
+ import type { ViewerChannelSettings } from "./viewerChannelSettings";
7
4
  /** Returns the indices of channels that have either the volume or isosurface enabled. */
8
5
  export declare function getEnabledChannelIndices(channelSettings: ChannelState[]): number[];
9
6
  export declare function colorHexToArray(hex: string): ColorArray | null;
@@ -0,0 +1,29 @@
1
+ import type { StateCreator } from "zustand";
2
+ import type { ViewerChannelSettings } from "../shared/utils/viewerChannelSettings";
3
+ import type { ViewerState } from "../state/types";
4
+ import type { ViewerStore } from "./store";
5
+ export type ResetStateActions = {
6
+ /**
7
+ * Removes the channel from the list of channels to be reset (as given by
8
+ * `getChannelsAwaitingReset()` or `getChannelsAwaitingResetOnLoad()`).
9
+ */
10
+ onResetChannel: (channelIndex: number) => void;
11
+ /**
12
+ * Resets the viewer and all channels to a saved initial state, determined
13
+ * by viewer props.
14
+ */
15
+ resetToSavedViewerState: (savedState?: Partial<ViewerState>, viewerChannelSettings?: ViewerChannelSettings) => void;
16
+ /**
17
+ * Resets the viewer and all channels to the default state, as though
18
+ * loaded from scratch with no initial parameters set.
19
+ * Uses the default channel settings as given by `getDefaultViewerChannelSettings()`.
20
+ */
21
+ resetToDefaultViewerState: () => void;
22
+ };
23
+ export type ResetState = {
24
+ useDefaultViewerChannelSettings: boolean;
25
+ channelsToReset: number[];
26
+ channelsToResetOnLoad: number[];
27
+ };
28
+ export type ResetStateSlice = ResetStateActions & ResetState;
29
+ export declare const createResetSlice: StateCreator<ViewerStore, [], [], ResetStateSlice>;
@@ -0,0 +1,30 @@
1
+ import type { ColorArray } from "../shared/utils/colorRepresentations";
2
+ import { type ResetStateSlice } from "./reset";
3
+ import type { ChannelState, ViewerState } from "./types";
4
+ export type ViewerStateActions = {
5
+ changeViewerSetting: <K extends keyof ViewerState>(key: K, value: Partial<ViewerState[K]>) => void;
6
+ mergeViewerSettings: (value: Partial<{
7
+ [K in keyof ViewerState]: Partial<ViewerState[K]>;
8
+ }>) => void;
9
+ changeChannelSetting: <K extends keyof ChannelState>(index: number | number[], value: Partial<Record<K, ChannelState[K]>>) => void;
10
+ replaceAllChannelSettings: (channelSettings: ChannelState[]) => void;
11
+ applyColorPresets: (colors: ColorArray[]) => void;
12
+ };
13
+ export type ViewerStore = ViewerState & ViewerStateActions & ResetStateSlice & {
14
+ channelSettings: ChannelState[];
15
+ };
16
+ export declare const useViewerState: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<ViewerStore>, "subscribe"> & {
17
+ subscribe: {
18
+ (listener: (selectedState: ViewerStore, previousSelectedState: ViewerStore) => void): () => void;
19
+ <U>(selector: (state: ViewerStore) => U, listener: (selectedState: U, previousSelectedState: U) => void, options?: {
20
+ equalityFn?: ((a: U, b: U) => boolean) | undefined;
21
+ fireImmediately?: boolean;
22
+ } | undefined): () => void;
23
+ };
24
+ }>;
25
+ export declare const selectViewerSettings: (store: ViewerStore) => ViewerState;
26
+ /**
27
+ * A small boilerplate-reducer for subscribing to a single state value with `useViewerStore`.
28
+ * Should only be used with string literals for best type-checking results.
29
+ */
30
+ export declare const select: <K extends string>(key: K) => <V>(settings: Record<K, V>) => Record<K, V>[K];
@@ -0,0 +1,4 @@
1
+ import { type View3d, type Volume } from "@aics/vole-core";
2
+ import { type useViewerState } from "./store";
3
+ export declare const subscribeViewToState: (store: typeof useViewerState, view3d: View3d) => (() => void);
4
+ export declare const subscribeImageToState: (store: typeof useViewerState, view3d: View3d, image: Volume) => (() => void);
@@ -0,0 +1,46 @@
1
+ import type { CameraState, ControlPoint } from "@aics/vole-core";
2
+ import type { ImageType, RenderMode, ViewMode } from "../shared/enums";
3
+ import type { PerAxis } from "../shared/types";
4
+ import type { ColorArray } from "../shared/utils/colorRepresentations";
5
+ /** Global (not per-channel) viewer state which may be changed in the UI */
6
+ export type ViewerState = {
7
+ viewMode: ViewMode;
8
+ renderMode: RenderMode;
9
+ imageType: ImageType;
10
+ showAxes: boolean;
11
+ showBoundingBox: boolean;
12
+ boundingBoxColor: ColorArray;
13
+ backgroundColor: ColorArray;
14
+ autorotate: boolean;
15
+ maskAlpha: number;
16
+ brightness: number;
17
+ density: number;
18
+ levels: [number, number, number];
19
+ interpolationEnabled: boolean;
20
+ region: PerAxis<[number, number]>;
21
+ slice: PerAxis<number>;
22
+ time: number;
23
+ scene: number;
24
+ cameraState: Partial<CameraState> | undefined;
25
+ };
26
+ export type ChannelState = {
27
+ name: string;
28
+ displayName: string;
29
+ volumeEnabled: boolean;
30
+ isosurfaceEnabled: boolean;
31
+ isovalue: number;
32
+ colorizeEnabled: boolean;
33
+ colorizeAlpha: number;
34
+ opacity: number;
35
+ color: ColorArray;
36
+ ramp: [number, number];
37
+ useControlPoints: boolean;
38
+ controlPoints: ControlPoint[];
39
+ plotMin: number;
40
+ plotMax: number;
41
+ /**
42
+ * If true, when a new volume is loaded, keeps the current intensity values
43
+ * (ramp, control points, and isovalue) instead of reinitializing them.
44
+ */
45
+ keepIntensityRange: boolean;
46
+ };
@@ -0,0 +1,8 @@
1
+ import type { ViewerState } from "../state/types";
2
+ /**
3
+ * Accepts a `key` and a new (potentially partial) `value` for a single field of `ViewerState`, & returns a fragment of
4
+ * `ViewerState` that can safely be merged into `currentState` to apply that value without creating an illegal state.
5
+ */
6
+ export declare const validateStateValue: <K extends keyof ViewerState>(currentState: ViewerState, key: K, value: Partial<ViewerState[K]>) => Partial<ViewerState>;
7
+ /** Ensures a fragment of `ViewerState` can be safely merged into `currentState` without creating an illegal state. */
8
+ export declare const validateState: (currentState: ViewerState, newState: Partial<{ [K in keyof ViewerState]: Partial<ViewerState[K]>; }>) => Partial<ViewerState>;
@@ -1,9 +1,9 @@
1
- import { parseViewerUrlParams } from "./aics-image-viewer/shared/utils/urlParsing";
2
1
  import ImageViewerApp from "./aics-image-viewer/components/App";
3
- import ViewerStateProvider from "./aics-image-viewer/components/ViewerStateProvider";
2
+ export { addViewerParamsFromMessage, parseViewerUrlParams } from "./aics-image-viewer/shared/utils/urlParsing";
3
+ export { writeMetadata, writeScenes } from "./aics-image-viewer/shared/utils/storage";
4
4
  export type { ViewerChannelSettings, ViewerChannelGroup, ViewerChannelSetting, } from "./aics-image-viewer/shared/utils/viewerChannelSettings";
5
- export type { ViewerState } from "./aics-image-viewer/components/ViewerStateProvider/types";
5
+ export type { ViewerState } from "./aics-image-viewer/state/types";
6
6
  export { ViewMode, RenderMode, ImageType } from "./aics-image-viewer/shared/enums";
7
7
  export type { AppProps } from "./aics-image-viewer/components/App/types";
8
8
  export type { RawArrayData, RawArrayInfo } from "@aics/vole-core";
9
- export { ImageViewerApp, ViewerStateProvider, parseViewerUrlParams };
9
+ export { ImageViewerApp };
@@ -1,163 +0,0 @@
1
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
5
- function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
6
- function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
7
- function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
8
- function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
9
- function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
10
- function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
11
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
12
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
13
- import { isEqual } from "lodash";
14
- import { getDefaultViewerState, getDefaultCameraState, getDefaultChannelState, getDefaultViewerChannelSettings, getDefaultChannelColor } from "../../shared/constants";
15
- import { ViewMode } from "../../shared/enums";
16
- import { overrideViewerState, overrideChannelStates, getEnabledChannelIndices, initializeOneChannelSetting } from "../../shared/utils/viewerState";
17
- /**
18
- * Provides reset functionality for the viewer and channel states.
19
- */
20
- var ResetStateProvider = /*#__PURE__*/function () {
21
- function ResetStateProvider(viewerStateRef) {
22
- _classCallCheck(this, ResetStateProvider);
23
- this.ref = viewerStateRef;
24
- this.savedViewerState = {};
25
- this.channelsToReset = new Set();
26
- this.channelsToResetOnLoad = new Set();
27
- this.savedViewerChannelSettings = undefined;
28
- this.useDefaultViewerChannelSettings = false;
29
- this.resetToSavedViewerState = this.resetToSavedViewerState.bind(this);
30
- this.resetToDefaultViewerState = this.resetToDefaultViewerState.bind(this);
31
- this.resetToState = this.resetToState.bind(this);
32
- this.setSavedViewerState = this.setSavedViewerState.bind(this);
33
- this.setSavedViewerChannelSettings = this.setSavedViewerChannelSettings.bind(this);
34
- this.getChannelsAwaitingReset = this.getChannelsAwaitingReset.bind(this);
35
- this.getChannelsAwaitingResetOnLoad = this.getChannelsAwaitingResetOnLoad.bind(this);
36
- this.onResetChannel = this.onResetChannel.bind(this);
37
- this.getCurrentViewerChannelSettings = this.getCurrentViewerChannelSettings.bind(this);
38
- }
39
-
40
- // Setup Callbacks ////////////////////////////////////////////////////////////////////
41
- return _createClass(ResetStateProvider, [{
42
- key: "setSavedViewerState",
43
- value: function setSavedViewerState(state) {
44
- this.savedViewerState = state;
45
- }
46
- }, {
47
- key: "setSavedViewerChannelSettings",
48
- value: function setSavedViewerChannelSettings(settings) {
49
- this.savedViewerChannelSettings = settings;
50
- }
51
- }, {
52
- key: "getChannelsAwaitingReset",
53
- value: function getChannelsAwaitingReset() {
54
- return this.channelsToReset;
55
- }
56
- }, {
57
- key: "getChannelsAwaitingResetOnLoad",
58
- value: function getChannelsAwaitingResetOnLoad() {
59
- return this.channelsToResetOnLoad;
60
- }
61
- }, {
62
- key: "onResetChannel",
63
- value: function onResetChannel(channelIndex) {
64
- this.channelsToReset["delete"](channelIndex);
65
- this.channelsToResetOnLoad["delete"](channelIndex);
66
- }
67
-
68
- /**
69
- * Returns the current viewer channel settings that the viewer should use when
70
- * resetting channels to an initial state.
71
- */
72
- }, {
73
- key: "getCurrentViewerChannelSettings",
74
- value: function getCurrentViewerChannelSettings() {
75
- if (this.useDefaultViewerChannelSettings) {
76
- return getDefaultViewerChannelSettings();
77
- }
78
- return this.savedViewerChannelSettings;
79
- }
80
-
81
- /**
82
- * Helper method. Resets the viewer and all channels to the provided state. If new data needs to
83
- * be loaded, handles setup so the reset will be applied to each channel as it loads in.
84
- */
85
- }, {
86
- key: "resetToState",
87
- value: function resetToState(newState, newChannelStates) {
88
- var _this$ref$current = this.ref.current,
89
- changeViewerSetting = _this$ref$current.changeViewerSetting,
90
- setChannelSettings = _this$ref$current.setChannelSettings,
91
- channelSettings = _this$ref$current.channelSettings,
92
- viewMode = _this$ref$current.viewMode,
93
- time = _this$ref$current.time,
94
- slice = _this$ref$current.slice;
95
-
96
- // Needs reset on reload if one of the view modes is 2D while the other is 3D,
97
- // if the timestamp is different, or if we're on a different z slice.
98
- // TODO: Handle stopping playback? Requires playback to be part of ViewerStateContext
99
- var isInDifferentViewMode = viewMode !== newState.viewMode && (viewMode === ViewMode.xy || newState.viewMode === ViewMode.xy);
100
- var isAtDifferentTime = time !== newState.time;
101
- var isAtDifferentZSlice = newState.viewMode === ViewMode.xy && !isEqual(newState.slice.z, slice.z);
102
- var willNeedResetOnLoad = isInDifferentViewMode || isAtDifferentTime || isAtDifferentZSlice;
103
- overrideViewerState(changeViewerSetting, newState);
104
- overrideChannelStates(setChannelSettings, channelSettings, newChannelStates);
105
- this.channelsToReset = new Set(Array(newChannelStates.length).keys());
106
- if (willNeedResetOnLoad) {
107
- var enabledChannelsAndResetState = getEnabledChannelIndices(newChannelStates);
108
- this.channelsToResetOnLoad = new Set(enabledChannelsAndResetState);
109
- var _iterator = _createForOfIteratorHelper(enabledChannelsAndResetState),
110
- _step;
111
- try {
112
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
113
- var channelIndex = _step.value;
114
- this.channelsToReset["delete"](channelIndex);
115
- }
116
- } catch (err) {
117
- _iterator.e(err);
118
- } finally {
119
- _iterator.f();
120
- }
121
- }
122
- }
123
-
124
- /** Resets to the initial saved state of the viewer, as shown to the user on load. */
125
- }, {
126
- key: "resetToSavedViewerState",
127
- value: function resetToSavedViewerState() {
128
- var _this = this;
129
- var channelSettings = this.ref.current.channelSettings;
130
- var newViewerState = _objectSpread(_objectSpread({}, getDefaultViewerState()), {}, {
131
- cameraState: getDefaultCameraState(this.savedViewerState.viewMode || ViewMode.threeD)
132
- }, this.savedViewerState);
133
- var newChannelSettings = channelSettings.map(function (_, index) {
134
- var initialChannelSetting = initializeOneChannelSetting(channelSettings[index].name, index, getDefaultChannelColor(index), _this.savedViewerChannelSettings);
135
- return _objectSpread(_objectSpread({}, initialChannelSetting), {}, {
136
- plotMin: channelSettings[index].plotMin,
137
- plotMax: channelSettings[index].plotMax
138
- });
139
- });
140
- this.resetToState(newViewerState, newChannelSettings);
141
- this.useDefaultViewerChannelSettings = false;
142
- }
143
-
144
- /** Reset to global default viewer state, as if loading the volume with no parameters. */
145
- }, {
146
- key: "resetToDefaultViewerState",
147
- value: function resetToDefaultViewerState() {
148
- var channelSettings = this.ref.current.channelSettings;
149
- var defaultViewerState = _objectSpread(_objectSpread({}, getDefaultViewerState()), {}, {
150
- cameraState: getDefaultCameraState(ViewMode.threeD)
151
- });
152
- var defaultChannelStates = channelSettings.map(function (_, index) {
153
- return getDefaultChannelState(index);
154
- });
155
- for (var i = 0; i < Math.min(3, defaultChannelStates.length); i++) {
156
- defaultChannelStates[i].volumeEnabled = true;
157
- }
158
- this.resetToState(defaultViewerState, defaultChannelStates);
159
- this.useDefaultViewerChannelSettings = true;
160
- }
161
- }]);
162
- }();
163
- export { ResetStateProvider as default };