@@ -34,6 +34,10 @@ import { RadioGroup } from '../components/radio_group.js';
3434
3535const { div, h2, span, i } = van . tags ;
3636
37+ // https://www.sam.today/blog/html5-dnd-globe-icon
38+ const EMPTY_IMAGE = new Image ( 1 , 1 ) ;
39+ EMPTY_IMAGE . src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' ;
40+
3741const DataCatalog = ( /** @type Properties */ props ) => {
3842 loadStylesheet ( 'data-catalog' , stylesheet ) ;
3943 Streamlit . setFrameHeight ( 1 ) ; // Non-zero value is needed to render
@@ -77,14 +81,46 @@ const DataCatalog = (/** @type Properties */ props) => {
7781 }
7882 } ) ;
7983
84+ const treeDomId = 'data-catalog-tree' ;
85+ const dragState = van . state ( null ) ;
86+ const dragConstraints = { min : 250 , max : 600 } ;
87+ const dragResize = ( event ) => {
88+ // https://stackoverflow.com/questions/36308460/why-is-clientx-reset-to-0-on-last-drag-event-and-how-to-solve-it
89+ if ( event . screenX && dragState . val ) {
90+ const dragWidth = dragState . val . startWidth + event . screenX - dragState . val . startX ;
91+ const constrainedWidth = Math . min ( dragConstraints . max , Math . max ( dragWidth , dragConstraints . min ) ) ;
92+ document . getElementById ( treeDomId ) . style . minWidth = `${ constrainedWidth } px` ;
93+ }
94+ } ;
95+
8096 return div (
81- { class : 'flex-row tg-dh' } ,
97+ {
98+ class : 'flex-row tg-dh' ,
99+ ondragover : ( event ) => event . preventDefault ( ) ,
100+ } ,
82101 Tree ( {
102+ id : treeDomId ,
83103 nodes : treeNodes ,
84104 // Use .rawVal, so only initial value from query params is passed to tree
85105 selected : selectedItem . rawVal ? `${ selectedItem . rawVal . type } _${ selectedItem . rawVal . id } ` : null ,
86106 classes : 'tg-dh--tree' ,
87107 } ) ,
108+ div (
109+ {
110+ class : 'tg-dh--dragger' ,
111+ draggable : true ,
112+ ondragstart : ( event ) => {
113+ event . dataTransfer . effectAllowed = 'move' ;
114+ event . dataTransfer . setDragImage ( EMPTY_IMAGE , 0 , 0 ) ;
115+ dragState . val = { startX : event . screenX , startWidth : document . getElementById ( treeDomId ) . offsetWidth } ;
116+ } ,
117+ ondragend : ( event ) => {
118+ dragResize ( event ) ;
119+ dragState . val = null ;
120+ } ,
121+ ondrag : van . derive ( ( ) => dragState . val ? dragResize : null ) ,
122+ } ,
123+ ) ,
88124 ( ) => {
89125 const item = selectedItem . val ;
90126 if ( item ) {
@@ -239,6 +275,11 @@ stylesheet.replace(`
239275 align-items: stretch;
240276}
241277
278+ .tg-dh--dragger {
279+ min-width: 16px;
280+ cursor: col-resize;
281+ }
282+
242283.tg-dh--tree {
243284 min-width: 250px;
244285 border-radius: 8px;
@@ -247,7 +288,7 @@ stylesheet.replace(`
247288}
248289
249290.tg-dh--details {
250- padding: 8px 0 0 20px ;
291+ padding-top : 8px;
251292 overflow: auto;
252293 flex-grow: 1;
253294}
0 commit comments