lexgui 0.6.6 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  const LX = {
10
- version: "0.6.6",
10
+ version: "0.6.8",
11
11
  ready: false,
12
12
  components: [], // Specific pre-build components
13
13
  signals: {}, // Events and triggers
@@ -870,7 +870,7 @@ class Sheet {
870
870
  this.root.dataset["side"] = this.side;
871
871
  this.root.tabIndex = "1";
872
872
  this.root.role = "dialog";
873
- this.root.className = "lexsheet fixed z-100 bg-primary";
873
+ this.root.className = "lexsheet fixed z-1000 bg-primary";
874
874
  LX.root.appendChild( this.root );
875
875
 
876
876
  this.root.addEventListener( "keydown", (e) => {
@@ -2205,6 +2205,11 @@ class Tabs {
2205
2205
 
2206
2206
  delete( name ) {
2207
2207
 
2208
+ if( this.selected == name )
2209
+ {
2210
+ this.selected = null;
2211
+ }
2212
+
2208
2213
  const tabEl = this.tabDOMs[ name ];
2209
2214
 
2210
2215
  if( !tabEl || tabEl.fixed )
@@ -6420,16 +6425,15 @@ class Area {
6420
6425
  if( auto && type == "vertical" )
6421
6426
  {
6422
6427
  // Listen resize event on first area
6423
- const resizeObserver = new ResizeObserver( entries => {
6428
+ this._autoVerticalResizeObserver = new ResizeObserver( entries => {
6424
6429
  for ( const entry of entries )
6425
6430
  {
6426
6431
  const size = entry.target.getComputedSize();
6427
6432
  area2.root.style.height = "calc(100% - " + ( size.height ) + "px )";
6428
6433
  }
6429
- resizeObserver.disconnect();
6430
6434
  });
6431
6435
 
6432
- resizeObserver.observe( area1.root );
6436
+ this._autoVerticalResizeObserver.observe( area1.root );
6433
6437
  }
6434
6438
 
6435
6439
  // Being minimizable means it's also resizeable!
@@ -6951,6 +6955,12 @@ class Area {
6951
6955
  return;
6952
6956
  }
6953
6957
 
6958
+ // When manual resizing, we don't need the observer anymore
6959
+ if( this._autoVerticalResizeObserver )
6960
+ {
6961
+ this._autoVerticalResizeObserver.disconnect();
6962
+ }
6963
+
6954
6964
  const a1 = this.sections[ 0 ];
6955
6965
  var a1Root = a1.root;
6956
6966
 
@@ -7371,7 +7381,7 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7371
7381
 
7372
7382
  LX.Panel.prototype[ 'add' + customWidgetName ] = function( name, instance, callback ) {
7373
7383
 
7374
- options.nameWidth = "100%";
7384
+ const userParams = Array.from( arguments ).slice( 3 );
7375
7385
 
7376
7386
  let widget = new Widget( Widget.CUSTOM, name, null, options );
7377
7387
  this._attachWidget( widget );
@@ -7393,6 +7403,11 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7393
7403
  }
7394
7404
  };
7395
7405
 
7406
+ widget.onResize = ( rect ) => {
7407
+ const realNameWidth = ( widget.root.domName?.style.width ?? "0px" );
7408
+ container.style.width = `calc( 100% - ${ realNameWidth })`;
7409
+ };
7410
+
7396
7411
  const element = widget.root;
7397
7412
 
7398
7413
  let container, customWidgetsDom;
@@ -7402,11 +7417,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7402
7417
 
7403
7418
  const refresh_widget = () => {
7404
7419
 
7405
- if( instance )
7406
- {
7407
- widget.instance = instance = Object.assign( LX.deepCopy(defaultInstance), instance );
7408
- }
7409
-
7410
7420
  if( container ) container.remove();
7411
7421
  if( customWidgetsDom ) customWidgetsDom.remove();
7412
7422
 
@@ -7471,13 +7481,36 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7471
7481
  this.queue( customWidgetsDom );
7472
7482
 
7473
7483
  const on_instance_changed = ( key, value, event ) => {
7474
- instance[ key ] = value;
7484
+ const setter = options[ `_set_${ key }` ];
7485
+ if( setter )
7486
+ {
7487
+ setter.call( instance, value );
7488
+ }
7489
+ else
7490
+ {
7491
+ instance[ key ] = value;
7492
+ }
7475
7493
  widget._trigger( new LX.IEvent( name, instance, event ), callback );
7476
7494
  };
7477
7495
 
7478
7496
  for( let key in defaultInstance )
7479
7497
  {
7480
- const value = instance[ key ] ?? defaultInstance[ key ];
7498
+ let value = null;
7499
+
7500
+ const getter = options[ `_get_${ key }` ];
7501
+ if( getter )
7502
+ {
7503
+ value = instance[ key ] ? getter.call( instance ) : getter.call( defaultInstance );
7504
+ }
7505
+ else
7506
+ {
7507
+ value = instance[ key ] ?? defaultInstance[ key ];
7508
+ }
7509
+
7510
+ if( !value )
7511
+ {
7512
+ continue;
7513
+ }
7481
7514
 
7482
7515
  switch( value.constructor )
7483
7516
  {
@@ -7507,9 +7540,17 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7507
7540
  this._addVector( value.length, key, value, on_instance_changed.bind( this, key ) );
7508
7541
  }
7509
7542
  break;
7543
+ default:
7544
+ console.warn( `Unsupported property type: ${ value.constructor.name }` );
7545
+ break;
7510
7546
  }
7511
7547
  }
7512
7548
 
7549
+ if( options.onCreate )
7550
+ {
7551
+ options.onCreate.call( this, this, ...userParams );
7552
+ }
7553
+
7513
7554
  this.clearQueue();
7514
7555
  }
7515
7556
  };
@@ -8444,6 +8485,27 @@ class Button extends Widget {
8444
8485
  wValue.innerHTML = `<span>${ ( value || "" ) }</span>`;
8445
8486
  }
8446
8487
 
8488
+ if( options.fileInput )
8489
+ {
8490
+ const fileInput = document.createElement( "input" );
8491
+ fileInput.type = "file";
8492
+ fileInput.className = "file-input";
8493
+ fileInput.style.display = "none";
8494
+ wValue.appendChild( fileInput );
8495
+
8496
+ fileInput.addEventListener( 'change', function( e ) {
8497
+ const files = e.target.files;
8498
+ if( !files.length ) return;
8499
+
8500
+ const reader = new FileReader();
8501
+ if( options.fileInputType === 'text' ) reader.readAsText( files[ 0 ] );
8502
+ else if( options.fileInputType === 'buffer' ) reader.readAsArrayBuffer( files[ 0 ] );
8503
+ else if( options.fileInputType === 'bin' ) reader.readAsBinaryString( files[ 0 ] );
8504
+ else if( options.fileInputType === 'url' ) reader.readAsDataURL( files[ 0 ] );
8505
+ reader.onload = e => { callback.call( this, e.target.result, files[ 0 ] ); } ;
8506
+ });
8507
+ }
8508
+
8447
8509
  if( options.disabled )
8448
8510
  {
8449
8511
  this.disabled = true;
@@ -8496,8 +8558,15 @@ class Button extends Widget {
8496
8558
  wValue.classList.toggle('selected');
8497
8559
  }
8498
8560
 
8499
- const swapInput = wValue.querySelector( "input" );
8500
- this._trigger( new LX.IEvent( name, swapInput?.checked ?? value, e ), callback );
8561
+ if( options.fileInput )
8562
+ {
8563
+ wValue.querySelector( ".file-input" ).click();
8564
+ }
8565
+ else
8566
+ {
8567
+ const swapInput = wValue.querySelector( "input" );
8568
+ this._trigger( new LX.IEvent( name, swapInput?.checked ?? value, e ), callback );
8569
+ }
8501
8570
  });
8502
8571
 
8503
8572
  if( options.tooltip )
@@ -11513,16 +11582,16 @@ class Table extends Widget {
11513
11582
  container.className = "lextable";
11514
11583
  this.root.appendChild( container );
11515
11584
 
11516
- this.centered = options.centered ?? false;
11517
- if( this.centered === true )
11585
+ this._centered = options.centered ?? false;
11586
+ if( this._centered === true )
11518
11587
  {
11519
11588
  container.classList.add( "centered" );
11520
11589
  }
11521
11590
 
11591
+ this.activeCustomFilters = {};
11522
11592
  this.filter = options.filter ?? false;
11523
- this.toggleColumns = options.toggleColumns ?? false;
11524
11593
  this.customFilters = options.customFilters ?? false;
11525
- this.activeCustomFilters = {};
11594
+ this._toggleColumns = options.toggleColumns ?? false;
11526
11595
  this._currentFilter = options.filterValue;
11527
11596
 
11528
11597
  data.head = data.head ?? [];
@@ -11530,6 +11599,7 @@ class Table extends Widget {
11530
11599
  data.checkMap = { };
11531
11600
  data.colVisibilityMap = { };
11532
11601
  data.head.forEach( (col, index) => { data.colVisibilityMap[ index ] = true; });
11602
+ this.data = data;
11533
11603
 
11534
11604
  const compareFn = ( idx, order, a, b) => {
11535
11605
  if (a[idx] < b[idx]) return -order;
@@ -11543,7 +11613,7 @@ class Table extends Widget {
11543
11613
  };
11544
11614
 
11545
11615
  // Append header
11546
- if( this.filter || this.customFilters || this.toggleColumns )
11616
+ if( this.filter || this.customFilters || this._toggleColumns )
11547
11617
  {
11548
11618
  const headerContainer = LX.makeContainer( [ "100%", "auto" ], "flex flex-row" );
11549
11619
 
@@ -11655,7 +11725,7 @@ class Table extends Widget {
11655
11725
  this._resetCustomFiltersBtn.root.classList.add( "hidden" );
11656
11726
  }
11657
11727
 
11658
- if( this.toggleColumns )
11728
+ if( this._toggleColumns )
11659
11729
  {
11660
11730
  const icon = LX.makeIcon( "Settings2" );
11661
11731
  const toggleColumnsBtn = new LX.Button( "toggleColumnsBtn", icon.innerHTML + "View", (value, e) => {
@@ -11743,7 +11813,7 @@ class Table extends Widget {
11743
11813
  th.querySelector( "span" ).appendChild( LX.makeIcon( "MenuArrows", { svgClass: "sm" } ) );
11744
11814
 
11745
11815
  const idx = data.head.indexOf( headData );
11746
- if( this.centered && this.centered.indexOf( idx ) > -1 )
11816
+ if( this._centered?.indexOf && this._centered.indexOf( idx ) > -1 )
11747
11817
  {
11748
11818
  th.classList.add( "centered" );
11749
11819
  }
@@ -11753,7 +11823,7 @@ class Table extends Widget {
11753
11823
  { name: "Desc", icon: "ArrowDownAZ", callback: sortFn.bind( this, idx, -1 ) }
11754
11824
  ];
11755
11825
 
11756
- if( this.toggleColumns )
11826
+ if( this._toggleColumns )
11757
11827
  {
11758
11828
  menuOptions.push(
11759
11829
  null,
@@ -11815,6 +11885,9 @@ class Table extends Widget {
11815
11885
  // Origin row should go to the target row, and the rest should be moved up/down
11816
11886
  const fromIdx = rIdx - 1;
11817
11887
  const targetIdx = movePending[ 1 ] - 1;
11888
+
11889
+ LX.emit( "@on_table_sort", { instance: this, fromIdx, targetIdx } );
11890
+
11818
11891
  const b = data.body[ fromIdx ];
11819
11892
  let targetOffset = 0;
11820
11893
 
@@ -12020,7 +12093,7 @@ class Table extends Widget {
12020
12093
  td.innerHTML = `${ rowData }`;
12021
12094
 
12022
12095
  const idx = bodyData.indexOf( rowData );
12023
- if( this.centered && this.centered.indexOf( idx ) > -1 )
12096
+ if( this._centered?.indexOf && this._centered.indexOf( idx ) > -1 )
12024
12097
  {
12025
12098
  td.classList.add( "centered" );
12026
12099
  }
@@ -12110,8 +12183,50 @@ class Table extends Widget {
12110
12183
 
12111
12184
  LX.doAsync( this.onResize.bind( this ) );
12112
12185
  }
12186
+
12187
+ getSelectedRows() {
12188
+
12189
+ const selectedRows = [];
12190
+
12191
+ for( const row of this.data.body )
12192
+ {
12193
+ const rowId = LX.getSupportedDOMName( row.join( '-' ) ).substr( 0, 32 );
12194
+ if( this.data.checkMap[ rowId ] === true )
12195
+ {
12196
+ selectedRows.push( row );
12197
+ }
12198
+ }
12199
+
12200
+ return selectedRows;
12201
+ }
12202
+
12203
+ _setCentered( v ) {
12204
+
12205
+ if( v.constructor == Boolean )
12206
+ {
12207
+ const container = this.root.querySelector( ".lextable" );
12208
+ container.classList.toggle( "centered", v );
12209
+ }
12210
+ else
12211
+ {
12212
+ // Make sure this is an array containing which columns have
12213
+ // to be centered
12214
+ v = [].concat( v );
12215
+ }
12216
+
12217
+ this._centered = v;
12218
+
12219
+ this.refresh();
12220
+ }
12113
12221
  }
12114
12222
 
12223
+ Object.defineProperty( Table.prototype, "centered", {
12224
+ get: function() { return this._centered; },
12225
+ set: function( v ) { this._setCentered( v ); },
12226
+ enumerable: true,
12227
+ configurable: true
12228
+ });
12229
+
12115
12230
  LX.Table = Table;
12116
12231
 
12117
12232
  /**
@@ -12833,6 +12948,8 @@ class Panel {
12833
12948
  * hideName: Don't use name as label [false]
12834
12949
  * disabled: Make the widget disabled [false]
12835
12950
  * icon: Icon class to show as button value
12951
+ * fileInput: Button click requests a file
12952
+ * fileInputType: Type of the requested file
12836
12953
  * img: Path to image to show as button value
12837
12954
  * title: Text to show in native Element title
12838
12955
  * buttonClass: Class to add to the native button element
@@ -14173,6 +14290,13 @@ class Sidebar {
14173
14290
  info.appendChild( infoSubtext );
14174
14291
  }
14175
14292
 
14293
+ // Add icon if onHeaderPressed is defined and not collapsable (it uses the toggler icon)
14294
+ if( options.onHeaderPressed && !this.collapsable )
14295
+ {
14296
+ const icon = LX.makeIcon( "MenuArrows" );
14297
+ header.appendChild( icon );
14298
+ }
14299
+
14176
14300
  return header;
14177
14301
  }
14178
14302
 
@@ -14218,8 +14342,13 @@ class Sidebar {
14218
14342
  info.appendChild( infoSubtext );
14219
14343
  }
14220
14344
 
14221
- const icon = LX.makeIcon( "MenuArrows" );
14222
- footer.appendChild( icon );
14345
+ // Add icon if onFooterPressed is defined
14346
+ // Useful to indicate that the footer is clickable
14347
+ if( options.onFooterPressed )
14348
+ {
14349
+ const icon = LX.makeIcon( "MenuArrows" );
14350
+ footer.appendChild( icon );
14351
+ }
14223
14352
 
14224
14353
  return footer;
14225
14354
  }