diff --git a/plugins/svg/src/SvgFeatureRenderer/components/FeatureGlyph.tsx b/plugins/svg/src/SvgFeatureRenderer/components/FeatureGlyph.tsx index 863005aa5f..d40f22ba3e 100644 --- a/plugins/svg/src/SvgFeatureRenderer/components/FeatureGlyph.tsx +++ b/plugins/svg/src/SvgFeatureRenderer/components/FeatureGlyph.tsx @@ -21,8 +21,8 @@ function FeatureGlyph(props: { shouldShowDescription: boolean fontHeight: number allowedWidthExpansion: number - exportSVG: unknown - displayModel: DisplayModel + exportSVG?: unknown + displayModel?: DisplayModel selected?: boolean reversed?: boolean topLevel?: boolean diff --git a/plugins/svg/src/SvgFeatureRenderer/components/FeatureLabel.tsx b/plugins/svg/src/SvgFeatureRenderer/components/FeatureLabel.tsx index e3bb32a935..1e9d05727e 100644 --- a/plugins/svg/src/SvgFeatureRenderer/components/FeatureLabel.tsx +++ b/plugins/svg/src/SvgFeatureRenderer/components/FeatureLabel.tsx @@ -31,9 +31,9 @@ export default observer( allowedWidthExpansion?: number feature: Feature reversed?: boolean - displayModel: DisplayModel + displayModel?: DisplayModel + exportSVG?: unknown region: Region - exportSVG: unknown viewParams: { start: number end: number diff --git a/plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.test.js b/plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.test.tsx similarity index 93% rename from plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.test.js rename to plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.test.tsx index 316164807e..528eef1eb1 100644 --- a/plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.test.js +++ b/plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.test.tsx @@ -1,8 +1,10 @@ +import React from 'react' +import { render, fireEvent } from '@testing-library/react' import GranularRectLayout from '@jbrowse/core/util/layouts/GranularRectLayout' import PrecomputedLayout from '@jbrowse/core/util/layouts/PrecomputedLayout' import SimpleFeature from '@jbrowse/core/util/simpleFeature' -import React from 'react' -import { render } from '@testing-library/react' + +// locals import SvgRendererConfigSchema from '../configSchema' import Rendering from './SvgFeatureRendering' import SvgOverlay from './SvgOverlay' @@ -12,12 +14,21 @@ import '@testing-library/jest-dom/extend-expect' test('no features', () => { const { container } = render( , ) @@ -28,11 +39,12 @@ test('no features', () => { test('one feature', () => { const { container } = render( { expect(container.firstChild).toMatchSnapshot() }) +test('click on one feature, and do not re-render', () => { + let counter = 0 + const { container, getByTestId } = render( + counter++} + />, + ) + fireEvent.click(getByTestId('box-one')) + expect(counter).toBe(3) + + expect(container.firstChild).toMatchSnapshot() +}) + test('one feature (compact mode)', () => { const config = SvgRendererConfigSchema.create({ displayMode: 'compact' }) const { container } = render( { }) const { container } = render( { test('processed transcript', () => { const { container } = render( { test('processed transcript (exons + impliedUTR)', () => { const { container } = render( { const { container } = render( { return [0, 0, 10, 10] @@ -1037,7 +1084,6 @@ test('svg selected', () => { featureIdUnderMouse: 'one', selectedFeatureId: 'one', }} - config={SvgRendererConfigSchema.create({})} bpPerPx={3} /> , diff --git a/plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.tsx b/plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.tsx index 071e7b7a48..4b89e4652c 100644 --- a/plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.tsx +++ b/plugins/svg/src/SvgFeatureRenderer/components/SvgFeatureRendering.tsx @@ -30,10 +30,11 @@ function RenderedFeatureGlyph(props: { region: Region config: AnyConfigurationModel layout: BaseLayout - extraGlyphs: ExtraGlyphValidator[] + extraGlyphs?: ExtraGlyphValidator[] displayMode: string - exportSVG: unknown - displayModel: DisplayModel + exportSVG?: unknown + displayModel?: DisplayModel + detectRerender?: () => void viewParams: { start: number end: number @@ -42,8 +43,20 @@ function RenderedFeatureGlyph(props: { } [key: string]: unknown }) { - const { feature, bpPerPx, region, config, displayMode, layout, extraGlyphs } = - props + const { + feature, + detectRerender, + bpPerPx, + region, + config, + displayMode, + layout, + extraGlyphs, + } = props + + // used for unit testing, difficult to mock out so it is in actual source code + detectRerender?.() + const { reversed } = region const start = feature.get(reversed ? 'end' : 'start') const startPx = bpToPx(start, region, bpPerPx) @@ -139,15 +152,15 @@ function RenderedFeatureGlyph(props: { const RenderedFeatures = observer( (props: { - features: Map - isFeatureDisplayed: (f: Feature) => boolean + features?: Map + isFeatureDisplayed?: (f: Feature) => boolean bpPerPx: number config: AnyConfigurationModel displayMode: string - displayModel: DisplayModel + displayModel?: DisplayModel region: Region - exportSVG: unknown - extraGlyphs: ExtraGlyphValidator[] + exportSVG?: unknown + extraGlyphs?: ExtraGlyphValidator[] layout: BaseLayout viewParams: { start: number @@ -161,7 +174,9 @@ const RenderedFeatures = observer( return ( <> {[...features.values()] - .filter(feature => isFeatureDisplayed(feature)) + .filter(feature => + isFeatureDisplayed ? isFeatureDisplayed(feature) : true, + ) .map(feature => ( void config: AnyConfigurationModel features: Map - displayModel: DisplayModel - exportSVG: boolean + displayModel?: DisplayModel + exportSVG?: boolean viewParams: { start: number end: number offsetPx: number offsetPx1: number } - featureDisplayHandler: (f: Feature) => boolean - extraGlyphs: ExtraGlyphValidator[] + featureDisplayHandler?: (f: Feature) => boolean + extraGlyphs?: ExtraGlyphValidator[] onMouseOut?: React.MouseEventHandler onMouseDown?: React.MouseEventHandler onMouseLeave?: React.MouseEventHandler @@ -208,7 +224,7 @@ function SvgFeatureRendering(props: { config, displayModel = {}, exportSVG, - featureDisplayHandler = () => true, + featureDisplayHandler, onMouseOut, onMouseDown, onMouseLeave, @@ -218,6 +234,7 @@ function SvgFeatureRendering(props: { onMouseUp, onClick, } = props + const [region] = regions || [] const width = (region.end - region.start) / bpPerPx const displayMode = readConfObject(config, 'displayMode') as string @@ -227,6 +244,7 @@ function SvgFeatureRendering(props: { const [height, setHeight] = useState(0) const [movedDuringLastMouseDown, setMovedDuringLastMouseDown] = useState(false) + const mouseDown = useCallback( (event: React.MouseEvent) => { setMouseIsDown(true) @@ -327,6 +345,7 @@ function SvgFeatureRendering(props: { isFeatureDisplayed={featureDisplayHandler} {...props} /> + LayoutRecord selectedFeatureId?: string featureIdUnderMouse?: string @@ -15,7 +16,7 @@ interface SvgOverlayProps { } bpPerPx: number blockKey: string - movedDuringLastMouseDown: boolean + movedDuringLastMouseDown?: boolean onFeatureMouseDown?( event: React.MouseEvent, featureId: string, diff --git a/plugins/svg/src/SvgFeatureRenderer/components/__snapshots__/SvgFeatureRendering.test.js.snap b/plugins/svg/src/SvgFeatureRenderer/components/__snapshots__/SvgFeatureRendering.test.tsx.snap similarity index 95% rename from plugins/svg/src/SvgFeatureRenderer/components/__snapshots__/SvgFeatureRendering.test.js.snap rename to plugins/svg/src/SvgFeatureRenderer/components/__snapshots__/SvgFeatureRendering.test.tsx.snap index 09d5530a95..a8782e276a 100644 --- a/plugins/svg/src/SvgFeatureRenderer/components/__snapshots__/SvgFeatureRendering.test.js.snap +++ b/plugins/svg/src/SvgFeatureRenderer/components/__snapshots__/SvgFeatureRendering.test.tsx.snap @@ -1,5 +1,47 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`click on one feature, and do not re-render 1`] = ` + + + + + + + + + + + +`; + exports[`no features 1`] = `