@aics/vole-app 3.4.3 → 3.5.0

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 (55) hide show
  1. package/es/aics-image-viewer/components/App/index.js +5 -5
  2. package/es/aics-image-viewer/components/ColorPicker/index.js +9 -1
  3. package/es/aics-image-viewer/components/ControlPanel/CopySettingsButton.js +415 -0
  4. package/es/aics-image-viewer/components/ControlPanel/index.js +12 -4
  5. package/es/aics-image-viewer/components/ControlPanel/styles.css +29 -2
  6. package/es/aics-image-viewer/components/StyleProvider/index.js +17 -2
  7. package/es/aics-image-viewer/components/Toolbar/ViewModeRadioButtons.js +1 -1
  8. package/es/aics-image-viewer/components/Toolbar/index.js +1 -1
  9. package/es/aics-image-viewer/components/{CellViewerCanvasWrapper → ViewerCanvasWrapper}/index.js +1 -1
  10. package/es/aics-image-viewer/components/dimension_sliders/RotationSliders.js +1 -1
  11. package/es/aics-image-viewer/components/shared/ContextualAlert.js +101 -0
  12. package/es/aics-image-viewer/components/useVolume.js +1 -1
  13. package/es/aics-image-viewer/shared/constants.js +1 -1
  14. package/es/aics-image-viewer/shared/types.js +1 -1
  15. package/es/aics-image-viewer/shared/utils/controlPointsToLut.js +4 -0
  16. package/es/aics-image-viewer/shared/utils/parseSnapshot.js +179 -0
  17. package/es/aics-image-viewer/shared/utils/{urlParsing.js → parseUrl.js} +14 -52
  18. package/es/aics-image-viewer/shared/utils/permissions.js +46 -0
  19. package/es/aics-image-viewer/shared/utils/test/camera.test.js +0 -1
  20. package/es/aics-image-viewer/shared/utils/test/{urlParsing.test.js → parseUrl.test.js} +8 -5
  21. package/es/aics-image-viewer/state/deserialize.js +443 -331
  22. package/es/aics-image-viewer/state/reset.js +1 -1
  23. package/es/aics-image-viewer/state/serialize.js +168 -78
  24. package/es/aics-image-viewer/state/subscribers.js +1 -1
  25. package/es/aics-image-viewer/state/test/deserialize.test.js +62 -76
  26. package/es/aics-image-viewer/state/test/reset.test.js +1 -1
  27. package/es/aics-image-viewer/state/test/serialize.test.js +41 -43
  28. package/es/aics-image-viewer/state/test/test_data.js +119 -1
  29. package/es/aics-image-viewer/state/types.js +157 -245
  30. package/es/aics-image-viewer/state/util.js +39 -1
  31. package/es/index.js +4 -2
  32. package/package.json +2 -2
  33. package/type-declarations/aics-image-viewer/components/App/types.d.ts +3 -3
  34. package/type-declarations/aics-image-viewer/components/ControlPanel/CopySettingsButton.d.ts +9 -0
  35. package/type-declarations/aics-image-viewer/components/Toolbar/ViewModeRadioButtons.d.ts +1 -1
  36. package/type-declarations/aics-image-viewer/components/{CellViewerCanvasWrapper → ViewerCanvasWrapper}/index.d.ts +3 -3
  37. package/type-declarations/aics-image-viewer/components/dimension_sliders/AxisClipSliders.d.ts +6 -6
  38. package/type-declarations/aics-image-viewer/components/shared/ContextualAlert.d.ts +29 -0
  39. package/type-declarations/aics-image-viewer/shared/constants.d.ts +1 -2
  40. package/type-declarations/aics-image-viewer/shared/types.d.ts +2 -2
  41. package/type-declarations/aics-image-viewer/shared/utils/controlPointsToLut.d.ts +1 -1
  42. package/type-declarations/aics-image-viewer/shared/utils/parseSnapshot.d.ts +47 -0
  43. package/type-declarations/aics-image-viewer/shared/utils/{urlParsing.d.ts → parseUrl.d.ts} +2 -16
  44. package/type-declarations/aics-image-viewer/shared/utils/permissions.d.ts +7 -0
  45. package/type-declarations/aics-image-viewer/shared/utils/viewerChannelSettings.d.ts +1 -1
  46. package/type-declarations/aics-image-viewer/state/deserialize.d.ts +70 -35
  47. package/type-declarations/aics-image-viewer/state/reset.d.ts +1 -1
  48. package/type-declarations/aics-image-viewer/state/serialize.d.ts +44 -10
  49. package/type-declarations/aics-image-viewer/state/types.d.ts +265 -159
  50. package/type-declarations/aics-image-viewer/state/util.d.ts +3 -1
  51. package/type-declarations/index.d.ts +5 -3
  52. package/es/aics-image-viewer/shared/enums.js +0 -18
  53. package/type-declarations/aics-image-viewer/shared/enums.d.ts +0 -15
  54. package/type-declarations/aics-image-viewer/shared/utils/math.d.ts +0 -1
  55. /package/es/aics-image-viewer/components/{CellViewerCanvasWrapper → ViewerCanvasWrapper}/styles.css +0 -0
@@ -20,7 +20,8 @@ var palette = {
20
20
  veryLtPurple: "#e7e4f2",
21
21
  brightRed: "#dc4446",
22
22
  brightYellow: "#e39b0d",
23
- brightGreen: "#61d900",
23
+ darkGreen: "#294c2f",
24
+ brightGreen: "#0ccf4d",
24
25
  veryBrightGreen: "#61ff00",
25
26
  brightBlue: "#0099ff",
26
27
  veryBrightBlue: "#0dc4d9",
@@ -126,6 +127,10 @@ var theme = {
126
127
  textPlaceholder: palette.ltPurple
127
128
  },
128
129
  alert: {
130
+ success: {
131
+ text: palette.brightGreen,
132
+ bg: palette.darkGreen
133
+ },
129
134
  warning: {
130
135
  text: palette.brightYellow,
131
136
  bg: palette.darkYellow
@@ -150,7 +155,7 @@ var theme = {
150
155
  }
151
156
  };
152
157
  /** Makes theme styling available to child components via CSS variables. */
153
- var CssProvider = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n width: 100%;\n height: 100%;\n\n ", "\n\n h1, h2, h3, h4, p {\n font-family: var(--font-family);\n }\n\n h1 {\n color: var(--color-text-header);\n font-size: 28px;\n font-weight: 400;\n }\n\n h2 {\n color: var(--color-text-section);\n font-size: 19px;\n font-weight: 400;\n }\n\n h3 {\n color: var(--color-text-header);\n font-size: 16px;\n font-weight: 600;\n }\n\n h4 {\n color: var(--color-text-header);\n font-size: 14px;\n font-weight: 400;\n }\n\n p {\n color: var(--color-text-body);\n font-size: 14px;\n font-weight: 400;\n }\n\n a {\n color: var(--color-text-link);\n }\n\n *::selection {\n background-color: var(--color-text-selection-bg);\n color: var(--color-text-selection-text);\n }\n\n /** TODO: Go through these styles and see if we can use Ant ConfigProvider for them instead. */\n .ant-btn-link,\n .ant-btn-text,\n .ant-btn-primary,\n .ant-btn-icon-only {\n box-shadow: none;\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: var(--color-button-primary-hover-bg);\n border-color: var(--color-button-primary-hover-bg);\n color: var(--color-button-primary-text);\n outline: none;\n }\n\n &:active:not(:disabled) {\n background-color: var(--color-button-primary-hover-bg);\n border: 1px solid var(--color-button-primary-active-outline);\n color: var(--color-button-primary-text);\n }\n }\n\n /* Let us use buttons with type=\"text\" as purely semantic containers - don't bring any styling! */\n .ant-btn-text {\n width: unset;\n height: unset;\n padding: unset;\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: unset;\n border-color: transparent;\n }\n }\n\n .ant-btn-icon-only:disabled {\n color: var(--color-button-icon-disabled-text);\n }\n\n .ant-btn-link:not(:disabled) {\n // Change from default blue link text\n color: var(--color-button-link-text);\n }\n\n /**\n * Tertiary style buttons. Grey outline by default, turns to light\n * purple outline on hover.\n */\n .ant-btn-default:not(.ant-btn-icon-only) {\n background-color: var(--color-button-tertiary-bg);\n color: var(--color-button-tertiary-text);\n border-color: var(--color-button-tertiary-outline);\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: transparent;\n border-color: var(--color-button-tertiary-hover-outline);\n color: var(--color-button-tertiary-hover-text);\n }\n }\n\n // Overrides for checkbox styling\n .ant-checkbox-input {\n &:hover,\n &:focus-visible {\n border: 1px solid white;\n }\n }\n\n .ant-checkbox.ant-checkbox-checked {\n background-color: var(--color-checkbox-bg);\n }\n\n .ant-checkbox-inner {\n background-color: transparent !important;\n }\n\n // Add outlines to modals and dropdowns\n .ant-select-dropdown,\n .ant-dropdown-menu,\n .ant-modal-content {\n border: 1px solid var(--color-modal-border);\n }\n\n // Force active/hovered text to be white instead of grey for better contrast\n .ant-dropdown-menu-item-active {\n color: var(--color-menu-hover-text);\n }\n\n // Remove padding in dropdown menus and make items reactangular + flush with the edge\n .ant-dropdown-menu,\n .ant-select-dropdown {\n padding: 0;\n overflow: hidden;\n\n .ant-dropdown-menu-item,\n .ant-select-item:not(.ant-select-item-option-disabled) {\n border-radius: 0;\n color: var(--color-button-icon-active-text);\n }\n }\n\n .ant-select {\n &.ant-select-disabled .ant-select-selector {\n border-color: var(--color-button-icon-disabled-outline);\n }\n\n .ant-select-arrow {\n transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);\n }\n\n /* Control response to hover + active menu */\n &:hover:not(.ant-select-disabled),\n &:focus-visible:not(.ant-select-disabled),\n &.ant-select.ant-select-open {\n .ant-select-selector,\n .ant-select-arrow,\n .ant-select-selection-item {\n color: var(--color-button-tertiary-hover-text);\n outline-color: var(--color-button-tertiary-hover-outline);\n }\n }\n }\n\n // Toolbar has special colors for radio buttons and will use these variables to apply them\n --color-button-radio-hover-outline: var(--color-button-tertiary-hover-outline);\n --color-button-radio-hover-text: var(--color-button-tertiary-hover-text);\n\n .ant-radio-button-wrapper {\n &::before {\n content: none;\n }\n\n &.ant-radio-button-wrapper-checked {\n color: var(--color-button-icon-active-text);\n\n &:not(:first-child) {\n box-shadow: -1px 0px 0px 0px var(--color-button-tertiary-active-outline);\n }\n }\n\n &:hover,\n &:has(:focus-visible) {\n color: var(--color-button-radio-hover-text);\n border-color: var(--color-button-radio-hover-outline);\n outline: none;\n z-index: 2;\n\n &:not(:first-child) {\n box-shadow: -1px 0px 0px 0px var(--color-button-radio-hover-outline);\n }\n }\n }\n\n"])), function (_ref) {
158
+ var CssProvider = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n width: 100%;\n height: 100%;\n\n ", "\n\n h1, h2, h3, h4, p {\n font-family: var(--font-family);\n }\n\n h1 {\n color: var(--color-text-header);\n font-size: 28px;\n font-weight: 400;\n }\n\n h2 {\n color: var(--color-text-section);\n font-size: 19px;\n font-weight: 400;\n }\n\n h3 {\n color: var(--color-text-header);\n font-size: 16px;\n font-weight: 600;\n }\n\n h4 {\n color: var(--color-text-header);\n font-size: 14px;\n font-weight: 400;\n }\n\n p {\n color: var(--color-text-body);\n font-size: 14px;\n font-weight: 400;\n }\n\n a {\n color: var(--color-text-link);\n }\n\n *::selection {\n background-color: var(--color-text-selection-bg);\n color: var(--color-text-selection-text);\n }\n\n /** TODO: Go through these styles and see if we can use Ant ConfigProvider for them instead. */\n .ant-btn-link,\n .ant-btn-text,\n .ant-btn-primary,\n .ant-btn-icon-only {\n box-shadow: none;\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: var(--color-button-primary-hover-bg);\n border-color: var(--color-button-primary-hover-bg);\n color: var(--color-button-primary-text);\n outline: none;\n }\n\n &:active:not(:disabled) {\n background-color: var(--color-button-primary-hover-bg);\n border: 1px solid var(--color-button-primary-active-outline);\n color: var(--color-button-primary-text);\n }\n }\n\n /* Let us use buttons with type=\"text\" as purely semantic containers - don't bring any styling! */\n .ant-btn-text {\n width: unset;\n height: unset;\n padding: unset;\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: unset;\n border-color: transparent;\n }\n }\n\n .ant-btn-icon-only:disabled {\n color: var(--color-button-icon-disabled-text);\n }\n\n .ant-btn-link:not(:disabled) {\n // Change from default blue link text\n color: var(--color-button-link-text);\n }\n\n /**\n * Tertiary style buttons. Grey outline by default, turns to light\n * purple outline on hover.\n */\n .ant-btn-default:not(.ant-btn-icon-only) {\n background-color: var(--color-button-tertiary-bg);\n color: var(--color-button-tertiary-text);\n border-color: var(--color-button-tertiary-outline);\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: transparent;\n border-color: var(--color-button-tertiary-hover-outline);\n color: var(--color-button-tertiary-hover-text);\n }\n }\n\n // Overrides for checkbox styling\n .ant-checkbox-input {\n &:hover,\n &:focus-visible {\n border: 1px solid white;\n }\n }\n\n .ant-checkbox.ant-checkbox-checked {\n background-color: var(--color-checkbox-bg);\n }\n\n .ant-checkbox-inner {\n background-color: transparent !important;\n }\n\n // Add outlines to modals and dropdowns\n .ant-select-dropdown,\n .ant-dropdown-menu,\n .ant-modal-content {\n border: 1px solid var(--color-modal-border);\n }\n\n // Force active/hovered text to be white instead of grey for better contrast\n .ant-dropdown-menu-item-active {\n color: var(--color-menu-hover-text);\n }\n\n // Remove padding in dropdown menus and make items reactangular + flush with the edge\n .ant-dropdown-menu,\n .ant-select-dropdown {\n padding: 0;\n overflow: hidden;\n\n .ant-dropdown-menu-item,\n .ant-select-item:not(.ant-select-item-option-disabled) {\n border-radius: 0;\n color: var(--color-button-icon-active-text);\n }\n }\n\n .ant-select {\n &.ant-select-disabled .ant-select-selector {\n border-color: var(--color-button-icon-disabled-outline);\n }\n\n .ant-select-arrow {\n transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);\n }\n\n /* Control response to hover + active menu */\n &:hover:not(.ant-select-disabled),\n &:focus-visible:not(.ant-select-disabled),\n &.ant-select.ant-select-open {\n .ant-select-selector,\n .ant-select-arrow,\n .ant-select-selection-item {\n color: var(--color-button-tertiary-hover-text);\n outline-color: var(--color-button-tertiary-hover-outline);\n }\n }\n }\n\n // Toolbar has special colors for radio buttons and will use these variables to apply them\n --color-button-radio-hover-outline: var(--color-button-tertiary-hover-outline);\n --color-button-radio-hover-text: var(--color-button-tertiary-hover-text);\n\n .ant-radio-button-wrapper {\n &::before {\n content: none;\n }\n\n &.ant-radio-button-wrapper-checked {\n color: var(--color-button-icon-active-text);\n\n &:not(:first-child) {\n box-shadow: -1px 0px 0px 0px var(--color-button-tertiary-active-outline);\n }\n }\n\n &:hover,\n &:has(:focus-visible) {\n color: var(--color-button-radio-hover-text);\n border-color: var(--color-button-radio-hover-outline);\n outline: none;\n z-index: 2;\n\n &:not(:first-child) {\n box-shadow: -1px 0px 0px 0px var(--color-button-radio-hover-outline);\n }\n }\n }\n"])), function (_ref) {
154
159
  var $theme = _ref.$theme;
155
160
  return css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n /* Component and color variables. */\n // TODO: Fix inconsistent use of border vs. outline\n // TODO: Remove variables that aren't used in other CSS files. These should be set directly\n // from the $theme object to reduce unnecessary variables.\n --color-text-link: ", ";\n --color-text-header: ", ";\n --color-text-section: ", ";\n --color-text-body: ", ";\n --color-text-error: ", ";\n\n --color-text-selection-bg: ", ";\n --color-text-selection-text: ", ";\n\n --color-header-title: ", ";\n --color-header-hover-title: ", ";\n --color-header-bg: ", ";\n --color-header-border: ", ";\n\n --color-button-primary-bg: ", ";\n --color-button-primary-text: ", ";\n --color-button-primary-hover-bg: ", ";\n --color-button-primary-active-bg: ", ";\n --color-button-primary-active-outline: ", ";\n --color-button-primary-disabled-bg: ", ";\n\n --color-button-link-text: ", ";\n\n --color-button-secondary-bg: ", ";\n --color-button-secondary-text: ", ";\n --color-button-secondary-outline: ", ";\n\n --color-button-tertiary-bg: transparent;\n --color-button-tertiary-text: ", ";\n --color-button-tertiary-outline: ", ";\n --color-button-tertiary-hover-outline: ", ";\n --color-button-tertiary-hover-text: ", ";\n --color-button-tertiary-active-outline: ", ";\n --color-button-tertiary-active-text: ", ";\n\n --color-button-icon-disabled-outline: ", ";\n --color-button-icon-disabled-text: ", ";\n --color-button-icon-active-text: ", ";\n --color-button-icon-active-bg: ", ";\n --color-button-icon-active-outline: ", ";\n\n --color-toolbar-button-bg: ", ";\n\n --color-controlpanel-bg: ", ";\n --color-controlpanel-border: ", ";\n --color-controlpanel-section-text: ", ";\n --color-controlpanel-text: ", ";\n --color-controlpanel-section-bg: ", ";\n --color-controlpanel-drawer-bg: ", ";\n --color-controlpanel-ramp-slider: ", ";\n --color-controlpanel-isovalue-slider: ", ";\n\n --color-landingpage-bg: ", ";\n --color-landingpage-bg-alt: ", ";\n --color-landingpage-text: ", ";\n --color-landingpage-banner-highlight-bg: ", ";\n\n --color-statusflag-border: ", ";\n --color-statusflag-text: ", ";\n\n --color-alert-warning-text: ", ";\n --color-alert-warning-bg: ", ";\n --color-alert-info-text: ", ";\n --color-alert-info-bg: ", ";\n\n --color-layout-dividers: ", ";\n\n --color-modal-border: ", ";\n\n --color-menu-hover-text: ", ";\n --color-menu-selected-text: ", ";\n\n --color-checkbox-bg: ", ";\n\n --font-family: ", ";\n "])), $theme.colors.text.link, $theme.colors.text.header, $theme.colors.text.section, $theme.colors.text.body, $theme.colors.text.error, $theme.colors.text.selectionBg, $theme.colors.text.selectionText, $theme.colors.header.title, $theme.colors.header.hoverTitle, $theme.colors.header.bg, $theme.colors.header.border, $theme.colors.button.primary.bg, $theme.colors.button.primary.text, $theme.colors.button.primary.hoverBg, $theme.colors.button.primary.hoverBg, $theme.colors.button.primary.activeOutline, $theme.colors.button.primary.disabledBg, $theme.colors.button.link.text, $theme.colors.button.secondary.bg, $theme.colors.button.secondary.text, $theme.colors.button.secondary.outline, $theme.colors.button.tertiary.text, $theme.colors.button.tertiary.outline, $theme.colors.button.tertiary.hoverOutline, $theme.colors.button.tertiary.hoverText, $theme.colors.button.tertiary.activeOutline, $theme.colors.button.tertiary.hoverText, $theme.colors.button.tertiary.disabledOutline, $theme.colors.button.tertiary.disabledText, $theme.colors.button.tertiary.activeText, $theme.colors.button.tertiary.activeBg, $theme.colors.button.tertiary.activeOutline, $theme.colors.toolbar.buttonBg, $theme.colors.controlPanel.bg, $theme.colors.controlPanel.border, $theme.colors.controlPanel.sectionText, $theme.colors.controlPanel.text, $theme.colors.controlPanel.sectionBg, $theme.colors.controlPanel.drawerBg, $theme.colors.controlPanel.rampSlider, $theme.colors.controlPanel.isovalueSlider, $theme.colors.landingPage.bg, $theme.colors.landingPage.bgAlt, $theme.colors.landingPage.text, $theme.colors.landingPage.bannerBg, $theme.colors.statusFlag.border, $theme.colors.statusFlag.text, $theme.colors.alert.warning.text, $theme.colors.alert.warning.bg, $theme.colors.alert.info.text, $theme.colors.alert.info.bg, $theme.colors.layout.dividers, $theme.colors.modal.border, $theme.colors.menu.hoverText, $theme.colors.menu.selectedText, $theme.colors.checkbox.bg, $theme.fonts.family);
156
161
  });
@@ -172,6 +177,10 @@ export default function StyleProvider(props) {
172
177
  colorBgContainer: "transparent",
173
178
  colorSplit: theme.colors.layout.split,
174
179
  colorPrimaryTextHover: theme.colors.text.selectionText,
180
+ colorSuccess: theme.colors.alert.success.text,
181
+ colorSuccessBg: theme.colors.alert.success.bg,
182
+ colorSuccessBorder: theme.colors.alert.success.text,
183
+ colorSuccessText: theme.colors.alert.success.text,
175
184
  colorWarning: theme.colors.alert.warning.text,
176
185
  colorWarningBg: theme.colors.alert.warning.bg,
177
186
  colorWarningBorder: theme.colors.alert.warning.text,
@@ -236,11 +245,17 @@ export default function StyleProvider(props) {
236
245
  colorTextPlaceholder: theme.colors.button.tertiary.hoverText,
237
246
  colorBgContainerDisabled: "transparent"
238
247
  },
248
+ Tabs: {
249
+ horizontalItemPaddingLG: "5px 0"
250
+ },
239
251
  // Additional tooltip overrides (font-weight, box-shadow, layout) are in GlobalTooltipStyle below,
240
252
  // which is required because antd renders tooltips in portals outside the scoped CssProvider.
241
253
  Tooltip: {
242
254
  colorBgSpotlight: theme.colors.tooltip.bg,
243
255
  fontSize: 12
256
+ },
257
+ Upload: {
258
+ padding: 32
244
259
  }
245
260
  }
246
261
  }
@@ -1,6 +1,6 @@
1
1
  import { Radio } from "antd";
2
2
  import React from "react";
3
- import { ViewMode } from "../../shared/enums";
3
+ import { ViewMode } from "../../state/types";
4
4
  var viewModes = [ViewMode.threeD, ViewMode.xy, ViewMode.xz, ViewMode.yz];
5
5
  var ViewModeRadioButtons = function ViewModeRadioButtons(props) {
6
6
  var onChangeButton = function onChangeButton(_ref) {
@@ -8,8 +8,8 @@ import { ReloadOutlined } from "@ant-design/icons";
8
8
  import { Button, Radio, Select, Tooltip } from "antd";
9
9
  import { debounce } from "lodash";
10
10
  import React from "react";
11
- import { ImageType, RenderMode, ViewMode } from "../../shared/enums";
12
11
  import { select, useViewerState } from "../../state/store";
12
+ import { ImageType, RenderMode, ViewMode } from "../../state/types";
13
13
  import ViewerIcon from "../shared/ViewerIcon";
14
14
  import DownloadButton from "./DownloadButton";
15
15
  import ViewModeRadioButtons from "./ViewModeRadioButtons";
@@ -7,8 +7,8 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
7
7
  import { LoadingOutlined } from "@ant-design/icons";
8
8
  import React from "react";
9
9
  import { CLIPPING_PANEL_HEIGHT_DEFAULT, CLIPPING_PANEL_HEIGHT_TALL } from "../../shared/constants";
10
- import { ViewMode } from "../../shared/enums";
11
10
  import { select, useViewerState } from "../../state/store";
11
+ import { ViewMode } from "../../state/types";
12
12
  import BottomPanel from "../BottomPanel";
13
13
  import { AxisClipSliders } from "../dimension_sliders/AxisClipSliders";
14
14
  import { RotationSliders } from "../dimension_sliders/RotationSliders";
@@ -12,9 +12,9 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
12
12
  function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
13
13
  import { Button, Space } from "antd";
14
14
  import React, { useCallback, useEffect, useRef, useState } from "react";
15
- import { ViewMode } from "../../shared/enums";
16
15
  import { applyMatrix, defaultOrientedCamera, getRotationAngles, rotationMatrix, useCameraCallback } from "../../shared/utils/camera";
17
16
  import { select, useViewerState } from "../../state/store";
17
+ import { ViewMode } from "../../state/types";
18
18
  import { DimensionSliderRow } from "./SliderRows";
19
19
 
20
20
  /** Convert an angle from degrees to radians */
@@ -0,0 +1,101 @@
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 _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
3
+ 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; }
4
+ 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; }
5
+ 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; }
6
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
7
+ 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); }
8
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
9
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
10
+ 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; } }
11
+ 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; }
12
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
13
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
14
+ import { Alert } from "antd";
15
+ import React from "react";
16
+ import { createPortal } from "react-dom";
17
+ var ALERT_STYLE = {
18
+ position: "absolute",
19
+ bottom: "auto",
20
+ right: "auto",
21
+ zIndex: 1000
22
+ };
23
+
24
+ /**
25
+ * Antd's `Alert`, but positioned immediately under a `target` element to provide contextual information.
26
+ *
27
+ * This is relatively specialized to the use case of attaching to components inside the control panel. Since the
28
+ * control panel can be vertically scrolled and hidden, it has specific props for responding to both.
29
+ */
30
+ export var ContextualAlert = function ContextualAlert(props) {
31
+ var message = props.message,
32
+ target = props.target,
33
+ scrollContainer = props.scrollContainer,
34
+ hide = props.hide;
35
+ var _React$useState = React.useState({
36
+ top: 0,
37
+ left: 0
38
+ }),
39
+ _React$useState2 = _slicedToArray(_React$useState, 2),
40
+ alertPosition = _React$useState2[0],
41
+ setAlertPosition = _React$useState2[1];
42
+ React.useEffect(function () {
43
+ var setPosition = function setPosition() {
44
+ if (target !== null) {
45
+ var rect = target.getBoundingClientRect();
46
+ setAlertPosition({
47
+ top: rect.bottom + 10,
48
+ left: rect.left
49
+ });
50
+ }
51
+ };
52
+ setPosition();
53
+ if (scrollContainer) {
54
+ scrollContainer.addEventListener("scroll", setPosition);
55
+ return function () {
56
+ return scrollContainer.removeEventListener("scroll", setPosition);
57
+ };
58
+ }
59
+ return undefined;
60
+ }, [scrollContainer, target]);
61
+ return /*#__PURE__*/createPortal(/*#__PURE__*/React.createElement("div", {
62
+ style: _objectSpread(_objectSpread(_objectSpread({}, ALERT_STYLE), alertPosition), {}, {
63
+ display: !message || hide ? "none" : "block"
64
+ })
65
+ }, /*#__PURE__*/React.createElement(Alert, props)), document.body);
66
+ };
67
+
68
+ /**
69
+ * Creates an `antd` `Alert` element that stays positioned beneath the `target` element, and a function to show
70
+ * time-limited messages in the `Alert`.
71
+ *
72
+ * This is relatively specialized to the use case of attaching to components inside the control panel. Since the
73
+ * control panel can be vertically scrolled and hidden, it has specific props for responding to both.
74
+ */
75
+ export var useContextualAlert = function useContextualAlert(target, options) {
76
+ var _React$useState3 = React.useState(undefined),
77
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
78
+ message = _React$useState4[0],
79
+ setMessage = _React$useState4[1];
80
+ var _React$useState5 = React.useState(undefined),
81
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
82
+ messageType = _React$useState6[0],
83
+ setMessageType = _React$useState6[1];
84
+ var messageTimeoutRef = React.useRef(undefined);
85
+ var showMessage = React.useCallback(function (message, messageType) {
86
+ if (messageTimeoutRef.current !== undefined) {
87
+ window.clearTimeout(messageTimeoutRef.current);
88
+ }
89
+ messageTimeoutRef.current = window.setTimeout(function () {
90
+ return setMessage(undefined);
91
+ }, options.timeout);
92
+ setMessage(message);
93
+ setMessageType(messageType);
94
+ }, [options.timeout]);
95
+ var alert = /*#__PURE__*/React.createElement(ContextualAlert, _extends({
96
+ message: message,
97
+ target: target,
98
+ type: messageType !== null && messageType !== void 0 ? messageType : "success"
99
+ }, options));
100
+ return [alert, showMessage];
101
+ };
@@ -25,12 +25,12 @@ import { LoadSpec, VolumeLoaderContext } from "@aics/vole-core";
25
25
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
26
26
  import { Box3, Vector3 } from "three";
27
27
  import { AXIS_TO_LOADER_PRIORITY, CACHE_MAX_SIZE, getDefaultViewerChannelSettings, QUEUE_MAX_LOW_PRIORITY_SIZE, QUEUE_MAX_SIZE } from "../shared/constants";
28
- import { ViewMode } from "../shared/enums";
29
28
  import { useConstructor, useRefWithSetter } from "../shared/utils/hooks";
30
29
  import PlayControls from "../shared/utils/playControls";
31
30
  import SceneStore from "../shared/utils/sceneStore";
32
31
  import { makeChannelIndexGrouping } from "../shared/utils/viewerChannelSettings";
33
32
  import { select, useViewerState } from "../state/store";
33
+ import { ViewMode } from "../state/types";
34
34
  export var ImageLoadStatus = /*#__PURE__*/function (ImageLoadStatus) {
35
35
  ImageLoadStatus[ImageLoadStatus["REQUESTED"] = 0] = "REQUESTED";
36
36
  ImageLoadStatus[ImageLoadStatus["LOADING"] = 1] = "LOADING";
@@ -3,7 +3,7 @@ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object
3
3
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
4
4
  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); }
5
5
  import { PrefetchDirection } from "@aics/vole-core";
6
- import { ImageType, RenderMode, ViewMode } from "./enums";
6
+ import { ImageType, RenderMode, ViewMode } from "../state/types";
7
7
  // Add all exported constants here to prevent circular dependencies
8
8
  export var
9
9
  // Control panel will automatically close if viewport is less than this width
@@ -2,5 +2,5 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
2
2
  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; }
3
3
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
4
4
  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); }
5
- import { ViewMode } from "./enums";
5
+ import { ViewMode } from "../state/types";
6
6
  export var activeAxisMap = _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, ViewMode.yz, "x"), ViewMode.xz, "y"), ViewMode.xy, "z"), ViewMode.threeD, null);
@@ -40,6 +40,10 @@ export function getDefaultLut(histogram) {
40
40
  * Parses a single LUT value from a string, where the value is either a number, a percentile, or a median multiplier.
41
41
  */
42
42
  function parseLutValue(value, histogram) {
43
+ if (typeof value === "number") {
44
+ return value;
45
+ }
46
+
43
47
  // look at first char of string.
44
48
  var firstChar = value.charAt(0);
45
49
  if (firstChar === "m") {
@@ -0,0 +1,179 @@
1
+ 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; }
2
+ 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; }
3
+ 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; }
4
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
5
+ 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); }
6
+ 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; } } }; }
7
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
8
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
9
+ 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; } }
10
+ 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; }
11
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
12
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
13
+ 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); }
14
+ import { snapshotToChannelState, snapshotToViewerChannelSetting } from "../../state/deserialize";
15
+ import { channelStateToSnapshot } from "../../state/serialize";
16
+ import { cloneChannelState } from "../../state/util";
17
+
18
+ /**
19
+ * A message sent from an external application after this app was opened,
20
+ * containing data that was too large to pack into the URL.
21
+ */
22
+
23
+ /** A snapshot of app state, containing (optional) global and per-channel settings. */
24
+
25
+ /**
26
+ * A complete description of a viewer session, containing image URLs, global
27
+ * and per-channel settings, and optional image metadata.
28
+ */
29
+
30
+ /** Verifies that the given object is (likely) a `StoreSnapshot`. */
31
+ export var isStoreSnapshot = function isStoreSnapshot(settings) {
32
+ var castSettings = settings;
33
+ return settings !== null && settings !== undefined && typeof castSettings.version === "string" && _typeof(castSettings.channels) === "object" && !Array.isArray(castSettings.channels) && Object.entries(castSettings.channels).every(function (_ref) {
34
+ var _ref2 = _slicedToArray(_ref, 2),
35
+ key = _ref2[0],
36
+ value = _ref2[1];
37
+ return typeof key === "string" && _typeof(value) === "object" && !Array.isArray(value);
38
+ });
39
+ };
40
+
41
+ /** Verifies that the given object is (likely) a `SessionSnapshot`. */
42
+ export var isSessionSnapshot = function isSessionSnapshot(settings) {
43
+ if (!isStoreSnapshot(settings)) {
44
+ return false;
45
+ }
46
+ var _ref3 = settings,
47
+ scenes = _ref3.scenes;
48
+ return Array.isArray(scenes) && scenes.every(function (scene) {
49
+ return typeof scene === "string" || Array.isArray(scene) && scene.every(function (url) {
50
+ return typeof url === "string";
51
+ });
52
+ });
53
+ };
54
+
55
+ /** Converts an array of `ChannelState`s to a compact JSON representation that can be stringified into the clipboard. */
56
+ export var channelStatesToSnapshot = function channelStatesToSnapshot(channelStates, excludeKeys) {
57
+ var channels = {};
58
+ var _iterator = _createForOfIteratorHelper(channelStates),
59
+ _step;
60
+ try {
61
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
62
+ var ch = _step.value;
63
+ var setting = cloneChannelState(ch);
64
+ if (excludeKeys !== undefined) {
65
+ var _iterator2 = _createForOfIteratorHelper(excludeKeys),
66
+ _step2;
67
+ try {
68
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
69
+ var key = _step2.value;
70
+ delete setting[key];
71
+ }
72
+ } catch (err) {
73
+ _iterator2.e(err);
74
+ } finally {
75
+ _iterator2.f();
76
+ }
77
+ }
78
+ var state = channelStateToSnapshot(setting, false);
79
+ channels[ch.name] = state;
80
+ }
81
+ } catch (err) {
82
+ _iterator.e(err);
83
+ } finally {
84
+ _iterator.f();
85
+ }
86
+ return {
87
+ version: VOLEAPP_VERSION,
88
+ channels: channels
89
+ };
90
+ };
91
+
92
+ /** Converts a compacted set of `ChannelState`s from the clipboard into a record of channel names and their states. */
93
+ export var snapshotToChannelStates = function snapshotToChannelStates(serialized) {
94
+ var result = {};
95
+ for (var _i = 0, _Object$entries = Object.entries(serialized.channels); _i < _Object$entries.length; _i++) {
96
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
97
+ name = _Object$entries$_i[0],
98
+ state = _Object$entries$_i[1];
99
+ result[name] = _objectSpread(_objectSpread({}, snapshotToChannelState(state)), {}, {
100
+ name: name
101
+ });
102
+ }
103
+ return result;
104
+ };
105
+ export var snapshotToViewerChannelSettings = function snapshotToViewerChannelSettings(serialized) {
106
+ var snapshots = Object.entries(serialized.channels);
107
+ if (snapshots.length === 0) {
108
+ return undefined;
109
+ }
110
+ var channels = snapshots.map(function (_ref4) {
111
+ var _ref5 = _slicedToArray(_ref4, 2),
112
+ name = _ref5[0],
113
+ snap = _ref5[1];
114
+ return snapshotToViewerChannelSetting(name, snap);
115
+ });
116
+ return {
117
+ groups: [{
118
+ name: "Channels",
119
+ channels: channels
120
+ }]
121
+ };
122
+ };
123
+
124
+ /**
125
+ * Parses a `ViewerMessage` into the relevant entries in `AppProps`.
126
+ *
127
+ * Optionally accepts the current value of the `imageUrl` prop, for the case where the message contains only metadata
128
+ * and the image URLs that correspond to the metadata were passed in by other means.
129
+ */
130
+ export function viewerMessageToParams(message, propUrl) {
131
+ var _message$scenes;
132
+ // get scenes
133
+ var scenes = (_message$scenes = message.scenes) !== null && _message$scenes !== void 0 ? _message$scenes : propUrl && (typeof propUrl === "string" ? [propUrl] : propUrl.scenes);
134
+ if (scenes === undefined || scenes === "" || scenes.length === 0 || scenes.length === 1 && scenes[0] === "") {
135
+ return {};
136
+ }
137
+ var firstScene = scenes[0];
138
+ var imageUrl = scenes.length === 1 && typeof firstScene === "string" ? firstScene : {
139
+ scenes: scenes
140
+ };
141
+
142
+ // get metadata
143
+ var meta = message.meta;
144
+ var metadata = meta && scenes.map(function (scene) {
145
+ if (Array.isArray(scene)) {
146
+ // can't handle multi-source scenes (yet)
147
+ console.warn("Can't apply metadata to multi-source scene", scene);
148
+ return undefined;
149
+ }
150
+ return meta[scene];
151
+ });
152
+ return {
153
+ imageUrl: imageUrl,
154
+ metadata: metadata
155
+ };
156
+ }
157
+
158
+ /** Formats the values of the `imageUrl` and `metadata` props to `App` as a `ViewerMessage`. */
159
+ export function paramsToViewerMessage(imageUrl, metadata) {
160
+ var scenes = typeof imageUrl === "string" ? [imageUrl] : imageUrl.scenes;
161
+ if (metadata === undefined) {
162
+ return {
163
+ scenes: scenes
164
+ };
165
+ }
166
+ var meta = {};
167
+ scenes.forEach(function (scene, index) {
168
+ var value = metadata[index];
169
+ // Can't save a metadata record if there isn't any metadata or the image is multi-source
170
+ if (value === undefined || Array.isArray(scene) && scene.length !== 1) {
171
+ return;
172
+ }
173
+ meta[Array.isArray(scene) ? scene[0] : scene] = value;
174
+ });
175
+ return {
176
+ scenes: scenes,
177
+ meta: meta
178
+ };
179
+ }
@@ -29,9 +29,9 @@ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Can
29
29
  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; }
30
30
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
31
31
  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); }
32
- import { deserializeViewerChannelSetting, deserializeViewerState, parseKeyValueList } from "../../state/deserialize";
33
- import { objectToKeyValueList, serializeViewerChannelSetting, serializeViewerState } from "../../state/serialize";
34
- import { ViewerStateParams } from "../../state/types";
32
+ import { parseKeyValueList, stringSnapshotToViewerChannelSetting, stringSnapshotToViewerState } from "../../state/deserialize";
33
+ import { channelStateToStringSnapshot, objectToKeyValueList, viewerStateToStringSnapshot } from "../../state/serialize";
34
+ import { ViewerStateSnapshotKeys } from "../../state/types";
35
35
  import { removeUndefinedProperties } from "./datatypes";
36
36
  import FirebaseRequest from "./firebase";
37
37
  import { readStoredMetadata, readStoredScenes } from "./storage";
@@ -93,11 +93,7 @@ var DeprecatedParams = /*#__PURE__*/_createClass(function DeprecatedParams() {
93
93
  /** Deprecated query parameter for channel colors. */
94
94
  _defineProperty(this, "colors", undefined);
95
95
  });
96
- /**
97
- * A message sent from an external application after this app was opened,
98
- * containing data that was too large to pack into the URL.
99
- */
100
- var allowedParamKeys = [].concat(_toConsumableArray(Object.keys(new ViewerStateParams())), _toConsumableArray(Object.keys(new DataParams())), _toConsumableArray(Object.keys(new DeprecatedParams())));
96
+ var allowedParamKeys = [].concat(_toConsumableArray(Object.values(ViewerStateSnapshotKeys)), _toConsumableArray(Object.keys(new DataParams())), _toConsumableArray(Object.keys(new DeprecatedParams())));
101
97
  var isParamKey = function isParamKey(key) {
102
98
  return allowedParamKeys.indexOf(key) !== -1;
103
99
  };
@@ -248,7 +244,7 @@ function parseChannelSettings(params) {
248
244
  var channelIndex = Number.parseInt(key.slice(1), 10);
249
245
  try {
250
246
  var channelData = parseKeyValueList(params[key]);
251
- var channelSetting = deserializeViewerChannelSetting(channelIndex, channelData);
247
+ var channelSetting = stringSnapshotToViewerChannelSetting(channelIndex, channelData);
252
248
  channelIndexToSettings.set(channelIndex, channelSetting);
253
249
  } catch (e) {
254
250
  console.warn("url_utils.getArgsFromParams: Failed to parse channel settings for channel ".concat(channelIndex, " from URL parameters."), e);
@@ -448,7 +444,12 @@ export function parseViewerUrlParams(_x5, _x6) {
448
444
  return _parseViewerUrlParams.apply(this, arguments);
449
445
  }
450
446
 
451
- /** Adds the data in a newly-arrived `ViewerMessage` to an existing stored `AppProps` instance. */
447
+ /**
448
+ * Serializes the ViewerState and ChannelState of a ViewerStateContext into a URLSearchParams object.
449
+ * @param state ViewerStateContext to serialize.
450
+ * @param removeDefaults If true, shortens parameters by removing any properties that match the default state.
451
+ * This includes the output of GET_DEFAULT_VIEWER_STATE and GET_DEFAULT_CHANNEL_STATE.
452
+ */
452
453
  function _parseViewerUrlParams() {
453
454
  _parseViewerUrlParams = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(search, firestore) {
454
455
  var searchParams, params, args, viewerSettings, deprecatedChannelSettings, channelSettings, scenes, _yield$loadFromManife, manifestScenes, manifestMetadata, collectionid, msgorigin, getFromStorage, urlParamFromStorage, urlParam, firstScene, firstUrl, imageUrls, datasetArgs;
@@ -458,7 +459,7 @@ function _parseViewerUrlParams() {
458
459
  searchParams = new URLSearchParams(search);
459
460
  params = getAllowedParams(searchParams);
460
461
  args = {}; // Parse viewer state
461
- viewerSettings = deserializeViewerState(params); // Parse channel settings. If per-channel settings are provided, they will override
462
+ viewerSettings = stringSnapshotToViewerState(params); // Parse channel settings. If per-channel settings are provided, they will override
462
463
  // the old `ch` query parameter.
463
464
  deprecatedChannelSettings = parseDeprecatedChannelSettings(params);
464
465
  channelSettings = parseChannelSettings(params);
@@ -547,51 +548,12 @@ function _parseViewerUrlParams() {
547
548
  }));
548
549
  return _parseViewerUrlParams.apply(this, arguments);
549
550
  }
550
- export function addViewerParamsFromMessage(args, message) {
551
- var _message$scenes;
552
- // get scenes
553
- var imageUrl = args.imageUrl;
554
- var scenes = (_message$scenes = message.scenes) !== null && _message$scenes !== void 0 ? _message$scenes : typeof imageUrl === "string" ? [imageUrl] : imageUrl.scenes;
555
- var firstScene = scenes[0];
556
- var newImageUrl = scenes.length === 1 && typeof firstScene === "string" ? firstScene : {
557
- scenes: scenes
558
- };
559
-
560
- // get metadata
561
- var meta = message.meta;
562
- var messageMeta = meta && scenes.map(function (scene) {
563
- if (Array.isArray(scene)) {
564
- // can't handle multi-source scenes (yet)
565
- return undefined;
566
- }
567
- return meta[scene];
568
- });
569
- var newMetadata = messageMeta !== null && messageMeta !== void 0 ? messageMeta : args.metadata;
570
- if (newMetadata === undefined) {
571
- return _objectSpread(_objectSpread({}, args), {}, {
572
- imageUrl: newImageUrl
573
- });
574
- } else {
575
- return _objectSpread(_objectSpread({}, args), {}, {
576
- imageUrl: newImageUrl,
577
- metadata: newMetadata
578
- });
579
- }
580
- }
581
-
582
- /**
583
- * Serializes the ViewerState and ChannelState of a ViewerStateContext into a URLSearchParams object.
584
- * @param state ViewerStateContext to serialize.
585
- * @param removeDefaults If true, shortens parameters by removing any properties that match the default state.
586
- * This includes the output of GET_DEFAULT_VIEWER_STATE and GET_DEFAULT_CHANNEL_STATE.
587
- */
588
551
  export function serializeViewerUrlParams(state) {
589
552
  var _state$channelSetting;
590
553
  var removeDefaults = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
591
- var params = serializeViewerState(state, removeDefaults);
554
+ var params = viewerStateToStringSnapshot(state, removeDefaults);
592
555
  var channelParams = (_state$channelSetting = state.channelSettings) === null || _state$channelSetting === void 0 ? void 0 : _state$channelSetting.reduce(function (acc, channelSetting, index) {
593
- var key = "c".concat(index);
594
- acc[key] = objectToKeyValueList(serializeViewerChannelSetting(channelSetting, removeDefaults));
556
+ acc["c".concat(index)] = objectToKeyValueList(channelStateToStringSnapshot(channelSetting, removeDefaults));
595
557
  return acc;
596
558
  }, {});
597
559
  return _objectSpread(_objectSpread({}, params), channelParams);
@@ -0,0 +1,46 @@
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 _regeneratorRuntime() { "use strict"; var r = _regenerator(), e = r.m(_regeneratorRuntime), t = (Object.getPrototypeOf ? Object.getPrototypeOf(e) : e.__proto__).constructor; function n(r) { var e = "function" == typeof r && r.constructor; return !!e && (e === t || "GeneratorFunction" === (e.displayName || e.name)); } var o = { "throw": 1, "return": 2, "break": 3, "continue": 3 }; function a(r) { var e, t; return function (n) { e || (e = { stop: function stop() { return t(n.a, 2); }, "catch": function _catch() { return n.v; }, abrupt: function abrupt(r, e) { return t(n.a, o[r], e); }, delegateYield: function delegateYield(r, o, a) { return e.resultName = o, t(n.d, _regeneratorValues(r), a); }, finish: function finish(r) { return t(n.f, r); } }, t = function t(r, _t, o) { n.p = e.prev, n.n = e.next; try { return r(_t, o); } finally { e.next = n.n; } }), e.resultName && (e[e.resultName] = n.v, e.resultName = void 0), e.sent = n.v, e.next = n.n; try { return r.call(this, e); } finally { n.p = e.prev, n.n = e.next; } }; } return (_regeneratorRuntime = function _regeneratorRuntime() { return { wrap: function wrap(e, t, n, o) { return r.w(a(e), t, n, o && o.reverse()); }, isGeneratorFunction: n, mark: r.m, awrap: function awrap(r, e) { return new _OverloadYield(r, e); }, AsyncIterator: _regeneratorAsyncIterator, async: function async(r, e, t, o, u) { return (n(e) ? _regeneratorAsyncGen : _regeneratorAsync)(a(r), e, t, o, u); }, keys: _regeneratorKeys, values: _regeneratorValues }; })(); }
3
+ function _regeneratorValues(e) { if (null != e) { var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"], r = 0; if (t) return t.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) return { next: function next() { return e && r >= e.length && (e = void 0), { value: e && e[r++], done: !e }; } }; } throw new TypeError(_typeof(e) + " is not iterable"); }
4
+ function _regeneratorKeys(e) { var n = Object(e), r = []; for (var t in n) r.unshift(t); return function e() { for (; r.length;) if ((t = r.pop()) in n) return e.value = t, e.done = !1, e; return e.done = !0, e; }; }
5
+ function _regeneratorAsync(n, e, r, t, o) { var a = _regeneratorAsyncGen(n, e, r, t, o); return a.next().then(function (n) { return n.done ? n.value : a.next(); }); }
6
+ function _regeneratorAsyncGen(r, e, t, o, n) { return new _regeneratorAsyncIterator(_regenerator().w(r, e, t, o), n || Promise); }
7
+ function _regeneratorAsyncIterator(t, e) { function n(r, o, i, f) { try { var c = t[r](o), u = c.value; return u instanceof _OverloadYield ? e.resolve(u.v).then(function (t) { n("next", t, i, f); }, function (t) { n("throw", t, i, f); }) : e.resolve(u).then(function (t) { c.value = t, i(c); }, function (t) { return n("throw", t, i, f); }); } catch (t) { f(t); } } var r; this.next || (_regeneratorDefine2(_regeneratorAsyncIterator.prototype), _regeneratorDefine2(_regeneratorAsyncIterator.prototype, "function" == typeof Symbol && Symbol.asyncIterator || "@asyncIterator", function () { return this; })), _regeneratorDefine2(this, "_invoke", function (t, o, i) { function f() { return new e(function (e, r) { n(t, i, e, r); }); } return r = r ? r.then(f, f) : f(); }, !0); }
8
+ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
9
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
10
+ function _OverloadYield(e, d) { this.v = e, this.k = d; }
11
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
12
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
13
+ /**
14
+ * Try to determine whether attempting to access the clipboard will immediately fail.
15
+ *
16
+ * When this function returns `false`, accessing the clipboard *may* be successful, though some browsers require users
17
+ * to confirm every paste. When it returns `true`, access to the clipboard is definitely blocked.
18
+ */
19
+ export var queryPasteDenied = /*#__PURE__*/function () {
20
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
21
+ var permission;
22
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
23
+ while (1) switch (_context.prev = _context.next) {
24
+ case 0:
25
+ _context.prev = 0;
26
+ _context.next = 3;
27
+ return navigator.permissions.query({
28
+ name: "clipboard-read"
29
+ });
30
+ case 3:
31
+ permission = _context.sent;
32
+ return _context.abrupt("return", permission.state === "denied");
33
+ case 7:
34
+ _context.prev = 7;
35
+ _context.t0 = _context["catch"](0);
36
+ return _context.abrupt("return", false);
37
+ case 10:
38
+ case "end":
39
+ return _context.stop();
40
+ }
41
+ }, _callee, null, [[0, 7]]);
42
+ }));
43
+ return function queryPasteDenied() {
44
+ return _ref.apply(this, arguments);
45
+ };
46
+ }();