@czi-sds/data-viz 2.4.2 → 2.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -4164,6 +4164,35 @@ function useMolstarPlugin({ backgroundColor, chainColors, containerRef, download
|
|
|
4164
4164
|
};
|
|
4165
4165
|
}
|
|
4166
4166
|
//#endregion
|
|
4167
|
+
//#region src/core/ProteinStructureViewer/hooks/useSelection.ts
|
|
4168
|
+
/**
|
|
4169
|
+
* Reconciles the selection the consumer passes with the one the viewer keeps.
|
|
4170
|
+
*
|
|
4171
|
+
* Selection is controlled when `selection` is passed and owned here when it is
|
|
4172
|
+
* not, the same split `useChains` makes for visibility. The camera only ever
|
|
4173
|
+
* follows the selection, so without an owner a click on a viewer nobody holds
|
|
4174
|
+
* state for would mark the residue and never zoom in on it.
|
|
4175
|
+
* `onSelectionChange` fires either way: a consumer that only wants to follow
|
|
4176
|
+
* along should not have to take ownership to hear about it.
|
|
4177
|
+
*/
|
|
4178
|
+
function useSelection({ onSelectionChange, selection, structure }) {
|
|
4179
|
+
const isControlled = selection !== void 0;
|
|
4180
|
+
const [ownSelection, setOwnSelection] = (0, react.useState)(null);
|
|
4181
|
+
const onSelectionChangeRef = (0, react.useRef)(onSelectionChange);
|
|
4182
|
+
onSelectionChangeRef.current = onSelectionChange;
|
|
4183
|
+
(0, react.useEffect)(() => {
|
|
4184
|
+
setOwnSelection(null);
|
|
4185
|
+
}, [structure]);
|
|
4186
|
+
return {
|
|
4187
|
+
changeSelection: (0, react.useCallback)((next) => {
|
|
4188
|
+
var _onSelectionChangeRef;
|
|
4189
|
+
if (!isControlled) setOwnSelection(next);
|
|
4190
|
+
(_onSelectionChangeRef = onSelectionChangeRef.current) === null || _onSelectionChangeRef === void 0 || _onSelectionChangeRef.call(onSelectionChangeRef, next);
|
|
4191
|
+
}, [isControlled]),
|
|
4192
|
+
selection: isControlled ? selection : ownSelection
|
|
4193
|
+
};
|
|
4194
|
+
}
|
|
4195
|
+
//#endregion
|
|
4167
4196
|
//#region src/core/ProteinStructureViewer/utils/focusRepresentation.ts
|
|
4168
4197
|
/**
|
|
4169
4198
|
* What Mol* draws around a focused selection, as ball-and-stick over the
|
|
@@ -4282,10 +4311,11 @@ function focusWithShell(plugin, loci, includeNeighbours, currentShell, pluginRef
|
|
|
4282
4311
|
* chains around them instead, in `useChainHighlight`.
|
|
4283
4312
|
*
|
|
4284
4313
|
* The click subscription only reports the selection it was given, so a click
|
|
4285
|
-
* moves the camera only once the
|
|
4286
|
-
*
|
|
4287
|
-
* marks immediately, through Mol*'s own focus
|
|
4288
|
-
* responds to a click
|
|
4314
|
+
* moves the camera only once whoever owns the selection accepts it: the
|
|
4315
|
+
* consumer echoing it back when `selection` is controlled, the viewer itself
|
|
4316
|
+
* when it is not. Clicking still marks immediately, through Mol*'s own focus
|
|
4317
|
+
* behavior, so the structure responds to a click even when a consumer
|
|
4318
|
+
* controlling the selection declines it.
|
|
4289
4319
|
*/
|
|
4290
4320
|
function useSelectionFocus({ hiddenChains, isReady, pluginRef, selection, setClipRatio }) {
|
|
4291
4321
|
var _selection$chains, _selection$residues;
|
|
@@ -4575,14 +4605,16 @@ function resolveScaleProps(overlay, hasPlddt) {
|
|
|
4575
4605
|
* Interactive 3D protein structure viewer built on Mol*, with a sequence panel,
|
|
4576
4606
|
* pLDDT confidence coloring, per-residue value overlays, and a stats legend.
|
|
4577
4607
|
*
|
|
4578
|
-
* The
|
|
4579
|
-
*
|
|
4580
|
-
*
|
|
4581
|
-
*
|
|
4608
|
+
* The selection drives the camera: clicking a residue zooms in on it, and
|
|
4609
|
+
* clearing the selection zooms back out. It is controlled when `selection` is
|
|
4610
|
+
* passed and owned internally when it is not, so a click zooms without the
|
|
4611
|
+
* consumer holding any state. Hover state is always owned internally, so the
|
|
4612
|
+
* legend can show a live readout without the consumer round-tripping every
|
|
4613
|
+
* pointer move.
|
|
4582
4614
|
*/
|
|
4583
4615
|
const ProteinStructureViewer = (0, react.forwardRef)((props, ref) => {
|
|
4584
4616
|
var _selection$chains;
|
|
4585
|
-
const { backgroundColor, chainColors: chainColorOverrides, disableChainHighlightOnHover = false, download, hiddenChains: hiddenChainsProp, onChainVisibilityChange, onChainsChange, molstarSpec, onResidueClick, onResidueHover, onSelectionChange, structure, plddt, residueOverlay, selection
|
|
4617
|
+
const { backgroundColor, chainColors: chainColorOverrides, disableChainHighlightOnHover = false, download, hiddenChains: hiddenChainsProp, onChainVisibilityChange, onChainsChange, molstarSpec, onResidueClick, onResidueHover, onSelectionChange, structure, plddt, residueOverlay, selection: selectionProp, sequenceViewerBackgroundColor, showAxes = true, showChainLegend = true, showLegend = true, showSequenceViewer = true, stats } = props, rest = require_objectSpread2._objectWithoutProperties(props, _excluded);
|
|
4586
4618
|
const theme = (0, _mui_material_styles.useTheme)();
|
|
4587
4619
|
const mode = (0, _czi_sds_components.getMode)({ theme });
|
|
4588
4620
|
const semanticColors = (0, _czi_sds_components.getSemanticColors)({ theme });
|
|
@@ -4610,9 +4642,14 @@ const ProteinStructureViewer = (0, react.forwardRef)((props, ref) => {
|
|
|
4610
4642
|
return themeColor(semanticColors === null || semanticColors === void 0 || (_semanticColors$base3 = semanticColors.base) === null || _semanticColors$base3 === void 0 ? void 0 : _semanticColors$base3.fillSelected, FALLBACK_HIGHLIGHT_COLOR);
|
|
4611
4643
|
}, [semanticColors]);
|
|
4612
4644
|
const { handleResidueHover, hoveredResidue } = useResidueHoverState(onResidueHover);
|
|
4645
|
+
const { changeSelection, selection } = useSelection({
|
|
4646
|
+
onSelectionChange,
|
|
4647
|
+
selection: selectionProp,
|
|
4648
|
+
structure
|
|
4649
|
+
});
|
|
4613
4650
|
const handleSelectionClear = (0, react.useCallback)(() => {
|
|
4614
|
-
|
|
4615
|
-
}, [
|
|
4651
|
+
changeSelection(null);
|
|
4652
|
+
}, [changeSelection]);
|
|
4616
4653
|
/**
|
|
4617
4654
|
* Chains the selection covers whole, which is what makes a chain caption a
|
|
4618
4655
|
* toggle rather than a one-way switch. Keyed on its contents because the
|
|
@@ -4632,9 +4669,8 @@ const ProteinStructureViewer = (0, react.forwardRef)((props, ref) => {
|
|
|
4632
4669
|
*/
|
|
4633
4670
|
const handleChainSelect = (0, react.useCallback)((chainId) => {
|
|
4634
4671
|
var _selection$chains2, _selection$residues;
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
}, [onSelectionChange, selection]);
|
|
4672
|
+
changeSelection((selection === null || selection === void 0 || (_selection$chains2 = selection.chains) === null || _selection$chains2 === void 0 ? void 0 : _selection$chains2.length) === 1 && selection.chains[0] === chainId && !((_selection$residues = selection.residues) === null || _selection$residues === void 0 ? void 0 : _selection$residues.length) ? null : { chains: [chainId] });
|
|
4673
|
+
}, [changeSelection, selection]);
|
|
4638
4674
|
/**
|
|
4639
4675
|
* Dims every other chain while a chain's name is pointed at, in the legend
|
|
4640
4676
|
* or in the sequence panel's captions, and leaves the selected chain lit
|
|
@@ -4673,7 +4709,7 @@ const ProteinStructureViewer = (0, react.forwardRef)((props, ref) => {
|
|
|
4673
4709
|
onChainToggle: toggleChain,
|
|
4674
4710
|
onResidueClick,
|
|
4675
4711
|
onResidueHover: handleResidueHover,
|
|
4676
|
-
onSelectionChange,
|
|
4712
|
+
onSelectionChange: changeSelection,
|
|
4677
4713
|
onSelectionClear: handleSelectionClear,
|
|
4678
4714
|
selectedChains,
|
|
4679
4715
|
sequenceViewerBackgroundColor,
|
|
@@ -4163,6 +4163,35 @@ function useMolstarPlugin({ backgroundColor, chainColors, containerRef, download
|
|
|
4163
4163
|
};
|
|
4164
4164
|
}
|
|
4165
4165
|
//#endregion
|
|
4166
|
+
//#region src/core/ProteinStructureViewer/hooks/useSelection.ts
|
|
4167
|
+
/**
|
|
4168
|
+
* Reconciles the selection the consumer passes with the one the viewer keeps.
|
|
4169
|
+
*
|
|
4170
|
+
* Selection is controlled when `selection` is passed and owned here when it is
|
|
4171
|
+
* not, the same split `useChains` makes for visibility. The camera only ever
|
|
4172
|
+
* follows the selection, so without an owner a click on a viewer nobody holds
|
|
4173
|
+
* state for would mark the residue and never zoom in on it.
|
|
4174
|
+
* `onSelectionChange` fires either way: a consumer that only wants to follow
|
|
4175
|
+
* along should not have to take ownership to hear about it.
|
|
4176
|
+
*/
|
|
4177
|
+
function useSelection({ onSelectionChange, selection, structure }) {
|
|
4178
|
+
const isControlled = selection !== void 0;
|
|
4179
|
+
const [ownSelection, setOwnSelection] = useState(null);
|
|
4180
|
+
const onSelectionChangeRef = useRef(onSelectionChange);
|
|
4181
|
+
onSelectionChangeRef.current = onSelectionChange;
|
|
4182
|
+
useEffect(() => {
|
|
4183
|
+
setOwnSelection(null);
|
|
4184
|
+
}, [structure]);
|
|
4185
|
+
return {
|
|
4186
|
+
changeSelection: useCallback((next) => {
|
|
4187
|
+
var _onSelectionChangeRef;
|
|
4188
|
+
if (!isControlled) setOwnSelection(next);
|
|
4189
|
+
(_onSelectionChangeRef = onSelectionChangeRef.current) === null || _onSelectionChangeRef === void 0 || _onSelectionChangeRef.call(onSelectionChangeRef, next);
|
|
4190
|
+
}, [isControlled]),
|
|
4191
|
+
selection: isControlled ? selection : ownSelection
|
|
4192
|
+
};
|
|
4193
|
+
}
|
|
4194
|
+
//#endregion
|
|
4166
4195
|
//#region src/core/ProteinStructureViewer/utils/focusRepresentation.ts
|
|
4167
4196
|
/**
|
|
4168
4197
|
* What Mol* draws around a focused selection, as ball-and-stick over the
|
|
@@ -4281,10 +4310,11 @@ function focusWithShell(plugin, loci, includeNeighbours, currentShell, pluginRef
|
|
|
4281
4310
|
* chains around them instead, in `useChainHighlight`.
|
|
4282
4311
|
*
|
|
4283
4312
|
* The click subscription only reports the selection it was given, so a click
|
|
4284
|
-
* moves the camera only once the
|
|
4285
|
-
*
|
|
4286
|
-
* marks immediately, through Mol*'s own focus
|
|
4287
|
-
* responds to a click
|
|
4313
|
+
* moves the camera only once whoever owns the selection accepts it: the
|
|
4314
|
+
* consumer echoing it back when `selection` is controlled, the viewer itself
|
|
4315
|
+
* when it is not. Clicking still marks immediately, through Mol*'s own focus
|
|
4316
|
+
* behavior, so the structure responds to a click even when a consumer
|
|
4317
|
+
* controlling the selection declines it.
|
|
4288
4318
|
*/
|
|
4289
4319
|
function useSelectionFocus({ hiddenChains, isReady, pluginRef, selection, setClipRatio }) {
|
|
4290
4320
|
var _selection$chains, _selection$residues;
|
|
@@ -4572,7 +4602,7 @@ function resolveScaleProps(overlay, hasPlddt) {
|
|
|
4572
4602
|
}
|
|
4573
4603
|
var ProteinStructureViewer_default = memo(forwardRef((props, ref) => {
|
|
4574
4604
|
var _selection$chains;
|
|
4575
|
-
const { backgroundColor, chainColors: chainColorOverrides, disableChainHighlightOnHover = false, download, hiddenChains: hiddenChainsProp, onChainVisibilityChange, onChainsChange, molstarSpec, onResidueClick, onResidueHover, onSelectionChange, structure, plddt, residueOverlay, selection
|
|
4605
|
+
const { backgroundColor, chainColors: chainColorOverrides, disableChainHighlightOnHover = false, download, hiddenChains: hiddenChainsProp, onChainVisibilityChange, onChainsChange, molstarSpec, onResidueClick, onResidueHover, onSelectionChange, structure, plddt, residueOverlay, selection: selectionProp, sequenceViewerBackgroundColor, showAxes = true, showChainLegend = true, showLegend = true, showSequenceViewer = true, stats } = props, rest = _objectWithoutProperties(props, _excluded);
|
|
4576
4606
|
const theme = useTheme();
|
|
4577
4607
|
const mode = getMode({ theme });
|
|
4578
4608
|
const semanticColors = getSemanticColors({ theme });
|
|
@@ -4600,9 +4630,14 @@ var ProteinStructureViewer_default = memo(forwardRef((props, ref) => {
|
|
|
4600
4630
|
return themeColor(semanticColors === null || semanticColors === void 0 || (_semanticColors$base3 = semanticColors.base) === null || _semanticColors$base3 === void 0 ? void 0 : _semanticColors$base3.fillSelected, FALLBACK_HIGHLIGHT_COLOR);
|
|
4601
4631
|
}, [semanticColors]);
|
|
4602
4632
|
const { handleResidueHover, hoveredResidue } = useResidueHoverState(onResidueHover);
|
|
4633
|
+
const { changeSelection, selection } = useSelection({
|
|
4634
|
+
onSelectionChange,
|
|
4635
|
+
selection: selectionProp,
|
|
4636
|
+
structure
|
|
4637
|
+
});
|
|
4603
4638
|
const handleSelectionClear = useCallback(() => {
|
|
4604
|
-
|
|
4605
|
-
}, [
|
|
4639
|
+
changeSelection(null);
|
|
4640
|
+
}, [changeSelection]);
|
|
4606
4641
|
/**
|
|
4607
4642
|
* Chains the selection covers whole, which is what makes a chain caption a
|
|
4608
4643
|
* toggle rather than a one-way switch. Keyed on its contents because the
|
|
@@ -4622,9 +4657,8 @@ var ProteinStructureViewer_default = memo(forwardRef((props, ref) => {
|
|
|
4622
4657
|
*/
|
|
4623
4658
|
const handleChainSelect = useCallback((chainId) => {
|
|
4624
4659
|
var _selection$chains2, _selection$residues;
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
}, [onSelectionChange, selection]);
|
|
4660
|
+
changeSelection((selection === null || selection === void 0 || (_selection$chains2 = selection.chains) === null || _selection$chains2 === void 0 ? void 0 : _selection$chains2.length) === 1 && selection.chains[0] === chainId && !((_selection$residues = selection.residues) === null || _selection$residues === void 0 ? void 0 : _selection$residues.length) ? null : { chains: [chainId] });
|
|
4661
|
+
}, [changeSelection, selection]);
|
|
4628
4662
|
/**
|
|
4629
4663
|
* Dims every other chain while a chain's name is pointed at, in the legend
|
|
4630
4664
|
* or in the sequence panel's captions, and leaves the selected chain lit
|
|
@@ -4663,7 +4697,7 @@ var ProteinStructureViewer_default = memo(forwardRef((props, ref) => {
|
|
|
4663
4697
|
onChainToggle: toggleChain,
|
|
4664
4698
|
onResidueClick,
|
|
4665
4699
|
onResidueHover: handleResidueHover,
|
|
4666
|
-
onSelectionChange,
|
|
4700
|
+
onSelectionChange: changeSelection,
|
|
4667
4701
|
onSelectionClear: handleSelectionClear,
|
|
4668
4702
|
selectedChains,
|
|
4669
4703
|
sequenceViewerBackgroundColor,
|
|
@@ -50,12 +50,12 @@ interface ResidueValueOverlay {
|
|
|
50
50
|
* address it.
|
|
51
51
|
*
|
|
52
52
|
* `index` is the viewer's own key: the position in `plddt` and in
|
|
53
|
-
* `residueOverlay`'s map, and what `
|
|
54
|
-
* and `insCode` are what the file says, which is what the sequence
|
|
55
|
-
* and what a system that supplied the structure will recognise.
|
|
56
|
-
* from `index` whenever the file does not number a single chain
|
|
57
|
-
* crop, or a complex -- so address a residue outside the viewer
|
|
58
|
-
* three, not with `index`.
|
|
53
|
+
* `residueOverlay`'s map, and what `selection.residues` takes. `chainId`,
|
|
54
|
+
* `seqId` and `insCode` are what the file says, which is what the sequence
|
|
55
|
+
* panel shows and what a system that supplied the structure will recognise.
|
|
56
|
+
* They differ from `index` whenever the file does not number a single chain
|
|
57
|
+
* from 1 -- a crop, or a complex -- so address a residue outside the viewer
|
|
58
|
+
* with those three, not with `index`.
|
|
59
59
|
*
|
|
60
60
|
* `insCode` is rarely set but is part of the address when it is: `10` and `10A`
|
|
61
61
|
* are different residues on the same chain, so chain and number alone do not
|
|
@@ -208,13 +208,15 @@ interface ProteinStructureViewerProps extends Omit<HTMLAttributes<HTMLDivElement
|
|
|
208
208
|
/** Per-residue values that override pLDDT coloring while set. */
|
|
209
209
|
residueOverlay?: ResidueValueOverlay | null;
|
|
210
210
|
/**
|
|
211
|
-
* What is selected, or null when nothing is.
|
|
212
|
-
*
|
|
213
|
-
*
|
|
211
|
+
* What is selected, or null when nothing is. Leave undefined to let the
|
|
212
|
+
* viewer own the selection, so clicking a residue zooms in on it with no
|
|
213
|
+
* state on the consumer's side; passing it takes that over, and a click then
|
|
214
|
+
* moves the camera only once `onSelectionChange` is echoed back here.
|
|
214
215
|
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
216
|
+
* Either way the camera frames whatever the selection covers, and clearing
|
|
217
|
+
* it zooms back out to the default view. Residues are drawn in
|
|
218
|
+
* ball-and-stick over the cartoon; whole chains are left as they are and the
|
|
219
|
+
* chains around them dim, the same as hovering a chain's name.
|
|
218
220
|
*/
|
|
219
221
|
selection?: StructureSelection | null;
|
|
220
222
|
/**
|
|
@@ -286,6 +288,8 @@ interface ProteinStructureViewerProps extends Omit<HTMLAttributes<HTMLDivElement
|
|
|
286
288
|
*
|
|
287
289
|
* A whole-chain selection arrives as `{ chains: [id] }` rather than as every
|
|
288
290
|
* index on it, so echoing it straight back into `selection` costs nothing.
|
|
291
|
+
* Fires whether or not `selection` is controlled, so a consumer can follow
|
|
292
|
+
* the viewer's own selection without owning it.
|
|
289
293
|
*/
|
|
290
294
|
onSelectionChange?: (selection: StructureSelection | null) => void;
|
|
291
295
|
/**
|
|
@@ -52,12 +52,12 @@ interface ResidueValueOverlay {
|
|
|
52
52
|
* address it.
|
|
53
53
|
*
|
|
54
54
|
* `index` is the viewer's own key: the position in `plddt` and in
|
|
55
|
-
* `residueOverlay`'s map, and what `
|
|
56
|
-
* and `insCode` are what the file says, which is what the sequence
|
|
57
|
-
* and what a system that supplied the structure will recognise.
|
|
58
|
-
* from `index` whenever the file does not number a single chain
|
|
59
|
-
* crop, or a complex -- so address a residue outside the viewer
|
|
60
|
-
* three, not with `index`.
|
|
55
|
+
* `residueOverlay`'s map, and what `selection.residues` takes. `chainId`,
|
|
56
|
+
* `seqId` and `insCode` are what the file says, which is what the sequence
|
|
57
|
+
* panel shows and what a system that supplied the structure will recognise.
|
|
58
|
+
* They differ from `index` whenever the file does not number a single chain
|
|
59
|
+
* from 1 -- a crop, or a complex -- so address a residue outside the viewer
|
|
60
|
+
* with those three, not with `index`.
|
|
61
61
|
*
|
|
62
62
|
* `insCode` is rarely set but is part of the address when it is: `10` and `10A`
|
|
63
63
|
* are different residues on the same chain, so chain and number alone do not
|
|
@@ -210,13 +210,15 @@ interface ProteinStructureViewerProps extends Omit<HTMLAttributes<HTMLDivElement
|
|
|
210
210
|
/** Per-residue values that override pLDDT coloring while set. */
|
|
211
211
|
residueOverlay?: ResidueValueOverlay | null;
|
|
212
212
|
/**
|
|
213
|
-
* What is selected, or null when nothing is.
|
|
214
|
-
*
|
|
215
|
-
*
|
|
213
|
+
* What is selected, or null when nothing is. Leave undefined to let the
|
|
214
|
+
* viewer own the selection, so clicking a residue zooms in on it with no
|
|
215
|
+
* state on the consumer's side; passing it takes that over, and a click then
|
|
216
|
+
* moves the camera only once `onSelectionChange` is echoed back here.
|
|
216
217
|
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
218
|
+
* Either way the camera frames whatever the selection covers, and clearing
|
|
219
|
+
* it zooms back out to the default view. Residues are drawn in
|
|
220
|
+
* ball-and-stick over the cartoon; whole chains are left as they are and the
|
|
221
|
+
* chains around them dim, the same as hovering a chain's name.
|
|
220
222
|
*/
|
|
221
223
|
selection?: StructureSelection | null;
|
|
222
224
|
/**
|
|
@@ -288,6 +290,8 @@ interface ProteinStructureViewerProps extends Omit<HTMLAttributes<HTMLDivElement
|
|
|
288
290
|
*
|
|
289
291
|
* A whole-chain selection arrives as `{ chains: [id] }` rather than as every
|
|
290
292
|
* index on it, so echoing it straight back into `selection` costs nothing.
|
|
293
|
+
* Fires whether or not `selection` is controlled, so a consumer can follow
|
|
294
|
+
* the viewer's own selection without owning it.
|
|
291
295
|
*/
|
|
292
296
|
onSelectionChange?: (selection: StructureSelection | null) => void;
|
|
293
297
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@czi-sds/data-viz",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.3",
|
|
4
4
|
"main": "dist/index.cjs.js",
|
|
5
5
|
"types": "dist/index.cjs.d.ts",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -147,5 +147,5 @@
|
|
|
147
147
|
"echarts": "^6.0.0",
|
|
148
148
|
"lodash": "^4.17.21"
|
|
149
149
|
},
|
|
150
|
-
"gitHead": "
|
|
150
|
+
"gitHead": "52f0027db4ead40a4a311a27aefd762ed8823d47"
|
|
151
151
|
}
|