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.
package/build/lexgui.js CHANGED
@@ -14,7 +14,7 @@ console.warn( 'Script _build/lexgui.js_ is depracated and will be removed soon.
14
14
  */
15
15
 
16
16
  const LX = {
17
- version: "0.6.6",
17
+ version: "0.6.8",
18
18
  ready: false,
19
19
  components: [], // Specific pre-build components
20
20
  signals: {}, // Events and triggers
@@ -877,7 +877,7 @@ class Sheet {
877
877
  this.root.dataset["side"] = this.side;
878
878
  this.root.tabIndex = "1";
879
879
  this.root.role = "dialog";
880
- this.root.className = "lexsheet fixed z-100 bg-primary";
880
+ this.root.className = "lexsheet fixed z-1000 bg-primary";
881
881
  LX.root.appendChild( this.root );
882
882
 
883
883
  this.root.addEventListener( "keydown", (e) => {
@@ -2212,6 +2212,11 @@ class Tabs {
2212
2212
 
2213
2213
  delete( name ) {
2214
2214
 
2215
+ if( this.selected == name )
2216
+ {
2217
+ this.selected = null;
2218
+ }
2219
+
2215
2220
  const tabEl = this.tabDOMs[ name ];
2216
2221
 
2217
2222
  if( !tabEl || tabEl.fixed )
@@ -6427,16 +6432,15 @@ class Area {
6427
6432
  if( auto && type == "vertical" )
6428
6433
  {
6429
6434
  // Listen resize event on first area
6430
- const resizeObserver = new ResizeObserver( entries => {
6435
+ this._autoVerticalResizeObserver = new ResizeObserver( entries => {
6431
6436
  for ( const entry of entries )
6432
6437
  {
6433
6438
  const size = entry.target.getComputedSize();
6434
6439
  area2.root.style.height = "calc(100% - " + ( size.height ) + "px )";
6435
6440
  }
6436
- resizeObserver.disconnect();
6437
6441
  });
6438
6442
 
6439
- resizeObserver.observe( area1.root );
6443
+ this._autoVerticalResizeObserver.observe( area1.root );
6440
6444
  }
6441
6445
 
6442
6446
  // Being minimizable means it's also resizeable!
@@ -6958,6 +6962,12 @@ class Area {
6958
6962
  return;
6959
6963
  }
6960
6964
 
6965
+ // When manual resizing, we don't need the observer anymore
6966
+ if( this._autoVerticalResizeObserver )
6967
+ {
6968
+ this._autoVerticalResizeObserver.disconnect();
6969
+ }
6970
+
6961
6971
  const a1 = this.sections[ 0 ];
6962
6972
  var a1Root = a1.root;
6963
6973
 
@@ -7378,7 +7388,7 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7378
7388
 
7379
7389
  LX.Panel.prototype[ 'add' + customWidgetName ] = function( name, instance, callback ) {
7380
7390
 
7381
- options.nameWidth = "100%";
7391
+ const userParams = Array.from( arguments ).slice( 3 );
7382
7392
 
7383
7393
  let widget = new Widget( Widget.CUSTOM, name, null, options );
7384
7394
  this._attachWidget( widget );
@@ -7400,6 +7410,11 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7400
7410
  }
7401
7411
  };
7402
7412
 
7413
+ widget.onResize = ( rect ) => {
7414
+ const realNameWidth = ( widget.root.domName?.style.width ?? "0px" );
7415
+ container.style.width = `calc( 100% - ${ realNameWidth })`;
7416
+ };
7417
+
7403
7418
  const element = widget.root;
7404
7419
 
7405
7420
  let container, customWidgetsDom;
@@ -7409,11 +7424,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7409
7424
 
7410
7425
  const refresh_widget = () => {
7411
7426
 
7412
- if( instance )
7413
- {
7414
- widget.instance = instance = Object.assign( LX.deepCopy(defaultInstance), instance );
7415
- }
7416
-
7417
7427
  if( container ) container.remove();
7418
7428
  if( customWidgetsDom ) customWidgetsDom.remove();
7419
7429
 
@@ -7478,13 +7488,36 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7478
7488
  this.queue( customWidgetsDom );
7479
7489
 
7480
7490
  const on_instance_changed = ( key, value, event ) => {
7481
- instance[ key ] = value;
7491
+ const setter = options[ `_set_${ key }` ];
7492
+ if( setter )
7493
+ {
7494
+ setter.call( instance, value );
7495
+ }
7496
+ else
7497
+ {
7498
+ instance[ key ] = value;
7499
+ }
7482
7500
  widget._trigger( new LX.IEvent( name, instance, event ), callback );
7483
7501
  };
7484
7502
 
7485
7503
  for( let key in defaultInstance )
7486
7504
  {
7487
- const value = instance[ key ] ?? defaultInstance[ key ];
7505
+ let value = null;
7506
+
7507
+ const getter = options[ `_get_${ key }` ];
7508
+ if( getter )
7509
+ {
7510
+ value = instance[ key ] ? getter.call( instance ) : getter.call( defaultInstance );
7511
+ }
7512
+ else
7513
+ {
7514
+ value = instance[ key ] ?? defaultInstance[ key ];
7515
+ }
7516
+
7517
+ if( !value )
7518
+ {
7519
+ continue;
7520
+ }
7488
7521
 
7489
7522
  switch( value.constructor )
7490
7523
  {
@@ -7514,9 +7547,17 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7514
7547
  this._addVector( value.length, key, value, on_instance_changed.bind( this, key ) );
7515
7548
  }
7516
7549
  break;
7550
+ default:
7551
+ console.warn( `Unsupported property type: ${ value.constructor.name }` );
7552
+ break;
7517
7553
  }
7518
7554
  }
7519
7555
 
7556
+ if( options.onCreate )
7557
+ {
7558
+ options.onCreate.call( this, this, ...userParams );
7559
+ }
7560
+
7520
7561
  this.clearQueue();
7521
7562
  }
7522
7563
  };
@@ -8451,6 +8492,27 @@ class Button extends Widget {
8451
8492
  wValue.innerHTML = `<span>${ ( value || "" ) }</span>`;
8452
8493
  }
8453
8494
 
8495
+ if( options.fileInput )
8496
+ {
8497
+ const fileInput = document.createElement( "input" );
8498
+ fileInput.type = "file";
8499
+ fileInput.className = "file-input";
8500
+ fileInput.style.display = "none";
8501
+ wValue.appendChild( fileInput );
8502
+
8503
+ fileInput.addEventListener( 'change', function( e ) {
8504
+ const files = e.target.files;
8505
+ if( !files.length ) return;
8506
+
8507
+ const reader = new FileReader();
8508
+ if( options.fileInputType === 'text' ) reader.readAsText( files[ 0 ] );
8509
+ else if( options.fileInputType === 'buffer' ) reader.readAsArrayBuffer( files[ 0 ] );
8510
+ else if( options.fileInputType === 'bin' ) reader.readAsBinaryString( files[ 0 ] );
8511
+ else if( options.fileInputType === 'url' ) reader.readAsDataURL( files[ 0 ] );
8512
+ reader.onload = e => { callback.call( this, e.target.result, files[ 0 ] ); } ;
8513
+ });
8514
+ }
8515
+
8454
8516
  if( options.disabled )
8455
8517
  {
8456
8518
  this.disabled = true;
@@ -8503,8 +8565,15 @@ class Button extends Widget {
8503
8565
  wValue.classList.toggle('selected');
8504
8566
  }
8505
8567
 
8506
- const swapInput = wValue.querySelector( "input" );
8507
- this._trigger( new LX.IEvent( name, swapInput?.checked ?? value, e ), callback );
8568
+ if( options.fileInput )
8569
+ {
8570
+ wValue.querySelector( ".file-input" ).click();
8571
+ }
8572
+ else
8573
+ {
8574
+ const swapInput = wValue.querySelector( "input" );
8575
+ this._trigger( new LX.IEvent( name, swapInput?.checked ?? value, e ), callback );
8576
+ }
8508
8577
  });
8509
8578
 
8510
8579
  if( options.tooltip )
@@ -11520,16 +11589,16 @@ class Table extends Widget {
11520
11589
  container.className = "lextable";
11521
11590
  this.root.appendChild( container );
11522
11591
 
11523
- this.centered = options.centered ?? false;
11524
- if( this.centered === true )
11592
+ this._centered = options.centered ?? false;
11593
+ if( this._centered === true )
11525
11594
  {
11526
11595
  container.classList.add( "centered" );
11527
11596
  }
11528
11597
 
11598
+ this.activeCustomFilters = {};
11529
11599
  this.filter = options.filter ?? false;
11530
- this.toggleColumns = options.toggleColumns ?? false;
11531
11600
  this.customFilters = options.customFilters ?? false;
11532
- this.activeCustomFilters = {};
11601
+ this._toggleColumns = options.toggleColumns ?? false;
11533
11602
  this._currentFilter = options.filterValue;
11534
11603
 
11535
11604
  data.head = data.head ?? [];
@@ -11537,6 +11606,7 @@ class Table extends Widget {
11537
11606
  data.checkMap = { };
11538
11607
  data.colVisibilityMap = { };
11539
11608
  data.head.forEach( (col, index) => { data.colVisibilityMap[ index ] = true; });
11609
+ this.data = data;
11540
11610
 
11541
11611
  const compareFn = ( idx, order, a, b) => {
11542
11612
  if (a[idx] < b[idx]) return -order;
@@ -11550,7 +11620,7 @@ class Table extends Widget {
11550
11620
  };
11551
11621
 
11552
11622
  // Append header
11553
- if( this.filter || this.customFilters || this.toggleColumns )
11623
+ if( this.filter || this.customFilters || this._toggleColumns )
11554
11624
  {
11555
11625
  const headerContainer = LX.makeContainer( [ "100%", "auto" ], "flex flex-row" );
11556
11626
 
@@ -11662,7 +11732,7 @@ class Table extends Widget {
11662
11732
  this._resetCustomFiltersBtn.root.classList.add( "hidden" );
11663
11733
  }
11664
11734
 
11665
- if( this.toggleColumns )
11735
+ if( this._toggleColumns )
11666
11736
  {
11667
11737
  const icon = LX.makeIcon( "Settings2" );
11668
11738
  const toggleColumnsBtn = new LX.Button( "toggleColumnsBtn", icon.innerHTML + "View", (value, e) => {
@@ -11750,7 +11820,7 @@ class Table extends Widget {
11750
11820
  th.querySelector( "span" ).appendChild( LX.makeIcon( "MenuArrows", { svgClass: "sm" } ) );
11751
11821
 
11752
11822
  const idx = data.head.indexOf( headData );
11753
- if( this.centered && this.centered.indexOf( idx ) > -1 )
11823
+ if( this._centered?.indexOf && this._centered.indexOf( idx ) > -1 )
11754
11824
  {
11755
11825
  th.classList.add( "centered" );
11756
11826
  }
@@ -11760,7 +11830,7 @@ class Table extends Widget {
11760
11830
  { name: "Desc", icon: "ArrowDownAZ", callback: sortFn.bind( this, idx, -1 ) }
11761
11831
  ];
11762
11832
 
11763
- if( this.toggleColumns )
11833
+ if( this._toggleColumns )
11764
11834
  {
11765
11835
  menuOptions.push(
11766
11836
  null,
@@ -11822,6 +11892,9 @@ class Table extends Widget {
11822
11892
  // Origin row should go to the target row, and the rest should be moved up/down
11823
11893
  const fromIdx = rIdx - 1;
11824
11894
  const targetIdx = movePending[ 1 ] - 1;
11895
+
11896
+ LX.emit( "@on_table_sort", { instance: this, fromIdx, targetIdx } );
11897
+
11825
11898
  const b = data.body[ fromIdx ];
11826
11899
  let targetOffset = 0;
11827
11900
 
@@ -12027,7 +12100,7 @@ class Table extends Widget {
12027
12100
  td.innerHTML = `${ rowData }`;
12028
12101
 
12029
12102
  const idx = bodyData.indexOf( rowData );
12030
- if( this.centered && this.centered.indexOf( idx ) > -1 )
12103
+ if( this._centered?.indexOf && this._centered.indexOf( idx ) > -1 )
12031
12104
  {
12032
12105
  td.classList.add( "centered" );
12033
12106
  }
@@ -12117,8 +12190,50 @@ class Table extends Widget {
12117
12190
 
12118
12191
  LX.doAsync( this.onResize.bind( this ) );
12119
12192
  }
12193
+
12194
+ getSelectedRows() {
12195
+
12196
+ const selectedRows = [];
12197
+
12198
+ for( const row of this.data.body )
12199
+ {
12200
+ const rowId = LX.getSupportedDOMName( row.join( '-' ) ).substr( 0, 32 );
12201
+ if( this.data.checkMap[ rowId ] === true )
12202
+ {
12203
+ selectedRows.push( row );
12204
+ }
12205
+ }
12206
+
12207
+ return selectedRows;
12208
+ }
12209
+
12210
+ _setCentered( v ) {
12211
+
12212
+ if( v.constructor == Boolean )
12213
+ {
12214
+ const container = this.root.querySelector( ".lextable" );
12215
+ container.classList.toggle( "centered", v );
12216
+ }
12217
+ else
12218
+ {
12219
+ // Make sure this is an array containing which columns have
12220
+ // to be centered
12221
+ v = [].concat( v );
12222
+ }
12223
+
12224
+ this._centered = v;
12225
+
12226
+ this.refresh();
12227
+ }
12120
12228
  }
12121
12229
 
12230
+ Object.defineProperty( Table.prototype, "centered", {
12231
+ get: function() { return this._centered; },
12232
+ set: function( v ) { this._setCentered( v ); },
12233
+ enumerable: true,
12234
+ configurable: true
12235
+ });
12236
+
12122
12237
  LX.Table = Table;
12123
12238
 
12124
12239
  /**
@@ -12840,6 +12955,8 @@ class Panel {
12840
12955
  * hideName: Don't use name as label [false]
12841
12956
  * disabled: Make the widget disabled [false]
12842
12957
  * icon: Icon class to show as button value
12958
+ * fileInput: Button click requests a file
12959
+ * fileInputType: Type of the requested file
12843
12960
  * img: Path to image to show as button value
12844
12961
  * title: Text to show in native Element title
12845
12962
  * buttonClass: Class to add to the native button element
@@ -14180,6 +14297,13 @@ class Sidebar {
14180
14297
  info.appendChild( infoSubtext );
14181
14298
  }
14182
14299
 
14300
+ // Add icon if onHeaderPressed is defined and not collapsable (it uses the toggler icon)
14301
+ if( options.onHeaderPressed && !this.collapsable )
14302
+ {
14303
+ const icon = LX.makeIcon( "MenuArrows" );
14304
+ header.appendChild( icon );
14305
+ }
14306
+
14183
14307
  return header;
14184
14308
  }
14185
14309
 
@@ -14225,8 +14349,13 @@ class Sidebar {
14225
14349
  info.appendChild( infoSubtext );
14226
14350
  }
14227
14351
 
14228
- const icon = LX.makeIcon( "MenuArrows" );
14229
- footer.appendChild( icon );
14352
+ // Add icon if onFooterPressed is defined
14353
+ // Useful to indicate that the footer is clickable
14354
+ if( options.onFooterPressed )
14355
+ {
14356
+ const icon = LX.makeIcon( "MenuArrows" );
14357
+ footer.appendChild( icon );
14358
+ }
14230
14359
 
14231
14360
  return footer;
14232
14361
  }