11// @flow
22
3- import React , { useState , useRef } from "react"
3+ import React , { useState , useRef , useEffect } from "react"
44import type {
55 SequenceItem as SequenceItemData ,
66 Relationship
@@ -9,8 +9,8 @@ import { styled } from "@material-ui/styles"
99import stringToSequence from "../../string-to-sequence.js"
1010import Tooltip from "@material-ui/core/Tooltip"
1111import RelationshipArrows from "../RelationshipArrows"
12- import Measure from "react-measure"
1312import colors from "../../colors"
13+ import { useTimeout , useWindowSize } from "react-use"
1414
1515const Container = styled ( "div" ) ( ( { relationshipsOn } ) => ( {
1616 lineHeight : 1.5 ,
@@ -69,11 +69,17 @@ export default function Document({
6969 relationships,
7070 onHighlightedChanged = ( ) => null ,
7171 onSequenceChange = ( ) => null ,
72+ onRelationshipsChange = ( ) => null ,
7273 nothingHighlighted = false ,
7374 colorLabelMap = { }
7475} : Props ) {
7576 const sequenceItemPositionsRef = useRef ( { } )
7677 const [ mouseDown , changeMouseDown ] = useState ( )
78+ const [ timeoutCalled , cancelTimeout , resetTimeout ] = useTimeout ( 100 ) // Force rerender after mounting
79+ const windowSize = useWindowSize ( )
80+ useEffect ( ( ) => {
81+ resetTimeout ( )
82+ } , [ windowSize ] )
7783 const [
7884 [ firstSelected , lastSelected ] ,
7985 changeHighlightedRangeState
@@ -102,82 +108,81 @@ export default function Document({
102108 onMouseUp = { ( ) => changeMouseDown ( false ) }
103109 >
104110 { sequence . map ( ( seq , i ) => (
105- < Measure
106- offset
111+ < SequenceItem
107112 key = { seq . textId || i }
108- onResize = { contentRect => {
109- if ( ! sequenceItemPositionsRef . current ) return
110- sequenceItemPositionsRef . current [ seq . textId ] = contentRect
113+ ref = { elm => {
114+ if ( ! elm ) return
115+ sequenceItemPositionsRef . current [ seq . textId ] = {
116+ offset : {
117+ left : elm . offsetLeft ,
118+ top : elm . offsetTop ,
119+ width : elm . offsetWidth ,
120+ height : elm . offsetHeight
121+ }
122+ }
123+ } }
124+ relationshipsOn = { Boolean ( relationships ) }
125+ onMouseDown = { ( ) => {
126+ if ( seq . label ) return
127+ changeHighlightedRange ( [ i , i ] )
111128 } }
129+ onMouseMove = { ( ) => {
130+ if ( seq . label ) return
131+ if ( mouseDown && i !== lastSelected ) {
132+ changeHighlightedRange ( [
133+ firstSelected === null ? i : firstSelected ,
134+ i
135+ ] )
136+ }
137+ } }
138+ className = { seq . label ? "label" : "unlabeled" }
139+ color = {
140+ seq . label
141+ ? seq . color || colorLabelMap [ seq . label ] || "#333"
142+ : seq . text !== " " && highlightedItems . includes ( i )
143+ ? "#ccc"
144+ : "inherit"
145+ }
146+ key = { i }
112147 >
113- { ( { measureRef } ) => (
114- < SequenceItem
115- ref = { measureRef }
116- relationshipsOn = { Boolean ( relationships ) }
117- onMouseDown = { ( ) => {
118- if ( seq . label ) return
119- changeHighlightedRange ( [ i , i ] )
120- } }
121- onMouseMove = { ( ) => {
122- if ( seq . label ) return
123- if ( mouseDown && i !== lastSelected ) {
124- changeHighlightedRange ( [
125- firstSelected === null ? i : firstSelected ,
126- i
127- ] )
128- }
148+ { seq . label ? (
149+ < Tooltip title = { seq . label } placement = "bottom" >
150+ < div > { seq . text } </ div >
151+ </ Tooltip >
152+ ) : (
153+ < div > { seq . text } </ div >
154+ ) }
155+ { seq . label && (
156+ < LabeledText
157+ onClick = { ( ) => {
158+ onSequenceChange (
159+ sequence
160+ . flatMap ( s => ( s !== seq ? s : stringToSequence ( s . text ) ) )
161+ . filter ( s => s . text . length > 0 )
162+ )
129163 } }
130- className = { seq . label ? "label" : "unlabeled" }
131- color = {
132- seq . label
133- ? seq . color || colorLabelMap [ seq . label ] || "#333"
134- : seq . text !== " " && highlightedItems . includes ( i )
135- ? "#ccc"
136- : "inherit"
137- }
138- key = { i }
139164 >
140- { seq . label ? (
141- < Tooltip title = { seq . label } placement = "bottom" >
142- < div > { seq . text } </ div >
143- </ Tooltip >
144- ) : (
145- < div > { seq . text } </ div >
146- ) }
147- { seq . label && (
148- < LabeledText
149- onClick = { ( ) => {
150- onSequenceChange (
151- sequence
152- . flatMap ( s =>
153- s !== seq ? s : stringToSequence ( s . text )
154- )
155- . filter ( s => s . text . length > 0 )
156- )
157- } }
158- >
159- < span > { "\u2716" } </ span >
160- </ LabeledText >
161- ) }
162- </ SequenceItem >
165+ < span > { "\u2716" } </ span >
166+ </ LabeledText >
163167 ) }
164- </ Measure >
168+ </ SequenceItem >
165169 ) ) }
166- < RelationshipArrows
167- positions = { sequenceItemPositionsRef . current }
168- arrows = { [
169- { from : "l2" , to : "l4" , label : "R1" } ,
170- { from : "l1" , to : "l4" , label : "R2" } ,
171- { from : "l0" , to : "l4" , label : "R2" } ,
172- { from : "l5" , to : "l6" , label : "R3" } ,
173- { from : "l7" , to : "l6" , label : "R3" } ,
174- { from : "l8" , to : "l6" , label : "R3" } ,
175- { from : "l2" , to : "l1" , label : "R4" } ,
176- { from : "l4" , to : "l10" , label : "R5" } ,
177- { from : "l1" , to : "l12" , label : "R6" } ,
178- { from : "l12" , to : "l1" , label : "R6" }
179- ] . map ( ( a , i ) => ( { ...a , color : colors [ i % colors . length ] } ) ) }
180- />
170+ { relationships && (
171+ < RelationshipArrows
172+ onClickArrow = { ( { label, from, to } ) => {
173+ onRelationshipsChange (
174+ relationships . filter (
175+ r => ! ( r . from === from && r . to === to && r . label === label )
176+ )
177+ )
178+ } }
179+ positions = { sequenceItemPositionsRef . current }
180+ arrows = { relationships . map ( ( a , i ) => ( {
181+ ...a ,
182+ color : a . color || colors [ i % colors . length ]
183+ } ) ) }
184+ />
185+ ) }
181186 </ Container >
182187 )
183188}
0 commit comments