11/* eslint-disable react/require-default-props */
22/* eslint-disable @typescript-eslint/no-empty-function */
33/* eslint-disable no-param-reassign */
4- import { Typography , colors } from '@mui/material' ;
4+ import { Typography , colors , IconButton } from '@mui/material' ;
55import { styled } from '@mui/styles' ;
66import React from 'react' ;
77import _ from 'lodash' ;
@@ -74,6 +74,14 @@ const BlockChild = ({ elindex, shortcuts, displayAs, isCollapsed, setCollapsed,
7474 />
7575) ;
7676
77+ const dropIndicatorStyles = {
78+ position : 'absolute' ,
79+ height : '6px' ,
80+ marginTop : '-3px' ,
81+ marginBottom : '1px' ,
82+ zIndex : 999 ,
83+ } ;
84+
7785const BlockChildren = ( {
7886 isChildren,
7987 subentities,
@@ -98,13 +106,7 @@ const BlockChildren = ({
98106 dndContext = { tabContext . viewId }
99107 listId = { data ?. uid }
100108 arrayId = { data ?. _value ?. children ?. uid }
101- style = { {
102- position : 'absolute' ,
103- height : '6px' ,
104- marginTop : '-3px' ,
105- marginBottom : '1px' ,
106- zIndex : 999 ,
107- } }
109+ style = { dropIndicatorStyles }
108110 transformOnDrop = { ( props : any ) => {
109111 return {
110112 ...props ,
@@ -175,51 +177,40 @@ const Outline = styled('div')({
175177 display : 'flex' ,
176178 alignItems : 'baseline' ,
177179 position : 'relative' ,
180+ transition : 'transform 0.1s ease-in' ,
178181} ) ;
179182
180- const ControlsContainer = styled ( 'div' ) ( {
183+ const controlStyles = {
181184 flex : '0 0 1rem' ,
182- display : 'flex' ,
183185 width : '1rem' ,
184186 height : '1rem' ,
187+ display : 'flex' ,
185188 justifyContent : 'center' ,
186189 alignItems : 'center' ,
187- transform : 'translateY(-0.2rem)' , // fine tune vertical alignment
188- position : 'relative' ,
189- } ) ;
190+ } ;
190191
191192const Bullet = styled ( 'div' ) ( {
192- flex : '0 0 1rem' ,
193- display : 'flex' ,
194- width : '1rem' ,
195- height : '1rem' ,
196- borderRadius : '50%' ,
197- justifyContent : 'center' ,
198- alignItems : 'center' ,
199- transition : 'background 0.1s ease-in' ,
200- '& > svg' : {
201- fill : colors . common . black ,
193+ ...controlStyles ,
194+ position : 'relative' ,
195+ top : '0.125rem' ,
196+ '& > svg > circle' : {
197+ transition : 'fill 0.1s ease-in' ,
202198 } ,
203199} ) ;
204200
205201const Toggle = styled ( 'button' ) ( {
206- position : 'absolute' ,
207- top : 0 ,
208- left : '-1rem' ,
209- width : '1rem' ,
210- height : '1rem' ,
211- display : 'flex' ,
212- justifyContent : 'center' ,
213- alignItems : 'center' ,
202+ ...controlStyles ,
203+ position : 'relative' ,
204+ top : '0.125rem' ,
214205 cursor : 'pointer' ,
215206 background : 'none' ,
216207 border : 'none' ,
217208 borderRadius : '50%' ,
218209 outline : 'none' ,
219210 margin : 0 ,
220211 padding : '0.1rem' ,
221- fontSize : '1.25rem ' ,
222- transition : 'transform 0.1s ease-in' ,
212+ fontSize : '1rem ' ,
213+ transition : 'transform 0.1s ease-in, background 0.1s ease-in ' ,
223214 '&:hover' : {
224215 backgroundColor : colors . grey [ 200 ] ,
225216 } ,
@@ -231,7 +222,7 @@ const ChildrenLeftBorder = styled('div')({
231222 width : '1px' ,
232223 backgroundColor : colors . grey [ 300 ] ,
233224 position : 'absolute' ,
234- left : 'calc(-0.8rem - 0.5px)' ,
225+ left : 'calc(0.2rem - 0.5px)' ,
235226} ) ;
236227
237228const ChildrenContainer = styled ( 'div' ) ( {
@@ -276,29 +267,31 @@ export function OutlineComponent({
276267 const toggleChildren = React . useCallback ( ( ) => setCollapsed && setCollapsed ( ! collapsed ) , [ collapsed , setCollapsed ] ) ;
277268
278269 return (
279- < Outline onPointerMove = { onPointerMove } onPointerLeave = { onPointerLeave } >
280- < ControlsContainer >
281- < Toggle
282- style = { {
283- visibility : showCollapse && hover ? 'visible' : 'hidden' ,
284- transform : `rotate(${ collapsed ? '0deg' : '90deg' } )` ,
285- } }
286- onClick = { toggleChildren }
287- >
288- < ChevronRight fontSize = "inherit" />
289- </ Toggle >
290- { displayAs === 'outliner' && (
291- < Bullet
292- style = { {
293- backgroundColor : collapsed ? colors . grey [ 200 ] : 'transparent' ,
294- } }
295- >
296- < svg width = "0.375rem" viewBox = "0 0 16 16" xmlns = "http://www.w3.org/2000/svg" >
297- < circle cx = "8" cy = "8" r = "8" />
298- </ svg >
299- </ Bullet >
300- ) }
301- </ ControlsContainer >
270+ < Outline
271+ onPointerMove = { onPointerMove }
272+ onPointerLeave = { onPointerLeave }
273+ style = { {
274+ transform : displayAs === 'outliner' ? 'translateX(-1rem)' : 'translateX(-1.3rem)' ,
275+ width : displayAs === 'outliner' ? 'calc(100% + 1rem)' : 'calc(100% + 1.3rem)' ,
276+ } }
277+ >
278+ < Toggle
279+ style = { {
280+ visibility : showCollapse && hover ? 'visible' : 'hidden' ,
281+ transform : `rotate(${ collapsed ? '0deg' : '90deg' } )` ,
282+ } }
283+ onClick = { toggleChildren }
284+ >
285+ < ChevronRight fontSize = "inherit" />
286+ </ Toggle >
287+ { displayAs === 'outliner' && (
288+ < Bullet >
289+ < svg width = "100%" height = "100%" viewBox = "0 0 24 24" xmlns = "http://www.w3.org/2000/svg" >
290+ < circle cx = "12" cy = "12" r = "10" style = { { fill : collapsed ? colors . grey [ 200 ] : 'transparent' } } />
291+ < circle cx = "12" cy = "12" r = "4" style = { { fill : 'black' } } />
292+ </ svg >
293+ </ Bullet >
294+ ) }
302295 { displayAs === 'outliner' && (
303296 < ChildrenLeftBorder
304297 style = { {
@@ -381,24 +374,85 @@ export function ParentsAndReferences({ data }: any) {
381374}
382375
383376function NoteViewPageWrapper ( { children, isRoot } : any ) {
384- return ! isRoot ? children : < div style = { { height : '100%' , width : '100%' , padding : '16px' } } > { children } </ div > ;
377+ return ! isRoot ? (
378+ children
379+ ) : (
380+ < div style = { { height : '100%' , width : '100%' , padding : '1rem 2rem' , overflow : 'auto' } } > { children } </ div >
381+ ) ;
385382}
386383
387- function NoteViewTextWrapper ( { children, semanticChildren, isRoot, onContextMenu, callbacks, isEditing } : any ) {
388- // console.log(callbacks.BacklinkComponent);
384+ /** Renders both page title and content of each note block. */
385+ function NoteViewTextWrapper ( {
386+ children,
387+ semanticChildren,
388+ isRoot,
389+ isEditing,
390+ onContextMenu,
391+ callbacks,
392+ } : {
393+ children : React . ReactNode ;
394+ semanticChildren : React . ReactNode ;
395+ isRoot : boolean ;
396+ isEditing : boolean ;
397+ onContextMenu : React . MouseEventHandler ;
398+ callbacks : any ;
399+ } ) {
389400 return (
390401 < div
391402 style = { { display : 'flex' , alignItems : 'center' } }
392403 onContextMenu = { isRoot || isEditing ? undefined : onContextMenu }
393404 >
394405 { children }
395406 { semanticChildren }
396- { isRoot ? < MoreVert onClick = { onContextMenu } style = { { marginLeft : '8px' } } /> : [ ] }
397- { callbacks . BacklinkComponent ? callbacks . BacklinkComponent : [ ] }
407+ { isRoot && (
408+ < IconButton onClick = { onContextMenu } style = { { marginLeft : '8px' } } aria-label = "more" size = "small" >
409+ < MoreVert fontSize = "small" />
410+ </ IconButton >
411+ ) }
412+ { callbacks . BacklinkComponent }
398413 </ div >
399414 ) ;
400415}
401416
417+ const DateContainer = styled ( 'div' ) ( {
418+ marginTop : '4px' ,
419+ marginBottom : '12px' ,
420+ display : 'flex' ,
421+ alignItems : 'center' ,
422+ color : colors . grey [ 500 ] ,
423+ fontSize : '0.9rem' ,
424+ } ) ;
425+
426+ const ChildrenIndicator = React . memo ( function ChildrenIndicator ( {
427+ count,
428+ onClick,
429+ } : {
430+ count : number ;
431+ onClick ?: React . MouseEventHandler ;
432+ } ) {
433+ return (
434+ < Typography
435+ style = { {
436+ position : 'absolute' ,
437+ top : 0 ,
438+ left : '100%' ,
439+ height : '100%' ,
440+ display : 'flex' ,
441+ alignItems : 'center' ,
442+ padding : '0.125rem' ,
443+ color : colors . grey [ 500 ] ,
444+ wordBreak : 'keep-all' ,
445+ fontSize : '0.8rem' ,
446+ cursor : 'pointer' ,
447+ } }
448+ title = { `Show ${ count } children` }
449+ onClick = { onClick }
450+ >
451+ ({ count } )
452+ </ Typography >
453+ ) ;
454+ } ) ;
455+
402456export function DetailedOutlinerBlock ( {
403457 data,
404458 isChildren,
@@ -580,6 +634,22 @@ export function DetailedOutlinerBlock({
580634 [ rOutlineContentEl ] ,
581635 ) ;
582636
637+ const onContextMenu = React . useCallback (
638+ ( event : React . MouseEvent ) => {
639+ onUnigraphContextMenu ( event , data , undefined , { ...callbacks , componentId } ) ;
640+ } ,
641+ [ callbacks , componentId , data ] ,
642+ ) ;
643+
644+ const onClickChildrenIndicator = React . useCallback (
645+ ( ev : React . MouseEvent ) => {
646+ ev . preventDefault ( ) ;
647+ ev . stopPropagation ( ) ;
648+ setCollapsed ( false ) ;
649+ } ,
650+ [ setCollapsed ] ,
651+ ) ;
652+
583653 return (
584654 < NoteViewPageWrapper isRoot = { ! isChildren } >
585655 < div
@@ -591,9 +661,7 @@ export function DetailedOutlinerBlock({
591661 < NoteViewTextWrapper
592662 isRoot = { ! isChildren }
593663 isEditing = { isEditing }
594- onContextMenu = { ( event : any ) =>
595- onUnigraphContextMenu ( event , data , undefined , { ...callbacks , componentId } )
596- }
664+ onContextMenu = { onContextMenu }
597665 callbacks = { callbacks }
598666 semanticChildren = { otherChildren
599667 . filter ( ( el : any ) => el ?. type )
@@ -658,30 +726,22 @@ export function DetailedOutlinerBlock({
658726 editorContext ,
659727 ) }
660728 { NoteEditorInner }
661- < Typography
662- style = { {
663- display : isEditing || ! isCollapsed ? 'none' : '' ,
664- marginLeft : '6px' ,
665- color : 'gray' ,
666- cursor : 'pointer' ,
667- } }
668- onClick = { ( ev ) => {
669- ev . preventDefault ( ) ;
670- ev . stopPropagation ( ) ;
671- setCollapsed ( false ) ;
672- } }
673- > { `(${ subentities . length } )` } </ Typography >
729+ { ! isEditing && isCollapsed && (
730+ < ChildrenIndicator count = { subentities . length } onClick = { onClickChildrenIndicator } />
731+ ) }
674732 </ div >
675733 </ NoteViewTextWrapper >
676- { ! isChildren && ! callbacks . isEmbed ? (
677- < div style = { { marginTop : '4px' , marginBottom : '12px' , display : 'flex' , color : 'gray' } } >
678- < Icon path = { mdiClockOutline } size = { 0.8 } style = { { marginRight : '4px' } } />
679- { `${ new Date ( data . _updatedAt || 0 ) . toLocaleString ( ) } (${ Sugar . Date . relative (
734+ { ! isChildren && ! callbacks . isEmbed && (
735+ < DateContainer >
736+ < Icon
737+ path = { mdiClockOutline }
738+ size = { 0.75 }
739+ style = { { marginRight : '0.25rem' , transform : 'translateY(-0.08rem)' } }
740+ />
741+ < span > { `${ Sugar . Date ( data . _updatedAt || 0 ) . long ( ) } (${ Sugar . Date . relative (
680742 new Date ( data . _updatedAt || 0 ) ,
681- ) } )`}
682- </ div >
683- ) : (
684- [ ]
743+ ) } )`} </ span >
744+ </ DateContainer >
685745 ) }
686746 { ! isCollapsed && (
687747 < BlockChildren
0 commit comments