@jbrowse/plugin-alignments 2.13.1 → 2.15.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 (155) hide show
  1. package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +5 -3
  2. package/dist/AlignmentsFeatureDetail/BreakendOptionDialog.js +12 -4
  3. package/dist/AlignmentsFeatureDetail/Formatter.js +6 -2
  4. package/dist/AlignmentsFeatureDetail/SuppAlignmentsLocStrings.js +4 -2
  5. package/dist/AlignmentsFeatureDetail/getSAFeatures.js +4 -4
  6. package/dist/AlignmentsFeatureDetail/launchBreakpointSplitView.js +2 -2
  7. package/dist/BamAdapter/BamAdapter.js +12 -18
  8. package/dist/BamAdapter/BamSlightlyLazyFeature.js +0 -1
  9. package/dist/CramAdapter/CramAdapter.d.ts +1 -1
  10. package/dist/CramAdapter/CramAdapter.js +7 -6
  11. package/dist/CramAdapter/CramTestAdapters.js +8 -2
  12. package/dist/GuessAlignmentsTypes/index.js +2 -2
  13. package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +2 -2
  14. package/dist/LinearAlignmentsDisplay/models/model.d.ts +13 -20
  15. package/dist/LinearAlignmentsDisplay/models/model.js +13 -3
  16. package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +9 -4
  17. package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +41 -22
  18. package/dist/LinearPileupDisplay/components/{ColorByModifications.js → ColorByModificationsDialog.js} +3 -1
  19. package/dist/LinearPileupDisplay/components/{ColorByTag.js → ColorByTagDialog.js} +4 -2
  20. package/dist/LinearPileupDisplay/components/GroupByDialog.d.ts +11 -0
  21. package/dist/LinearPileupDisplay/components/GroupByDialog.js +129 -0
  22. package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +1 -3
  23. package/dist/LinearPileupDisplay/components/{SetFeatureHeight.js → SetFeatureHeightDialog.js} +9 -3
  24. package/{esm/LinearPileupDisplay/components/SetMaxHeight.d.ts → dist/LinearPileupDisplay/components/SetMaxHeightDialog.d.ts} +1 -1
  25. package/dist/LinearPileupDisplay/components/{SetMaxHeight.js → SetMaxHeightDialog.js} +7 -3
  26. package/dist/LinearPileupDisplay/components/{SortByTag.d.ts → SortByTagDialog.d.ts} +1 -1
  27. package/dist/LinearPileupDisplay/components/{SortByTag.js → SortByTagDialog.js} +7 -3
  28. package/dist/LinearPileupDisplay/configSchema.js +0 -1
  29. package/dist/LinearPileupDisplay/model.d.ts +58 -46
  30. package/dist/LinearPileupDisplay/model.js +69 -41
  31. package/dist/LinearReadArcsDisplay/components/ReactComponent.js +1 -0
  32. package/dist/LinearReadArcsDisplay/model.d.ts +2 -2
  33. package/dist/LinearReadArcsDisplay/model.js +37 -13
  34. package/dist/LinearReadCloudDisplay/components/ReactComponent.js +4 -1
  35. package/dist/LinearReadCloudDisplay/drawPairChains.js +3 -3
  36. package/dist/LinearReadCloudDisplay/model.d.ts +4 -8
  37. package/dist/LinearReadCloudDisplay/model.js +16 -6
  38. package/dist/LinearSNPCoverageDisplay/components/Tooltip.d.ts +1 -1
  39. package/dist/LinearSNPCoverageDisplay/components/Tooltip.js +1 -1
  40. package/dist/LinearSNPCoverageDisplay/models/model.d.ts +1 -1
  41. package/dist/LinearSNPCoverageDisplay/models/model.js +15 -5
  42. package/dist/MismatchParser/index.js +12 -10
  43. package/dist/PileupRPC/base.d.ts +1 -1
  44. package/dist/PileupRPC/methods/GetGlobalValueForTag.d.ts +1 -1
  45. package/dist/PileupRPC/methods/GetReducedFeatures.d.ts +3 -3
  46. package/dist/PileupRPC/methods/GetVisibleModifications.d.ts +1 -1
  47. package/dist/PileupRenderer/PileupLayoutSession.d.ts +1 -1
  48. package/dist/PileupRenderer/PileupLayoutSession.js +3 -2
  49. package/dist/PileupRenderer/PileupRenderer.d.ts +1 -1
  50. package/dist/PileupRenderer/PileupRenderer.js +16 -13
  51. package/dist/PileupRenderer/colorBy.js +3 -5
  52. package/dist/PileupRenderer/components/PileupRendering.d.ts +1 -1
  53. package/dist/PileupRenderer/components/PileupRendering.js +65 -60
  54. package/dist/PileupRenderer/getAlignmentShapeColor.js +24 -16
  55. package/dist/PileupRenderer/layoutFeature.js +6 -1
  56. package/dist/PileupRenderer/layoutFeatures.js +1 -7
  57. package/dist/PileupRenderer/makeImageData.d.ts +1 -1
  58. package/dist/PileupRenderer/makeImageData.js +1 -0
  59. package/dist/PileupRenderer/renderAlignmentShape.js +1 -1
  60. package/dist/PileupRenderer/renderMismatches.js +1 -1
  61. package/dist/PileupRenderer/renderSoftClipping.js +1 -1
  62. package/dist/PileupRenderer/util.js +3 -5
  63. package/dist/SNPCoverageAdapter/generateCoverageBins.js +4 -10
  64. package/dist/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +2 -2
  65. package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js +2 -5
  66. package/dist/index.js +3 -1
  67. package/dist/shared/BaseDisplayComponent.js +3 -1
  68. package/dist/shared/{FilterByTag.js → FilterByTagDialog.js} +16 -6
  69. package/dist/shared/color.js +2 -2
  70. package/dist/shared/index.d.ts +24 -20
  71. package/dist/shared/index.js +4 -5
  72. package/dist/shared/renderSvg.js +1 -3
  73. package/dist/util.d.ts +1 -1
  74. package/esm/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +5 -3
  75. package/esm/AlignmentsFeatureDetail/BreakendOptionDialog.js +12 -4
  76. package/esm/AlignmentsFeatureDetail/Formatter.js +6 -2
  77. package/esm/AlignmentsFeatureDetail/SuppAlignmentsLocStrings.js +4 -2
  78. package/esm/AlignmentsFeatureDetail/getSAFeatures.js +4 -4
  79. package/esm/AlignmentsFeatureDetail/launchBreakpointSplitView.js +2 -2
  80. package/esm/BamAdapter/BamAdapter.js +12 -18
  81. package/esm/BamAdapter/BamSlightlyLazyFeature.js +0 -1
  82. package/esm/CramAdapter/CramAdapter.d.ts +1 -1
  83. package/esm/CramAdapter/CramAdapter.js +7 -6
  84. package/esm/CramAdapter/CramTestAdapters.js +8 -2
  85. package/esm/GuessAlignmentsTypes/index.js +2 -2
  86. package/esm/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +2 -2
  87. package/esm/LinearAlignmentsDisplay/models/model.d.ts +13 -20
  88. package/esm/LinearAlignmentsDisplay/models/model.js +13 -3
  89. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +9 -4
  90. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +42 -23
  91. package/esm/LinearPileupDisplay/components/{ColorByModifications.js → ColorByModificationsDialog.js} +3 -1
  92. package/esm/LinearPileupDisplay/components/{ColorByTag.js → ColorByTagDialog.js} +4 -2
  93. package/esm/LinearPileupDisplay/components/GroupByDialog.d.ts +11 -0
  94. package/esm/LinearPileupDisplay/components/GroupByDialog.js +104 -0
  95. package/esm/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +1 -3
  96. package/esm/LinearPileupDisplay/components/{SetFeatureHeight.js → SetFeatureHeightDialog.js} +9 -3
  97. package/{dist/LinearPileupDisplay/components/SetMaxHeight.d.ts → esm/LinearPileupDisplay/components/SetMaxHeightDialog.d.ts} +1 -1
  98. package/esm/LinearPileupDisplay/components/{SetMaxHeight.js → SetMaxHeightDialog.js} +7 -3
  99. package/esm/LinearPileupDisplay/components/{SortByTag.d.ts → SortByTagDialog.d.ts} +1 -1
  100. package/esm/LinearPileupDisplay/components/{SortByTag.js → SortByTagDialog.js} +7 -3
  101. package/esm/LinearPileupDisplay/configSchema.js +0 -1
  102. package/esm/LinearPileupDisplay/model.d.ts +58 -46
  103. package/esm/LinearPileupDisplay/model.js +69 -41
  104. package/esm/LinearReadArcsDisplay/components/ReactComponent.js +1 -0
  105. package/esm/LinearReadArcsDisplay/model.d.ts +2 -2
  106. package/esm/LinearReadArcsDisplay/model.js +37 -13
  107. package/esm/LinearReadCloudDisplay/components/ReactComponent.js +4 -1
  108. package/esm/LinearReadCloudDisplay/drawPairChains.js +3 -3
  109. package/esm/LinearReadCloudDisplay/model.d.ts +4 -8
  110. package/esm/LinearReadCloudDisplay/model.js +16 -6
  111. package/esm/LinearSNPCoverageDisplay/components/Tooltip.d.ts +1 -1
  112. package/esm/LinearSNPCoverageDisplay/components/Tooltip.js +1 -1
  113. package/esm/LinearSNPCoverageDisplay/models/model.d.ts +1 -1
  114. package/esm/LinearSNPCoverageDisplay/models/model.js +15 -5
  115. package/esm/MismatchParser/index.js +12 -10
  116. package/esm/PileupRPC/base.d.ts +1 -1
  117. package/esm/PileupRPC/methods/GetGlobalValueForTag.d.ts +1 -1
  118. package/esm/PileupRPC/methods/GetReducedFeatures.d.ts +3 -3
  119. package/esm/PileupRPC/methods/GetVisibleModifications.d.ts +1 -1
  120. package/esm/PileupRenderer/PileupLayoutSession.d.ts +1 -1
  121. package/esm/PileupRenderer/PileupLayoutSession.js +3 -2
  122. package/esm/PileupRenderer/PileupRenderer.d.ts +1 -1
  123. package/esm/PileupRenderer/PileupRenderer.js +16 -13
  124. package/esm/PileupRenderer/colorBy.js +3 -5
  125. package/esm/PileupRenderer/components/PileupRendering.d.ts +1 -1
  126. package/esm/PileupRenderer/components/PileupRendering.js +65 -60
  127. package/esm/PileupRenderer/getAlignmentShapeColor.js +24 -16
  128. package/esm/PileupRenderer/layoutFeature.js +6 -1
  129. package/esm/PileupRenderer/layoutFeatures.js +1 -7
  130. package/esm/PileupRenderer/makeImageData.d.ts +1 -1
  131. package/esm/PileupRenderer/makeImageData.js +1 -0
  132. package/esm/PileupRenderer/renderAlignmentShape.js +1 -1
  133. package/esm/PileupRenderer/renderMismatches.js +1 -1
  134. package/esm/PileupRenderer/renderSoftClipping.js +1 -1
  135. package/esm/PileupRenderer/util.js +3 -5
  136. package/esm/SNPCoverageAdapter/generateCoverageBins.js +4 -10
  137. package/esm/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +2 -2
  138. package/esm/SNPCoverageRenderer/SNPCoverageRenderer.js +2 -5
  139. package/esm/index.js +3 -1
  140. package/esm/shared/BaseDisplayComponent.js +3 -1
  141. package/esm/shared/{FilterByTag.js → FilterByTagDialog.js} +16 -6
  142. package/esm/shared/color.js +2 -2
  143. package/esm/shared/index.d.ts +24 -20
  144. package/esm/shared/index.js +4 -5
  145. package/esm/shared/renderSvg.js +1 -3
  146. package/esm/util.d.ts +1 -1
  147. package/package.json +6 -6
  148. /package/dist/LinearPileupDisplay/components/{ColorByModifications.d.ts → ColorByModificationsDialog.d.ts} +0 -0
  149. /package/dist/LinearPileupDisplay/components/{ColorByTag.d.ts → ColorByTagDialog.d.ts} +0 -0
  150. /package/dist/LinearPileupDisplay/components/{SetFeatureHeight.d.ts → SetFeatureHeightDialog.d.ts} +0 -0
  151. /package/dist/shared/{FilterByTag.d.ts → FilterByTagDialog.d.ts} +0 -0
  152. /package/esm/LinearPileupDisplay/components/{ColorByModifications.d.ts → ColorByModificationsDialog.d.ts} +0 -0
  153. /package/esm/LinearPileupDisplay/components/{ColorByTag.d.ts → ColorByTagDialog.d.ts} +0 -0
  154. /package/esm/LinearPileupDisplay/components/{SetFeatureHeight.d.ts → SetFeatureHeightDialog.d.ts} +0 -0
  155. /package/esm/shared/{FilterByTag.d.ts → FilterByTagDialog.d.ts} +0 -0
@@ -27,65 +27,39 @@ const react_1 = __importStar(require("react"));
27
27
  const ui_1 = require("@jbrowse/core/ui");
28
28
  const util_1 = require("@jbrowse/core/util");
29
29
  const mobx_react_1 = require("mobx-react");
30
- // used so that user can click-away-from-feature below the laid out features
31
- // (issue #1248)
32
- const canvasPadding = 100;
33
30
  const PileupRendering = (0, mobx_react_1.observer)(function (props) {
34
31
  var _a;
35
32
  const { onMouseMove, blockKey, displayModel, width, height, regions, bpPerPx, sortedBy, colorBy, filterBy, } = props;
36
- const { selectedFeatureId, featureIdUnderMouse, contextMenuFeature } = displayModel;
37
- const [region] = regions;
38
- const highlightOverlayCanvas = (0, react_1.useRef)(null);
33
+ const { selectedFeatureId, featureIdUnderMouse, contextMenuFeature } = displayModel || {};
34
+ const [firstRender, setFirstRender] = (0, react_1.useState)(false);
35
+ (0, react_1.useEffect)(() => {
36
+ setFirstRender(true);
37
+ }, []);
38
+ const region = regions[0];
39
+ const ref = (0, react_1.useRef)(null);
39
40
  const [mouseIsDown, setMouseIsDown] = (0, react_1.useState)(false);
40
41
  const [movedDuringLastMouseDown, setMovedDuringLastMouseDown] = (0, react_1.useState)(false);
41
- (0, react_1.useEffect)(() => {
42
- var _a, _b;
43
- const canvas = highlightOverlayCanvas.current;
44
- if (!canvas) {
45
- return;
46
- }
47
- const ctx = canvas.getContext('2d');
48
- if (!ctx) {
49
- return;
50
- }
51
- ctx.clearRect(0, 0, canvas.width, canvas.height);
52
- const selectedRect = selectedFeatureId
53
- ? (_a = displayModel.getFeatureByID) === null || _a === void 0 ? void 0 : _a.call(displayModel, blockKey, selectedFeatureId)
54
- : undefined;
55
- if (selectedRect) {
56
- const [leftBp, topPx, rightBp, bottomPx] = selectedRect;
57
- const [leftPx, rightPx] = (0, util_1.bpSpanPx)(leftBp, rightBp, region, bpPerPx);
58
- const rectTop = Math.round(topPx);
59
- const rectHeight = Math.round(bottomPx - topPx);
60
- ctx.shadowColor = '#222266';
61
- ctx.shadowBlur = 10;
62
- ctx.lineJoin = 'bevel';
63
- ctx.lineWidth = 2;
64
- ctx.strokeStyle = '#00b8ff';
65
- ctx.strokeRect(leftPx - 2, rectTop - 2, rightPx - leftPx + 4, rectHeight + 4);
66
- ctx.clearRect(leftPx, rectTop, rightPx - leftPx, rectHeight);
67
- }
68
- const highlightedFeature = featureIdUnderMouse || (contextMenuFeature === null || contextMenuFeature === void 0 ? void 0 : contextMenuFeature.id());
69
- const highlightedRect = highlightedFeature
70
- ? (_b = displayModel.getFeatureByID) === null || _b === void 0 ? void 0 : _b.call(displayModel, blockKey, highlightedFeature)
71
- : undefined;
72
- if (highlightedRect) {
73
- const [leftBp, topPx, rightBp, bottomPx] = highlightedRect;
74
- const [leftPx, rightPx] = (0, util_1.bpSpanPx)(leftBp, rightBp, region, bpPerPx);
75
- const rectTop = Math.round(topPx);
76
- const rectHeight = Math.round(bottomPx - topPx);
77
- ctx.fillStyle = '#0003';
78
- ctx.fillRect(leftPx, rectTop, rightPx - leftPx, rectHeight);
79
- }
80
- }, [
81
- bpPerPx,
82
- region,
83
- blockKey,
84
- selectedFeatureId,
85
- displayModel,
86
- featureIdUnderMouse,
87
- contextMenuFeature,
88
- ]);
42
+ const selectedRect = selectedFeatureId
43
+ ? displayModel === null || displayModel === void 0 ? void 0 : displayModel.getFeatureByID(blockKey, selectedFeatureId)
44
+ : undefined;
45
+ const highlightedFeature = featureIdUnderMouse || (contextMenuFeature === null || contextMenuFeature === void 0 ? void 0 : contextMenuFeature.id());
46
+ const highlightedRect = highlightedFeature
47
+ ? displayModel === null || displayModel === void 0 ? void 0 : displayModel.getFeatureByID(blockKey, highlightedFeature)
48
+ : undefined;
49
+ function makeRect(r, offset = 2) {
50
+ const [leftBp, topPx, rightBp, bottomPx] = r;
51
+ const [leftPx, rightPx] = (0, util_1.bpSpanPx)(leftBp, rightBp, region, bpPerPx);
52
+ const rectTop = Math.round(topPx);
53
+ const rectHeight = Math.round(bottomPx - topPx);
54
+ return {
55
+ left: leftPx - offset,
56
+ top: rectTop - offset,
57
+ width: rightPx - leftPx,
58
+ height: rectHeight,
59
+ };
60
+ }
61
+ const selected = selectedRect ? makeRect(selectedRect) : undefined;
62
+ const highlight = highlightedRect ? makeRect(highlightedRect, 0) : undefined;
89
63
  function onMouseDown(event) {
90
64
  setMouseIsDown(true);
91
65
  setMovedDuringLastMouseDown(false);
@@ -118,18 +92,18 @@ const PileupRendering = (0, mobx_react_1.observer)(function (props) {
118
92
  callMouseHandler('ContextMenu', event);
119
93
  }
120
94
  function mouseMove(event) {
121
- if (!highlightOverlayCanvas.current) {
95
+ if (!ref.current) {
122
96
  return;
123
97
  }
124
98
  if (mouseIsDown) {
125
99
  setMovedDuringLastMouseDown(true);
126
100
  }
127
- const rect = highlightOverlayCanvas.current.getBoundingClientRect();
101
+ const rect = ref.current.getBoundingClientRect();
128
102
  const offsetX = event.clientX - rect.left;
129
103
  const offsetY = event.clientY - rect.top;
130
104
  const px = region.reversed ? width - offsetX : offsetX;
131
105
  const clientBp = region.start + bpPerPx * px;
132
- onMouseMove === null || onMouseMove === void 0 ? void 0 : onMouseMove(event, displayModel.getFeatureOverlapping(blockKey, clientBp, offsetY));
106
+ onMouseMove === null || onMouseMove === void 0 ? void 0 : onMouseMove(event, displayModel === null || displayModel === void 0 ? void 0 : displayModel.getFeatureOverlapping(blockKey, clientBp, offsetY));
133
107
  }
134
108
  function callMouseHandler(handlerName, event) {
135
109
  // @ts-expect-error
@@ -145,15 +119,46 @@ const PileupRendering = (0, mobx_react_1.observer)(function (props) {
145
119
  }
146
120
  const canvasWidth = Math.ceil(width);
147
121
  // need to call this in render so we get the right observer behavior
148
- return (react_1.default.createElement("div", { "data-testid": `pileup-${[
122
+ return (react_1.default.createElement("div", { ref: ref, "data-testid": [
123
+ 'pileup-overlay',
149
124
  sortedBy === null || sortedBy === void 0 ? void 0 : sortedBy.type,
150
125
  colorBy === null || colorBy === void 0 ? void 0 : colorBy.type,
151
126
  colorBy === null || colorBy === void 0 ? void 0 : colorBy.tag,
152
127
  (_a = filterBy === null || filterBy === void 0 ? void 0 : filterBy.tagFilter) === null || _a === void 0 ? void 0 : _a.tag,
153
128
  ]
154
129
  .filter(f => !!f)
155
- .join('-')}`, style: { position: 'relative', width: canvasWidth, height } },
130
+ .join('-'), style: { position: 'relative', width: canvasWidth, height }, onMouseDown: event => {
131
+ onMouseDown(event);
132
+ }, onMouseEnter: event => {
133
+ onMouseEnter(event);
134
+ }, onMouseOut: event => {
135
+ onMouseOut(event);
136
+ }, onMouseOver: event => {
137
+ onMouseOver(event);
138
+ }, onMouseUp: event => {
139
+ onMouseUp(event);
140
+ }, onMouseLeave: event => {
141
+ onMouseLeave(event);
142
+ }, onMouseMove: event => {
143
+ mouseMove(event);
144
+ }, onClick: event => {
145
+ onClick(event);
146
+ }, onContextMenu: event => {
147
+ onContextMenu(event);
148
+ }, onFocus: () => { }, onBlur: () => { } },
156
149
  react_1.default.createElement(ui_1.PrerenderedCanvas, { ...props, style: { position: 'absolute', left: 0, top: 0 } }),
157
- react_1.default.createElement("canvas", { "data-testid": "pileup_overlay_canvas", width: canvasWidth, height: height + canvasPadding, style: { position: 'absolute', left: 0, top: 0 }, className: "highlightOverlayCanvas", ref: highlightOverlayCanvas, onMouseDown: event => onMouseDown(event), onMouseEnter: event => onMouseEnter(event), onMouseOut: event => onMouseOut(event), onMouseOver: event => onMouseOver(event), onMouseUp: event => onMouseUp(event), onMouseLeave: event => onMouseLeave(event), onMouseMove: event => mouseMove(event), onClick: event => onClick(event), onContextMenu: event => onContextMenu(event), onFocus: () => { }, onBlur: () => { } })));
150
+ firstRender && highlight ? (react_1.default.createElement("div", { style: {
151
+ position: 'absolute',
152
+ backgroundColor: '#0003',
153
+ pointerEvents: 'none',
154
+ ...highlight,
155
+ } })) : null,
156
+ firstRender && selected ? (react_1.default.createElement("div", { style: {
157
+ position: 'absolute',
158
+ border: '2px solid #00b8ff',
159
+ boxSizing: 'content-box',
160
+ pointerEvents: 'none',
161
+ ...selected,
162
+ } })) : null));
158
163
  });
159
164
  exports.default = PileupRendering;
@@ -23,24 +23,32 @@ function getAlignmentShapeColor({ colorType, tag, feature, config, defaultColor,
23
23
  const tags = feature.get('tags');
24
24
  const val = tags ? tags[tag] : feature.get(tag);
25
25
  if (tag === 'XS' || tag === 'TS') {
26
- return color_1.fillColor[{
27
- '-': 'color_rev_strand',
28
- '+': 'color_fwd_strand',
29
- }[val] || 'color_nostrand'];
26
+ if (val === '-') {
27
+ return color_1.fillColor.color_rev_strand;
28
+ }
29
+ else if (val === '+') {
30
+ return color_1.fillColor.color_fwd_strand;
31
+ }
32
+ else {
33
+ return color_1.fillColor.color_nostrand;
34
+ }
30
35
  }
31
- else if (tag === 'ts') {
32
- return color_1.fillColor[{
33
- '-': feature.get('strand') === -1
34
- ? 'color_fwd_strand'
35
- : 'color_rev_strand',
36
- '+': feature.get('strand') === -1
37
- ? 'color_rev_strand'
38
- : 'color_fwd_strand',
39
- }[val] || 'color_nostrand'];
40
- }
41
- else {
42
- return colorTagMap[val] || color_1.fillColor.color_nostrand;
36
+ if (tag === 'ts') {
37
+ if (val === '-') {
38
+ return feature.get('strand') === -1
39
+ ? color_1.fillColor.color_fwd_strand
40
+ : color_1.fillColor.color_rev_strand;
41
+ }
42
+ else if (val === '+') {
43
+ return feature.get('strand') === -1
44
+ ? color_1.fillColor.color_rev_strand
45
+ : color_1.fillColor.color_fwd_strand;
46
+ }
47
+ else {
48
+ return color_1.fillColor.color_nostrand;
49
+ }
43
50
  }
51
+ return colorTagMap[val] || color_1.fillColor.color_nostrand;
44
52
  }
45
53
  case 'insertSizeAndPairOrientation':
46
54
  break;
@@ -12,7 +12,12 @@ function layoutFeature({ feature, layout, bpPerPx, region, showSoftClip, heightP
12
12
  if (seq) {
13
13
  for (const { type, start, cliplen = 0 } of mismatches) {
14
14
  if (type === 'softclip') {
15
- start === 0 ? (expansionBefore = cliplen) : (expansionAfter = cliplen);
15
+ if (start === 0) {
16
+ expansionBefore = cliplen;
17
+ }
18
+ else {
19
+ expansionAfter = cliplen;
20
+ }
16
21
  }
17
22
  }
18
23
  }
@@ -9,13 +9,7 @@ const sortUtil_1 = require("./sortUtil");
9
9
  // layout determines the height of the canvas that we use to render
10
10
  function layoutFeats(props) {
11
11
  const { layout, features, sortedBy, config, bpPerPx, showSoftClip, regions } = props;
12
- const [region] = regions;
13
- if (!layout) {
14
- throw new Error(`layout required`);
15
- }
16
- if (!layout.addRect) {
17
- throw new Error('invalid layout object');
18
- }
12
+ const region = regions[0];
19
13
  const featureMap = (sortedBy === null || sortedBy === void 0 ? void 0 : sortedBy.type) && region.start === sortedBy.pos
20
14
  ? (0, sortUtil_1.sortFeature)(features, sortedBy)
21
15
  : features;
@@ -11,5 +11,5 @@ export declare function makeImageData({ ctx, layoutRecords, canvasWidth, renderA
11
11
  canvasWidth: number;
12
12
  layoutRecords: LayoutFeature[];
13
13
  renderArgs: RenderArgsWithColor;
14
- }): void;
14
+ }): undefined;
15
15
  export {};
@@ -59,4 +59,5 @@ function makeImageData({ ctx, layoutRecords, canvasWidth, renderArgs, }) {
59
59
  });
60
60
  }
61
61
  }
62
+ return undefined;
62
63
  }
@@ -5,7 +5,7 @@ const util_1 = require("@jbrowse/core/util");
5
5
  function renderAlignmentShape({ ctx, feat, renderArgs, }) {
6
6
  const { regions, bpPerPx } = renderArgs;
7
7
  const { heightPx, topPx, feature } = feat;
8
- const [region] = regions;
8
+ const region = regions[0];
9
9
  const s = feature.get('start');
10
10
  const e = feature.get('end');
11
11
  const [leftPx, rightPx] = (0, util_1.bpSpanPx)(s, e, region, bpPerPx);
@@ -7,7 +7,7 @@ const colord_1 = require("@jbrowse/core/util/colord");
7
7
  function renderMismatches({ ctx, feat, renderArgs, minSubfeatureWidth, largeInsertionIndicatorScale, mismatchAlpha, charWidth, charHeight, colorForBase, contrastForBase, canvasWidth, drawSNPsMuted, drawIndels = true, }) {
8
8
  const { bpPerPx, regions } = renderArgs;
9
9
  const { heightPx, topPx, feature } = feat;
10
- const [region] = regions;
10
+ const region = regions[0];
11
11
  const start = feature.get('start');
12
12
  const pxPerBp = Math.min(1 / bpPerPx, 2);
13
13
  const mismatches = feature.get('mismatches');
@@ -9,7 +9,7 @@ const util_2 = require("./util");
9
9
  function renderSoftClipping({ ctx, feat, renderArgs, config, theme, colorForBase, canvasWidth, }) {
10
10
  const { feature, topPx, heightPx } = feat;
11
11
  const { regions, bpPerPx } = renderArgs;
12
- const [region] = regions;
12
+ const region = regions[0];
13
13
  const minFeatWidth = (0, configuration_1.readConfObject)(config, 'minSubfeatureWidth');
14
14
  const mismatches = feature.get('mismatches');
15
15
  const seq = feature.get('seq');
@@ -11,12 +11,10 @@ function fillRect(ctx, l, t, w, h, cw, color) {
11
11
  if (l + w < 0 || l > cw) {
12
12
  return;
13
13
  }
14
- else {
15
- if (color) {
16
- ctx.fillStyle = color;
17
- }
18
- ctx.fillRect(l, t, w, h);
14
+ if (color) {
15
+ ctx.fillStyle = color;
19
16
  }
17
+ ctx.fillRect(l, t, w, h);
20
18
  }
21
19
  function getColorBaseMap(theme) {
22
20
  const { bases } = theme.palette;
@@ -10,7 +10,6 @@ function mismatchLen(mismatch) {
10
10
  function isInterbase(type) {
11
11
  return type === 'softclip' || type === 'hardclip' || type === 'insertion';
12
12
  }
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
13
  function inc(bin, strand, type, field) {
15
14
  let thisBin = bin[type][field];
16
15
  if (thisBin === undefined) {
@@ -95,12 +94,7 @@ async function generateCoverageBins(features, region, opts, fetchSequence) {
95
94
  };
96
95
  }
97
96
  const bin = bins[epos];
98
- if (bin) {
99
- inc(bin, fstrand, 'cov', mod);
100
- }
101
- else {
102
- console.warn('Undefined position in modifications snpcoverage encountered');
103
- }
97
+ inc(bin, fstrand, 'cov', mod);
104
98
  }
105
99
  }
106
100
  }
@@ -145,14 +139,14 @@ async function generateCoverageBins(features, region, opts, fetchSequence) {
145
139
  }
146
140
  else {
147
141
  if (bin0) {
148
- if (!(dels === null || dels === void 0 ? void 0 : dels.some(d => (0, util_2.doesIntersect2)(j, j + 1, d.start + fstart, d.start + fstart + d.length)))) {
142
+ if (!dels.some(d => (0, util_2.doesIntersect2)(j, j + 1, d.start + fstart, d.start + fstart + d.length))) {
149
143
  inc(bin0, fstrand, 'cov', 'unmeth');
150
144
  bin0.ref--;
151
- bin0[fstrand];
145
+ bin0[fstrand]--;
152
146
  }
153
147
  }
154
148
  if (bin1) {
155
- if (!(dels === null || dels === void 0 ? void 0 : dels.some(d => (0, util_2.doesIntersect2)(j + 1, j + 2, d.start + fstart, d.start + fstart + d.length)))) {
149
+ if (!dels.some(d => (0, util_2.doesIntersect2)(j + 1, j + 2, d.start + fstart, d.start + fstart + d.length))) {
156
150
  inc(bin1, fstrand, 'cov', 'unmeth');
157
151
  bin1.ref--;
158
152
  bin1[fstrand]--;
@@ -13,8 +13,8 @@ export interface RenderArgsDeserializedWithFeatures extends RenderArgsDeserializ
13
13
  values: number[];
14
14
  };
15
15
  displayCrossHatches: boolean;
16
- modificationTagMap?: Record<string, string | undefined>;
16
+ modificationTagMap?: Record<string, string>;
17
17
  }
18
18
  export default class SNPCoverageRenderer extends WiggleBaseRenderer {
19
- draw(ctx: CanvasRenderingContext2D, props: RenderArgsDeserializedWithFeatures): Promise<void>;
19
+ draw(ctx: CanvasRenderingContext2D, props: RenderArgsDeserializedWithFeatures): Promise<undefined>;
20
20
  }
@@ -11,17 +11,13 @@ class SNPCoverageRenderer extends plugin_wiggle_1.WiggleBaseRenderer {
11
11
  async draw(ctx, props) {
12
12
  const { features, regions, bpPerPx, displayCrossHatches, modificationTagMap = {}, scaleOpts, height: unadjustedHeight, theme: configTheme, config: cfg, ticks, } = props;
13
13
  const theme = (0, ui_1.createJBrowseTheme)(configTheme);
14
- const [region] = regions;
14
+ const region = regions[0];
15
15
  const width = (region.end - region.start) / bpPerPx;
16
16
  // the adjusted height takes into account YSCALEBAR_LABEL_OFFSET from the
17
17
  // wiggle display, and makes the height of the actual drawn area add
18
18
  // "padding" to the top and bottom of the display
19
19
  const offset = plugin_wiggle_1.YSCALEBAR_LABEL_OFFSET;
20
20
  const height = unadjustedHeight - offset * 2;
21
- const { domain } = scaleOpts;
22
- if (!domain) {
23
- return;
24
- }
25
21
  const opts = { ...scaleOpts, range: [0, height] };
26
22
  const viewScale = (0, plugin_wiggle_1.getScale)(opts);
27
23
  // clipping and insertion indicators, uses a smaller height/2 scale
@@ -178,6 +174,7 @@ class SNPCoverageRenderer extends plugin_wiggle_1.WiggleBaseRenderer {
178
174
  ctx.stroke();
179
175
  });
180
176
  }
177
+ return undefined;
181
178
  }
182
179
  }
183
180
  exports.default = SNPCoverageRenderer;
package/dist/index.js CHANGED
@@ -66,7 +66,9 @@ class AlignmentsPlugin extends Plugin_1.default {
66
66
  LinearAlignmentsDisplay_1.default,
67
67
  AlignmentsFeatureDetail_1.default,
68
68
  GuessAlignmentsTypes_1.default,
69
- ].map(f => f(pluginManager));
69
+ ].map(f => {
70
+ f(pluginManager);
71
+ });
70
72
  }
71
73
  }
72
74
  exports.default = AlignmentsPlugin;
@@ -26,7 +26,9 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
26
26
  const BaseDisplayComponent = (0, mobx_react_1.observer)(function ({ model, children, }) {
27
27
  const { error, regionTooLarge } = model;
28
28
  return error ? (react_1.default.createElement(plugin_linear_genome_view_1.BlockMsg, { message: `${error}`, severity: "error", action: react_1.default.createElement(material_1.Tooltip, { title: "Reload" },
29
- react_1.default.createElement(material_1.Button, { "data-testid": "reload_button", onClick: () => model.reload() }, "Reload")) })) : regionTooLarge ? (model.regionCannotBeRendered()) : (react_1.default.createElement(DataDisplay, { model: model }, children));
29
+ react_1.default.createElement(material_1.Button, { "data-testid": "reload_button", onClick: () => {
30
+ model.reload();
31
+ } }, "Reload")) })) : regionTooLarge ? (model.regionCannotBeRendered()) : (react_1.default.createElement(DataDisplay, { model: model }, children));
30
32
  });
31
33
  const DataDisplay = (0, mobx_react_1.observer)(function ({ model, children, }) {
32
34
  const { drawn, loading } = model;
@@ -54,7 +54,9 @@ const flagNames = [
54
54
  function Bitmask(props) {
55
55
  const { flag = 0, setFlag } = props;
56
56
  return (react_1.default.createElement(react_1.default.Fragment, null,
57
- react_1.default.createElement(material_1.TextField, { type: "number", value: flag, onChange: event => setFlag(+event.target.value) }),
57
+ react_1.default.createElement(material_1.TextField, { type: "number", value: flag, onChange: event => {
58
+ setFlag(+event.target.value);
59
+ } }),
58
60
  flagNames.map((name, index) => {
59
61
  const val = flag & (1 << index);
60
62
  const key = `${name}_${val}`;
@@ -80,7 +82,7 @@ const FilterByTagDialog = (0, mobx_react_1.observer)(function (props) {
80
82
  const [tag, setTag] = (0, react_1.useState)(((_a = filterBy.tagFilter) === null || _a === void 0 ? void 0 : _a.tag) || '');
81
83
  const [tagValue, setTagValue] = (0, react_1.useState)(((_b = filterBy.tagFilter) === null || _b === void 0 ? void 0 : _b.value) || '');
82
84
  const [readName, setReadName] = (0, react_1.useState)(filterBy.readName || '');
83
- const validTag = tag.match(/^[A-Za-z][A-Za-z0-9]$/);
85
+ const validTag = /^[A-Za-z][A-Za-z0-9]$/.exec(tag);
84
86
  const site = 'https://broadinstitute.github.io/picard/explain-flags.html';
85
87
  return (react_1.default.createElement(ui_1.Dialog, { open: true, onClose: handleClose, title: "Filter options" },
86
88
  react_1.default.createElement(material_1.DialogContent, null,
@@ -99,11 +101,17 @@ const FilterByTagDialog = (0, mobx_react_1.observer)(function (props) {
99
101
  react_1.default.createElement(Bitmask, { flag: flagExclude, setFlag: setFlagExclude })))),
100
102
  react_1.default.createElement(material_1.Paper, { className: classes.paper, variant: "outlined" },
101
103
  react_1.default.createElement(material_1.Typography, null, "Filter by tag name and value. Use * in the value field to get all reads containing any value for that tag. Example: filter tag name SA with value * to get all split/supplementary reads. Other examples include HP for haplotype, or RG for read group"),
102
- react_1.default.createElement(material_1.TextField, { className: classes.field, value: tag, onChange: event => setTag(event.target.value), placeholder: "Enter tag name", inputProps: { maxLength: 2 }, error: tag.length === 2 && !validTag, helperText: tag.length === 2 && !validTag ? 'Not a valid tag' : '' }),
103
- react_1.default.createElement(material_1.TextField, { className: classes.field, value: tagValue, onChange: event => setTagValue(event.target.value), placeholder: "Enter tag value" })),
104
+ react_1.default.createElement(material_1.TextField, { className: classes.field, value: tag, onChange: event => {
105
+ setTag(event.target.value);
106
+ }, placeholder: "Enter tag name", inputProps: { maxLength: 2 }, error: tag.length === 2 && !validTag, helperText: tag.length === 2 && !validTag ? 'Not a valid tag' : '' }),
107
+ react_1.default.createElement(material_1.TextField, { className: classes.field, value: tagValue, onChange: event => {
108
+ setTagValue(event.target.value);
109
+ }, placeholder: "Enter tag value" })),
104
110
  react_1.default.createElement(material_1.Paper, { className: classes.paper, variant: "outlined" },
105
111
  react_1.default.createElement(material_1.Typography, null, "Filter by read name"),
106
- react_1.default.createElement(material_1.TextField, { className: classes.field, value: readName, onChange: event => setReadName(event.target.value), placeholder: "Enter read name" })),
112
+ react_1.default.createElement(material_1.TextField, { className: classes.field, value: readName, onChange: event => {
113
+ setReadName(event.target.value);
114
+ }, placeholder: "Enter read name" })),
107
115
  react_1.default.createElement(material_1.DialogActions, null,
108
116
  react_1.default.createElement(material_1.Button, { variant: "contained", color: "primary", autoFocus: true, type: "submit", onClick: () => {
109
117
  model.setFilterBy({
@@ -119,6 +127,8 @@ const FilterByTagDialog = (0, mobx_react_1.observer)(function (props) {
119
127
  });
120
128
  handleClose();
121
129
  } }, "Submit"),
122
- react_1.default.createElement(material_1.Button, { variant: "contained", color: "secondary", onClick: () => handleClose() }, "Cancel")))));
130
+ react_1.default.createElement(material_1.Button, { variant: "contained", color: "secondary", onClick: () => {
131
+ handleClose();
132
+ } }, "Cancel")))));
123
133
  });
124
134
  exports.default = FilterByTagDialog;
@@ -56,10 +56,10 @@ function getPairedInsertSizeColor(f1, f2, stats) {
56
56
  if (sameRef && tlen > ((stats === null || stats === void 0 ? void 0 : stats.upper) || 0)) {
57
57
  return [exports.fillColor.color_longinsert, exports.strokeColor.color_longinsert];
58
58
  }
59
- else if (sameRef && tlen < ((stats === null || stats === void 0 ? void 0 : stats.lower) || 0)) {
59
+ if (sameRef && tlen < ((stats === null || stats === void 0 ? void 0 : stats.lower) || 0)) {
60
60
  return [exports.fillColor.color_shortinsert, exports.strokeColor.color_shortinsert];
61
61
  }
62
- else if (!sameRef) {
62
+ if (!sameRef) {
63
63
  return [exports.fillColor.color_interchrom, exports.strokeColor.color_interchrom];
64
64
  }
65
65
  return undefined;
@@ -1,28 +1,32 @@
1
1
  import { IAnyStateTreeNode } from 'mobx-state-tree';
2
2
  import { BlockSet } from '@jbrowse/core/util/blockTypes';
3
3
  import { AnyConfigurationModel } from '@jbrowse/core/configuration';
4
- export declare function getUniqueTagValues(self: IAnyStateTreeNode & {
5
- adapterConfig: AnyConfigurationModel;
6
- }, colorScheme: {
7
- type: string;
8
- tag?: string;
9
- }, blocks: BlockSet, opts?: {
10
- headers?: Record<string, string>;
11
- signal?: AbortSignal;
12
- filters?: string[];
4
+ export declare function getUniqueTagValues({ self, tag, blocks, opts, }: {
5
+ self: IAnyStateTreeNode & {
6
+ adapterConfig: AnyConfigurationModel;
7
+ };
8
+ tag: string;
9
+ blocks: BlockSet;
10
+ opts?: {
11
+ headers?: Record<string, string>;
12
+ signal?: AbortSignal;
13
+ filters: string[];
14
+ };
13
15
  }): Promise<string[]>;
14
16
  type Track = IAnyStateTreeNode & {
15
17
  configuration: AnyConfigurationModel;
16
18
  };
17
- export declare function getUniqueModificationValues(self: IAnyStateTreeNode & {
18
- parentTrack: Track;
19
- }, adapterConfig: AnyConfigurationModel, colorScheme: {
20
- type: string;
21
- tag?: string;
22
- }, blocks: BlockSet, opts?: {
23
- headers?: Record<string, string>;
24
- signal?: AbortSignal;
25
- filters?: string[];
19
+ export declare function getUniqueModificationValues({ self, adapterConfig, blocks, opts, }: {
20
+ self: IAnyStateTreeNode & {
21
+ parentTrack: Track;
22
+ };
23
+ adapterConfig: AnyConfigurationModel;
24
+ blocks: BlockSet;
25
+ opts?: {
26
+ headers?: Record<string, string>;
27
+ signal?: AbortSignal;
28
+ filters: string[];
29
+ };
26
30
  }): Promise<string[]>;
27
31
  export declare const FilterModel: import("mobx-state-tree").IModelType<{
28
32
  flagInclude: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<number>, [undefined]>;
@@ -30,7 +34,7 @@ export declare const FilterModel: import("mobx-state-tree").IModelType<{
30
34
  readName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
31
35
  tagFilter: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IModelType<{
32
36
  tag: import("mobx-state-tree").ISimpleType<string>;
33
- value: import("mobx-state-tree").ISimpleType<string>;
37
+ value: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
34
38
  }, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
35
39
  }, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
36
40
  export interface IFilter {
@@ -39,7 +43,7 @@ export interface IFilter {
39
43
  readName?: string;
40
44
  tagFilter?: {
41
45
  tag: string;
42
- value: string;
46
+ value?: string;
43
47
  };
44
48
  }
45
49
  export {};
@@ -6,25 +6,24 @@ exports.getUniqueModificationValues = getUniqueModificationValues;
6
6
  const mobx_state_tree_1 = require("mobx-state-tree");
7
7
  const util_1 = require("@jbrowse/core/util");
8
8
  const tracks_1 = require("@jbrowse/core/util/tracks");
9
- async function getUniqueTagValues(self, colorScheme, blocks, opts) {
9
+ async function getUniqueTagValues({ self, tag, blocks, opts, }) {
10
10
  const { rpcManager } = (0, util_1.getSession)(self);
11
11
  const { adapterConfig } = self;
12
12
  const sessionId = (0, tracks_1.getRpcSessionId)(self);
13
13
  const values = await rpcManager.call((0, tracks_1.getRpcSessionId)(self), 'PileupGetGlobalValueForTag', {
14
14
  adapterConfig,
15
- tag: colorScheme.tag,
15
+ tag,
16
16
  sessionId,
17
17
  regions: blocks.contentBlocks,
18
18
  ...opts,
19
19
  });
20
20
  return values;
21
21
  }
22
- async function getUniqueModificationValues(self, adapterConfig, colorScheme, blocks, opts) {
22
+ async function getUniqueModificationValues({ self, adapterConfig, blocks, opts, }) {
23
23
  const { rpcManager } = (0, util_1.getSession)(self);
24
24
  const sessionId = (0, tracks_1.getRpcSessionId)(self);
25
25
  const values = await rpcManager.call(sessionId, 'PileupGetVisibleModifications', {
26
26
  adapterConfig,
27
- tag: colorScheme.tag,
28
27
  sessionId,
29
28
  regions: blocks.contentBlocks,
30
29
  ...opts,
@@ -37,6 +36,6 @@ exports.FilterModel = mobx_state_tree_1.types.model({
37
36
  readName: mobx_state_tree_1.types.maybe(mobx_state_tree_1.types.string),
38
37
  tagFilter: mobx_state_tree_1.types.maybe(mobx_state_tree_1.types.model({
39
38
  tag: mobx_state_tree_1.types.string,
40
- value: mobx_state_tree_1.types.string,
39
+ value: mobx_state_tree_1.types.maybe(mobx_state_tree_1.types.string),
41
40
  })),
42
41
  });
@@ -60,8 +60,6 @@ async function renderSvg(self, opts, cb) {
60
60
  react_1.default.createElement("defs", null,
61
61
  react_1.default.createElement("clipPath", { id: clipid },
62
62
  react_1.default.createElement("rect", { x: 0, y: 0, width: width, height: height }))),
63
- react_1.default.createElement("g", {
64
- /* eslint-disable-next-line react/no-danger */
65
- dangerouslySetInnerHTML: { __html: ctx.getSvg().innerHTML }, clipPath: `url(#${clipid})` })));
63
+ react_1.default.createElement("g", { dangerouslySetInnerHTML: { __html: ctx.getSvg().innerHTML }, clipPath: `url(#${clipid})` })));
66
64
  }
67
65
  }
package/dist/util.d.ts CHANGED
@@ -18,7 +18,7 @@ export declare const pairMap: {
18
18
  export declare function getColorWGBS(strand: number, base: string): "#f00" | "#00f" | "#888";
19
19
  export declare function fetchSequence(region: AugmentedRegion, adapter: BaseFeatureDataAdapter): Promise<any>;
20
20
  export declare function shouldFetchReferenceSequence(type?: string): type is "methylation";
21
- export declare const modificationColors: Record<string, string | undefined>;
21
+ export declare const modificationColors: Record<string, string>;
22
22
  type DisplayModel = IAnyStateTreeNode & {
23
23
  setError: (arg: unknown) => void;
24
24
  };
@@ -14,13 +14,15 @@ import Formatter from './Formatter';
14
14
  const omit = ['clipPos', 'flags'];
15
15
  const AlignmentsFeatureDetails = observer(function (props) {
16
16
  const { model } = props;
17
- const feat = clone(model.featureData);
17
+ const { featureData } = model;
18
+ const feat = clone(featureData);
18
19
  const SA = getTag('SA', feat);
20
+ const { flags } = feat;
19
21
  return (React.createElement(Paper, { "data-testid": "alignment-side-drawer" },
20
22
  React.createElement(FeatureDetails, { ...props, omit: omit,
21
23
  // @ts-expect-error
22
24
  descriptions: { ...tags, tags: tags }, feature: feat, formatter: (value, key) => key === 'next_segment_position' ? (React.createElement(PairLink, { model: model, locString: value })) : (React.createElement(Formatter, { value: value })) }),
23
- SA ? React.createElement(SuppAlignments, { model: model, tag: SA, feature: feat }) : null,
24
- feat.flags !== undefined ? React.createElement(Flags, { feature: feat, ...props }) : null));
25
+ SA !== undefined ? (React.createElement(SuppAlignments, { model: model, tag: SA, feature: feat })) : null,
26
+ flags !== undefined ? React.createElement(Flags, { feature: feat, ...props }) : null));
25
27
  });
26
28
  export default AlignmentsFeatureDetails;