@jbrowse/core 1.7.9 → 2.0.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 (86) hide show
  1. package/BaseFeatureWidget/BaseFeatureDetail.d.ts +14 -7
  2. package/BaseFeatureWidget/BaseFeatureDetail.js +203 -125
  3. package/BaseFeatureWidget/SequenceFeatureDetails.js +20 -15
  4. package/BaseFeatureWidget/index.d.ts +23 -2
  5. package/BaseFeatureWidget/index.js +100 -3
  6. package/BaseFeatureWidget/index.test.js +48 -30
  7. package/PluginManager.d.ts +58 -86
  8. package/ReExports/Attributes.d.ts +2 -0
  9. package/ReExports/Attributes.js +12 -0
  10. package/ReExports/BaseCard.d.ts +2 -0
  11. package/ReExports/BaseCard.js +12 -0
  12. package/ReExports/DataGrid.d.ts +2 -0
  13. package/ReExports/DataGrid.js +13 -0
  14. package/ReExports/FeatureDetails.d.ts +2 -0
  15. package/ReExports/FeatureDetails.js +12 -0
  16. package/ReExports/list.js +1 -1
  17. package/ReExports/material-ui-colors.d.ts +1 -19
  18. package/ReExports/material-ui-colors.js +11 -152
  19. package/ReExports/modules.d.ts +59 -91
  20. package/ReExports/modules.js +683 -127
  21. package/TextSearch/TextSearchManager.d.ts +3 -1
  22. package/assemblyManager/assembly.d.ts +6 -7
  23. package/assemblyManager/assembly.js +27 -16
  24. package/assemblyManager/assemblyManager.d.ts +82 -24
  25. package/assemblyManager/assemblyManager.js +32 -36
  26. package/configuration/util.d.ts +1 -1
  27. package/package.json +15 -15
  28. package/pluggableElementTypes/models/BaseDisplayModel.d.ts +10 -10
  29. package/pluggableElementTypes/models/BaseTrackModel.d.ts +1 -1
  30. package/pluggableElementTypes/models/BaseTrackModel.js +24 -25
  31. package/pluggableElementTypes/models/baseTrackConfig.js +20 -13
  32. package/pluggableElementTypes/renderers/ServerSideRenderedContent.js +2 -2
  33. package/pluggableElementTypes/renderers/ServerSideRendererType.d.ts +2 -2
  34. package/pluggableElementTypes/renderers/ServerSideRendererType.js +1 -1
  35. package/rpc/BaseRpcDriver.js +1 -1
  36. package/tsconfig.build.tsbuildinfo +1 -1
  37. package/ui/AboutDialog.d.ts +1 -1
  38. package/ui/AboutDialog.js +38 -16
  39. package/ui/App.js +18 -37
  40. package/ui/AssemblySelector.d.ts +1 -1
  41. package/ui/AssemblySelector.js +10 -5
  42. package/ui/CascadingMenu.d.ts +9 -0
  43. package/ui/CascadingMenu.js +207 -0
  44. package/ui/Drawer.js +8 -5
  45. package/ui/DrawerWidget.js +39 -45
  46. package/ui/DropDownMenu.d.ts +0 -8
  47. package/ui/DropDownMenu.js +9 -15
  48. package/ui/EditableTypography.d.ts +1 -1
  49. package/ui/EditableTypography.js +42 -48
  50. package/ui/ErrorMessage.js +13 -23
  51. package/ui/FactoryResetDialog.js +6 -6
  52. package/ui/FatalErrorDialog.js +5 -5
  53. package/ui/FileSelector/FileSelector.js +19 -19
  54. package/ui/FileSelector/LocalFileChooser.js +12 -8
  55. package/ui/FileSelector/UrlChooser.js +2 -2
  56. package/ui/Icons.d.ts +1 -1
  57. package/ui/Icons.js +1 -1
  58. package/ui/Menu.d.ts +11 -1
  59. package/ui/Menu.js +32 -38
  60. package/ui/PrerenderedCanvas.js +10 -1
  61. package/ui/ResizeHandle.js +8 -6
  62. package/ui/ReturnToImportFormDialog.js +14 -10
  63. package/ui/SanitizedHTML.js +15 -21
  64. package/ui/Snackbar.js +11 -9
  65. package/ui/Tooltip.d.ts +3 -1
  66. package/ui/Tooltip.js +5 -3
  67. package/ui/ViewContainer.js +38 -25
  68. package/ui/index.d.ts +1 -0
  69. package/ui/index.js +9 -0
  70. package/ui/theme.d.ts +279 -131
  71. package/ui/theme.js +174 -154
  72. package/ui/theme.test.js +56 -75
  73. package/util/Base1DViewModel.d.ts +1 -8
  74. package/util/Base1DViewModel.js +11 -13
  75. package/util/color/index.js +6 -6
  76. package/util/index.d.ts +4 -8
  77. package/util/index.js +29 -19
  78. package/util/jexl.js +42 -43
  79. package/util/layouts/GranularRectLayout.js +1 -3
  80. package/util/layouts/PrecomputedLayout.js +1 -3
  81. package/util/offscreenCanvasPonyfill.js +10 -12
  82. package/util/tracks.js +4 -2
  83. package/util/types/index.d.ts +14 -4
  84. package/util/types/index.js +6 -0
  85. package/util/types/mst.d.ts +3 -3
  86. package/util/types/mst.js +11 -7
@@ -2,9 +2,19 @@ import React from 'react';
2
2
  import { IAnyStateTreeNode } from 'mobx-state-tree';
3
3
  import { BaseCardProps, BaseProps } from './types';
4
4
  import { SimpleFeatureSerialized } from '../util/simpleFeature';
5
- export declare const useStyles: (props?: any) => import("@material-ui/styles").ClassNameMap<"expandIcon" | "expansionPanelDetails" | "field" | "fieldDescription" | "fieldName" | "fieldValue" | "fieldSubvalue">;
5
+ export declare const useStyles: (params: void, styleOverrides?: {
6
+ props: {
7
+ classes?: Record<string, string> | undefined;
8
+ } & Record<string, unknown>;
9
+ ownerState?: Record<string, unknown> | undefined;
10
+ } | undefined) => {
11
+ classes: Record<"expansionPanelDetails" | "expandIcon" | "field" | "fieldDescription" | "fieldName" | "fieldValue" | "fieldSubvalue", string>;
12
+ theme: import("@mui/material").Theme;
13
+ css: import("tss-react/types").Css;
14
+ cx: import("tss-react/types").Cx;
15
+ };
6
16
  export declare function BaseCard({ children, title, defaultExpanded, }: BaseCardProps): JSX.Element;
7
- export declare const FieldName: ({ description, name, prefix, width, }: {
17
+ export declare const FieldName: ({ description, name, width, prefix, }: {
8
18
  description?: React.ReactNode;
9
19
  name: string;
10
20
  prefix?: string[] | undefined;
@@ -28,7 +38,7 @@ interface AttributeProps {
28
38
  descriptions?: Record<string, React.ReactNode>;
29
39
  prefix?: string[];
30
40
  }
31
- export declare const Attributes: React.FunctionComponent<AttributeProps>;
41
+ export declare function Attributes(props: AttributeProps): JSX.Element;
32
42
  export declare const BaseAttributes: (props: BaseProps) => JSX.Element;
33
43
  export interface BaseInputProps extends BaseCardProps {
34
44
  omit?: string[];
@@ -38,10 +48,7 @@ export interface BaseInputProps extends BaseCardProps {
38
48
  }
39
49
  export declare const FeatureDetails: (props: {
40
50
  model: IAnyStateTreeNode;
41
- feature: SimpleFeatureSerialized & {
42
- name?: string;
43
- id?: string;
44
- };
51
+ feature: SimpleFeatureSerialized;
45
52
  depth?: number | undefined;
46
53
  omit?: string[] | undefined;
47
54
  formatter?: ((val: unknown, key: string) => React.ReactElement) | undefined;
@@ -7,7 +7,8 @@ var _typeof = require("@babel/runtime/helpers/typeof");
7
7
  Object.defineProperty(exports, "__esModule", {
8
8
  value: true
9
9
  });
10
- exports.BaseAttributes = exports.Attributes = void 0;
10
+ exports.Attributes = Attributes;
11
+ exports.BaseAttributes = void 0;
11
12
  exports.BaseCard = BaseCard;
12
13
  exports.useStyles = exports.default = exports.SimpleValue = exports.FieldName = exports.FeatureDetails = exports.BasicValue = exports.BaseCoreDetails = void 0;
13
14
 
@@ -25,16 +26,16 @@ var _react = _interopRequireWildcard(require("react"));
25
26
 
26
27
  var _reactErrorBoundary = require("react-error-boundary");
27
28
 
28
- var _core = require("@material-ui/core");
29
+ var _material = require("@mui/material");
30
+
31
+ var _mui = require("tss-react/mui");
29
32
 
30
- var _ExpandMore = _interopRequireDefault(require("@material-ui/icons/ExpandMore"));
33
+ var _ExpandMore = _interopRequireDefault(require("@mui/icons-material/ExpandMore"));
31
34
 
32
35
  var _xDataGrid = require("@mui/x-data-grid");
33
36
 
34
37
  var _mobxReact = require("mobx-react");
35
38
 
36
- var _clsx = _interopRequireDefault(require("clsx"));
37
-
38
39
  var _isObject = _interopRequireDefault(require("is-object"));
39
40
 
40
41
  var _configuration = require("../configuration");
@@ -47,7 +48,8 @@ var _SequenceFeatureDetails = _interopRequireDefault(require("./SequenceFeatureD
47
48
 
48
49
  var _util2 = require("./util");
49
50
 
50
- var _excluded = ["id"];
51
+ var _excluded = ["id"],
52
+ _excluded2 = ["__jbrowsefmt"];
51
53
 
52
54
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
53
55
 
@@ -59,10 +61,10 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
59
61
 
60
62
  var MAX_FIELD_NAME_WIDTH = 170; // these are always omitted as too detailed
61
63
 
62
- var globalOmit = ['length', 'position', 'subfeatures', 'uniqueId', 'exonFrames', 'parentId', 'thickStart', 'thickEnd']; // coreDetails are omitted in some circumstances
64
+ var globalOmit = ['__jbrowsefmt', 'length', 'position', 'subfeatures', 'uniqueId', 'exonFrames', 'parentId', 'thickStart', 'thickEnd']; // coreDetails are omitted in some circumstances
63
65
 
64
66
  var coreDetails = ['name', 'start', 'end', 'strand', 'refName', 'description', 'type'];
65
- var useStyles = (0, _core.makeStyles)(function (theme) {
67
+ var useStyles = (0, _mui.makeStyles)()(function (theme) {
66
68
  return {
67
69
  expansionPanelDetails: {
68
70
  display: 'block',
@@ -84,6 +86,7 @@ var useStyles = (0, _core.makeStyles)(function (theme) {
84
86
  wordBreak: 'break-all',
85
87
  minWidth: '90px',
86
88
  borderBottom: '1px solid #0003',
89
+ fontSize: 12,
87
90
  background: theme.palette.grey[200],
88
91
  marginRight: theme.spacing(1),
89
92
  padding: theme.spacing(0.5)
@@ -91,6 +94,7 @@ var useStyles = (0, _core.makeStyles)(function (theme) {
91
94
  fieldValue: {
92
95
  wordBreak: 'break-word',
93
96
  maxHeight: 300,
97
+ fontSize: 12,
94
98
  padding: theme.spacing(0.5),
95
99
  overflow: 'auto'
96
100
  },
@@ -112,14 +116,16 @@ function BaseCard(_ref) {
112
116
  title = _ref.title,
113
117
  _ref$defaultExpanded = _ref.defaultExpanded,
114
118
  defaultExpanded = _ref$defaultExpanded === void 0 ? true : _ref$defaultExpanded;
115
- var classes = useStyles();
119
+
120
+ var _useStyles = useStyles(),
121
+ classes = _useStyles.classes;
116
122
 
117
123
  var _useState = (0, _react.useState)(defaultExpanded),
118
124
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
119
125
  expanded = _useState2[0],
120
126
  setExpanded = _useState2[1];
121
127
 
122
- return /*#__PURE__*/_react.default.createElement(_core.Accordion, {
128
+ return /*#__PURE__*/_react.default.createElement(_material.Accordion, {
123
129
  expanded: expanded,
124
130
  onChange: function onChange() {
125
131
  return setExpanded(function (s) {
@@ -129,13 +135,13 @@ function BaseCard(_ref) {
129
135
  TransitionProps: {
130
136
  unmountOnExit: true
131
137
  }
132
- }, /*#__PURE__*/_react.default.createElement(_core.AccordionSummary, {
138
+ }, /*#__PURE__*/_react.default.createElement(_material.AccordionSummary, {
133
139
  expandIcon: /*#__PURE__*/_react.default.createElement(_ExpandMore.default, {
134
140
  className: classes.expandIcon
135
141
  })
136
- }, /*#__PURE__*/_react.default.createElement(_core.Typography, {
142
+ }, /*#__PURE__*/_react.default.createElement(_material.Typography, {
137
143
  variant: "button"
138
- }, " ", title)), /*#__PURE__*/_react.default.createElement(_core.AccordionDetails, {
144
+ }, " ", title)), /*#__PURE__*/_react.default.createElement(_material.AccordionDetails, {
139
145
  className: classes.expansionPanelDetails
140
146
  }, children));
141
147
  }
@@ -143,16 +149,20 @@ function BaseCard(_ref) {
143
149
  var FieldName = function FieldName(_ref2) {
144
150
  var description = _ref2.description,
145
151
  name = _ref2.name,
152
+ width = _ref2.width,
146
153
  _ref2$prefix = _ref2.prefix,
147
- prefix = _ref2$prefix === void 0 ? [] : _ref2$prefix,
148
- width = _ref2.width;
149
- var classes = useStyles();
154
+ prefix = _ref2$prefix === void 0 ? [] : _ref2$prefix;
155
+
156
+ var _useStyles2 = useStyles(),
157
+ classes = _useStyles2.classes,
158
+ cx = _useStyles2.cx;
159
+
150
160
  var val = [].concat((0, _toConsumableArray2.default)(prefix), [name]).join('.');
151
- return description ? /*#__PURE__*/_react.default.createElement(_core.Tooltip, {
161
+ return description ? /*#__PURE__*/_react.default.createElement(_material.Tooltip, {
152
162
  title: description,
153
163
  placement: "left"
154
164
  }, /*#__PURE__*/_react.default.createElement("div", {
155
- className: (0, _clsx.default)(classes.fieldDescription, classes.fieldName)
165
+ className: cx(classes.fieldDescription, classes.fieldName)
156
166
  }, val)) : /*#__PURE__*/_react.default.createElement("div", {
157
167
  className: classes.fieldName,
158
168
  style: {
@@ -165,10 +175,16 @@ exports.FieldName = FieldName;
165
175
 
166
176
  var BasicValue = function BasicValue(_ref3) {
167
177
  var value = _ref3.value;
168
- var classes = useStyles();
178
+
179
+ var _useStyles3 = useStyles(),
180
+ classes = _useStyles3.classes;
181
+
182
+ var isLink = "".concat(value).match(/^https?:\/\//);
169
183
  return /*#__PURE__*/_react.default.createElement("div", {
170
184
  className: classes.fieldValue
171
- }, /*#__PURE__*/_react.default.isValidElement(value) ? value : /*#__PURE__*/_react.default.createElement(_SanitizedHTML.default, {
185
+ }, /*#__PURE__*/_react.default.isValidElement(value) ? value : isLink ? /*#__PURE__*/_react.default.createElement(_SanitizedHTML.default, {
186
+ html: "<a href=\"".concat(value, "\">").concat(value, "</a>")
187
+ }) : /*#__PURE__*/_react.default.createElement(_SanitizedHTML.default, {
172
188
  html: (0, _isObject.default)(value) ? JSON.stringify(value) : String(value)
173
189
  }));
174
190
  };
@@ -181,7 +197,10 @@ var SimpleValue = function SimpleValue(_ref4) {
181
197
  description = _ref4.description,
182
198
  prefix = _ref4.prefix,
183
199
  width = _ref4.width;
184
- var classes = useStyles();
200
+
201
+ var _useStyles4 = useStyles(),
202
+ classes = _useStyles4.classes;
203
+
185
204
  return value !== null && value !== undefined ? /*#__PURE__*/_react.default.createElement("div", {
186
205
  className: classes.field
187
206
  }, /*#__PURE__*/_react.default.createElement(FieldName, {
@@ -202,76 +221,89 @@ var ArrayValue = function ArrayValue(_ref5) {
202
221
  description = _ref5.description,
203
222
  _ref5$prefix = _ref5.prefix,
204
223
  prefix = _ref5$prefix === void 0 ? [] : _ref5$prefix;
205
- var classes = useStyles();
206
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, value.length === 1 ? (0, _isObject.default)(value[0]) ? /*#__PURE__*/_react.default.createElement(Attributes, {
207
- attributes: value[0],
208
- prefix: [].concat((0, _toConsumableArray2.default)(prefix), [name])
209
- }) : /*#__PURE__*/_react.default.createElement("div", {
210
- className: classes.field
211
- }, /*#__PURE__*/_react.default.createElement(FieldName, {
212
- prefix: prefix,
213
- description: description,
214
- name: name
215
- }), /*#__PURE__*/_react.default.createElement(BasicValue, {
216
- value: value[0]
217
- })) : value.every(function (val) {
224
+
225
+ var _useStyles5 = useStyles(),
226
+ classes = _useStyles5.classes;
227
+
228
+ if (value.length === 1) {
229
+ return (0, _isObject.default)(value[0]) ? /*#__PURE__*/_react.default.createElement(Attributes, {
230
+ attributes: value[0],
231
+ prefix: [].concat((0, _toConsumableArray2.default)(prefix), [name])
232
+ }) : /*#__PURE__*/_react.default.createElement("div", {
233
+ className: classes.field
234
+ }, /*#__PURE__*/_react.default.createElement(FieldName, {
235
+ prefix: prefix,
236
+ description: description,
237
+ name: name
238
+ }), /*#__PURE__*/_react.default.createElement(BasicValue, {
239
+ value: value[0]
240
+ }));
241
+ } else if (value.every(function (val) {
218
242
  return (0, _isObject.default)(val);
219
- }) ? value.map(function (val, i) {
220
- return /*#__PURE__*/_react.default.createElement(Attributes, {
221
- key: JSON.stringify(val) + '-' + i,
222
- attributes: val,
223
- prefix: [].concat((0, _toConsumableArray2.default)(prefix), [name + '-' + i])
224
- });
225
- }) : /*#__PURE__*/_react.default.createElement("div", {
226
- className: classes.field
227
- }, /*#__PURE__*/_react.default.createElement(FieldName, {
228
- prefix: prefix,
229
- description: description,
230
- name: name
231
- }), value.map(function (val, i) {
243
+ })) {
244
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, value.map(function (val, i) {
245
+ return /*#__PURE__*/_react.default.createElement(Attributes, {
246
+ key: JSON.stringify(val) + '-' + i,
247
+ attributes: val,
248
+ prefix: [].concat((0, _toConsumableArray2.default)(prefix), [name + '-' + i])
249
+ });
250
+ }));
251
+ } else {
232
252
  return /*#__PURE__*/_react.default.createElement("div", {
233
- key: JSON.stringify(val) + '-' + i,
234
- className: classes.fieldSubvalue
235
- }, /*#__PURE__*/_react.default.createElement(BasicValue, {
236
- value: val
253
+ className: classes.field
254
+ }, /*#__PURE__*/_react.default.createElement(FieldName, {
255
+ prefix: prefix,
256
+ description: description,
257
+ name: name
258
+ }), value.map(function (val, i) {
259
+ return /*#__PURE__*/_react.default.createElement("div", {
260
+ key: JSON.stringify(val) + '-' + i,
261
+ className: classes.fieldSubvalue
262
+ }, /*#__PURE__*/_react.default.createElement(BasicValue, {
263
+ value: val
264
+ }));
237
265
  }));
238
- })));
266
+ }
267
+ };
268
+
269
+ var toLocale = function toLocale(n) {
270
+ return n.toLocaleString('en-US');
239
271
  };
240
272
 
241
273
  function CoreDetails(props) {
242
274
  var feature = props.feature;
243
- var _ref6 = feature,
244
- refName = _ref6.refName,
245
- start = _ref6.start,
246
- end = _ref6.end,
247
- strand = _ref6.strand;
275
+ var obj = feature; // eslint-disable-next-line no-underscore-dangle
276
+
277
+ var formattedFeat = _objectSpread(_objectSpread({}, obj), obj.__jbrowsefmt);
278
+
279
+ var start = formattedFeat.start,
280
+ strand = formattedFeat.strand,
281
+ end = formattedFeat.end,
282
+ refName = formattedFeat.refName;
248
283
  var strandMap = {
249
284
  '-1': '-',
250
285
  '0': '',
251
286
  '1': '+'
252
287
  };
253
- var strandStr = strandMap[strand] ? "(".concat(strandMap[strand], ")") : '';
254
- var displayStart = (start + 1).toLocaleString('en-US');
255
- var displayEnd = end.toLocaleString('en-US');
256
- var displayRef = refName ? "".concat(refName, ":") : '';
257
-
258
- var displayedDetails = _objectSpread(_objectSpread({}, feature), {}, {
259
- length: (end - start).toLocaleString('en-US'),
260
- position: "".concat(displayRef).concat(displayStart, "..").concat(displayEnd, " ").concat(strandStr)
288
+ var str = strandMap[strand] ? "(".concat(strandMap[strand], ")") : '';
289
+
290
+ var displayedDetails = _objectSpread(_objectSpread({}, formattedFeat), {}, {
291
+ length: toLocale(end - start),
292
+ position: "".concat(refName, ":").concat(toLocale(start + 1), "..").concat(toLocale(end), " ").concat(str)
261
293
  });
262
294
 
263
295
  var coreRenderedDetails = ['Position', 'Description', 'Name', 'Length', 'Type'];
264
296
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, coreRenderedDetails.map(function (key) {
265
297
  return [key, displayedDetails[key.toLowerCase()]];
266
- }).filter(function (_ref7) {
267
- var _ref8 = (0, _slicedToArray2.default)(_ref7, 2),
268
- value = _ref8[1];
298
+ }).filter(function (_ref6) {
299
+ var _ref7 = (0, _slicedToArray2.default)(_ref6, 2),
300
+ value = _ref7[1];
269
301
 
270
302
  return value !== null && value !== undefined;
271
- }).map(function (_ref9) {
272
- var _ref10 = (0, _slicedToArray2.default)(_ref9, 2),
273
- key = _ref10[0],
274
- value = _ref10[1];
303
+ }).map(function (_ref8) {
304
+ var _ref9 = (0, _slicedToArray2.default)(_ref8, 2),
305
+ key = _ref9[0],
306
+ value = _ref9[1];
275
307
 
276
308
  return /*#__PURE__*/_react.default.createElement(SimpleValue, {
277
309
  key: key,
@@ -289,10 +321,10 @@ var BaseCoreDetails = function BaseCoreDetails(props) {
289
321
 
290
322
  exports.BaseCoreDetails = BaseCoreDetails;
291
323
 
292
- var DataGridDetails = function DataGridDetails(_ref11) {
293
- var value = _ref11.value,
294
- prefix = _ref11.prefix,
295
- name = _ref11.name;
324
+ var DataGridDetails = function DataGridDetails(_ref10) {
325
+ var value = _ref10.value,
326
+ prefix = _ref10.prefix,
327
+ name = _ref10.name;
296
328
  var keys = Object.keys(value[0]).sort();
297
329
  var unionKeys = new Set(keys);
298
330
  value.forEach(function (val) {
@@ -303,10 +335,10 @@ var DataGridDetails = function DataGridDetails(_ref11) {
303
335
 
304
336
  if (unionKeys.size < keys.length + 5) {
305
337
  // avoids key 'id' from being used in row data
306
- var rows = Object.entries(value).map(function (_ref12) {
307
- var _ref13 = (0, _slicedToArray2.default)(_ref12, 2),
308
- k = _ref13[0],
309
- val = _ref13[1];
338
+ var rows = Object.entries(value).map(function (_ref11) {
339
+ var _ref12 = (0, _slicedToArray2.default)(_ref11, 2),
340
+ k = _ref12[0],
341
+ val = _ref12[1];
310
342
 
311
343
  var id = val.id,
312
344
  rest = (0, _objectWithoutProperties2.default)(val, _excluded);
@@ -327,12 +359,18 @@ var DataGridDetails = function DataGridDetails(_ref11) {
327
359
  colNames = (0, _toConsumableArray2.default)(unionKeys);
328
360
  }
329
361
 
362
+ var getStr = function getStr(obj) {
363
+ return (0, _isObject.default)(obj) ? JSON.stringify(obj) : String(obj);
364
+ };
365
+
330
366
  var columns = colNames.map(function (val) {
331
367
  return {
332
368
  field: val,
369
+ renderCell: function renderCell(val) {
370
+ return getStr(val.formattedValue);
371
+ },
333
372
  width: Math.max.apply(Math, (0, _toConsumableArray2.default)(rows.map(function (row) {
334
- var result = String(row[val]);
335
- return Math.min(Math.max((0, _util.measureText)(result, 14) + 50, 80), 1000);
373
+ return Math.min(Math.max((0, _util.measureText)(getStr(row[val]), 14) + 50, 80), 1000);
336
374
  })))
337
375
  };
338
376
  }); // disableSelection on click helps avoid
@@ -348,11 +386,9 @@ var DataGridDetails = function DataGridDetails(_ref11) {
348
386
  }
349
387
  }, /*#__PURE__*/_react.default.createElement(_xDataGrid.DataGrid, {
350
388
  disableSelectionOnClick: true,
351
- rowHeight: 20,
352
- headerHeight: 25,
389
+ rowHeight: 25,
353
390
  rows: rows,
354
391
  rowsPerPageOptions: [],
355
- hideFooterRowCount: true,
356
392
  hideFooterSelectedRowCount: true,
357
393
  columns: columns,
358
394
  hideFooter: rows.length < 100
@@ -386,7 +422,36 @@ function generateMaxWidth(array, prefix) {
386
422
  return Math.ceil(Math.max.apply(Math, arr)) + 10;
387
423
  }
388
424
 
389
- var Attributes = function Attributes(props) {
425
+ function UriAttribute(_ref13) {
426
+ var value = _ref13.value,
427
+ prefix = _ref13.prefix,
428
+ name = _ref13.name;
429
+
430
+ var _useStyles6 = useStyles(),
431
+ classes = _useStyles6.classes;
432
+
433
+ var uri = value.uri,
434
+ _value$baseUri = value.baseUri,
435
+ baseUri = _value$baseUri === void 0 ? '' : _value$baseUri;
436
+ var href;
437
+
438
+ try {
439
+ href = new URL(uri, baseUri).href;
440
+ } catch (e) {
441
+ href = uri;
442
+ }
443
+
444
+ return /*#__PURE__*/_react.default.createElement("div", {
445
+ className: classes.field
446
+ }, /*#__PURE__*/_react.default.createElement(FieldName, {
447
+ prefix: prefix,
448
+ name: name
449
+ }), /*#__PURE__*/_react.default.createElement(BasicValue, {
450
+ value: href
451
+ }));
452
+ }
453
+
454
+ function Attributes(props) {
390
455
  var attributes = props.attributes,
391
456
  _props$omit = props.omit,
392
457
  omit = _props$omit === void 0 ? [] : _props$omit,
@@ -398,15 +463,19 @@ var Attributes = function Attributes(props) {
398
463
  _props$prefix = props.prefix,
399
464
  prefix = _props$prefix === void 0 ? [] : _props$prefix;
400
465
  var omits = [].concat((0, _toConsumableArray2.default)(omit), globalOmit);
401
- var maxLabelWidth = generateMaxWidth(Object.entries(attributes).filter(function (_ref14) {
466
+ var __jbrowsefmt = attributes.__jbrowsefmt,
467
+ rest = (0, _objectWithoutProperties2.default)(attributes, _excluded2);
468
+
469
+ var formattedAttributes = _objectSpread(_objectSpread({}, rest), __jbrowsefmt);
470
+
471
+ var maxLabelWidth = generateMaxWidth(Object.entries(formattedAttributes).filter(function (_ref14) {
402
472
  var _ref15 = (0, _slicedToArray2.default)(_ref14, 2),
403
473
  k = _ref15[0],
404
474
  v = _ref15[1];
405
475
 
406
476
  return v !== undefined && !omits.includes(k);
407
477
  }), prefix);
408
- var labelWidth = maxLabelWidth <= MAX_FIELD_NAME_WIDTH ? maxLabelWidth : MAX_FIELD_NAME_WIDTH;
409
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, Object.entries(attributes).filter(function (_ref16) {
478
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, Object.entries(formattedAttributes).filter(function (_ref16) {
410
479
  var _ref17 = (0, _slicedToArray2.default)(_ref16, 2),
411
480
  k = _ref17[0],
412
481
  v = _ref17[1];
@@ -417,51 +486,50 @@ var Attributes = function Attributes(props) {
417
486
  key = _ref19[0],
418
487
  value = _ref19[1];
419
488
 
420
- if (Array.isArray(value) && value.length > 2 && value.every(function (val) {
421
- return (0, _isObject.default)(val);
422
- })) {
423
- return /*#__PURE__*/_react.default.createElement(DataGridDetails, {
424
- key: key,
425
- prefix: prefix,
426
- name: key,
427
- value: value
428
- });
429
- }
430
-
431
489
  var description = accessNested([].concat((0, _toConsumableArray2.default)(prefix), [key]), descriptions);
432
490
 
433
491
  if (Array.isArray(value)) {
434
- return /*#__PURE__*/_react.default.createElement(ArrayValue, {
492
+ // check if it looks like an array of objects, which could be used
493
+ // in data grid
494
+ return value.length > 1 && value.every(function (val) {
495
+ return (0, _isObject.default)(val);
496
+ }) ? /*#__PURE__*/_react.default.createElement(DataGridDetails, {
497
+ key: key,
498
+ name: key,
499
+ prefix: prefix,
500
+ value: value
501
+ }) : /*#__PURE__*/_react.default.createElement(ArrayValue, {
435
502
  key: key,
436
503
  name: key,
437
504
  value: value,
438
505
  description: description,
439
506
  prefix: prefix
440
507
  });
441
- }
442
-
443
- if ((0, _isObject.default)(value)) {
444
- return /*#__PURE__*/_react.default.createElement(Attributes, {
508
+ } else if ((0, _isObject.default)(value)) {
509
+ return (0, _util.isUriLocation)(value) ? /*#__PURE__*/_react.default.createElement(UriAttribute, {
510
+ key: key,
511
+ name: key,
512
+ prefix: prefix,
513
+ value: value
514
+ }) : /*#__PURE__*/_react.default.createElement(Attributes, {
445
515
  omit: omits,
446
516
  key: key,
447
517
  attributes: value,
448
518
  descriptions: descriptions,
449
519
  prefix: [].concat((0, _toConsumableArray2.default)(prefix), [key])
450
520
  });
521
+ } else {
522
+ return /*#__PURE__*/_react.default.createElement(SimpleValue, {
523
+ key: key,
524
+ name: key,
525
+ value: formatter(value, key),
526
+ description: description,
527
+ prefix: prefix,
528
+ width: Math.min(maxLabelWidth, MAX_FIELD_NAME_WIDTH)
529
+ });
451
530
  }
452
-
453
- return /*#__PURE__*/_react.default.createElement(SimpleValue, {
454
- key: key,
455
- name: key,
456
- value: formatter(value, key),
457
- description: description,
458
- prefix: prefix,
459
- width: labelWidth
460
- });
461
531
  }));
462
- };
463
-
464
- exports.Attributes = Attributes;
532
+ }
465
533
 
466
534
  var BaseAttributes = function BaseAttributes(props) {
467
535
  var feature = props.feature;
@@ -478,6 +546,12 @@ function isEmpty(obj) {
478
546
  return Object.keys(obj).length === 0;
479
547
  }
480
548
 
549
+ function generateTitle(name, id, type) {
550
+ return [(0, _util2.ellipses)("".concat(name) || "".concat(id)), "".concat(type)].filter(function (f) {
551
+ return !!f;
552
+ }).join(' - ');
553
+ }
554
+
481
555
  var FeatureDetails = function FeatureDetails(props) {
482
556
  var _props$omit2 = props.omit,
483
557
  omit = _props$omit2 === void 0 ? [] : _props$omit2,
@@ -496,19 +570,17 @@ var FeatureDetails = function FeatureDetails(props) {
496
570
  var defaultSeqTypes = ['mRNA', 'transcript'];
497
571
  var sequenceTypes = (0, _configuration.getConf)(session, ['featureDetails', 'sequenceTypes']) || defaultSeqTypes;
498
572
  return /*#__PURE__*/_react.default.createElement(BaseCard, {
499
- title: [(0, _util2.ellipses)(name || id), type].filter(function (f) {
500
- return !!f;
501
- }).join(' - ')
502
- }, /*#__PURE__*/_react.default.createElement(_core.Typography, null, "Core details"), /*#__PURE__*/_react.default.createElement(CoreDetails, props), /*#__PURE__*/_react.default.createElement(_core.Divider, null), /*#__PURE__*/_react.default.createElement(_core.Typography, null, "Attributes"), /*#__PURE__*/_react.default.createElement(Attributes, (0, _extends2.default)({
573
+ title: generateTitle(name, id, type)
574
+ }, /*#__PURE__*/_react.default.createElement(_material.Typography, null, "Core details"), /*#__PURE__*/_react.default.createElement(CoreDetails, props), /*#__PURE__*/_react.default.createElement(_material.Divider, null), /*#__PURE__*/_react.default.createElement(_material.Typography, null, "Attributes"), /*#__PURE__*/_react.default.createElement(Attributes, (0, _extends2.default)({
503
575
  attributes: feature
504
576
  }, props, {
505
577
  omit: [].concat((0, _toConsumableArray2.default)(omit), coreDetails)
506
578
  })), sequenceTypes.includes(feature.type) ? /*#__PURE__*/_react.default.createElement(_reactErrorBoundary.ErrorBoundary, {
507
579
  FallbackComponent: function FallbackComponent(_ref20) {
508
580
  var error = _ref20.error;
509
- return /*#__PURE__*/_react.default.createElement(_core.Typography, {
581
+ return /*#__PURE__*/_react.default.createElement(_material.Typography, {
510
582
  color: "error"
511
- }, "Failed to fetch sequence for feature: ", "".concat(error));
583
+ }, "".concat(error));
512
584
  }
513
585
  }, /*#__PURE__*/_react.default.createElement(_SequenceFeatureDetails.default, props)) : null, subfeatures !== null && subfeatures !== void 0 && subfeatures.length ? /*#__PURE__*/_react.default.createElement(BaseCard, {
514
586
  title: "Subfeatures",
@@ -530,9 +602,15 @@ var BaseFeatureDetails = (0, _mobxReact.observer)(function (props) {
530
602
 
531
603
  if (!featureData) {
532
604
  return null;
533
- }
605
+ } // replacing undefined with null helps with allowing fields to be hidden,
606
+ // setting null is not allowed by jexl so we set it to undefined to hide. see
607
+ // config guide. this replacement happens both here and when snapshotting the
608
+ // featureData
609
+
534
610
 
535
- var feature = JSON.parse(JSON.stringify(featureData));
611
+ var feature = JSON.parse(JSON.stringify(featureData, function (_, v) {
612
+ return typeof v === 'undefined' ? null : v;
613
+ }));
536
614
 
537
615
  if (isEmpty(feature)) {
538
616
  return null;