1- import React , { FormEvent , useCallback , useContext , useEffect , useMemo , useRef , useState } from 'react' ;
1+ import React , {
2+ FormEvent ,
3+ useCallback ,
4+ useContext ,
5+ useEffect ,
6+ useMemo ,
7+ useRef ,
8+ useState
9+ } from 'react' ;
210import { Dropdown , Menu } from 'antd' ;
311
412import { useToggle } from '../../hooks/useToggle' ;
@@ -7,7 +15,9 @@ import { LsChevron } from '../../assets/icons';
715import TreeStructure from '../TreeStructure/TreeStructure' ;
816
917import styles from './Taxonomy.module.scss' ;
10- import { FF_DEV_4075 , isFF } from '../../utils/feature-flags' ;
18+ import { FF_DEV_4075 , FF_PROD_309 , isFF } from '../../utils/feature-flags' ;
19+ import { Tooltip } from '../../common/Tooltip/Tooltip' ;
20+ import { CNTagName } from '../../utils/bem' ;
1121
1222type TaxonomyPath = string [ ] ;
1323type onAddLabelCallback = ( path : string [ ] ) => any ;
@@ -19,6 +29,7 @@ type TaxonomyItem = {
1929 depth : number ,
2030 children ?: TaxonomyItem [ ] ,
2131 origin ?: 'config' | 'user' | 'session' ,
32+ hint ?: string ,
2233} ;
2334
2435type TaxonomyOptions = {
@@ -74,6 +85,7 @@ interface RowProps {
7485 padding : number ,
7586 isLeaf : boolean ,
7687 origin ?: any ,
88+ hint ?: string ,
7789 } ,
7890 children ?: any ,
7991 toggle : ( id : string ) => void ,
@@ -148,9 +160,38 @@ function isSubArray(item: string[], parent: string[]) {
148160 return parent . every ( ( n , i ) => item [ i ] === n ) ;
149161}
150162
163+ type HintTooltipProps = {
164+ // Without title there is no tooltip at all as a component
165+ title ?: string ,
166+ // wrapper is used as a tag in JSX to wrap child elements to make Tooltip to work with the single child element
167+ // it can be a real tag or a component that provides real HTMLElement (not a text) as the result
168+ wrapper ?: CNTagName ,
169+ children : JSX . Element ,
170+ }
171+
172+ export const HintTooltip : React . FC < HintTooltipProps > = ( {
173+ title,
174+ wrapper : Wrapper ,
175+ children,
176+ ...rest
177+ } ) => {
178+ if ( ! isFF ( FF_PROD_309 ) ) return children ;
179+
180+ const content = Wrapper ? < Wrapper > { children } </ Wrapper > : children ;
181+
182+ if ( title ) {
183+ return (
184+ < Tooltip title = { title } mouseEnterDelay = { 500 } { ...rest } >
185+ { content }
186+ </ Tooltip >
187+ ) ;
188+ }
189+ return content ;
190+ } ;
191+
151192const Item : React . FC < RowProps > = ( { style, item, dimensionCallback, maxWidth, isEditable } : RowProps ) => {
152193 const {
153- row : { id, isOpen, childCount, isFiltering, name, path, padding, isLeaf } ,
194+ row : { id, isOpen, childCount, isFiltering, name, path, padding, isLeaf, hint } ,
154195 toggle,
155196 addInside : addChild ,
156197 } = item ;
@@ -222,67 +263,69 @@ const Item: React.FC<RowProps> = ({ style, item, dimensionCallback, maxWidth, is
222263 </ div >
223264 ) }
224265 </ div >
225- < div className = { [ styles . taxonomy__item , customClassname ] . join ( ' ' ) } >
226- < div className = { styles . taxonomy__grouping } onClick = { ( ) => toggle ( id ) } >
227- < LsChevron stroke = "#09f" style = { arrowStyle } />
228- </ div >
229- < input
230- className = "item"
231- id = { id }
232- name = { id }
233- type = "checkbox"
234- disabled = { disabled }
235- checked = { checked }
236- ref = { setIndeterminate }
237- onChange = { e => {
238- if ( isEditable ) {
239- setSelected ( path , e . currentTarget . checked ) ;
240- }
241- } }
242- />
243- < label
244- htmlFor = { id }
245- style = { isFF ( FF_DEV_4075 ) ? { } : { maxWidth : `${ labelMaxWidth } px` } }
246- onClick = { isEditable ? onClick : undefined }
247- title = { title }
248- className = { disabled ? styles . taxonomy__collapsable : undefined }
249- >
250- { name }
251- </ label >
252- { ! isFiltering && (
253- < div className = { styles . taxonomy__extra } >
254- < span className = { styles . taxonomy__extra_count } > { childCount } </ span >
255- { isEditable && onAddLabel && (
256- < div className = { styles . taxonomy__extra_actions } >
257- < Dropdown
258- destroyPopupOnHide // important for long interactions with huge taxonomy
259- trigger = { [ 'click' ] }
260- overlay = { (
261- < Menu >
262- < Menu . Item
263- key = "add-inside"
264- className = { styles . taxonomy__action }
265- onClick = { ( ) => {
266- addChild ( id ) ;
267- } }
268- >
266+ < HintTooltip title = { hint } >
267+ < div className = { [ styles . taxonomy__item , customClassname ] . join ( ' ' ) } >
268+ < div className = { styles . taxonomy__grouping } onClick = { ( ) => toggle ( id ) } >
269+ < LsChevron stroke = "#09f" style = { arrowStyle } />
270+ </ div >
271+ < input
272+ className = "item"
273+ id = { id }
274+ name = { id }
275+ type = "checkbox"
276+ disabled = { disabled }
277+ checked = { checked }
278+ ref = { setIndeterminate }
279+ onChange = { e => {
280+ if ( isEditable ) {
281+ setSelected ( path , e . currentTarget . checked ) ;
282+ }
283+ } }
284+ />
285+ < label
286+ htmlFor = { id }
287+ style = { isFF ( FF_DEV_4075 ) ? { } : { maxWidth : `${ labelMaxWidth } px` } }
288+ onClick = { isEditable ? onClick : undefined }
289+ title = { title }
290+ className = { disabled ? styles . taxonomy__collapsable : undefined }
291+ >
292+ { name }
293+ </ label >
294+ { ! isFiltering && (
295+ < div className = { styles . taxonomy__extra } >
296+ < span className = { styles . taxonomy__extra_count } > { childCount } </ span >
297+ { isEditable && onAddLabel && (
298+ < div className = { styles . taxonomy__extra_actions } >
299+ < Dropdown
300+ destroyPopupOnHide // important for long interactions with huge taxonomy
301+ trigger = { [ 'click' ] }
302+ overlay = { (
303+ < Menu >
304+ < Menu . Item
305+ key = "add-inside"
306+ className = { styles . taxonomy__action }
307+ onClick = { ( ) => {
308+ addChild ( id ) ;
309+ } }
310+ >
269311 Add Inside
270- </ Menu . Item >
271- { item . row . origin === 'session' && (
272- < Menu . Item key = "delete" className = { styles . taxonomy__action } onClick = { onDelete } >
273- Delete
274312 </ Menu . Item >
275- ) }
276- </ Menu >
277- ) }
278- >
279- < div > ...</ div >
280- </ Dropdown >
281- </ div >
282- ) }
283- </ div >
284- ) }
285- </ div >
313+ { item . row . origin === 'session' && (
314+ < Menu . Item key = "delete" className = { styles . taxonomy__action } onClick = { onDelete } >
315+ Delete
316+ </ Menu . Item >
317+ ) }
318+ </ Menu >
319+ ) }
320+ >
321+ < div > ...</ div >
322+ </ Dropdown >
323+ </ div >
324+ ) }
325+ </ div >
326+ ) }
327+ </ div >
328+ </ HintTooltip >
286329 </ >
287330 ) : (
288331 < UserLabelForm key = "" onAddLabel = { onAddLabel } onFinish = { ( ) => addChild ( ) } path = { path } />
@@ -358,7 +401,7 @@ const TaxonomyDropdown = ({ show, flatten, items, dropdownRef, isEditable }: Tax
358401 } , [ show ] ) ;
359402
360403 const dataTransformation = ( {
361- node : { children, depth, label, origin, path } ,
404+ node : { children, depth, label, origin, path, hint } ,
362405 nestingLevel,
363406 isFiltering,
364407 isOpen,
@@ -381,6 +424,7 @@ const TaxonomyDropdown = ({ show, flatten, items, dropdownRef, isEditable }: Tax
381424 origin,
382425 padding : nestingLevel * 10 + 10 ,
383426 path,
427+ hint,
384428 } ) ;
385429
386430 return (
0 commit comments