lexgui 0.5.2 → 0.5.3

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
@@ -12,7 +12,7 @@ console.warn( 'Script _build/lexgui.js_ is depracated and will be removed soon.
12
12
  */
13
13
 
14
14
  var LX = {
15
- version: "0.5.2",
15
+ version: "0.5.3",
16
16
  ready: false,
17
17
  components: [], // Specific pre-build components
18
18
  signals: {}, // Events and triggers
@@ -1631,7 +1631,7 @@ class DropdownMenu {
1631
1631
  {
1632
1632
  f.call( this, key, menuItem, v );
1633
1633
  }
1634
- });
1634
+ }, { className: "accent" });
1635
1635
  const input = checkbox.root.querySelector( "input" );
1636
1636
  menuItem.prepend( input );
1637
1637
 
@@ -1795,7 +1795,7 @@ class Area {
1795
1795
  root.className += " " + options.className;
1796
1796
  }
1797
1797
 
1798
- var width = options.width || "calc( 100% )";
1798
+ var width = options.width || "100%";
1799
1799
  var height = options.height || "100%";
1800
1800
 
1801
1801
  // This has default options..
@@ -2387,7 +2387,7 @@ class Area {
2387
2387
 
2388
2388
  if( options.sticky ?? true )
2389
2389
  {
2390
- bar.root.classList.add( "sticky" );
2390
+ bar.root.className += " sticky top-0";
2391
2391
  }
2392
2392
 
2393
2393
  return menubar;
@@ -2484,7 +2484,8 @@ class Area {
2484
2484
  selected: b.selected,
2485
2485
  icon: b.icon,
2486
2486
  img: b.img,
2487
- className: b.class
2487
+ className: b.class ?? "",
2488
+ title: b.name
2488
2489
  };
2489
2490
 
2490
2491
  if( group )
@@ -2787,6 +2788,12 @@ class Tabs {
2787
2788
 
2788
2789
  this.area = area.sections[1];
2789
2790
  this.area.root.className += " lexareatabscontent";
2791
+
2792
+ if( options.contentClass )
2793
+ {
2794
+ this.area.root.className += ` ${ options.contentClass }`;
2795
+ }
2796
+
2790
2797
  this.selected = null;
2791
2798
  this.root = container;
2792
2799
  this.tabs = {};
@@ -2806,8 +2813,8 @@ class Tabs {
2806
2813
  var transition = this.thumb.style.transition;
2807
2814
  this.thumb.style.transition = "none";
2808
2815
  this.thumb.style.transform = "translate( " + ( tabEl.childIndex * tabEl.offsetWidth ) + "px )";
2809
- this.thumb.style.width = ( tabEl.offsetWidth - 5 ) + "px";
2810
- this.thumb.style.height = ( tabEl.offsetHeight - 6 ) + "px";
2816
+ this.thumb.style.width = ( tabEl.offsetWidth ) + "px";
2817
+ this.thumb.style.height = ( tabEl.offsetHeight ) + "px";
2811
2818
  flushCss( this.thumb );
2812
2819
  this.thumb.style.transition = transition;
2813
2820
  });
@@ -2979,8 +2986,8 @@ class Tabs {
2979
2986
  if( isSelected && this.thumb )
2980
2987
  {
2981
2988
  this.thumb.style.transform = "translate( " + ( tabEl.childIndex * tabEl.offsetWidth ) + "px )";
2982
- this.thumb.style.width = ( tabEl.offsetWidth - 5 ) + "px";
2983
- this.thumb.style.height = ( tabEl.offsetHeight - 6 ) + "px";
2989
+ this.thumb.style.width = ( tabEl.offsetWidth ) + "px";
2990
+ this.thumb.style.height = ( tabEl.offsetHeight ) + "px";
2984
2991
  this.thumb.item = tabEl;
2985
2992
  }
2986
2993
 
@@ -3744,12 +3751,11 @@ class SideBar {
3744
3751
  // Entry filter
3745
3752
  if( ( options.filter ?? false ) )
3746
3753
  {
3747
- const panel = new Panel();
3748
- panel.addText(null, "", (value, event) => {
3754
+ const filterTextInput = new TextInput(null, "", (value, event) => {
3749
3755
  this.filterString = value;
3750
3756
  this.update();
3751
- }, { placeholder: "Search...", icon: "fa-solid fa-magnifying-glass" });
3752
- this.filter = panel.root.childNodes[ 0 ];
3757
+ }, { inputClass: "outline", placeholder: "Search...", icon: "fa-solid fa-magnifying-glass", className: "lexsidebarfilter" });
3758
+ this.filter = filterTextInput.root;
3753
3759
  this.root.appendChild( this.filter );
3754
3760
  }
3755
3761
 
@@ -3772,7 +3778,7 @@ class SideBar {
3772
3778
  // Set width depending on header/footer
3773
3779
  doAsync( () => {
3774
3780
  // This account for header, footer and all inner paddings
3775
- const contentOffset = 32 + ( this.header?.offsetHeight ?? 0 ) +
3781
+ const contentOffset = ( this.header?.offsetHeight ?? 0 ) +
3776
3782
  ( this.filter?.offsetHeight ?? 0 ) +
3777
3783
  ( this.footer?.offsetHeight ?? 0 );
3778
3784
  this.content.style.height = `calc(100% - ${ contentOffset }px)`;
@@ -4144,7 +4150,7 @@ class SideBar {
4144
4150
  const f = options.callback;
4145
4151
  item.value = value;
4146
4152
  if( f ) f.call( this, key, value, event );
4147
- }, { label: key, signal: ( "@checkbox_" + key ) });
4153
+ }, { className: "accent", label: key, signal: ( "@checkbox_" + key ) });
4148
4154
  itemDom.appendChild( panel.root.childNodes[ 0 ] );
4149
4155
  }
4150
4156
  else
@@ -4384,8 +4390,6 @@ class Widget {
4384
4390
 
4385
4391
  if( type != Widget.TITLE )
4386
4392
  {
4387
- // root.style.width = "calc(100% - " + (this._currentBranch || type == Widget.FILE || type == Widget.TREE ? 10 : 20) + "px)";
4388
-
4389
4393
  if( options.width )
4390
4394
  {
4391
4395
  root.style.width = root.style.minWidth = options.width;
@@ -4421,6 +4425,7 @@ class Widget {
4421
4425
  domName.innerHTML = name;
4422
4426
  domName.title = options.title ?? domName.innerHTML;
4423
4427
  domName.style.width = options.nameWidth || LX.DEFAULT_NAME_WIDTH;
4428
+ domName.style.minWidth = domName.style.width;
4424
4429
 
4425
4430
  root.appendChild( domName );
4426
4431
  root.domName = domName;
@@ -4651,16 +4656,18 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4651
4656
  container.className = "lexcustomcontainer";
4652
4657
  container.style.width = "100%";
4653
4658
  element.appendChild( container );
4659
+ element.dataset["opened"] = false;
4654
4660
 
4655
- let buttonName = "<a class='fa-solid " + (options.icon ?? "fa-cube") + "' style='float:left'></a>";
4661
+ let buttonName = "<a class='fa-solid " + (options.icon ?? "fa-cube") + "'></a>";
4656
4662
  buttonName += customWidgetName + (!instance ? " [empty]" : "");
4657
4663
  // Add always icon to keep spacing right
4658
- buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu' style='float:right; width:5%;'></a>";
4664
+ buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu'></a>";
4659
4665
 
4660
4666
  let buttonEl = this.addButton(null, buttonName, (value, event) => {
4661
4667
  if( instance )
4662
4668
  {
4663
4669
  element.querySelector(".lexcustomitems").toggleAttribute('hidden');
4670
+ element.dataset["opened"] = !element.querySelector(".lexcustomitems").hasAttribute("hidden");
4664
4671
  }
4665
4672
  else
4666
4673
  {
@@ -4669,6 +4676,7 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4669
4676
  instance = {};
4670
4677
  refresh_widget();
4671
4678
  element.querySelector(".lexcustomitems").toggleAttribute('hidden', false);
4679
+ element.dataset["opened"] = !element.querySelector(".lexcustomitems").hasAttribute("hidden");
4672
4680
  });
4673
4681
  });
4674
4682
  }
@@ -4783,7 +4791,7 @@ class NodeTree {
4783
4791
  _createItem( parent, node, level = 0, selectedId ) {
4784
4792
 
4785
4793
  const that = this;
4786
- const nodeFilterInput = this.domEl.querySelector( "#lexnodetree_filter" );
4794
+ const nodeFilterInput = this.domEl.querySelector( ".lexnodetree_filter" );
4787
4795
 
4788
4796
  node.children = node.children ?? [];
4789
4797
  if( nodeFilterInput && nodeFilterInput.value != "" && !node.id.includes( nodeFilterInput.value ) )
@@ -5362,14 +5370,7 @@ class TextInput extends Widget {
5362
5370
 
5363
5371
  this._lastValueTriggered = value = newValue;
5364
5372
 
5365
- if( options.disabled )
5366
- {
5367
- wValue.innerText = newValue;
5368
- }
5369
- else
5370
- {
5371
- wValue.value = newValue;
5372
- }
5373
+ wValue.value = newValue;
5373
5374
 
5374
5375
  if( !skipCallback )
5375
5376
  {
@@ -5390,21 +5391,17 @@ class TextInput extends Widget {
5390
5391
  };
5391
5392
 
5392
5393
  let container = document.createElement( 'div' );
5393
- container.className = "lextext" + ( options.warning ? " lexwarning" : "" );
5394
+ container.className = ( options.warning ? " lexwarning" : "" );
5394
5395
  container.style.display = "flex";
5395
5396
  this.root.appendChild( container );
5396
5397
 
5397
- if( options.textClass )
5398
- {
5399
- container.classList.add( options.textClass );
5400
- }
5401
-
5402
5398
  this.disabled = ( options.disabled || options.warning ) ?? ( options.url ? true : false );
5403
5399
  let wValue = null;
5404
5400
 
5405
5401
  if( !this.disabled )
5406
5402
  {
5407
5403
  wValue = document.createElement( 'input' );
5404
+ wValue.className = "lextext " + ( options.inputClass ?? "" );
5408
5405
  wValue.type = options.type || "";
5409
5406
  wValue.value = wValue.iValue = value || "";
5410
5407
  wValue.style.width = "100%";
@@ -5457,21 +5454,29 @@ class TextInput extends Widget {
5457
5454
  }
5458
5455
 
5459
5456
  }
5460
- else
5457
+ else if( options.url )
5461
5458
  {
5462
- wValue = document.createElement( options.url ? 'a' : 'div' );
5463
-
5464
- if( options.url )
5465
- {
5466
- wValue.href = options.url;
5467
- wValue.target = "_blank";
5468
- }
5459
+ wValue = document.createElement( 'a' );
5460
+ wValue.href = options.url;
5461
+ wValue.target = "_blank";
5469
5462
 
5470
5463
  const icon = options.warning ? '<i class="fa-solid fa-triangle-exclamation"></i>' : '';
5471
5464
  wValue.innerHTML = ( icon + value ) || "";
5472
5465
  wValue.style.width = "100%";
5473
5466
  wValue.style.textAlign = options.float ?? "";
5474
- wValue.className = "ellipsis-overflow";
5467
+ wValue.className = "lextext ellipsis-overflow";
5468
+ }
5469
+ else
5470
+ {
5471
+ wValue = document.createElement( 'input' );
5472
+
5473
+ const icon = options.warning ? '<i class="fa-solid fa-triangle-exclamation"></i>' : '';
5474
+ wValue.disabled = true;
5475
+ wValue.innerHTML = icon;
5476
+ wValue.value = value;
5477
+ wValue.style.width = "100%";
5478
+ wValue.style.textAlign = options.float ?? "";
5479
+ wValue.className = "lextext ellipsis-overflow " + ( options.inputClass ?? "" );
5475
5480
  }
5476
5481
 
5477
5482
  Object.assign( wValue.style, options.style ?? {} );
@@ -5602,6 +5607,12 @@ class Button extends Widget {
5602
5607
  var wValue = document.createElement( 'button' );
5603
5608
  wValue.title = options.title ?? "";
5604
5609
  wValue.className = "lexbutton " + ( options.buttonClass ?? "" );
5610
+
5611
+ if( options.icon )
5612
+ {
5613
+ wValue.classList.add( "justify-center" );
5614
+ }
5615
+
5605
5616
  this.root.appendChild( wValue );
5606
5617
 
5607
5618
  if( options.selected )
@@ -5908,7 +5919,7 @@ class Form extends Widget {
5908
5919
  }
5909
5920
 
5910
5921
  entryData.placeholder = entryData.placeholder ?? entry;
5911
- entryData.width = "calc(100% - 10px)";
5922
+ entryData.width = "100%";
5912
5923
 
5913
5924
  // this.addLabel( entry, { textClass: "formlabel" } );
5914
5925
 
@@ -5938,7 +5949,7 @@ class Form extends Widget {
5938
5949
  {
5939
5950
  callback( container.formData, event );
5940
5951
  }
5941
- }, { buttonClass: "primary", width: "calc(100% - 10px)" } );
5952
+ }, { buttonClass: "primary" } );
5942
5953
 
5943
5954
  container.appendChild( submitButton.root );
5944
5955
  }
@@ -5981,7 +5992,7 @@ class Select extends Widget {
5981
5992
  // Reset filter
5982
5993
  if( filter )
5983
5994
  {
5984
- filter.querySelector( "input" ).value = "";
5995
+ filter.root.querySelector( "input" ).value = "";
5985
5996
  const filteredOptions = this._filterOptions( values, "" );
5986
5997
  list.refresh( filteredOptions );
5987
5998
  }
@@ -6008,7 +6019,7 @@ class Select extends Widget {
6008
6019
 
6009
6020
  // Add select widget button
6010
6021
  let buttonName = value;
6011
- buttonName += "<a class='fa-solid fa-angle-down' style='float:right; margin-right: 3px;'></a>";
6022
+ buttonName += "<a class='fa-solid fa-angle-down'></a>";
6012
6023
 
6013
6024
  const _placeOptions = ( parent ) => {
6014
6025
 
@@ -6034,6 +6045,7 @@ class Select extends Widget {
6034
6045
  {
6035
6046
  const rect = nestedDialog.getBoundingClientRect();
6036
6047
  topPosition -= rect.y;
6048
+ maxY -= rect.y;
6037
6049
  }
6038
6050
 
6039
6051
  parent.style.top = ( topPosition + selectRoot.offsetHeight ) + 'px';
@@ -6099,7 +6111,7 @@ class Select extends Widget {
6099
6111
 
6100
6112
  if( filter )
6101
6113
  {
6102
- filter.querySelector( "input" ).focus();
6114
+ filter.root.querySelector( "input" ).focus();
6103
6115
  }
6104
6116
 
6105
6117
  }, { buttonClass: "array", skipInlineCount: true, disabled: options.disabled } );
@@ -6138,7 +6150,7 @@ class Select extends Widget {
6138
6150
  this.unfocus_event = true;
6139
6151
  setTimeout( () => delete this.unfocus_event, 200 );
6140
6152
  }
6141
- else if ( e.relatedTarget && e.relatedTarget.tagName == "INPUT" )
6153
+ else if ( e.relatedTarget && ( e.relatedTarget.tagName == "INPUT" || e.relatedTarget.classList.contains("lexoptions") ) )
6142
6154
  {
6143
6155
  return;
6144
6156
  }
@@ -6159,12 +6171,13 @@ class Select extends Widget {
6159
6171
  filterOptions.trigger = "input";
6160
6172
  filterOptions.icon = "fa-solid fa-magnifying-glass";
6161
6173
  filterOptions.className = "lexfilter";
6174
+ filterOptions.inputClass = "outline";
6162
6175
 
6163
- let filter = new TextInput(null, options.filterValue ?? "", ( v ) => {
6176
+ filter = new TextInput(null, options.filterValue ?? "", ( v ) => {
6164
6177
  const filteredOptions = this._filterOptions( values, v );
6165
6178
  list.refresh( filteredOptions );
6166
6179
  }, filterOptions );
6167
- filter.root.querySelector( ".lextext" ).classList.remove( "lextext" );
6180
+ filter.root.querySelector( ".lextext" ).style.border = "1px solid transparent";
6168
6181
 
6169
6182
  const input = filter.root.querySelector( "input" );
6170
6183
 
@@ -6185,12 +6198,12 @@ class Select extends Widget {
6185
6198
  list.appendChild( listOptions );
6186
6199
 
6187
6200
  // Add select options list
6188
- list.refresh = ( options ) => {
6201
+ list.refresh = ( currentOptions ) => {
6189
6202
 
6190
6203
  // Empty list
6191
6204
  listOptions.innerHTML = "";
6192
6205
 
6193
- if( !options.length )
6206
+ if( !currentOptions.length )
6194
6207
  {
6195
6208
  let iValue = options.emptyMsg ?? "No options found.";
6196
6209
 
@@ -6206,9 +6219,9 @@ class Select extends Widget {
6206
6219
  return;
6207
6220
  }
6208
6221
 
6209
- for( let i = 0; i < options.length; i++ )
6222
+ for( let i = 0; i < currentOptions.length; i++ )
6210
6223
  {
6211
- let iValue = options[ i ];
6224
+ let iValue = currentOptions[ i ];
6212
6225
  let li = document.createElement( "li" );
6213
6226
  let option = document.createElement( "div" );
6214
6227
  option.className = "option";
@@ -6533,13 +6546,15 @@ class ItemArray extends Widget {
6533
6546
  container.className = "lexarray";
6534
6547
  container.style.width = "100%";
6535
6548
  this.root.appendChild( container );
6549
+ this.root.dataset["opened"] = false;
6536
6550
 
6537
- const angleDown = `<a class='fa-solid fa-angle-down' style='float:right; margin-right: 3px;'></a>`;
6551
+ const angleDown = `<a class='fa-solid fa-angle-down'></a>`;
6538
6552
 
6539
6553
  let buttonName = "Array (size " + values.length + ")";
6540
6554
  buttonName += angleDown;
6541
6555
 
6542
6556
  const toggleButton = new Button(null, buttonName, () => {
6557
+ this.root.dataset["opened"] = this.root.dataset["opened"] == "true" ? false : true;
6543
6558
  this.root.querySelector(".lexarrayitems").toggleAttribute('hidden');
6544
6559
  }, { buttonClass: 'array' });
6545
6560
  container.appendChild( toggleButton.root );
@@ -6603,7 +6618,7 @@ class ItemArray extends Widget {
6603
6618
  }
6604
6619
 
6605
6620
  buttonName = "Add item";
6606
- buttonName += "<a class='fa-solid fa-plus' style='float:right; margin-right: 3px; margin-top: 2px;'></a>";
6621
+ buttonName += "<a class='fa-solid fa-plus'></a>";
6607
6622
 
6608
6623
  const addButton = new Button(null, buttonName, (v, event) => {
6609
6624
  values.push( options.innerValues ? options.innerValues[ 0 ] : "" );
@@ -6853,7 +6868,7 @@ class Checkbox extends Widget {
6853
6868
 
6854
6869
  let checkbox = document.createElement( "input" );
6855
6870
  checkbox.type = "checkbox";
6856
- checkbox.className = "lexcheckbox " + ( options.className ?? "" );
6871
+ checkbox.className = "lexcheckbox " + ( options.className ?? "primary" );
6857
6872
  checkbox.checked = value;
6858
6873
  checkbox.disabled = options.disabled ?? false;
6859
6874
  container.appendChild( checkbox );
@@ -7074,8 +7089,7 @@ class ColorInput extends Widget {
7074
7089
  newValue = hexToRgb( newValue );
7075
7090
  }
7076
7091
 
7077
- // Means it was called from the color input listener, not the text
7078
- if( event )
7092
+ if( !this._skipTextUpdate )
7079
7093
  {
7080
7094
  textWidget.set( newValue, true, event );
7081
7095
  }
@@ -7101,9 +7115,8 @@ class ColorInput extends Widget {
7101
7115
  color.style.width = "32px";
7102
7116
  color.type = 'color';
7103
7117
  color.className = "colorinput";
7104
- color.id = "color" + simple_guidGenerator();
7105
7118
  color.useRGB = options.useRGB ?? false;
7106
- color.value = color.iValue = value;
7119
+ color.value = value;
7107
7120
  container.appendChild( color );
7108
7121
 
7109
7122
  if( options.disabled )
@@ -7116,8 +7129,10 @@ class ColorInput extends Widget {
7116
7129
  }, false );
7117
7130
 
7118
7131
  const textWidget = new TextInput( null, color.value, v => {
7132
+ this._skipTextUpdate = true;
7119
7133
  this.set( v );
7120
- }, { width: "calc( 100% - 32px )"});
7134
+ delete this._skipTextUpdate;
7135
+ }, { width: "calc( 100% - 32px )", disabled: options.disabled });
7121
7136
 
7122
7137
  textWidget.root.style.marginLeft = "4px";
7123
7138
  container.appendChild( textWidget.root );
@@ -7169,12 +7184,23 @@ class RangeInput extends Widget {
7169
7184
 
7170
7185
  let slider = document.createElement( 'input' );
7171
7186
  slider.className = "lexrangeslider " + ( options.className ?? "" );
7172
- slider.value = slider.iValue = value;
7173
7187
  slider.min = options.min ?? 0;
7174
7188
  slider.max = options.max ?? 100;
7175
7189
  slider.step = options.step ?? 1;
7176
7190
  slider.type = "range";
7177
7191
  slider.disabled = options.disabled ?? false;
7192
+
7193
+ if( value.constructor == Number )
7194
+ {
7195
+ value = clamp( value, +slider.min, +slider.max );
7196
+ }
7197
+
7198
+ if( options.left )
7199
+ {
7200
+ value = ( ( +slider.max ) - value + ( +slider.min ) );
7201
+ }
7202
+
7203
+ slider.value = value;
7178
7204
  container.appendChild( slider );
7179
7205
 
7180
7206
  if( options.left ?? false )
@@ -7213,11 +7239,6 @@ class RangeInput extends Widget {
7213
7239
  Widget._dispatchEvent( slider, "input", true );
7214
7240
  };
7215
7241
 
7216
- if( value.constructor == Number )
7217
- {
7218
- value = clamp( value, +slider.min, +slider.max );
7219
- }
7220
-
7221
7242
  doAsync( this.onResize.bind( this ) );
7222
7243
  }
7223
7244
  }
@@ -8139,7 +8160,7 @@ class FileInput extends Widget {
8139
8160
  {
8140
8161
  let settingsDialog = null;
8141
8162
 
8142
- const settingButton = new Button(null, "<a style='margin-top: 0px;' class='fa-solid fa-gear'></a>", () => {
8163
+ const settingButton = new Button(null, "", () => {
8143
8164
 
8144
8165
  if( settingsDialog )
8145
8166
  {
@@ -8151,7 +8172,7 @@ class FileInput extends Widget {
8151
8172
  p.addButton( null, "Reload", v => { input.dispatchEvent( new Event( 'change' ) ) } );
8152
8173
  }, { onclose: ( root ) => { root.remove(); settingsDialog = null; } } );
8153
8174
 
8154
- }, { className: "micro", skipInlineCount: true, title: "Settings" });
8175
+ }, { skipInlineCount: true, title: "Settings", disabled: options.disabled, icon: "fa-solid fa-gear" });
8155
8176
 
8156
8177
  this.root.appendChild( settingButton.root );
8157
8178
  }
@@ -8214,9 +8235,9 @@ class Tree extends Widget {
8214
8235
  if( options.filter )
8215
8236
  {
8216
8237
  nodeFilterInput = document.createElement('input');
8217
- nodeFilterInput.id = "lexnodetree_filter";
8238
+ nodeFilterInput.className = "lexnodetree_filter";
8218
8239
  nodeFilterInput.setAttribute("placeholder", "Filter..");
8219
- nodeFilterInput.style.width = "calc( 100% - 17px )";
8240
+ nodeFilterInput.style.width = "100%";
8220
8241
  nodeFilterInput.addEventListener('input', () => {
8221
8242
  this.innerTree.refresh();
8222
8243
  });
@@ -8366,11 +8387,11 @@ class Counter extends Widget {
8366
8387
  container.className = "lexcounter";
8367
8388
  this.root.appendChild( container );
8368
8389
 
8369
- const substrButton = new Button(null, "<a style='margin-top: 0px;' class='fa-solid fa-minus'></a>", ( value, e ) => {
8390
+ const substrButton = new Button(null, "", ( value, e ) => {
8370
8391
  let mult = step ?? 1;
8371
8392
  if( e.shiftKey ) mult *= 10;
8372
8393
  this.set( counterText.count - mult, false, e );
8373
- }, { className: "micro", skipInlineCount: true, title: "Minus" });
8394
+ }, { skipInlineCount: true, title: "Minus", icon: "fa-solid fa-minus" });
8374
8395
 
8375
8396
  container.appendChild( substrButton.root );
8376
8397
 
@@ -8392,11 +8413,11 @@ class Counter extends Widget {
8392
8413
  containerBox.appendChild( counterLabel );
8393
8414
  }
8394
8415
 
8395
- const addButton = new Button(null, "<a style='margin-top: 0px;' class='fa-solid fa-plus'></a>", ( value, e ) => {
8416
+ const addButton = new Button(null, "", ( value, e ) => {
8396
8417
  let mult = step ?? 1;
8397
8418
  if( e.shiftKey ) mult *= 10;
8398
8419
  this.set( counterText.count + mult, false, e );
8399
- }, { className: "micro", skipInlineCount: true, title: "Plus" });
8420
+ }, { skipInlineCount: true, title: "Plus", icon: "fa-solid fa-plus" });
8400
8421
  container.appendChild( addButton.root );
8401
8422
  }
8402
8423
  }
@@ -8467,7 +8488,7 @@ class Table extends Widget {
8467
8488
  filterOptions.placeholder = `Filter ${ this.filter }...`;
8468
8489
  filterOptions.skipWidget = true;
8469
8490
  filterOptions.trigger = "input";
8470
- filterOptions.textClass = "outline";
8491
+ filterOptions.inputClass = "outline";
8471
8492
 
8472
8493
  let filter = new TextInput(null, "", ( v ) => {
8473
8494
  this._currentFilter = v;
@@ -8500,7 +8521,7 @@ class Table extends Widget {
8500
8521
  return item;
8501
8522
  } );
8502
8523
  new DropdownMenu( customFilterBtn.root, menuOptions, { side: "bottom", align: "start" });
8503
- }, { buttonClass: "dashed" } );
8524
+ }, { buttonClass: " primary dashed" } );
8504
8525
  headerContainer.appendChild( customFilterBtn.root );
8505
8526
  }
8506
8527
 
@@ -8575,7 +8596,7 @@ class Table extends Widget {
8575
8596
  th.style.width = "0px";
8576
8597
  const input = document.createElement( 'input' );
8577
8598
  input.type = "checkbox";
8578
- input.className = "lexcheckbox";
8599
+ input.className = "lexcheckbox accent";
8579
8600
  input.checked = data.checkMap[ ":root" ] ?? false;
8580
8601
  th.appendChild( input );
8581
8602
 
@@ -8742,7 +8763,7 @@ class Table extends Widget {
8742
8763
 
8743
8764
  const row = document.createElement( 'tr' );
8744
8765
  const rowId = LX.getSupportedDOMName( bodyData.join( '-' ) );
8745
- row.setAttribute( "rowId", rowId.substr(0, 16) );
8766
+ row.setAttribute( "rowId", rowId.substr(0, 32) );
8746
8767
 
8747
8768
  if( options.sortable )
8748
8769
  {
@@ -8793,7 +8814,7 @@ class Table extends Widget {
8793
8814
  const td = document.createElement( 'td' );
8794
8815
  const input = document.createElement( 'input' );
8795
8816
  input.type = "checkbox";
8796
- input.className = "lexcheckbox";
8817
+ input.className = "lexcheckbox accent";
8797
8818
  input.checked = data.checkMap[ rowId ];
8798
8819
  td.appendChild( input );
8799
8820
 
@@ -8940,7 +8961,7 @@ class Panel {
8940
8961
  root.className += " " + options.className;
8941
8962
  }
8942
8963
 
8943
- root.style.width = options.width || "calc( 100% - 6px )";
8964
+ root.style.width = options.width || "100%";
8944
8965
  root.style.height = options.height || "100%";
8945
8966
  Object.assign( root.style, options.style ?? {} );
8946
8967
 
@@ -9055,10 +9076,11 @@ class Panel {
9055
9076
 
9056
9077
  /**
9057
9078
  * @method endLine
9079
+ * @param {String} className Extra class to customize inline widgets parent container
9058
9080
  * @description Stop inlining widgets. Use it only if the number of widgets to be inlined is NOT specified.
9059
9081
  */
9060
9082
 
9061
- endLine( justifyContent ) {
9083
+ endLine( className ) {
9062
9084
 
9063
9085
  if( this._inlineWidgetsLeft == -1 )
9064
9086
  {
@@ -9073,9 +9095,9 @@ class Panel {
9073
9095
  this._inlineContainer = document.createElement('div');
9074
9096
  this._inlineContainer.className = "lexinlinewidgets";
9075
9097
 
9076
- if( justifyContent )
9098
+ if( className )
9077
9099
  {
9078
- this._inlineContainer.style.justifyContent = justifyContent;
9100
+ this._inlineContainer.className += ` ${ className }`;
9079
9101
  }
9080
9102
  }
9081
9103
 
@@ -9218,7 +9240,7 @@ class Panel {
9218
9240
  }
9219
9241
  else
9220
9242
  {
9221
- el.classList.add("nobranch");
9243
+ el.className += " nobranch w-full";
9222
9244
  this.root.appendChild( el );
9223
9245
  }
9224
9246
  }
@@ -9282,7 +9304,7 @@ class Panel {
9282
9304
  let input = document.createElement('input');
9283
9305
  input.className = 'lexinput-filter';
9284
9306
  input.setAttribute( "placeholder", options.placeholder );
9285
- input.style.width = "calc( 100% - 17px )";
9307
+ input.style.width = "100%";
9286
9308
  input.value = options.filterValue || "";
9287
9309
 
9288
9310
  let searchIcon = document.createElement('a');
@@ -9460,6 +9482,7 @@ class Panel {
9460
9482
  * pattern: Regular expression that value must match
9461
9483
  * trigger: Choose onchange trigger (default, input) [default]
9462
9484
  * inputWidth: Width of the text input
9485
+ * inputClass: Class to add to the native input element
9463
9486
  * skipReset: Don't add the reset value button when value changes
9464
9487
  * float: Justify input text content
9465
9488
  * justifyName: Justify name content
@@ -9499,6 +9522,7 @@ class Panel {
9499
9522
 
9500
9523
  addLabel( value, options = {} ) {
9501
9524
  options.disabled = true;
9525
+ options.inputClass = ( options.inputClass ?? "" ) + " nobg";
9502
9526
  const widget = this.addText( null, value, null, options );
9503
9527
  widget.type = Widget.LABEL;
9504
9528
  return widget;
@@ -9515,6 +9539,7 @@ class Panel {
9515
9539
  * icon: Icon class to show as button value
9516
9540
  * img: Path to image to show as button value
9517
9541
  * title: Text to show in native Element title
9542
+ * buttonClass: Class to add to the native button element
9518
9543
  */
9519
9544
 
9520
9545
  addButton( name, value, callback, options = {} ) {
@@ -10054,7 +10079,6 @@ class Branch {
10054
10079
  root.className += " " + options.className;
10055
10080
  }
10056
10081
 
10057
- root.style.width = "calc(100% - 7px)";
10058
10082
  root.style.margin = "0 auto";
10059
10083
 
10060
10084
  var that = this;
@@ -10092,7 +10116,7 @@ class Branch {
10092
10116
  this.grabber.setAttribute( "hidden", true );
10093
10117
  doAsync( () => {
10094
10118
  this.content.setAttribute( "hidden", true );
10095
- }, 15 );
10119
+ }, 10 );
10096
10120
  }
10097
10121
 
10098
10122
  this.onclick = function( e ) {
@@ -10242,6 +10266,7 @@ class Branch {
10242
10266
  let value = element.children[ 1 ];
10243
10267
 
10244
10268
  name.style.width = size;
10269
+ name.style.minWidth = size;
10245
10270
 
10246
10271
  switch( widget.type )
10247
10272
  {
@@ -10276,7 +10301,8 @@ class Footer {
10276
10301
  root.className = "lexfooter";
10277
10302
 
10278
10303
  const wrapper = document.createElement( "div" );
10279
- wrapper.className = "wrapper";
10304
+ wrapper.style.minHeight = "48px";
10305
+ wrapper.className = "w-full";
10280
10306
  root.appendChild( wrapper );
10281
10307
 
10282
10308
  if( options.columns && options.columns.constructor == Array )
@@ -10351,6 +10377,10 @@ class Footer {
10351
10377
  // Append directly to body
10352
10378
  const parent = options.parent ?? document.body;
10353
10379
  parent.appendChild( root );
10380
+
10381
+ // Set always at bottom
10382
+ root.previousElementSibling.style.height = "unset";
10383
+ root.previousElementSibling.style.flexGrow = "1";
10354
10384
  }
10355
10385
 
10356
10386
  }
@@ -10549,7 +10579,6 @@ class Dialog {
10549
10579
  root.style.left = position[ 0 ] ?? "50%";
10550
10580
  root.style.top = position[ 1 ] ?? "50%";
10551
10581
 
10552
- panel.root.style.width = "calc( 100% - 30px )";
10553
10582
  panel.root.style.height = title ? "calc( 100% - " + ( titleDiv.offsetHeight + 30 ) + "px )" : "calc( 100% - 51px )";
10554
10583
  }
10555
10584
 
@@ -10621,8 +10650,8 @@ class PocketDialog extends Dialog {
10621
10650
  this.root.style.top = dragMargin + "px";
10622
10651
  }
10623
10652
 
10624
- this.panel.root.style.width = "calc( 100% - 12px )";
10625
- this.panel.root.style.height = "calc( 100% - 40px )";
10653
+ this.panel.root.style.width = "100%";
10654
+ this.panel.root.style.height = "100%";
10626
10655
  this.dock_pos = PocketDialog.TOP;
10627
10656
 
10628
10657
  this.minimized = false;
@@ -12028,11 +12057,15 @@ class AssetView {
12028
12057
  this.rightPanel.sameLine();
12029
12058
  this.rightPanel.addSelect( "Filter", this.allowedTypes, this.allowedTypes[ 0 ], v => this._refreshContent.call(this, null, v), { width: "30%", minWidth: "128px" } );
12030
12059
  this.rightPanel.addText( null, this.searchValue ?? "", v => this._refreshContent.call(this, v, null), { placeholder: "Search assets.." } );
12031
- this.rightPanel.addButton( null, "<a class='fa fa-arrow-up-short-wide'></a>", on_sort.bind(this), { className: "micro", title: "Sort" } );
12032
- this.rightPanel.addButton( null, "<a class='fa-solid fa-grip'></a>", on_change_view.bind(this), { className: "micro", title: "View" } );
12060
+ this.rightPanel.addButton( null, "<a class='fa fa-arrow-up-short-wide'></a>", on_sort.bind(this), { title: "Sort" } );
12061
+ this.rightPanel.addButton( null, "<a class='fa-solid fa-grip'></a>", on_change_view.bind(this), { title: "View" } );
12033
12062
  // Content Pages
12034
- this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-left'></a>", on_change_page.bind(this, -1), { className: "micro", title: "Previous Page" } );
12035
- this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-right'></a>", on_change_page.bind(this, 1), { className: "micro", title: "Next Page" } );
12063
+ this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-left'></a>", on_change_page.bind(this, -1), { title: "Previous Page", className: "ml-auto" } );
12064
+ this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-right'></a>", on_change_page.bind(this, 1), { title: "Next Page" } );
12065
+ const textString = "Page " + this.contentPage + " / " + ((((this.currentData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1);
12066
+ this.rightPanel.addText(null, textString, null, {
12067
+ inputClass: "nobg", disabled: true, signal: "@on_page_change", maxWidth: "16ch" }
12068
+ );
12036
12069
  this.rightPanel.endLine();
12037
12070
 
12038
12071
  if( !this.skipBrowser )
@@ -12066,9 +12099,13 @@ class AssetView {
12066
12099
  icon: "fa-solid fa-arrows-rotate",
12067
12100
  callback: domEl => { this._refreshContent(); }
12068
12101
  }
12069
- ], { width: "20%", minWidth: "164px", noSelection: true } );
12070
- this.rightPanel.addText(null, this.path.join('/'), null, { width: "70%", maxWidth: "calc(70% - 64px)", minWidth: "164px", disabled: true, signal: "@on_folder_change", style: { fontWeight: "bolder", fontSize: "16px", color: "#aaa" } });
12071
- this.rightPanel.addText(null, "Page " + this.contentPage + " / " + ((((this.currentData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1), null, {disabled: true, signal: "@on_page_change", width: "fit-content"})
12102
+ ], { noSelection: true } );
12103
+
12104
+ this.rightPanel.addText(null, this.path.join('/'), null, {
12105
+ inputClass: "nobg", disabled: true, signal: "@on_folder_change",
12106
+ style: { fontWeight: "600", fontSize: "15px" }
12107
+ });
12108
+
12072
12109
  this.rightPanel.endLine();
12073
12110
  }
12074
12111
 
@@ -12346,7 +12383,9 @@ class AssetView {
12346
12383
  }
12347
12384
 
12348
12385
  this.allowNextPage = filteredData.length - 1 > AssetView.MAX_PAGE_ELEMENTS;
12349
- LX.emit("@on_page_change", "Page " + this.contentPage + " / " + ((((filteredData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1));
12386
+
12387
+ const textString = "Page " + this.contentPage + " / " + ((((filteredData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1);
12388
+ LX.emit( "@on_page_change", textString );
12350
12389
 
12351
12390
  if( this.onRefreshContent )
12352
12391
  {