lexgui 0.5.1 → 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.
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  var LX = {
9
- version: "0.5.1",
9
+ version: "0.5.3",
10
10
  ready: false,
11
11
  components: [], // Specific pre-build components
12
12
  signals: {}, // Events and triggers
@@ -46,7 +46,7 @@ else if( typeof Date != "undefined" && Date.now )
46
46
  else if ( typeof process != "undefined" )
47
47
  {
48
48
  LX.getTime = function() {
49
- var t = process.hrtime();
49
+ const t = process.hrtime();
50
50
  return t[ 0 ] * 0.001 + t[ 1 ] * 1e-6;
51
51
  };
52
52
  }
@@ -148,7 +148,7 @@ LX.setTheme = setTheme;
148
148
  */
149
149
  function setThemeColor( colorName, color )
150
150
  {
151
- var r = document.querySelector( ':root' );
151
+ const r = document.querySelector( ':root' );
152
152
  r.style.setProperty( '--' + colorName, color );
153
153
  }
154
154
 
@@ -190,10 +190,10 @@ LX.getThemeColor = getThemeColor;
190
190
  */
191
191
  function getBase64Image( img )
192
192
  {
193
- var canvas = document.createElement( 'canvas' );
193
+ const canvas = document.createElement( 'canvas' );
194
194
  canvas.width = img.width;
195
195
  canvas.height = img.height;
196
- var ctx = canvas.getContext( '2d' );
196
+ const ctx = canvas.getContext( '2d' );
197
197
  ctx.drawImage( img, 0, 0 );
198
198
  return canvas.toDataURL( 'image/png' );
199
199
  }
@@ -958,8 +958,8 @@ function init( options = { } )
958
958
  this.root = root;
959
959
  this.container = document.body;
960
960
 
961
- this.modal.classList.add( 'hiddenOpacity' );
962
- this.modal.toggle = function( force ) { this.classList.toggle( 'hiddenOpacity', force ); };
961
+ this.modal.classList.add( 'hidden-opacity' );
962
+ this.modal.toggle = function( force ) { this.classList.toggle( 'hidden-opacity', force ); };
963
963
 
964
964
  if( options.container )
965
965
  {
@@ -1035,6 +1035,17 @@ function init( options = { } )
1035
1035
  this.DEFAULT_SPLITBAR_SIZE = 4;
1036
1036
  this.OPEN_CONTEXTMENU_ENTRY = 'click';
1037
1037
 
1038
+ this.widgetResizeObserver = new ResizeObserver( entries => {
1039
+ for ( const entry of entries )
1040
+ {
1041
+ const widget = entry.target?.jsInstance;
1042
+ if( widget && widget.onResize )
1043
+ {
1044
+ widget.onResize( entry.contentRect );
1045
+ }
1046
+ }
1047
+ });
1048
+
1038
1049
  this.ready = true;
1039
1050
  this.menubars = [ ];
1040
1051
 
@@ -1478,6 +1489,7 @@ class DropdownMenu {
1478
1489
  }
1479
1490
 
1480
1491
  this._trigger = trigger;
1492
+ trigger.classList.add( "triggered" );
1481
1493
  trigger.ddm = this;
1482
1494
 
1483
1495
  this._items = items;
@@ -1504,7 +1516,7 @@ class DropdownMenu {
1504
1516
  this.root.focus();
1505
1517
 
1506
1518
  this._onClick = e => {
1507
- if( e.target && ( e.target.className.includes( "lexdropdown" ) || e.target == this._trigger ) )
1519
+ if( e.target && ( this.root.contains( e.target ) || e.target == this._trigger ) )
1508
1520
  {
1509
1521
  return;
1510
1522
  }
@@ -1517,6 +1529,8 @@ class DropdownMenu {
1517
1529
 
1518
1530
  destroy() {
1519
1531
 
1532
+ this._trigger.classList.remove( "triggered" );
1533
+
1520
1534
  delete this._trigger.ddm;
1521
1535
 
1522
1536
  document.body.removeEventListener( "click", this._onClick );
@@ -1582,12 +1596,6 @@ class DropdownMenu {
1582
1596
  menuItem.id = pKey;
1583
1597
  menuItem.innerHTML = `<span>${ key }</span>`;
1584
1598
 
1585
- if( item.icon )
1586
- {
1587
- const icon = LX.makeIcon( item.icon );
1588
- menuItem.prepend( icon );
1589
- }
1590
-
1591
1599
  menuItem.tabIndex = "1";
1592
1600
  parentDom.appendChild( menuItem );
1593
1601
 
@@ -1603,15 +1611,41 @@ class DropdownMenu {
1603
1611
  menuItem.appendChild( submenuIcon );
1604
1612
  }
1605
1613
 
1606
- menuItem.addEventListener( "click", () => {
1607
- const f = item[ 'callback' ];
1608
- if( f )
1609
- {
1610
- f.call( this, key, menuItem );
1611
- }
1614
+ if( item.icon )
1615
+ {
1616
+ const icon = LX.makeIcon( item.icon );
1617
+ menuItem.prepend( icon );
1618
+ }
1612
1619
 
1613
- this.destroy();
1614
- } );
1620
+ if( item.checked != undefined )
1621
+ {
1622
+ const checkbox = new Checkbox( pKey + "_entryChecked", item.checked, (v) => {
1623
+ const f = item[ 'callback' ];
1624
+ if( f )
1625
+ {
1626
+ f.call( this, key, menuItem, v );
1627
+ }
1628
+ }, { className: "accent" });
1629
+ const input = checkbox.root.querySelector( "input" );
1630
+ menuItem.prepend( input );
1631
+
1632
+ menuItem.addEventListener( "click", (e) => {
1633
+ if( e.target.type == "checkbox" ) return;
1634
+ input.checked = !input.checked;
1635
+ checkbox.set( input.checked );
1636
+ } );
1637
+ }
1638
+ else
1639
+ {
1640
+ menuItem.addEventListener( "click", () => {
1641
+ const f = item[ 'callback' ];
1642
+ if( f )
1643
+ {
1644
+ f.call( this, key, menuItem );
1645
+ }
1646
+ this.destroy();
1647
+ } );
1648
+ }
1615
1649
 
1616
1650
  menuItem.addEventListener("mouseover", e => {
1617
1651
 
@@ -1755,7 +1789,7 @@ class Area {
1755
1789
  root.className += " " + options.className;
1756
1790
  }
1757
1791
 
1758
- var width = options.width || "calc( 100% )";
1792
+ var width = options.width || "100%";
1759
1793
  var height = options.height || "100%";
1760
1794
 
1761
1795
  // This has default options..
@@ -1781,7 +1815,7 @@ class Area {
1781
1815
 
1782
1816
  if( !options.skipAppend )
1783
1817
  {
1784
- var lexroot = document.getElementById("lexroot");
1818
+ let lexroot = document.getElementById("lexroot");
1785
1819
  lexroot.appendChild( this.root );
1786
1820
  }
1787
1821
 
@@ -1852,12 +1886,12 @@ class Area {
1852
1886
  this.splitBar.addEventListener("mousedown", innerMouseDown);
1853
1887
  this.root.appendChild( this.splitBar );
1854
1888
 
1855
- var that = this;
1856
- var lastMousePosition = [ 0, 0 ];
1889
+ const that = this;
1890
+ let lastMousePosition = [ 0, 0 ];
1857
1891
 
1858
1892
  function innerMouseDown( e )
1859
1893
  {
1860
- var doc = that.root.ownerDocument;
1894
+ const doc = that.root.ownerDocument;
1861
1895
  doc.addEventListener( 'mousemove', innerMouseMove );
1862
1896
  doc.addEventListener( 'mouseup', innerMouseUp );
1863
1897
  lastMousePosition[ 0 ] = e.x;
@@ -1910,7 +1944,7 @@ class Area {
1910
1944
 
1911
1945
  function innerMouseUp( e )
1912
1946
  {
1913
- var doc = that.root.ownerDocument;
1947
+ const doc = that.root.ownerDocument;
1914
1948
  doc.removeEventListener( 'mousemove', innerMouseMove );
1915
1949
  doc.removeEventListener( 'mouseup', innerMouseUp );
1916
1950
  document.body.classList.remove( 'nocursor' );
@@ -1962,9 +1996,9 @@ class Area {
1962
1996
  this.root = this.sections[ 1 ].root;
1963
1997
  }
1964
1998
 
1965
- var type = options.type || "horizontal";
1966
- var sizes = options.sizes || [ "50%", "50%" ];
1967
- var auto = (options.sizes === 'auto');
1999
+ const type = options.type || "horizontal";
2000
+ const sizes = options.sizes || [ "50%", "50%" ];
2001
+ const auto = (options.sizes === 'auto');
1968
2002
 
1969
2003
  if( !sizes[ 1 ] )
1970
2004
  {
@@ -1980,8 +2014,8 @@ class Area {
1980
2014
  }
1981
2015
 
1982
2016
  // Create areas
1983
- var area1 = new Area( { skipAppend: true, className: "split" + ( options.menubar || options.sidebar ? "" : " origin" ) } );
1984
- var area2 = new Area( { skipAppend: true, className: "split" } );
2017
+ let area1 = new Area( { skipAppend: true, className: "split" + ( options.menubar || options.sidebar ? "" : " origin" ) } );
2018
+ let area2 = new Area( { skipAppend: true, className: "split" } );
1985
2019
 
1986
2020
  area1.parentArea = this;
1987
2021
  area2.parentArea = this;
@@ -1989,7 +2023,7 @@ class Area {
1989
2023
  let minimizable = options.minimizable ?? false;
1990
2024
  let resize = ( options.resize ?? true ) || minimizable;
1991
2025
 
1992
- var data = "0px";
2026
+ let data = "0px";
1993
2027
  this.offset = 0;
1994
2028
 
1995
2029
  if( resize )
@@ -2036,7 +2070,7 @@ class Area {
2036
2070
 
2037
2071
  if( type == "horizontal" )
2038
2072
  {
2039
- var width1 = sizes[ 0 ],
2073
+ let width1 = sizes[ 0 ],
2040
2074
  width2 = sizes[ 1 ];
2041
2075
 
2042
2076
  if( width1.constructor == Number )
@@ -2077,7 +2111,7 @@ class Area {
2077
2111
  }
2078
2112
  else
2079
2113
  {
2080
- var height1 = sizes[ 0 ],
2114
+ let height1 = sizes[ 0 ],
2081
2115
  height2 = sizes[ 1 ];
2082
2116
 
2083
2117
  if( height1.constructor == Number )
@@ -2115,11 +2149,11 @@ class Area {
2115
2149
  return this.sections;
2116
2150
  }
2117
2151
 
2118
- var that = this;
2152
+ const that = this;
2119
2153
 
2120
2154
  function innerMouseDown( e )
2121
2155
  {
2122
- var doc = that.root.ownerDocument;
2156
+ const doc = that.root.ownerDocument;
2123
2157
  doc.addEventListener( 'mousemove', innerMouseMove );
2124
2158
  doc.addEventListener( 'mouseup', innerMouseUp );
2125
2159
  e.stopPropagation();
@@ -2139,26 +2173,13 @@ class Area {
2139
2173
  that._moveSplit( -e.movementY );
2140
2174
  }
2141
2175
 
2142
- const widgets = that.root.querySelectorAll( ".lexwidget" );
2143
-
2144
- // Send area resize to every widget in the area
2145
- for( let widget of widgets )
2146
- {
2147
- const jsInstance = widget.jsInstance;
2148
-
2149
- if( jsInstance.onresize )
2150
- {
2151
- jsInstance.onresize();
2152
- }
2153
- }
2154
-
2155
2176
  e.stopPropagation();
2156
2177
  e.preventDefault();
2157
2178
  }
2158
2179
 
2159
2180
  function innerMouseUp( e )
2160
2181
  {
2161
- var doc = that.root.ownerDocument;
2182
+ const doc = that.root.ownerDocument;
2162
2183
  doc.removeEventListener( 'mousemove', innerMouseMove );
2163
2184
  doc.removeEventListener( 'mouseup', innerMouseUp );
2164
2185
  document.body.classList.remove( 'nocursor' );
@@ -2306,7 +2327,7 @@ class Area {
2306
2327
 
2307
2328
  propagateEvent( eventName ) {
2308
2329
 
2309
- for( var i = 0; i < this.sections.length; i++ )
2330
+ for( let i = 0; i < this.sections.length; i++ )
2310
2331
  {
2311
2332
  const area = this.sections[ i ];
2312
2333
 
@@ -2360,7 +2381,7 @@ class Area {
2360
2381
 
2361
2382
  if( options.sticky ?? true )
2362
2383
  {
2363
- bar.root.classList.add( "sticky" );
2384
+ bar.root.className += " sticky top-0";
2364
2385
  }
2365
2386
 
2366
2387
  return menubar;
@@ -2432,7 +2453,7 @@ class Area {
2432
2453
 
2433
2454
  if( float )
2434
2455
  {
2435
- for( var i = 0; i < float.length; i++ )
2456
+ for( let i = 0; i < float.length; i++ )
2436
2457
  {
2437
2458
  const t = float[i];
2438
2459
  switch( t )
@@ -2457,7 +2478,8 @@ class Area {
2457
2478
  selected: b.selected,
2458
2479
  icon: b.icon,
2459
2480
  img: b.img,
2460
- className: b.class
2481
+ className: b.class ?? "",
2482
+ title: b.name
2461
2483
  };
2462
2484
 
2463
2485
  if( group )
@@ -2651,7 +2673,7 @@ class Area {
2651
2673
 
2652
2674
  for( var i = 0; i < this.sections.length; i++ )
2653
2675
  {
2654
- this.sections[i]._update();
2676
+ this.sections[ i ]._update();
2655
2677
  }
2656
2678
  }
2657
2679
  };
@@ -2760,6 +2782,12 @@ class Tabs {
2760
2782
 
2761
2783
  this.area = area.sections[1];
2762
2784
  this.area.root.className += " lexareatabscontent";
2785
+
2786
+ if( options.contentClass )
2787
+ {
2788
+ this.area.root.className += ` ${ options.contentClass }`;
2789
+ }
2790
+
2763
2791
  this.selected = null;
2764
2792
  this.root = container;
2765
2793
  this.tabs = {};
@@ -2779,8 +2807,8 @@ class Tabs {
2779
2807
  var transition = this.thumb.style.transition;
2780
2808
  this.thumb.style.transition = "none";
2781
2809
  this.thumb.style.transform = "translate( " + ( tabEl.childIndex * tabEl.offsetWidth ) + "px )";
2782
- this.thumb.style.width = ( tabEl.offsetWidth - 5 ) + "px";
2783
- this.thumb.style.height = ( tabEl.offsetHeight - 6 ) + "px";
2810
+ this.thumb.style.width = ( tabEl.offsetWidth ) + "px";
2811
+ this.thumb.style.height = ( tabEl.offsetHeight ) + "px";
2784
2812
  flushCss( this.thumb );
2785
2813
  this.thumb.style.transition = transition;
2786
2814
  });
@@ -2952,8 +2980,8 @@ class Tabs {
2952
2980
  if( isSelected && this.thumb )
2953
2981
  {
2954
2982
  this.thumb.style.transform = "translate( " + ( tabEl.childIndex * tabEl.offsetWidth ) + "px )";
2955
- this.thumb.style.width = ( tabEl.offsetWidth - 5 ) + "px";
2956
- this.thumb.style.height = ( tabEl.offsetHeight - 6 ) + "px";
2983
+ this.thumb.style.width = ( tabEl.offsetWidth ) + "px";
2984
+ this.thumb.style.height = ( tabEl.offsetHeight ) + "px";
2957
2985
  this.thumb.item = tabEl;
2958
2986
  }
2959
2987
 
@@ -3717,12 +3745,11 @@ class SideBar {
3717
3745
  // Entry filter
3718
3746
  if( ( options.filter ?? false ) )
3719
3747
  {
3720
- const panel = new Panel();
3721
- panel.addText(null, "", (value, event) => {
3748
+ const filterTextInput = new TextInput(null, "", (value, event) => {
3722
3749
  this.filterString = value;
3723
3750
  this.update();
3724
- }, { placeholder: "Search...", icon: "fa-solid fa-magnifying-glass" });
3725
- this.filter = panel.root.childNodes[ 0 ];
3751
+ }, { inputClass: "outline", placeholder: "Search...", icon: "fa-solid fa-magnifying-glass", className: "lexsidebarfilter" });
3752
+ this.filter = filterTextInput.root;
3726
3753
  this.root.appendChild( this.filter );
3727
3754
  }
3728
3755
 
@@ -3745,7 +3772,7 @@ class SideBar {
3745
3772
  // Set width depending on header/footer
3746
3773
  doAsync( () => {
3747
3774
  // This account for header, footer and all inner paddings
3748
- const contentOffset = 32 + ( this.header?.offsetHeight ?? 0 ) +
3775
+ const contentOffset = ( this.header?.offsetHeight ?? 0 ) +
3749
3776
  ( this.filter?.offsetHeight ?? 0 ) +
3750
3777
  ( this.footer?.offsetHeight ?? 0 );
3751
3778
  this.content.style.height = `calc(100% - ${ contentOffset }px)`;
@@ -4117,7 +4144,7 @@ class SideBar {
4117
4144
  const f = options.callback;
4118
4145
  item.value = value;
4119
4146
  if( f ) f.call( this, key, value, event );
4120
- }, { label: key, signal: ( "@checkbox_" + key ) });
4147
+ }, { className: "accent", label: key, signal: ( "@checkbox_" + key ) });
4121
4148
  itemDom.appendChild( panel.root.childNodes[ 0 ] );
4122
4149
  }
4123
4150
  else
@@ -4357,8 +4384,6 @@ class Widget {
4357
4384
 
4358
4385
  if( type != Widget.TITLE )
4359
4386
  {
4360
- // root.style.width = "calc(100% - " + (this._currentBranch || type == Widget.FILE || type == Widget.TREE ? 10 : 20) + "px)";
4361
-
4362
4387
  if( options.width )
4363
4388
  {
4364
4389
  root.style.width = root.style.minWidth = options.width;
@@ -4375,6 +4400,8 @@ class Widget {
4375
4400
  {
4376
4401
  root.style.height = root.style.minHeight = options.height;
4377
4402
  }
4403
+
4404
+ LX.widgetResizeObserver.observe( root );
4378
4405
  }
4379
4406
 
4380
4407
  if( name != undefined )
@@ -4392,6 +4419,7 @@ class Widget {
4392
4419
  domName.innerHTML = name;
4393
4420
  domName.title = options.title ?? domName.innerHTML;
4394
4421
  domName.style.width = options.nameWidth || LX.DEFAULT_NAME_WIDTH;
4422
+ domName.style.minWidth = domName.style.width;
4395
4423
 
4396
4424
  root.appendChild( domName );
4397
4425
  root.domName = domName;
@@ -4575,15 +4603,17 @@ LX.Widget = Widget;
4575
4603
 
4576
4604
  function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4577
4605
  {
4578
- let custom_idx = simple_guidGenerator();
4606
+ let customIdx = simple_guidGenerator();
4579
4607
 
4580
4608
  Panel.prototype[ 'add' + customWidgetName ] = function( name, instance, callback ) {
4581
4609
 
4610
+ options.nameWidth = "100%";
4611
+
4582
4612
  let widget = new Widget( Widget.CUSTOM, name, null, options );
4583
4613
  this._attachWidget( widget );
4584
4614
 
4585
4615
  widget.customName = customWidgetName;
4586
- widget.customIdx = custom_idx;
4616
+ widget.customIdx = customIdx;
4587
4617
 
4588
4618
  widget.onGetValue = () => {
4589
4619
  return instance;
@@ -4600,7 +4630,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4600
4630
  };
4601
4631
 
4602
4632
  const element = widget.root;
4603
- element.style.flexWrap = "wrap";
4604
4633
 
4605
4634
  let container, customWidgetsDom;
4606
4635
  let default_instance = options.default ?? {};
@@ -4619,20 +4648,20 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4619
4648
 
4620
4649
  container = document.createElement('div');
4621
4650
  container.className = "lexcustomcontainer";
4622
- doAsync( () => {
4623
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
4624
- container.style.width = `calc( 100% - ${ realNameWidth })`;
4625
- } );
4651
+ container.style.width = "100%";
4652
+ element.appendChild( container );
4653
+ element.dataset["opened"] = false;
4626
4654
 
4627
- let buttonName = "<a class='fa-solid " + (options.icon ?? "fa-cube") + "' style='float:left'></a>";
4655
+ let buttonName = "<a class='fa-solid " + (options.icon ?? "fa-cube") + "'></a>";
4628
4656
  buttonName += customWidgetName + (!instance ? " [empty]" : "");
4629
- // Add alwayis icon to keep spacing right
4630
- buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu' style='float:right; width:5%;'></a>";
4657
+ // Add always icon to keep spacing right
4658
+ buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu'></a>";
4631
4659
 
4632
4660
  let buttonEl = this.addButton(null, buttonName, (value, event) => {
4633
4661
  if( instance )
4634
4662
  {
4635
4663
  element.querySelector(".lexcustomitems").toggleAttribute('hidden');
4664
+ element.dataset["opened"] = !element.querySelector(".lexcustomitems").hasAttribute("hidden");
4636
4665
  }
4637
4666
  else
4638
4667
  {
@@ -4641,12 +4670,12 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4641
4670
  instance = {};
4642
4671
  refresh_widget();
4643
4672
  element.querySelector(".lexcustomitems").toggleAttribute('hidden', false);
4673
+ element.dataset["opened"] = !element.querySelector(".lexcustomitems").hasAttribute("hidden");
4644
4674
  });
4645
4675
  });
4646
4676
  }
4647
4677
 
4648
4678
  }, { buttonClass: 'custom' });
4649
-
4650
4679
  container.appendChild( buttonEl.root );
4651
4680
 
4652
4681
  if( instance )
@@ -4668,8 +4697,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4668
4697
  customWidgetsDom = document.createElement('div');
4669
4698
  customWidgetsDom.className = "lexcustomitems";
4670
4699
  customWidgetsDom.toggleAttribute('hidden', true);
4671
-
4672
- element.appendChild( container );
4673
4700
  element.appendChild( customWidgetsDom );
4674
4701
 
4675
4702
  if( instance )
@@ -4758,7 +4785,7 @@ class NodeTree {
4758
4785
  _createItem( parent, node, level = 0, selectedId ) {
4759
4786
 
4760
4787
  const that = this;
4761
- const nodeFilterInput = this.domEl.querySelector( "#lexnodetree_filter" );
4788
+ const nodeFilterInput = this.domEl.querySelector( ".lexnodetree_filter" );
4762
4789
 
4763
4790
  node.children = node.children ?? [];
4764
4791
  if( nodeFilterInput && nodeFilterInput.value != "" && !node.id.includes( nodeFilterInput.value ) )
@@ -5187,6 +5214,7 @@ class NodeTree {
5187
5214
  }
5188
5215
 
5189
5216
  const _hasChild = function( parent, id ) {
5217
+ if( !parent.length ) return;
5190
5218
  for( var c of parent.children )
5191
5219
  {
5192
5220
  if( c.id == id ) return true;
@@ -5336,14 +5364,7 @@ class TextInput extends Widget {
5336
5364
 
5337
5365
  this._lastValueTriggered = value = newValue;
5338
5366
 
5339
- if( options.disabled )
5340
- {
5341
- wValue.innerText = newValue;
5342
- }
5343
- else
5344
- {
5345
- wValue.value = newValue;
5346
- }
5367
+ wValue.value = newValue;
5347
5368
 
5348
5369
  if( !skipCallback )
5349
5370
  {
@@ -5351,6 +5372,11 @@ class TextInput extends Widget {
5351
5372
  }
5352
5373
  };
5353
5374
 
5375
+ this.onResize = ( rect ) => {
5376
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5377
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5378
+ };
5379
+
5354
5380
  this.valid = ( v ) => {
5355
5381
  v = v ?? this.value();
5356
5382
  if( !v.length || wValue.pattern == "" ) return true;
@@ -5359,17 +5385,9 @@ class TextInput extends Widget {
5359
5385
  };
5360
5386
 
5361
5387
  let container = document.createElement( 'div' );
5362
- container.className = "lextext" + ( options.warning ? " lexwarning" : "" );
5388
+ container.className = ( options.warning ? " lexwarning" : "" );
5363
5389
  container.style.display = "flex";
5364
- doAsync( () => {
5365
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5366
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5367
- } );
5368
-
5369
- if( options.textClass )
5370
- {
5371
- container.classList.add( options.textClass );
5372
- }
5390
+ this.root.appendChild( container );
5373
5391
 
5374
5392
  this.disabled = ( options.disabled || options.warning ) ?? ( options.url ? true : false );
5375
5393
  let wValue = null;
@@ -5377,6 +5395,7 @@ class TextInput extends Widget {
5377
5395
  if( !this.disabled )
5378
5396
  {
5379
5397
  wValue = document.createElement( 'input' );
5398
+ wValue.className = "lextext " + ( options.inputClass ?? "" );
5380
5399
  wValue.type = options.type || "";
5381
5400
  wValue.value = wValue.iValue = value || "";
5382
5401
  wValue.style.width = "100%";
@@ -5429,27 +5448,35 @@ class TextInput extends Widget {
5429
5448
  }
5430
5449
 
5431
5450
  }
5432
- else
5451
+ else if( options.url )
5433
5452
  {
5434
- wValue = document.createElement( options.url ? 'a' : 'div' );
5435
-
5436
- if( options.url )
5437
- {
5438
- wValue.href = options.url;
5439
- wValue.target = "_blank";
5440
- }
5453
+ wValue = document.createElement( 'a' );
5454
+ wValue.href = options.url;
5455
+ wValue.target = "_blank";
5441
5456
 
5442
5457
  const icon = options.warning ? '<i class="fa-solid fa-triangle-exclamation"></i>' : '';
5443
5458
  wValue.innerHTML = ( icon + value ) || "";
5444
5459
  wValue.style.width = "100%";
5445
5460
  wValue.style.textAlign = options.float ?? "";
5461
+ wValue.className = "lextext ellipsis-overflow";
5462
+ }
5463
+ else
5464
+ {
5465
+ wValue = document.createElement( 'input' );
5466
+
5467
+ const icon = options.warning ? '<i class="fa-solid fa-triangle-exclamation"></i>' : '';
5468
+ wValue.disabled = true;
5469
+ wValue.innerHTML = icon;
5470
+ wValue.value = value;
5471
+ wValue.style.width = "100%";
5472
+ wValue.style.textAlign = options.float ?? "";
5473
+ wValue.className = "lextext ellipsis-overflow " + ( options.inputClass ?? "" );
5446
5474
  }
5447
5475
 
5448
5476
  Object.assign( wValue.style, options.style ?? {} );
5449
-
5450
5477
  container.appendChild( wValue );
5451
5478
 
5452
- this.root.appendChild( container );
5479
+ doAsync( this.onResize.bind( this ) );
5453
5480
  }
5454
5481
  }
5455
5482
 
@@ -5480,26 +5507,22 @@ class TextArea extends Widget {
5480
5507
  }
5481
5508
  };
5482
5509
 
5510
+ this.onResize = ( rect ) => {
5511
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5512
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5513
+ };
5514
+
5483
5515
  let container = document.createElement( "div" );
5484
5516
  container.className = "lextextarea";
5485
5517
  container.style.display = "flex";
5486
- doAsync( () => {
5487
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5488
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5489
- container.style.height = options.height;
5490
-
5491
- if( options.fitHeight )
5492
- {
5493
- // Update height depending on the content
5494
- wValue.style.height = wValue.scrollHeight + "px";
5495
- }
5496
- } );
5518
+ this.root.appendChild( container );
5497
5519
 
5498
5520
  let wValue = document.createElement( "textarea" );
5499
5521
  wValue.value = wValue.iValue = value || "";
5500
5522
  wValue.style.width = "100%";
5501
5523
  wValue.style.textAlign = options.float ?? "";
5502
5524
  Object.assign( wValue.style, options.style ?? {} );
5525
+ container.appendChild( wValue );
5503
5526
 
5504
5527
  if( options.disabled ?? false ) wValue.setAttribute( "disabled", true );
5505
5528
  if( options.placeholder ) wValue.setAttribute( "placeholder", options.placeholder );
@@ -5533,9 +5556,17 @@ class TextArea extends Widget {
5533
5556
  container.appendChild( icon );
5534
5557
  }
5535
5558
 
5536
- container.appendChild( wValue );
5559
+ doAsync( () => {
5560
+ container.style.height = options.height;
5537
5561
 
5538
- this.root.appendChild( container );
5562
+ if( options.fitHeight )
5563
+ {
5564
+ // Update height depending on the content
5565
+ wValue.style.height = wValue.scrollHeight + "px";
5566
+ }
5567
+
5568
+ this.onResize();
5569
+ }, 10 );
5539
5570
  }
5540
5571
  }
5541
5572
 
@@ -5562,10 +5593,22 @@ class Button extends Widget {
5562
5593
  ( options.img ? "<img src='" + options.img + "'>" : "<span>" + ( newValue || "" ) + "</span>" ) );
5563
5594
  };
5564
5595
 
5596
+ this.onResize = ( rect ) => {
5597
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5598
+ wValue.style.width = `calc( 100% - ${ realNameWidth }px)`;
5599
+ };
5600
+
5565
5601
  var wValue = document.createElement( 'button' );
5566
5602
  wValue.title = options.title ?? "";
5567
5603
  wValue.className = "lexbutton " + ( options.buttonClass ?? "" );
5568
5604
 
5605
+ if( options.icon )
5606
+ {
5607
+ wValue.classList.add( "justify-center" );
5608
+ }
5609
+
5610
+ this.root.appendChild( wValue );
5611
+
5569
5612
  if( options.selected )
5570
5613
  {
5571
5614
  wValue.classList.add( "selected" );
@@ -5575,11 +5618,6 @@ class Button extends Widget {
5575
5618
  ( options.icon ? "<a class='" + options.icon + "'></a>" :
5576
5619
  ( options.img ? "<img src='" + options.img + "'>" : "<span>" + ( value || "" ) + "</span>" ) );
5577
5620
 
5578
- doAsync( () => {
5579
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5580
- wValue.style.width = `calc( 100% - ${ realNameWidth })`;
5581
- } );
5582
-
5583
5621
  if( options.disabled )
5584
5622
  {
5585
5623
  wValue.setAttribute( "disabled", true );
@@ -5599,15 +5637,7 @@ class Button extends Widget {
5599
5637
  this._trigger( new IEvent( name, value, e ), callback );
5600
5638
  });
5601
5639
 
5602
- this.root.appendChild( wValue );
5603
-
5604
- // Remove branch padding and
5605
- const useNameAsLabel = !( options.hideName ?? false ) && !( options.icon || options.img );
5606
- if( !useNameAsLabel )
5607
- {
5608
- wValue.className += " noname";
5609
- wValue.style.width = "100%";
5610
- }
5640
+ doAsync( this.onResize.bind( this ) );
5611
5641
  }
5612
5642
  }
5613
5643
 
@@ -5635,14 +5665,10 @@ class ComboButtons extends Widget {
5635
5665
  container.className += options.float;
5636
5666
  }
5637
5667
 
5638
- doAsync( () => {
5639
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5640
- container.style.width = `calc( 100% - ${ realNameWidth })`;
5641
- } );
5642
-
5643
5668
  let currentValue = [];
5644
5669
  let buttonsBox = document.createElement('div');
5645
5670
  buttonsBox.className = "lexcombobuttonsbox ";
5671
+ container.appendChild( buttonsBox );
5646
5672
 
5647
5673
  for( let b of values )
5648
5674
  {
@@ -5754,9 +5780,14 @@ class ComboButtons extends Widget {
5754
5780
  }
5755
5781
  };
5756
5782
 
5757
- container.appendChild( buttonsBox );
5783
+ this.onResize = ( rect ) => {
5784
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5785
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
5786
+ };
5758
5787
 
5759
5788
  this.root.appendChild( container );
5789
+
5790
+ doAsync( this.onResize.bind( this ) );
5760
5791
  }
5761
5792
  }
5762
5793
 
@@ -5778,6 +5809,7 @@ class Card extends Widget {
5778
5809
  let container = document.createElement('div');
5779
5810
  container.className = "lexcard";
5780
5811
  container.style.width = "100%";
5812
+ this.root.appendChild( container );
5781
5813
 
5782
5814
  if( options.img )
5783
5815
  {
@@ -5800,6 +5832,7 @@ class Card extends Widget {
5800
5832
 
5801
5833
  let cardNameDom = document.createElement('span');
5802
5834
  cardNameDom.innerText = name;
5835
+ container.appendChild( cardNameDom );
5803
5836
 
5804
5837
  if( options.link != undefined )
5805
5838
  {
@@ -5818,9 +5851,6 @@ class Card extends Widget {
5818
5851
  this._trigger( new IEvent( name, null, e ), options.callback );
5819
5852
  });
5820
5853
  }
5821
-
5822
- container.appendChild( cardNameDom );
5823
- this.root.appendChild( container );
5824
5854
  }
5825
5855
  }
5826
5856
 
@@ -5871,6 +5901,7 @@ class Form extends Widget {
5871
5901
  container.className = "lexformdata";
5872
5902
  container.style.width = "100%";
5873
5903
  container.formData = {};
5904
+ this.root.appendChild( container );
5874
5905
 
5875
5906
  for( let entry in data )
5876
5907
  {
@@ -5882,7 +5913,7 @@ class Form extends Widget {
5882
5913
  }
5883
5914
 
5884
5915
  entryData.placeholder = entryData.placeholder ?? entry;
5885
- entryData.width = "calc(100% - 10px)";
5916
+ entryData.width = "100%";
5886
5917
 
5887
5918
  // this.addLabel( entry, { textClass: "formlabel" } );
5888
5919
 
@@ -5912,11 +5943,9 @@ class Form extends Widget {
5912
5943
  {
5913
5944
  callback( container.formData, event );
5914
5945
  }
5915
- }, { buttonClass: "primary", width: "calc(100% - 10px)" } );
5946
+ }, { buttonClass: "primary" } );
5916
5947
 
5917
5948
  container.appendChild( submitButton.root );
5918
-
5919
- this.root.appendChild( container );
5920
5949
  }
5921
5950
  }
5922
5951
 
@@ -5957,7 +5986,7 @@ class Select extends Widget {
5957
5986
  // Reset filter
5958
5987
  if( filter )
5959
5988
  {
5960
- filter.querySelector( "input" ).value = "";
5989
+ filter.root.querySelector( "input" ).value = "";
5961
5990
  const filteredOptions = this._filterOptions( values, "" );
5962
5991
  list.refresh( filteredOptions );
5963
5992
  }
@@ -5968,12 +5997,14 @@ class Select extends Widget {
5968
5997
  }
5969
5998
  };
5970
5999
 
6000
+ this.onResize = ( rect ) => {
6001
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6002
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6003
+ };
6004
+
5971
6005
  let container = document.createElement( "div" );
5972
6006
  container.className = "lexselect";
5973
- doAsync( () => {
5974
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5975
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5976
- } );
6007
+ this.root.appendChild( container );
5977
6008
 
5978
6009
  let wValue = document.createElement( 'div' );
5979
6010
  wValue.className = "lexselect lexoption";
@@ -5982,7 +6013,7 @@ class Select extends Widget {
5982
6013
 
5983
6014
  // Add select widget button
5984
6015
  let buttonName = value;
5985
- buttonName += "<a class='fa-solid fa-angle-down' style='float:right; margin-right: 3px;'></a>";
6016
+ buttonName += "<a class='fa-solid fa-angle-down'></a>";
5986
6017
 
5987
6018
  const _placeOptions = ( parent ) => {
5988
6019
 
@@ -6008,6 +6039,7 @@ class Select extends Widget {
6008
6039
  {
6009
6040
  const rect = nestedDialog.getBoundingClientRect();
6010
6041
  topPosition -= rect.y;
6042
+ maxY -= rect.y;
6011
6043
  }
6012
6044
 
6013
6045
  parent.style.top = ( topPosition + selectRoot.offsetHeight ) + 'px';
@@ -6073,7 +6105,7 @@ class Select extends Widget {
6073
6105
 
6074
6106
  if( filter )
6075
6107
  {
6076
- filter.querySelector( "input" ).focus();
6108
+ filter.root.querySelector( "input" ).focus();
6077
6109
  }
6078
6110
 
6079
6111
  }, { buttonClass: "array", skipInlineCount: true, disabled: options.disabled } );
@@ -6112,7 +6144,7 @@ class Select extends Widget {
6112
6144
  this.unfocus_event = true;
6113
6145
  setTimeout( () => delete this.unfocus_event, 200 );
6114
6146
  }
6115
- else if ( e.relatedTarget && e.relatedTarget.tagName == "INPUT" )
6147
+ else if ( e.relatedTarget && ( e.relatedTarget.tagName == "INPUT" || e.relatedTarget.classList.contains("lexoptions") ) )
6116
6148
  {
6117
6149
  return;
6118
6150
  }
@@ -6132,13 +6164,14 @@ class Select extends Widget {
6132
6164
  filterOptions.skipWidget = filterOptions.skipWidget ?? true;
6133
6165
  filterOptions.trigger = "input";
6134
6166
  filterOptions.icon = "fa-solid fa-magnifying-glass";
6135
- filterOptions.className = "lexfilter noname";
6167
+ filterOptions.className = "lexfilter";
6168
+ filterOptions.inputClass = "outline";
6136
6169
 
6137
- let filter = new TextInput(null, options.filterValue ?? "", ( v ) => {
6170
+ filter = new TextInput(null, options.filterValue ?? "", ( v ) => {
6138
6171
  const filteredOptions = this._filterOptions( values, v );
6139
6172
  list.refresh( filteredOptions );
6140
6173
  }, filterOptions );
6141
- filter.root.querySelector( ".lextext" ).classList.remove( "lextext" );
6174
+ filter.root.querySelector( ".lextext" ).style.border = "1px solid transparent";
6142
6175
 
6143
6176
  const input = filter.root.querySelector( "input" );
6144
6177
 
@@ -6159,12 +6192,12 @@ class Select extends Widget {
6159
6192
  list.appendChild( listOptions );
6160
6193
 
6161
6194
  // Add select options list
6162
- list.refresh = ( options ) => {
6195
+ list.refresh = ( currentOptions ) => {
6163
6196
 
6164
6197
  // Empty list
6165
6198
  listOptions.innerHTML = "";
6166
6199
 
6167
- if( !options.length )
6200
+ if( !currentOptions.length )
6168
6201
  {
6169
6202
  let iValue = options.emptyMsg ?? "No options found.";
6170
6203
 
@@ -6180,9 +6213,9 @@ class Select extends Widget {
6180
6213
  return;
6181
6214
  }
6182
6215
 
6183
- for( let i = 0; i < options.length; i++ )
6216
+ for( let i = 0; i < currentOptions.length; i++ )
6184
6217
  {
6185
- let iValue = options[ i ];
6218
+ let iValue = currentOptions[ i ];
6186
6219
  let li = document.createElement( "li" );
6187
6220
  let option = document.createElement( "div" );
6188
6221
  option.className = "option";
@@ -6250,7 +6283,7 @@ class Select extends Widget {
6250
6283
 
6251
6284
  container.appendChild( listDialog );
6252
6285
 
6253
- this.root.appendChild( container );
6286
+ doAsync( this.onResize.bind( this ) );
6254
6287
  }
6255
6288
 
6256
6289
  _filterOptions( options, value ) {
@@ -6306,12 +6339,17 @@ class Curve extends Widget {
6306
6339
  }
6307
6340
  };
6308
6341
 
6342
+ this.onResize = ( rect ) => {
6343
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6344
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6345
+ flushCss( container );
6346
+ curveInstance.canvas.width = container.offsetWidth;
6347
+ curveInstance.redraw();
6348
+ };
6349
+
6309
6350
  var container = document.createElement( "div" );
6310
6351
  container.className = "lexcurve";
6311
- doAsync( () => {
6312
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6313
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6314
- } );
6352
+ this.root.appendChild( container );
6315
6353
 
6316
6354
  options.callback = (v, e) => {
6317
6355
  this._trigger( new IEvent( name, v, e ), callback );
@@ -6321,16 +6359,9 @@ class Curve extends Widget {
6321
6359
 
6322
6360
  let curveInstance = new CanvasCurve( values, options );
6323
6361
  container.appendChild( curveInstance.element );
6324
- this.root.appendChild( container );
6325
-
6326
- // Resize
6327
- this.onresize = curveInstance.redraw.bind( curveInstance );
6328
6362
  this.curveInstance = curveInstance;
6329
6363
 
6330
- doAsync(() => {
6331
- curveInstance.canvas.width = container.offsetWidth;
6332
- curveInstance.redraw();
6333
- });
6364
+ doAsync( this.onResize.bind( this ) );
6334
6365
  }
6335
6366
  }
6336
6367
 
@@ -6350,24 +6381,32 @@ class Dial extends Widget {
6350
6381
  super( Widget.DIAL, name, defaultValues, options );
6351
6382
 
6352
6383
  this.onGetValue = () => {
6353
- return JSON.parse( JSON.stringify( curveInstance.element.value ) );
6384
+ return JSON.parse( JSON.stringify( dialInstance.element.value ) );
6354
6385
  };
6355
6386
 
6356
6387
  this.onSetValue = ( newValue, skipCallback, event ) => {
6357
- curveInstance.element.value = JSON.parse( JSON.stringify( newValue ) );
6358
- curveInstance.redraw();
6388
+ dialInstance.element.value = JSON.parse( JSON.stringify( newValue ) );
6389
+ dialInstance.redraw();
6359
6390
  if( !skipCallback )
6360
6391
  {
6361
- this._trigger( new IEvent( name, curveInstance.element.value, event ), callback );
6392
+ this._trigger( new IEvent( name, dialInstance.element.value, event ), callback );
6362
6393
  }
6363
6394
  };
6364
6395
 
6396
+ this.onResize = ( rect ) => {
6397
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6398
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6399
+ flushCss( container );
6400
+ dialInstance.element.style.height = dialInstance.element.offsetWidth + "px";
6401
+ dialInstance.canvas.width = dialInstance.element.offsetWidth;
6402
+ container.style.width = dialInstance.element.offsetWidth + "px";
6403
+ dialInstance.canvas.height = dialInstance.canvas.width;
6404
+ dialInstance.redraw();
6405
+ };
6406
+
6365
6407
  var container = document.createElement( "div" );
6366
6408
  container.className = "lexcurve";
6367
- doAsync( () => {
6368
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6369
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6370
- } );
6409
+ this.root.appendChild( container );
6371
6410
 
6372
6411
  options.callback = ( v, e ) => {
6373
6412
  this._trigger( new IEvent( name, v, e ), callback );
@@ -6375,21 +6414,11 @@ class Dial extends Widget {
6375
6414
 
6376
6415
  options.name = name;
6377
6416
 
6378
- let curveInstance = new CanvasDial( this, values, options );
6379
- container.appendChild( curveInstance.element );
6380
- this.root.appendChild( container );
6417
+ let dialInstance = new CanvasDial( this, values, options );
6418
+ container.appendChild( dialInstance.element );
6419
+ this.dialInstance = dialInstance;
6381
6420
 
6382
- // Resize
6383
- this.onresize = curveInstance.redraw.bind( curveInstance );
6384
- this.curveInstance = curveInstance;
6385
-
6386
- doAsync(() => {
6387
- curveInstance.element.style.height = curveInstance.element.offsetWidth + "px";
6388
- curveInstance.canvas.width = curveInstance.element.offsetWidth;
6389
- container.style.width = curveInstance.element.offsetWidth + "px";
6390
- curveInstance.canvas.height = curveInstance.canvas.width;
6391
- curveInstance.redraw();
6392
- });
6421
+ doAsync( this.onResize.bind( this ) );
6393
6422
  }
6394
6423
  }
6395
6424
 
@@ -6412,25 +6441,27 @@ class Layers extends Widget {
6412
6441
 
6413
6442
  this.onSetValue = ( newValue, skipCallback, event ) => {
6414
6443
  value = newValue;
6415
- setLayers();
6444
+ this.setLayers( value );
6416
6445
  if( !skipCallback )
6417
6446
  {
6418
6447
  this._trigger( new IEvent(name, value, event), callback );
6419
6448
  }
6420
6449
  };
6421
6450
 
6451
+ this.onResize = ( rect ) => {
6452
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6453
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6454
+ };
6455
+
6422
6456
  var container = document.createElement( "div" );
6423
6457
  container.className = "lexlayers";
6424
- doAsync( () => {
6425
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6426
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6427
- } );
6458
+ this.root.appendChild( container );
6428
6459
 
6429
- const setLayers = () => {
6460
+ this.setLayers = ( val ) => {
6430
6461
 
6431
6462
  container.innerHTML = "";
6432
6463
 
6433
- let binary = value.toString( 2 );
6464
+ let binary = val.toString( 2 );
6434
6465
  let nbits = binary.length;
6435
6466
 
6436
6467
  // fill zeros
@@ -6444,7 +6475,7 @@ class Layers extends Widget {
6444
6475
  let layer = document.createElement( "div" );
6445
6476
  layer.className = "lexlayer";
6446
6477
 
6447
- if( value != undefined )
6478
+ if( val != undefined )
6448
6479
  {
6449
6480
  const valueBit = binary[ 16 - bit - 1 ];
6450
6481
  if( valueBit != undefined && valueBit == '1' )
@@ -6461,15 +6492,15 @@ class Layers extends Widget {
6461
6492
  e.stopPropagation();
6462
6493
  e.stopImmediatePropagation();
6463
6494
  e.target.classList.toggle( "selected" );
6464
- const newValue = value ^ ( 1 << bit );
6495
+ const newValue = val ^ ( 1 << bit );
6465
6496
  this.set( newValue, false, e );
6466
6497
  } );
6467
6498
  }
6468
6499
  };
6469
6500
 
6470
- setLayers();
6501
+ this.setLayers( value );
6471
6502
 
6472
- this.root.appendChild( container );
6503
+ doAsync( this.onResize.bind( this ) );
6473
6504
  }
6474
6505
  }
6475
6506
 
@@ -6484,6 +6515,8 @@ class ItemArray extends Widget {
6484
6515
 
6485
6516
  constructor( name, values = [], callback, options = {} ) {
6486
6517
 
6518
+ options.nameWidth = "100%";
6519
+
6487
6520
  super( Widget.ARRAY, name, null, options );
6488
6521
 
6489
6522
  this.onGetValue = () => {
@@ -6499,28 +6532,25 @@ class ItemArray extends Widget {
6499
6532
  }
6500
6533
  };
6501
6534
 
6502
- this.root.style.flexWrap = "wrap";
6503
-
6504
6535
  // Add open array button
6505
6536
 
6506
6537
  const itemNameWidth = "4%";
6507
6538
 
6508
6539
  var container = document.createElement('div');
6509
6540
  container.className = "lexarray";
6510
- doAsync( () => {
6511
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6512
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6513
- } );
6541
+ container.style.width = "100%";
6542
+ this.root.appendChild( container );
6543
+ this.root.dataset["opened"] = false;
6514
6544
 
6515
- const angleDown = `<a class='fa-solid fa-angle-down' style='float:right; margin-right: 3px;'></a>`;
6545
+ const angleDown = `<a class='fa-solid fa-angle-down'></a>`;
6516
6546
 
6517
6547
  let buttonName = "Array (size " + values.length + ")";
6518
6548
  buttonName += angleDown;
6519
6549
 
6520
6550
  const toggleButton = new Button(null, buttonName, () => {
6551
+ this.root.dataset["opened"] = this.root.dataset["opened"] == "true" ? false : true;
6521
6552
  this.root.querySelector(".lexarrayitems").toggleAttribute('hidden');
6522
6553
  }, { buttonClass: 'array' });
6523
-
6524
6554
  container.appendChild( toggleButton.root );
6525
6555
 
6526
6556
  // Show elements
@@ -6528,8 +6558,6 @@ class ItemArray extends Widget {
6528
6558
  let arrayItems = document.createElement( "div" );
6529
6559
  arrayItems.className = "lexarrayitems";
6530
6560
  arrayItems.toggleAttribute( "hidden", true );
6531
-
6532
- this.root.appendChild( container );
6533
6561
  this.root.appendChild( arrayItems );
6534
6562
 
6535
6563
  this._updateItems = () => {
@@ -6546,10 +6574,6 @@ class ItemArray extends Widget {
6546
6574
  {
6547
6575
  const value = values[ i ];
6548
6576
  let baseclass = options.innerValues ? 'select' : value.constructor;
6549
-
6550
- // TODO
6551
- // this.sameLine( 2 );
6552
-
6553
6577
  let widget = null;
6554
6578
 
6555
6579
  switch( baseclass )
@@ -6578,17 +6602,17 @@ class ItemArray extends Widget {
6578
6602
 
6579
6603
  arrayItems.appendChild( widget.root );
6580
6604
 
6581
- widget = new Button( null, "<a class='lexicon fa-solid fa-trash'></a>", ( v, event) => {
6605
+ const removeWidget = new Button( null, "<a class='lexicon fa-solid fa-trash'></a>", ( v, event) => {
6582
6606
  values.splice( values.indexOf( value ), 1 );
6583
6607
  this._updateItems();
6584
6608
  this._trigger( new IEvent(name, values, event), callback );
6585
6609
  }, { title: "Remove item", className: 'micro'} );
6586
6610
 
6587
- arrayItems.appendChild( widget.root );
6611
+ widget.root.appendChild( removeWidget.root );
6588
6612
  }
6589
6613
 
6590
6614
  buttonName = "Add item";
6591
- buttonName += "<a class='fa-solid fa-plus' style='float:right; margin-right: 3px; margin-top: 2px;'></a>";
6615
+ buttonName += "<a class='fa-solid fa-plus'></a>";
6592
6616
 
6593
6617
  const addButton = new Button(null, buttonName, (v, event) => {
6594
6618
  values.push( options.innerValues ? options.innerValues[ 0 ] : "" );
@@ -6649,6 +6673,11 @@ class List extends Widget {
6649
6673
  }
6650
6674
  };
6651
6675
 
6676
+ this.onResize = ( rect ) => {
6677
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6678
+ listContainer.style.width = `calc( 100% - ${ realNameWidth }px)`;
6679
+ };
6680
+
6652
6681
  this._updateValues = ( newValues ) => {
6653
6682
 
6654
6683
  values = newValues;
@@ -6684,14 +6713,11 @@ class List extends Widget {
6684
6713
 
6685
6714
  let listContainer = document.createElement( 'div' );
6686
6715
  listContainer.className = "lexlist";
6687
- doAsync( () => {
6688
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6689
- listContainer.style.width = `calc( 100% - ${ realNameWidth })`;
6690
- } );
6716
+ this.root.appendChild( listContainer );
6691
6717
 
6692
6718
  this._updateValues( values );
6693
6719
 
6694
- this.root.appendChild( listContainer );
6720
+ doAsync( this.onResize.bind( this ) );
6695
6721
  }
6696
6722
  }
6697
6723
 
@@ -6717,23 +6743,25 @@ class Tags extends Widget {
6717
6743
 
6718
6744
  this.onSetValue = ( newValue, skipCallback, event ) => {
6719
6745
  value = [].concat( newValue );
6720
- _generateTags();
6746
+ this.generateTags( value );
6721
6747
  if( !skipCallback )
6722
6748
  {
6723
6749
  this._trigger( new IEvent( name, value, event ), callback );
6724
6750
  }
6725
6751
  };
6726
6752
 
6753
+ this.onResize = ( rect ) => {
6754
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6755
+ tagsContainer.style.width = `calc( 100% - ${ realNameWidth }px)`;
6756
+ };
6757
+
6727
6758
  // Show tags
6728
6759
 
6729
6760
  const tagsContainer = document.createElement('div');
6730
6761
  tagsContainer.className = "lextags";
6731
- doAsync( () => {
6732
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6733
- tagsContainer.style.width = `calc( 100% - ${ realNameWidth })`;
6734
- } );
6762
+ this.root.appendChild( tagsContainer );
6735
6763
 
6736
- const _generateTags = () => {
6764
+ this.generateTags = ( value ) => {
6737
6765
 
6738
6766
  tagsContainer.innerHTML = "";
6739
6767
 
@@ -6777,9 +6805,9 @@ class Tags extends Widget {
6777
6805
  tagInput.focus();
6778
6806
  }
6779
6807
 
6780
- _generateTags();
6808
+ this.generateTags( value );
6781
6809
 
6782
- this.root.appendChild( tagsContainer );
6810
+ doAsync( this.onResize.bind( this ) );
6783
6811
  }
6784
6812
  }
6785
6813
 
@@ -6823,35 +6851,33 @@ class Checkbox extends Widget {
6823
6851
  }
6824
6852
  };
6825
6853
 
6854
+ this.onResize = ( rect ) => {
6855
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6856
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6857
+ };
6858
+
6826
6859
  var container = document.createElement( "div" );
6827
6860
  container.className = "lexcheckboxcont";
6828
- doAsync( () => {
6829
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6830
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
6831
- } );
6861
+ this.root.appendChild( container );
6832
6862
 
6833
6863
  let checkbox = document.createElement( "input" );
6834
6864
  checkbox.type = "checkbox";
6835
- checkbox.className = "lexcheckbox " + ( options.className ?? "" );
6865
+ checkbox.className = "lexcheckbox " + ( options.className ?? "primary" );
6836
6866
  checkbox.checked = value;
6837
6867
  checkbox.disabled = options.disabled ?? false;
6868
+ container.appendChild( checkbox );
6838
6869
 
6839
6870
  let valueName = document.createElement( "span" );
6840
6871
  valueName.className = "checkboxtext";
6841
6872
  valueName.innerHTML = options.label ?? "On";
6842
-
6843
- container.appendChild( checkbox );
6844
6873
  container.appendChild( valueName );
6845
6874
 
6846
6875
  checkbox.addEventListener( "change" , e => {
6847
6876
  this.set( checkbox.checked, false, e );
6848
6877
  });
6849
6878
 
6850
- this.root.appendChild( container );
6851
-
6852
6879
  if( options.suboptions )
6853
6880
  {
6854
- this.root.style.flexWrap = "wrap";
6855
6881
  let suboptions = document.createElement( "div" );
6856
6882
  suboptions.className = "lexcheckboxsubmenu";
6857
6883
  suboptions.toggleAttribute( "hidden", !checkbox.checked );
@@ -6863,6 +6889,8 @@ class Checkbox extends Widget {
6863
6889
 
6864
6890
  this.root.appendChild( suboptions );
6865
6891
  }
6892
+
6893
+ doAsync( this.onResize.bind( this ) );
6866
6894
  }
6867
6895
  }
6868
6896
 
@@ -6906,12 +6934,14 @@ class Toggle extends Widget {
6906
6934
  }
6907
6935
  };
6908
6936
 
6937
+ this.onResize = ( rect ) => {
6938
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6939
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6940
+ };
6941
+
6909
6942
  var container = document.createElement('div');
6910
6943
  container.className = "lextogglecont";
6911
- doAsync( () => {
6912
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6913
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
6914
- } );
6944
+ this.root.appendChild( container );
6915
6945
 
6916
6946
  let toggle = document.createElement('input');
6917
6947
  toggle.type = "checkbox";
@@ -6919,23 +6949,19 @@ class Toggle extends Widget {
6919
6949
  toggle.checked = value;
6920
6950
  toggle.iValue = value;
6921
6951
  toggle.disabled = options.disabled ?? false;
6952
+ container.appendChild( toggle );
6922
6953
 
6923
6954
  let valueName = document.createElement( 'span' );
6924
6955
  valueName.className = "toggletext";
6925
6956
  valueName.innerHTML = options.label ?? "On";
6926
-
6927
- container.appendChild( toggle );
6928
6957
  container.appendChild( valueName );
6929
6958
 
6930
6959
  toggle.addEventListener( "change" , e => {
6931
6960
  this.set( toggle.checked, false, e );
6932
6961
  });
6933
6962
 
6934
- this.root.appendChild( container );
6935
-
6936
6963
  if( options.suboptions )
6937
6964
  {
6938
- this.root.style.flexWrap = "wrap";
6939
6965
  let suboptions = document.createElement('div');
6940
6966
  suboptions.className = "lextogglesubmenu";
6941
6967
  suboptions.toggleAttribute( 'hidden', !toggle.checked );
@@ -6947,6 +6973,8 @@ class Toggle extends Widget {
6947
6973
 
6948
6974
  this.root.appendChild( suboptions );
6949
6975
  }
6976
+
6977
+ doAsync( this.onResize.bind( this ) );
6950
6978
  }
6951
6979
  }
6952
6980
 
@@ -6991,6 +7019,7 @@ class RadioGroup extends Widget {
6991
7019
 
6992
7020
  var container = document.createElement( 'div' );
6993
7021
  container.className = "lexradiogroup " + ( options.className ?? "" );
7022
+ this.root.appendChild( container );
6994
7023
 
6995
7024
  let labelSpan = document.createElement( 'span' );
6996
7025
  labelSpan.innerHTML = label;
@@ -7025,8 +7054,6 @@ class RadioGroup extends Widget {
7025
7054
  currentIndex = options.selected;
7026
7055
  this.set( currentIndex, true );
7027
7056
  }
7028
-
7029
- this.root.appendChild( container );
7030
7057
  }
7031
7058
  }
7032
7059
 
@@ -7056,8 +7083,7 @@ class ColorInput extends Widget {
7056
7083
  newValue = hexToRgb( newValue );
7057
7084
  }
7058
7085
 
7059
- // Means it was called from the color input listener, not the text
7060
- if( event )
7086
+ if( !this._skipTextUpdate )
7061
7087
  {
7062
7088
  textWidget.set( newValue, true, event );
7063
7089
  }
@@ -7070,20 +7096,22 @@ class ColorInput extends Widget {
7070
7096
  }
7071
7097
  };
7072
7098
 
7099
+ this.onResize = ( rect ) => {
7100
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7101
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7102
+ };
7103
+
7073
7104
  var container = document.createElement( 'span' );
7074
7105
  container.className = "lexcolor";
7075
- doAsync( () => {
7076
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7077
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7078
- } );
7106
+ this.root.appendChild( container );
7079
7107
 
7080
7108
  let color = document.createElement( 'input' );
7081
7109
  color.style.width = "32px";
7082
7110
  color.type = 'color';
7083
7111
  color.className = "colorinput";
7084
- color.id = "color" + simple_guidGenerator();
7085
7112
  color.useRGB = options.useRGB ?? false;
7086
- color.value = color.iValue = value;
7113
+ color.value = value;
7114
+ container.appendChild( color );
7087
7115
 
7088
7116
  if( options.disabled )
7089
7117
  {
@@ -7094,17 +7122,16 @@ class ColorInput extends Widget {
7094
7122
  this.set( e.target.value, false, e );
7095
7123
  }, false );
7096
7124
 
7097
- container.appendChild( color );
7098
-
7099
7125
  const textWidget = new TextInput( null, color.value, v => {
7126
+ this._skipTextUpdate = true;
7100
7127
  this.set( v );
7101
- }, { width: "calc( 100% - 32px )"});
7128
+ delete this._skipTextUpdate;
7129
+ }, { width: "calc( 100% - 32px )", disabled: options.disabled });
7102
7130
 
7103
7131
  textWidget.root.style.marginLeft = "4px";
7104
-
7105
7132
  container.appendChild( textWidget.root );
7106
7133
 
7107
- this.root.appendChild( container );
7134
+ doAsync( this.onResize.bind( this ) );
7108
7135
  }
7109
7136
  }
7110
7137
 
@@ -7140,22 +7167,36 @@ class RangeInput extends Widget {
7140
7167
  }
7141
7168
  };
7142
7169
 
7143
- var container = document.createElement( 'div' );
7170
+ this.onResize = ( rect ) => {
7171
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7172
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
7173
+ };
7174
+
7175
+ const container = document.createElement( 'div' );
7144
7176
  container.className = "lexrange";
7145
- doAsync( () => {
7146
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7147
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
7148
- } );
7177
+ this.root.appendChild( container );
7149
7178
 
7150
7179
  let slider = document.createElement( 'input' );
7151
7180
  slider.className = "lexrangeslider " + ( options.className ?? "" );
7152
- slider.value = slider.iValue = value;
7153
7181
  slider.min = options.min ?? 0;
7154
7182
  slider.max = options.max ?? 100;
7155
7183
  slider.step = options.step ?? 1;
7156
7184
  slider.type = "range";
7157
7185
  slider.disabled = options.disabled ?? false;
7158
7186
 
7187
+ if( value.constructor == Number )
7188
+ {
7189
+ value = clamp( value, +slider.min, +slider.max );
7190
+ }
7191
+
7192
+ if( options.left )
7193
+ {
7194
+ value = ( ( +slider.max ) - value + ( +slider.min ) );
7195
+ }
7196
+
7197
+ slider.value = value;
7198
+ container.appendChild( slider );
7199
+
7159
7200
  if( options.left ?? false )
7160
7201
  {
7161
7202
  slider.classList.add( "left" );
@@ -7192,14 +7233,7 @@ class RangeInput extends Widget {
7192
7233
  Widget._dispatchEvent( slider, "input", true );
7193
7234
  };
7194
7235
 
7195
- if( value.constructor == Number )
7196
- {
7197
- value = clamp( value, +slider.min, +slider.max );
7198
- }
7199
-
7200
- container.appendChild( slider );
7201
-
7202
- this.root.appendChild( container );
7236
+ doAsync( this.onResize.bind( this ) );
7203
7237
  }
7204
7238
  }
7205
7239
 
@@ -7247,15 +7281,18 @@ class NumberInput extends Widget {
7247
7281
  }
7248
7282
  };
7249
7283
 
7284
+ this.onResize = ( rect ) => {
7285
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7286
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
7287
+ };
7288
+
7250
7289
  var container = document.createElement( 'div' );
7251
7290
  container.className = "lexnumber";
7252
- doAsync( () => {
7253
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7254
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
7255
- } );
7291
+ this.root.appendChild( container );
7256
7292
 
7257
7293
  let box = document.createElement( 'div' );
7258
7294
  box.className = "numberbox";
7295
+ container.appendChild( box );
7259
7296
 
7260
7297
  let vecinput = document.createElement( 'input' );
7261
7298
  vecinput.id = "number_" + simple_guidGenerator();
@@ -7429,9 +7466,7 @@ class NumberInput extends Widget {
7429
7466
 
7430
7467
  vecinput.addEventListener( "mousedown", innerMouseDown );
7431
7468
 
7432
- container.appendChild( box );
7433
-
7434
- this.root.appendChild( container );
7469
+ doAsync( this.onResize.bind( this ) );
7435
7470
  }
7436
7471
  }
7437
7472
 
@@ -7483,14 +7518,16 @@ class Vector extends Widget {
7483
7518
  }
7484
7519
  };
7485
7520
 
7521
+ this.onResize = ( rect ) => {
7522
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7523
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7524
+ };
7525
+
7486
7526
  const vectorInputs = [];
7487
7527
 
7488
7528
  var container = document.createElement( 'div' );
7489
7529
  container.className = "lexvector";
7490
- doAsync( () => {
7491
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7492
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7493
- } );
7530
+ this.root.appendChild( container );
7494
7531
 
7495
7532
  const that = this;
7496
7533
 
@@ -7693,7 +7730,7 @@ class Vector extends Widget {
7693
7730
  }
7694
7731
  }, false );
7695
7732
 
7696
- this.root.appendChild( container );
7733
+ doAsync( this.onResize.bind( this ) );
7697
7734
  }
7698
7735
  }
7699
7736
 
@@ -7823,24 +7860,28 @@ class Pad extends Widget {
7823
7860
  }
7824
7861
  };
7825
7862
 
7863
+ this.onResize = ( rect ) => {
7864
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7865
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7866
+ };
7867
+
7826
7868
  var container = document.createElement( 'div' );
7827
7869
  container.className = "lexpad";
7828
- doAsync( () => {
7829
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7830
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7831
- } );
7870
+ this.root.appendChild( container );
7832
7871
 
7833
7872
  let pad = document.createElement('div');
7834
7873
  pad.id = "lexpad-" + name;
7835
7874
  pad.className = "lexinnerpad";
7836
7875
  pad.style.width = options.padSize ?? '96px';
7837
7876
  pad.style.height = options.padSize ?? '96px';
7877
+ container.appendChild( pad );
7838
7878
 
7839
7879
  let thumb = document.createElement('div');
7840
7880
  thumb.className = "lexpadthumb";
7841
7881
  thumb.value = new LX.vec2( value[ 0 ], value[ 1 ] );
7842
7882
  thumb.min = options.min ?? 0;
7843
7883
  thumb.max = options.max ?? 1;
7884
+ pad.appendChild( thumb );
7844
7885
 
7845
7886
  let _updateValue = v => {
7846
7887
  const [ w, h ] = [ pad.offsetWidth, pad.offsetHeight ];
@@ -7848,14 +7889,6 @@ class Pad extends Widget {
7848
7889
  thumb.style.transform = `translate(calc( ${ w * value0to1.x }px - 50% ), calc( ${ h * value0to1.y }px - 50%)`;
7849
7890
  }
7850
7891
 
7851
- doAsync( () => {
7852
- _updateValue( thumb.value )
7853
- } );
7854
-
7855
- pad.appendChild( thumb );
7856
- container.appendChild( pad );
7857
- this.root.appendChild( container );
7858
-
7859
7892
  pad.addEventListener( "mousedown", innerMouseDown );
7860
7893
 
7861
7894
  let that = this;
@@ -7874,6 +7907,7 @@ class Pad extends Widget {
7874
7907
  document.body.classList.add( 'noevents' );
7875
7908
  e.stopImmediatePropagation();
7876
7909
  e.stopPropagation();
7910
+ thumb.classList.add( "active" );
7877
7911
 
7878
7912
  if( options.onPress )
7879
7913
  {
@@ -7905,12 +7939,18 @@ class Pad extends Widget {
7905
7939
  doc.removeEventListener( 'mouseup', innerMouseUp );
7906
7940
  document.body.classList.remove( 'nocursor' );
7907
7941
  document.body.classList.remove( 'noevents' );
7942
+ thumb.classList.remove( "active" );
7908
7943
 
7909
7944
  if( options.onRelease )
7910
7945
  {
7911
7946
  options.onRelease.bind( thumb )( e, thumb );
7912
7947
  }
7913
7948
  }
7949
+
7950
+ doAsync( () => {
7951
+ this.onResize();
7952
+ _updateValue( thumb.value )
7953
+ } );
7914
7954
  }
7915
7955
  }
7916
7956
 
@@ -7940,12 +7980,14 @@ class Progress extends Widget {
7940
7980
  }
7941
7981
  };
7942
7982
 
7943
- var container = document.createElement('div');
7983
+ this.onResize = ( rect ) => {
7984
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7985
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7986
+ };
7987
+
7988
+ const container = document.createElement('div');
7944
7989
  container.className = "lexprogress";
7945
- doAsync( () => {
7946
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7947
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7948
- } );
7990
+ this.root.appendChild( container );
7949
7991
 
7950
7992
  // add slider (0-1 if not specified different )
7951
7993
 
@@ -7959,6 +8001,7 @@ class Progress extends Widget {
7959
8001
  progress.high = options.high ?? progress.high;
7960
8002
  progress.optimum = options.optimum ?? progress.optimum;
7961
8003
  progress.value = value;
8004
+ container.appendChild( progress );
7962
8005
 
7963
8006
  const _updateColor = () => {
7964
8007
 
@@ -7976,9 +8019,6 @@ class Progress extends Widget {
7976
8019
  progress.style.background = `color-mix(in srgb, ${backgroundColor} 20%, transparent)`;
7977
8020
  };
7978
8021
 
7979
- container.appendChild( progress );
7980
- this.root.appendChild( container );
7981
-
7982
8022
  if( options.showValue )
7983
8023
  {
7984
8024
  if( document.getElementById('progressvalue-' + name ) )
@@ -8045,6 +8085,8 @@ class Progress extends Widget {
8045
8085
  }
8046
8086
 
8047
8087
  _updateColor();
8088
+
8089
+ doAsync( this.onResize.bind( this ) );
8048
8090
  }
8049
8091
  }
8050
8092
 
@@ -8065,15 +8107,17 @@ class FileInput extends Widget {
8065
8107
  let type = options.type ?? 'text';
8066
8108
  let read = options.read ?? true;
8067
8109
 
8110
+ this.onResize = ( rect ) => {
8111
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
8112
+ input.style.width = `calc( 100% - ${ realNameWidth }px)`;
8113
+ };
8114
+
8068
8115
  // Create hidden input
8069
8116
  let input = document.createElement( 'input' );
8070
8117
  input.className = "lexfileinput";
8071
8118
  input.type = 'file';
8072
8119
  input.disabled = options.disabled ?? false;
8073
- doAsync( () => {
8074
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
8075
- input.style.width = `calc( 100% - ${ realNameWidth } - 10%)`;
8076
- } );
8120
+ this.root.appendChild( input );
8077
8121
 
8078
8122
  if( options.placeholder )
8079
8123
  {
@@ -8106,13 +8150,11 @@ class FileInput extends Widget {
8106
8150
  callback( null );
8107
8151
  });
8108
8152
 
8109
- this.root.appendChild( input );
8110
-
8111
8153
  if( local )
8112
8154
  {
8113
8155
  let settingsDialog = null;
8114
8156
 
8115
- const settingButton = new Button(null, "<a style='margin-top: 0px;' class='fa-solid fa-gear'></a>", () => {
8157
+ const settingButton = new Button(null, "", () => {
8116
8158
 
8117
8159
  if( settingsDialog )
8118
8160
  {
@@ -8124,10 +8166,12 @@ class FileInput extends Widget {
8124
8166
  p.addButton( null, "Reload", v => { input.dispatchEvent( new Event( 'change' ) ) } );
8125
8167
  }, { onclose: ( root ) => { root.remove(); settingsDialog = null; } } );
8126
8168
 
8127
- }, { className: "micro", skipInlineCount: true, title: "Settings" });
8169
+ }, { skipInlineCount: true, title: "Settings", disabled: options.disabled, icon: "fa-solid fa-gear" });
8128
8170
 
8129
8171
  this.root.appendChild( settingButton.root );
8130
8172
  }
8173
+
8174
+ doAsync( this.onResize.bind( this ) );
8131
8175
  }
8132
8176
  }
8133
8177
 
@@ -8185,9 +8229,9 @@ class Tree extends Widget {
8185
8229
  if( options.filter )
8186
8230
  {
8187
8231
  nodeFilterInput = document.createElement('input');
8188
- nodeFilterInput.id = "lexnodetree_filter";
8232
+ nodeFilterInput.className = "lexnodetree_filter";
8189
8233
  nodeFilterInput.setAttribute("placeholder", "Filter..");
8190
- nodeFilterInput.style.width = "calc( 100% - 17px )";
8234
+ nodeFilterInput.style.width = "100%";
8191
8235
  nodeFilterInput.addEventListener('input', () => {
8192
8236
  this.innerTree.refresh();
8193
8237
  });
@@ -8337,11 +8381,11 @@ class Counter extends Widget {
8337
8381
  container.className = "lexcounter";
8338
8382
  this.root.appendChild( container );
8339
8383
 
8340
- const substrButton = new Button(null, "<a style='margin-top: 0px;' class='fa-solid fa-minus'></a>", ( value, e ) => {
8384
+ const substrButton = new Button(null, "", ( value, e ) => {
8341
8385
  let mult = step ?? 1;
8342
8386
  if( e.shiftKey ) mult *= 10;
8343
8387
  this.set( counterText.count - mult, false, e );
8344
- }, { className: "micro", skipInlineCount: true, title: "Minus" });
8388
+ }, { skipInlineCount: true, title: "Minus", icon: "fa-solid fa-minus" });
8345
8389
 
8346
8390
  container.appendChild( substrButton.root );
8347
8391
 
@@ -8363,12 +8407,11 @@ class Counter extends Widget {
8363
8407
  containerBox.appendChild( counterLabel );
8364
8408
  }
8365
8409
 
8366
- const addButton = new Button(null, "<a style='margin-top: 0px;' class='fa-solid fa-plus'></a>", ( value, e ) => {
8410
+ const addButton = new Button(null, "", ( value, e ) => {
8367
8411
  let mult = step ?? 1;
8368
8412
  if( e.shiftKey ) mult *= 10;
8369
8413
  this.set( counterText.count + mult, false, e );
8370
- }, { className: "micro", skipInlineCount: true, title: "Plus" });
8371
-
8414
+ }, { skipInlineCount: true, title: "Plus", icon: "fa-solid fa-plus" });
8372
8415
  container.appendChild( addButton.root );
8373
8416
  }
8374
8417
  }
@@ -8391,12 +8434,14 @@ class Table extends Widget {
8391
8434
 
8392
8435
  super( Widget.TABLE, name, null, options );
8393
8436
 
8437
+ this.onResize = ( rect ) => {
8438
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
8439
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
8440
+ };
8441
+
8394
8442
  const container = document.createElement('div');
8395
8443
  container.className = "lextable";
8396
- doAsync( () => {
8397
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
8398
- container.style.width = `calc( 100% - ${ realNameWidth })`;
8399
- } );
8444
+ this.root.appendChild( container );
8400
8445
 
8401
8446
  this.centered = options.centered ?? false;
8402
8447
  if( this.centered === true )
@@ -8404,13 +8449,16 @@ class Table extends Widget {
8404
8449
  container.classList.add( "centered" );
8405
8450
  }
8406
8451
 
8407
- const table = document.createElement( 'table' );
8408
- container.appendChild( table );
8452
+ this.filter = options.filter ?? false;
8453
+ this.toggleColumns = options.toggleColumns ?? false;
8454
+ this.customFilters = options.customFilters ?? false;
8455
+ this.activeCustomFilters = {};
8409
8456
 
8410
8457
  data.head = data.head ?? [];
8411
8458
  data.body = data.body ?? [];
8412
- data.colVisibilityMap = { };
8413
8459
  data.checkMap = { };
8460
+ data.colVisibilityMap = { };
8461
+ data.head.forEach( (col, index) => { data.colVisibilityMap[ index ] = true; })
8414
8462
 
8415
8463
  const compareFn = ( idx, order, a, b) => {
8416
8464
  if (a[idx] < b[idx]) return -order;
@@ -8420,14 +8468,105 @@ class Table extends Widget {
8420
8468
 
8421
8469
  const sortFn = ( idx, sign ) => {
8422
8470
  data.body = data.body.sort( compareFn.bind( this, idx, sign ) );
8423
- this.refreshTable();
8471
+ this.refresh();
8472
+ }
8473
+
8474
+ // Append header
8475
+ if( this.filter || this.customFilters || this.toggleColumns )
8476
+ {
8477
+ const headerContainer = LX.makeContainer( [ "100%", "auto" ] );
8478
+
8479
+ if( this.filter )
8480
+ {
8481
+ const filterOptions = LX.deepCopy( options );
8482
+ filterOptions.placeholder = `Filter ${ this.filter }...`;
8483
+ filterOptions.skipWidget = true;
8484
+ filterOptions.trigger = "input";
8485
+ filterOptions.inputClass = "outline";
8486
+
8487
+ let filter = new TextInput(null, "", ( v ) => {
8488
+ this._currentFilter = v;
8489
+ this.refresh();
8490
+ }, filterOptions );
8491
+
8492
+ headerContainer.appendChild( filter.root );
8493
+ }
8494
+
8495
+ if( this.customFilters )
8496
+ {
8497
+ const icon = LX.makeIcon( "circle-plus", null, "sm" );
8498
+
8499
+ for( let f of this.customFilters )
8500
+ {
8501
+ const customFilterBtn = new Button(null, icon.innerHTML + f.name, ( v ) => {
8502
+
8503
+ const menuOptions = f.options.map( ( colName, idx ) => {
8504
+ const item = {
8505
+ name: colName,
8506
+ checked: !!this.activeCustomFilters[ colName ],
8507
+ callback: (key, dom, v) => {
8508
+ if( v ) { this.activeCustomFilters[ key ] = f.name; }
8509
+ else {
8510
+ delete this.activeCustomFilters[ key ];
8511
+ }
8512
+ this.refresh();
8513
+ }
8514
+ }
8515
+ return item;
8516
+ } );
8517
+ new DropdownMenu( customFilterBtn.root, menuOptions, { side: "bottom", align: "start" });
8518
+ }, { buttonClass: " primary dashed" } );
8519
+ headerContainer.appendChild( customFilterBtn.root );
8520
+ }
8521
+
8522
+ // const resetIcon = LX.makeIcon( "xmark", null, "sm" );
8523
+ this._resetCustomFiltersBtn = new Button(null, "resetButton", ( v ) => {
8524
+ this.activeCustomFilters = {};
8525
+ this.refresh();
8526
+ this._resetCustomFiltersBtn.root.classList.add( "hidden" );
8527
+ }, { title: "Reset filters", icon: "fa fa-xmark" } );
8528
+ headerContainer.appendChild( this._resetCustomFiltersBtn.root );
8529
+ this._resetCustomFiltersBtn.root.classList.add( "hidden" );
8530
+ }
8531
+
8532
+ if( this.toggleColumns )
8533
+ {
8534
+ const icon = LX.makeIcon( "sliders" );
8535
+ const toggleColumnsBtn = new Button( "toggleColumnsBtn", icon.innerHTML + "View", (value, e) => {
8536
+ const menuOptions = data.head.map( ( colName, idx ) => {
8537
+ const item = {
8538
+ name: colName,
8539
+ icon: "check",
8540
+ callback: () => {
8541
+ data.colVisibilityMap[ idx ] = !data.colVisibilityMap[ idx ];
8542
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8543
+ cells.forEach(cell => {
8544
+ cell.style.display = (cell.style.display === "none") ? "" : "none";
8545
+ });
8546
+ }
8547
+ }
8548
+ if( !data.colVisibilityMap[ idx ] ) delete item.icon;
8549
+ return item;
8550
+ } );
8551
+ new DropdownMenu( e.target, menuOptions, { side: "bottom", align: "end" });
8552
+ }, { hideName: true } );
8553
+ headerContainer.appendChild( toggleColumnsBtn.root );
8554
+ toggleColumnsBtn.root.style.marginLeft = "auto";
8555
+ }
8556
+
8557
+ container.appendChild( headerContainer );
8424
8558
  }
8425
8559
 
8426
- this.refreshTable = () => {
8560
+ const table = document.createElement( 'table' );
8561
+ container.appendChild( table );
8562
+
8563
+ this.refresh = () => {
8564
+
8565
+ this._currentFilter = this._currentFilter ?? "";
8427
8566
 
8428
8567
  table.innerHTML = "";
8429
8568
 
8430
- let rowOffsetCount = 0;
8569
+ this.rowOffsetCount = 0;
8431
8570
 
8432
8571
  // Head
8433
8572
  {
@@ -8442,7 +8581,7 @@ class Table extends Widget {
8442
8581
  const th = document.createElement( 'th' );
8443
8582
  th.style.width = "0px";
8444
8583
  hrow.appendChild( th );
8445
- rowOffsetCount++;
8584
+ this.rowOffsetCount++;
8446
8585
  }
8447
8586
 
8448
8587
  if( options.selectable )
@@ -8451,7 +8590,7 @@ class Table extends Widget {
8451
8590
  th.style.width = "0px";
8452
8591
  const input = document.createElement( 'input' );
8453
8592
  input.type = "checkbox";
8454
- input.className = "lexcheckbox";
8593
+ input.className = "lexcheckbox accent";
8455
8594
  input.checked = data.checkMap[ ":root" ] ?? false;
8456
8595
  th.appendChild( input );
8457
8596
 
@@ -8467,14 +8606,15 @@ class Table extends Widget {
8467
8606
  }
8468
8607
  });
8469
8608
 
8470
- rowOffsetCount++;
8609
+ this.rowOffsetCount++;
8471
8610
  hrow.appendChild( th );
8472
8611
  }
8473
8612
 
8474
8613
  for( const headData of data.head )
8475
8614
  {
8476
8615
  const th = document.createElement( 'th' );
8477
- th.innerHTML = `${ headData } <a class="fa-solid fa-sort"></a>`;
8616
+ th.innerHTML = `<span>${ headData }</span>`;
8617
+ th.querySelector( "span" ).appendChild( LX.makeIcon( "menu-arrows", null, "sm" ) );
8478
8618
 
8479
8619
  const idx = data.head.indexOf( headData );
8480
8620
  if( this.centered && this.centered.indexOf( idx ) > -1 )
@@ -8482,19 +8622,29 @@ class Table extends Widget {
8482
8622
  th.classList.add( "centered" );
8483
8623
  }
8484
8624
 
8485
- th.addEventListener( 'click', event => {
8486
- new LX.DropdownMenu( event.target, [
8487
- { name: "Asc", icon: "up", callback: sortFn.bind( this, idx, 1 ) },
8488
- { name: "Desc", icon: "down", callback: sortFn.bind( this, idx, -1 ) },
8625
+ const menuOptions = [
8626
+ { name: "Asc", icon: "up", callback: sortFn.bind( this, idx, 1 ) },
8627
+ { name: "Desc", icon: "down", callback: sortFn.bind( this, idx, -1 ) }
8628
+ ];
8629
+
8630
+ if( this.toggleColumns )
8631
+ {
8632
+ menuOptions.push(
8489
8633
  null,
8490
- { name: "Hide", icon: "eye-slash", callback: () => {
8491
- data.colVisibilityMap[ idx ] = 0;
8492
- const cells = table.querySelectorAll(`tr > *:nth-child(${idx + rowOffsetCount + 1})`);
8493
- cells.forEach(cell => {
8494
- cell.style.display = (cell.style.display === "none") ? "" : "none";
8495
- });
8496
- } }
8497
- ], { side: "bottom", align: "start" });
8634
+ {
8635
+ name: "Hide", icon: "eye-slash", callback: () => {
8636
+ data.colVisibilityMap[ idx ] = false;
8637
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8638
+ cells.forEach(cell => {
8639
+ cell.style.display = (cell.style.display === "none") ? "" : "none";
8640
+ });
8641
+ }
8642
+ }
8643
+ );
8644
+ }
8645
+
8646
+ th.addEventListener( 'click', event => {
8647
+ new DropdownMenu( event.target, menuOptions, { side: "bottom", align: "start" });
8498
8648
  });
8499
8649
 
8500
8650
  hrow.appendChild( th );
@@ -8532,15 +8682,23 @@ class Table extends Widget {
8532
8682
  v.style.transition = `none`;
8533
8683
  } );
8534
8684
  flushCss( fromRow );
8535
- rIdx = null;
8536
8685
 
8537
8686
  if( movePending )
8538
8687
  {
8688
+ // Modify inner data first
8689
+ const fromIdx = rIdx - 1;
8690
+ const targetIdx = movePending[ 1 ] - 1;
8691
+ var b = data.body[fromIdx];
8692
+ data.body[fromIdx] = data.body[targetIdx];
8693
+ data.body[targetIdx] = b;
8694
+
8539
8695
  const parent = movePending[ 0 ].parentNode;
8540
8696
  parent.insertChildAtIndex( movePending[ 0 ], movePending[ 1 ] );
8541
8697
  movePending = null;
8542
8698
  }
8543
8699
 
8700
+ rIdx = null;
8701
+
8544
8702
  doAsync( () => {
8545
8703
  Array.from( table.rows ).forEach( v => {
8546
8704
  v.style.transition = `transform 0.2s ease-in`;
@@ -8556,13 +8714,50 @@ class Table extends Widget {
8556
8714
  fromRow.style.transform = `translateY(${fromRow.dY}px)`;
8557
8715
  };
8558
8716
 
8559
-
8560
8717
  for( let r = 0; r < data.body.length; ++r )
8561
8718
  {
8562
8719
  const bodyData = data.body[ r ];
8720
+
8721
+ if( this.filter )
8722
+ {
8723
+ const filterColIndex = data.head.indexOf( this.filter );
8724
+ if( filterColIndex > -1 )
8725
+ {
8726
+ if( !bodyData[ filterColIndex ].toLowerCase().includes( this._currentFilter.toLowerCase() ) )
8727
+ {
8728
+ continue;
8729
+ }
8730
+ }
8731
+ }
8732
+
8733
+ if( Object.keys( this.activeCustomFilters ).length )
8734
+ {
8735
+ let acfMap = {};
8736
+
8737
+ this._resetCustomFiltersBtn.root.classList.remove( "hidden" );
8738
+
8739
+ for( let acfValue in this.activeCustomFilters )
8740
+ {
8741
+ const acfName = this.activeCustomFilters[ acfValue ];
8742
+ acfMap[ acfName ] = acfMap[ acfName ] ?? false;
8743
+
8744
+ const filterColIndex = data.head.indexOf( acfName );
8745
+ if( filterColIndex > -1 )
8746
+ {
8747
+ acfMap[ acfName ] |= ( bodyData[ filterColIndex ] === acfValue );
8748
+ }
8749
+ }
8750
+
8751
+ const show = Object.values( acfMap ).reduce( ( e, acc ) => acc *= e );
8752
+ if( !show )
8753
+ {
8754
+ continue;
8755
+ }
8756
+ }
8757
+
8563
8758
  const row = document.createElement( 'tr' );
8564
8759
  const rowId = LX.getSupportedDOMName( bodyData.join( '-' ) );
8565
- row.setAttribute( "rowId", rowId.substr(0, 16) );
8760
+ row.setAttribute( "rowId", rowId.substr(0, 32) );
8566
8761
 
8567
8762
  if( options.sortable )
8568
8763
  {
@@ -8613,7 +8808,7 @@ class Table extends Widget {
8613
8808
  const td = document.createElement( 'td' );
8614
8809
  const input = document.createElement( 'input' );
8615
8810
  input.type = "checkbox";
8616
- input.className = "lexcheckbox";
8811
+ input.className = "lexcheckbox accent";
8617
8812
  input.checked = data.checkMap[ rowId ];
8618
8813
  td.appendChild( input );
8619
8814
 
@@ -8670,14 +8865,15 @@ class Table extends Widget {
8670
8865
  {
8671
8866
  button = LX.makeIcon( "more-horizontal", "Menu" );
8672
8867
  button.addEventListener( 'click', function( event ) {
8673
- addContextMenu( null, event, c => {
8674
- if( options.onMenuAction )
8675
- {
8676
- options.onMenuAction( c );
8677
- return;
8678
- }
8679
- console.warn( "Using <Menu action> without action callbacks." );
8680
- } );
8868
+ if( !options.onMenuAction )
8869
+ {
8870
+ return;
8871
+ }
8872
+
8873
+ const menuOptions = options.onMenuAction( r, data );
8874
+ console.assert( menuOptions.length, "Add items to the Menu Action Dropdown!" );
8875
+
8876
+ new DropdownMenu( event.target, menuOptions, { side: "bottom", align: "end" });
8681
8877
  });
8682
8878
  }
8683
8879
  else // custom actions
@@ -8691,7 +8887,7 @@ class Table extends Widget {
8691
8887
  const mustRefresh = action.callback( bodyData, table, e );
8692
8888
  if( mustRefresh )
8693
8889
  {
8694
- this.refreshTable();
8890
+ this.refresh();
8695
8891
  }
8696
8892
  });
8697
8893
  }
@@ -8713,7 +8909,7 @@ class Table extends Widget {
8713
8909
  const idx = parseInt( v );
8714
8910
  if( !data.colVisibilityMap[ idx ] )
8715
8911
  {
8716
- const cells = table.querySelectorAll(`tr > *:nth-child(${idx + rowOffsetCount + 1})`);
8912
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8717
8913
  cells.forEach(cell => {
8718
8914
  cell.style.display = (cell.style.display === "none") ? "" : "none";
8719
8915
  });
@@ -8721,9 +8917,9 @@ class Table extends Widget {
8721
8917
  }
8722
8918
  }
8723
8919
 
8724
- this.refreshTable();
8920
+ this.refresh();
8725
8921
 
8726
- this.root.appendChild( container );
8922
+ doAsync( this.onResize.bind( this ) );
8727
8923
  }
8728
8924
  }
8729
8925
 
@@ -8759,7 +8955,7 @@ class Panel {
8759
8955
  root.className += " " + options.className;
8760
8956
  }
8761
8957
 
8762
- root.style.width = options.width || "calc( 100% - 6px )";
8958
+ root.style.width = options.width || "100%";
8763
8959
  root.style.height = options.height || "100%";
8764
8960
  Object.assign( root.style, options.style ?? {} );
8765
8961
 
@@ -8874,10 +9070,11 @@ class Panel {
8874
9070
 
8875
9071
  /**
8876
9072
  * @method endLine
9073
+ * @param {String} className Extra class to customize inline widgets parent container
8877
9074
  * @description Stop inlining widgets. Use it only if the number of widgets to be inlined is NOT specified.
8878
9075
  */
8879
9076
 
8880
- endLine( justifyContent ) {
9077
+ endLine( className ) {
8881
9078
 
8882
9079
  if( this._inlineWidgetsLeft == -1 )
8883
9080
  {
@@ -8892,9 +9089,9 @@ class Panel {
8892
9089
  this._inlineContainer = document.createElement('div');
8893
9090
  this._inlineContainer.className = "lexinlinewidgets";
8894
9091
 
8895
- if( justifyContent )
9092
+ if( className )
8896
9093
  {
8897
- this._inlineContainer.style.justifyContent = justifyContent;
9094
+ this._inlineContainer.className += ` ${ className }`;
8898
9095
  }
8899
9096
  }
8900
9097
 
@@ -9037,7 +9234,7 @@ class Panel {
9037
9234
  }
9038
9235
  else
9039
9236
  {
9040
- el.classList.add("nobranch");
9237
+ el.className += " nobranch w-full";
9041
9238
  this.root.appendChild( el );
9042
9239
  }
9043
9240
  }
@@ -9096,12 +9293,12 @@ class Panel {
9096
9293
 
9097
9294
  let widget = new TextInput( null, null, null, options )
9098
9295
  const element = widget.root;
9099
- element.className += " lexfilter noname";
9296
+ element.className += " lexfilter";
9100
9297
 
9101
9298
  let input = document.createElement('input');
9102
9299
  input.className = 'lexinput-filter';
9103
9300
  input.setAttribute( "placeholder", options.placeholder );
9104
- input.style.width = "calc( 100% - 17px )";
9301
+ input.style.width = "100%";
9105
9302
  input.value = options.filterValue || "";
9106
9303
 
9107
9304
  let searchIcon = document.createElement('a');
@@ -9109,7 +9306,7 @@ class Panel {
9109
9306
  element.appendChild( searchIcon );
9110
9307
  element.appendChild( input );
9111
9308
 
9112
- input.addEventListener("input", (e) => {
9309
+ input.addEventListener("input", e => {
9113
9310
  if( options.callback )
9114
9311
  {
9115
9312
  options.callback( input.value, e );
@@ -9279,6 +9476,7 @@ class Panel {
9279
9476
  * pattern: Regular expression that value must match
9280
9477
  * trigger: Choose onchange trigger (default, input) [default]
9281
9478
  * inputWidth: Width of the text input
9479
+ * inputClass: Class to add to the native input element
9282
9480
  * skipReset: Don't add the reset value button when value changes
9283
9481
  * float: Justify input text content
9284
9482
  * justifyName: Justify name content
@@ -9318,6 +9516,7 @@ class Panel {
9318
9516
 
9319
9517
  addLabel( value, options = {} ) {
9320
9518
  options.disabled = true;
9519
+ options.inputClass = ( options.inputClass ?? "" ) + " nobg";
9321
9520
  const widget = this.addText( null, value, null, options );
9322
9521
  widget.type = Widget.LABEL;
9323
9522
  return widget;
@@ -9334,6 +9533,7 @@ class Panel {
9334
9533
  * icon: Icon class to show as button value
9335
9534
  * img: Path to image to show as button value
9336
9535
  * title: Text to show in native Element title
9536
+ * buttonClass: Class to add to the native button element
9337
9537
  */
9338
9538
 
9339
9539
  addButton( name, value, callback, options = {} ) {
@@ -9873,7 +10073,6 @@ class Branch {
9873
10073
  root.className += " " + options.className;
9874
10074
  }
9875
10075
 
9876
- root.style.width = "calc(100% - 7px)";
9877
10076
  root.style.margin = "0 auto";
9878
10077
 
9879
10078
  var that = this;
@@ -9911,7 +10110,7 @@ class Branch {
9911
10110
  this.grabber.setAttribute( "hidden", true );
9912
10111
  doAsync( () => {
9913
10112
  this.content.setAttribute( "hidden", true );
9914
- }, 15 );
10113
+ }, 10 );
9915
10114
  }
9916
10115
 
9917
10116
  this.onclick = function( e ) {
@@ -10047,7 +10246,7 @@ class Branch {
10047
10246
  var size = this.grabber.style.marginLeft;
10048
10247
 
10049
10248
  // Update sizes of widgets inside
10050
- for( var i = 0; i < this.widgets.length; i++ )
10249
+ for( let i = 0; i < this.widgets.length; i++ )
10051
10250
  {
10052
10251
  let widget = this.widgets[ i ];
10053
10252
  const element = widget.root;
@@ -10057,26 +10256,22 @@ class Branch {
10057
10256
  continue;
10058
10257
  }
10059
10258
 
10060
- var name = element.children[ 0 ];
10061
- var value = element.children[ 1 ];
10259
+ let name = element.children[ 0 ];
10260
+ let value = element.children[ 1 ];
10062
10261
 
10063
10262
  name.style.width = size;
10064
- let padding = "0px";
10263
+ name.style.minWidth = size;
10264
+
10065
10265
  switch( widget.type )
10066
10266
  {
10067
- case Widget.FILE:
10068
- padding = "10%";
10069
- break;
10267
+ case Widget.CUSTOM:
10268
+ case Widget.ARRAY:
10269
+ continue;
10070
10270
  };
10071
10271
 
10072
- value.style.width = "-moz-calc( 100% - " + size + " - " + padding + " )";
10073
- value.style.width = "-webkit-calc( 100% - " + size + " - " + padding + " )";
10074
- value.style.width = "calc( 100% - " + size + " - " + padding + " )";
10075
-
10076
- if( widget.onresize )
10077
- {
10078
- widget.onresize();
10079
- }
10272
+ value.style.width = "-moz-calc( 100% - " + size + " )";
10273
+ value.style.width = "-webkit-calc( 100% - " + size + " )";
10274
+ value.style.width = "calc( 100% - " + size + " )";
10080
10275
  }
10081
10276
  }
10082
10277
  };
@@ -10100,7 +10295,8 @@ class Footer {
10100
10295
  root.className = "lexfooter";
10101
10296
 
10102
10297
  const wrapper = document.createElement( "div" );
10103
- wrapper.className = "wrapper";
10298
+ wrapper.style.minHeight = "48px";
10299
+ wrapper.className = "w-full";
10104
10300
  root.appendChild( wrapper );
10105
10301
 
10106
10302
  if( options.columns && options.columns.constructor == Array )
@@ -10175,6 +10371,10 @@ class Footer {
10175
10371
  // Append directly to body
10176
10372
  const parent = options.parent ?? document.body;
10177
10373
  parent.appendChild( root );
10374
+
10375
+ // Set always at bottom
10376
+ root.previousElementSibling.style.height = "unset";
10377
+ root.previousElementSibling.style.flexGrow = "1";
10178
10378
  }
10179
10379
 
10180
10380
  }
@@ -10204,7 +10404,7 @@ class Dialog {
10204
10404
  draggable = options.draggable ?? true,
10205
10405
  modal = options.modal ?? false;
10206
10406
 
10207
- var root = document.createElement('dialog');
10407
+ let root = document.createElement('dialog');
10208
10408
  root.className = "lexdialog " + (options.className ?? "");
10209
10409
  root.id = options.id ?? "dialog" + Dialog._last_id++;
10210
10410
  LX.root.appendChild( root );
@@ -10215,7 +10415,7 @@ class Dialog {
10215
10415
 
10216
10416
  let that = this;
10217
10417
 
10218
- var titleDiv = document.createElement('div');
10418
+ const titleDiv = document.createElement('div');
10219
10419
 
10220
10420
  if( title )
10221
10421
  {
@@ -10280,7 +10480,7 @@ class Dialog {
10280
10480
  }, { icon: "fa-regular fa-window-restore" });
10281
10481
  };
10282
10482
 
10283
- root.appendChild(titleDiv);
10483
+ root.appendChild( titleDiv );
10284
10484
  }
10285
10485
 
10286
10486
  if( options.closable ?? true )
@@ -10373,7 +10573,6 @@ class Dialog {
10373
10573
  root.style.left = position[ 0 ] ?? "50%";
10374
10574
  root.style.top = position[ 1 ] ?? "50%";
10375
10575
 
10376
- panel.root.style.width = "calc( 100% - 30px )";
10377
10576
  panel.root.style.height = title ? "calc( 100% - " + ( titleDiv.offsetHeight + 30 ) + "px )" : "calc( 100% - 51px )";
10378
10577
  }
10379
10578
 
@@ -10445,8 +10644,8 @@ class PocketDialog extends Dialog {
10445
10644
  this.root.style.top = dragMargin + "px";
10446
10645
  }
10447
10646
 
10448
- this.panel.root.style.width = "calc( 100% - 12px )";
10449
- this.panel.root.style.height = "calc( 100% - 40px )";
10647
+ this.panel.root.style.width = "100%";
10648
+ this.panel.root.style.height = "100%";
10450
10649
  this.dock_pos = PocketDialog.TOP;
10451
10650
 
10452
10651
  this.minimized = false;
@@ -10479,7 +10678,7 @@ class PocketDialog extends Dialog {
10479
10678
 
10480
10679
  if( float )
10481
10680
  {
10482
- for( var i = 0; i < float.length; i++ )
10681
+ for( let i = 0; i < float.length; i++ )
10483
10682
  {
10484
10683
  const t = float[i];
10485
10684
  switch( t )
@@ -10612,14 +10811,14 @@ class ContextMenu {
10612
10811
  contextmenu.className = "lexcontextmenu";
10613
10812
  c.appendChild( contextmenu );
10614
10813
 
10615
- for( var i = 0; i < o[k].length; ++i )
10814
+ for( let i = 0; i < o[k].length; ++i )
10616
10815
  {
10617
10816
  const subitem = o[ k ][ i ];
10618
10817
  const subkey = Object.keys( subitem )[ 0 ];
10619
10818
  this._createEntry(subitem, subkey, contextmenu, d);
10620
10819
  }
10621
10820
 
10622
- var rect = c.getBoundingClientRect();
10821
+ const rect = c.getBoundingClientRect();
10623
10822
  contextmenu.style.left = rect.width + "px";
10624
10823
  contextmenu.style.marginTop = 3.5 - c.offsetHeight + "px";
10625
10824
 
@@ -10772,10 +10971,10 @@ class ContextMenu {
10772
10971
  _item[ key ].unshift( parent );
10773
10972
  }
10774
10973
 
10775
- for( var child of _item[ key ] )
10974
+ for( let child of _item[ key ] )
10776
10975
  {
10777
10976
  let k = Object.keys( child )[ 0 ];
10778
- for( var i = 0; i < child[ k ].length; ++i )
10977
+ for( let i = 0; i < child[ k ].length; ++i )
10779
10978
  {
10780
10979
  setParent( child );
10781
10980
  }
@@ -10816,7 +11015,7 @@ LX.ContextMenu = ContextMenu;
10816
11015
 
10817
11016
  function addContextMenu( title, event, callback, options )
10818
11017
  {
10819
- var menu = new ContextMenu( event, title, options );
11018
+ const menu = new ContextMenu( event, title, options );
10820
11019
  LX.root.appendChild( menu.root );
10821
11020
 
10822
11021
  if( callback )
@@ -10847,7 +11046,8 @@ class CanvasCurve {
10847
11046
  element.style.minHeight = "20px";
10848
11047
 
10849
11048
  element.bgcolor = options.bgColor || LX.getThemeColor( "global-intense-background" );
10850
- element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected-light" );
11049
+ element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected" );
11050
+ element.activepointscolor = options.activePointsColor || LX.getThemeColor( "global-selected-light" );
10851
11051
  element.linecolor = options.lineColor || "#555";
10852
11052
  element.value = value || [];
10853
11053
  element.xrange = options.xrange || [ 0, 1 ]; // min, max
@@ -10863,7 +11063,8 @@ class CanvasCurve {
10863
11063
 
10864
11064
  LX.addSignal( "@on_new_color_scheme", (el, value) => {
10865
11065
  element.bgcolor = options.bgColor || LX.getThemeColor( "global-intense-background" );
10866
- element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected-light" );
11066
+ element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected" );
11067
+ element.activepointscolor = options.activePointsColor || LX.getThemeColor( "global-selected-light" );
10867
11068
  this.redraw();
10868
11069
  } );
10869
11070
 
@@ -10884,11 +11085,11 @@ class CanvasCurve {
10884
11085
  return element.defaulty;
10885
11086
  }
10886
11087
 
10887
- var last = [ element.xrange[ 0 ], element.defaulty ];
10888
- var f = 0;
10889
- for( var i = 0; i < element.value.length; i += 1 )
11088
+ let last = [ element.xrange[ 0 ], element.defaulty ];
11089
+ let f = 0;
11090
+ for( let i = 0; i < element.value.length; i += 1 )
10890
11091
  {
10891
- var v = element.value[ i ];
11092
+ let v = element.value[ i ];
10892
11093
  if( x == v[ 0 ] ) return v[ 1 ];
10893
11094
  if( x < v[ 0 ] )
10894
11095
  {
@@ -10906,9 +11107,9 @@ class CanvasCurve {
10906
11107
 
10907
11108
  element.resample = function( samples ) {
10908
11109
 
10909
- var r = [];
10910
- var dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
10911
- for( var i = element.xrange[0]; i <= element.xrange[1]; i += dx )
11110
+ let r = [];
11111
+ let dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
11112
+ for( let i = element.xrange[0]; i <= element.xrange[1]; i += dx )
10912
11113
  {
10913
11114
  r.push( element.getValueAt(i) );
10914
11115
  }
@@ -10917,9 +11118,9 @@ class CanvasCurve {
10917
11118
 
10918
11119
  element.addValue = function(v) {
10919
11120
 
10920
- for( var i = 0; i < element.value; i++ )
11121
+ for( let i = 0; i < element.value; i++ )
10921
11122
  {
10922
- var value = element.value[i];
11123
+ let value = element.value[i];
10923
11124
  if(value[0] < v[0]) continue;
10924
11125
  element.value.splice(i,0,v);
10925
11126
  redraw();
@@ -10942,7 +11143,7 @@ class CanvasCurve {
10942
11143
  (v[1] * element.yrange[1] / canvas.height + element.yrange[0])];
10943
11144
  }
10944
11145
 
10945
- var selected = -1;
11146
+ let selected = -1;
10946
11147
 
10947
11148
  element.redraw = function( o = {} ) {
10948
11149
 
@@ -11004,7 +11205,7 @@ class CanvasCurve {
11004
11205
  var value = element.value[ i ];
11005
11206
  pos = convert( value );
11006
11207
  if( selected == i )
11007
- ctx.fillStyle = "white";
11208
+ ctx.fillStyle = element.activepointscolor;
11008
11209
  else
11009
11210
  ctx.fillStyle = element.pointscolor;
11010
11211
  ctx.beginPath();
@@ -11850,11 +12051,15 @@ class AssetView {
11850
12051
  this.rightPanel.sameLine();
11851
12052
  this.rightPanel.addSelect( "Filter", this.allowedTypes, this.allowedTypes[ 0 ], v => this._refreshContent.call(this, null, v), { width: "30%", minWidth: "128px" } );
11852
12053
  this.rightPanel.addText( null, this.searchValue ?? "", v => this._refreshContent.call(this, v, null), { placeholder: "Search assets.." } );
11853
- this.rightPanel.addButton( null, "<a class='fa fa-arrow-up-short-wide'></a>", on_sort.bind(this), { className: "micro", title: "Sort" } );
11854
- this.rightPanel.addButton( null, "<a class='fa-solid fa-grip'></a>", on_change_view.bind(this), { className: "micro", title: "View" } );
12054
+ this.rightPanel.addButton( null, "<a class='fa fa-arrow-up-short-wide'></a>", on_sort.bind(this), { title: "Sort" } );
12055
+ this.rightPanel.addButton( null, "<a class='fa-solid fa-grip'></a>", on_change_view.bind(this), { title: "View" } );
11855
12056
  // Content Pages
11856
- this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-left'></a>", on_change_page.bind(this, -1), { className: "micro", title: "Previous Page" } );
11857
- this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-right'></a>", on_change_page.bind(this, 1), { className: "micro", title: "Next Page" } );
12057
+ this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-left'></a>", on_change_page.bind(this, -1), { title: "Previous Page", className: "ml-auto" } );
12058
+ this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-right'></a>", on_change_page.bind(this, 1), { title: "Next Page" } );
12059
+ const textString = "Page " + this.contentPage + " / " + ((((this.currentData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1);
12060
+ this.rightPanel.addText(null, textString, null, {
12061
+ inputClass: "nobg", disabled: true, signal: "@on_page_change", maxWidth: "16ch" }
12062
+ );
11858
12063
  this.rightPanel.endLine();
11859
12064
 
11860
12065
  if( !this.skipBrowser )
@@ -11888,9 +12093,13 @@ class AssetView {
11888
12093
  icon: "fa-solid fa-arrows-rotate",
11889
12094
  callback: domEl => { this._refreshContent(); }
11890
12095
  }
11891
- ], { width: "20%", minWidth: "164px", noSelection: true } );
11892
- 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" } });
11893
- 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"})
12096
+ ], { noSelection: true } );
12097
+
12098
+ this.rightPanel.addText(null, this.path.join('/'), null, {
12099
+ inputClass: "nobg", disabled: true, signal: "@on_folder_change",
12100
+ style: { fontWeight: "600", fontSize: "15px" }
12101
+ });
12102
+
11894
12103
  this.rightPanel.endLine();
11895
12104
  }
11896
12105
 
@@ -12168,7 +12377,9 @@ class AssetView {
12168
12377
  }
12169
12378
 
12170
12379
  this.allowNextPage = filteredData.length - 1 > AssetView.MAX_PAGE_ELEMENTS;
12171
- LX.emit("@on_page_change", "Page " + this.contentPage + " / " + ((((filteredData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1));
12380
+
12381
+ const textString = "Page " + this.contentPage + " / " + ((((filteredData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1);
12382
+ LX.emit( "@on_page_change", textString );
12172
12383
 
12173
12384
  if( this.onRefreshContent )
12174
12385
  {
@@ -12192,7 +12403,7 @@ class AssetView {
12192
12403
  const hasImage = ['png', 'jpg'].indexOf( getExtension( file.src ) ) > -1 || is_base_64;
12193
12404
  if( hasImage )
12194
12405
  {
12195
- this.previewPanel.addImage( file.src, { style: { width: "100%" } } );
12406
+ this.previewPanel.addImage( null, file.src, { style: { width: "100%" } } );
12196
12407
  }
12197
12408
  }
12198
12409
 
@@ -12747,6 +12958,9 @@ LX.ICONS = {
12747
12958
  "floppy-disk": [448, 512, ["save"], "regular", "M48 96l0 320c0 8.8 7.2 16 16 16l320 0c8.8 0 16-7.2 16-16l0-245.5c0-4.2-1.7-8.3-4.7-11.3l33.9-33.9c12 12 18.7 28.3 18.7 45.3L448 416c0 35.3-28.7 64-64 64L64 480c-35.3 0-64-28.7-64-64L0 96C0 60.7 28.7 32 64 32l245.5 0c17 0 33.3 6.7 45.3 18.7l74.5 74.5-33.9 33.9L320.8 84.7c-.3-.3-.5-.5-.8-.8L320 184c0 13.3-10.7 24-24 24l-192 0c-13.3 0-24-10.7-24-24L80 80 64 80c-8.8 0-16 7.2-16 16zm80-16l0 80 144 0 0-80L128 80zm32 240a64 64 0 1 1 128 0 64 64 0 1 1 -128 0z"],
12748
12959
  "download": [512, 512, [], "solid", "M288 32c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 242.7-73.4-73.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l128 128c12.5 12.5 32.8 12.5 45.3 0l128-128c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L288 274.7 288 32zM64 352c-35.3 0-64 28.7-64 64l0 32c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-32c0-35.3-28.7-64-64-64l-101.5 0-45.3 45.3c-25 25-65.5 25-90.5 0L165.5 352 64 352zm368 56a24 24 0 1 1 0 48 24 24 0 1 1 0-48z"],
12749
12960
  "upload": [512, 512, [], "solid", "M288 109.3L288 352c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-242.7-73.4 73.4c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l128-128c12.5-12.5 32.8-12.5 45.3 0l128 128c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L288 109.3zM64 352l128 0c0 35.3 28.7 64 64 64s64-28.7 64-64l128 0c35.3 0 64 28.7 64 64l0 32c0 35.3-28.7 64-64 64L64 512c-35.3 0-64-28.7-64-64l0-32c0-35.3 28.7-64 64-64zM432 456a24 24 0 1 0 0-48 24 24 0 1 0 0 48z"],
12961
+ "gear": [512, 512, [], "solid", "M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"],
12962
+ "gears": [640, 512, [], "solid", "M308.5 135.3c7.1-6.3 9.9-16.2 6.2-25c-2.3-5.3-4.8-10.5-7.6-15.5L304 89.4c-3-5-6.3-9.9-9.8-14.6c-5.7-7.6-15.7-10.1-24.7-7.1l-28.2 9.3c-10.7-8.8-23-16-36.2-20.9L199 27.1c-1.9-9.3-9.1-16.7-18.5-17.8C173.9 8.4 167.2 8 160.4 8l-.7 0c-6.8 0-13.5 .4-20.1 1.2c-9.4 1.1-16.6 8.6-18.5 17.8L115 56.1c-13.3 5-25.5 12.1-36.2 20.9L50.5 67.8c-9-3-19-.5-24.7 7.1c-3.5 4.7-6.8 9.6-9.9 14.6l-3 5.3c-2.8 5-5.3 10.2-7.6 15.6c-3.7 8.7-.9 18.6 6.2 25l22.2 19.8C32.6 161.9 32 168.9 32 176s.6 14.1 1.7 20.9L11.5 216.7c-7.1 6.3-9.9 16.2-6.2 25c2.3 5.3 4.8 10.5 7.6 15.6l3 5.2c3 5.1 6.3 9.9 9.9 14.6c5.7 7.6 15.7 10.1 24.7 7.1l28.2-9.3c10.7 8.8 23 16 36.2 20.9l6.1 29.1c1.9 9.3 9.1 16.7 18.5 17.8c6.7 .8 13.5 1.2 20.4 1.2s13.7-.4 20.4-1.2c9.4-1.1 16.6-8.6 18.5-17.8l6.1-29.1c13.3-5 25.5-12.1 36.2-20.9l28.2 9.3c9 3 19 .5 24.7-7.1c3.5-4.7 6.8-9.5 9.8-14.6l3.1-5.4c2.8-5 5.3-10.2 7.6-15.5c3.7-8.7 .9-18.6-6.2-25l-22.2-19.8c1.1-6.8 1.7-13.8 1.7-20.9s-.6-14.1-1.7-20.9l22.2-19.8zM112 176a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zM504.7 500.5c6.3 7.1 16.2 9.9 25 6.2c5.3-2.3 10.5-4.8 15.5-7.6l5.4-3.1c5-3 9.9-6.3 14.6-9.8c7.6-5.7 10.1-15.7 7.1-24.7l-9.3-28.2c8.8-10.7 16-23 20.9-36.2l29.1-6.1c9.3-1.9 16.7-9.1 17.8-18.5c.8-6.7 1.2-13.5 1.2-20.4s-.4-13.7-1.2-20.4c-1.1-9.4-8.6-16.6-17.8-18.5L583.9 307c-5-13.3-12.1-25.5-20.9-36.2l9.3-28.2c3-9 .5-19-7.1-24.7c-4.7-3.5-9.6-6.8-14.6-9.9l-5.3-3c-5-2.8-10.2-5.3-15.6-7.6c-8.7-3.7-18.6-.9-25 6.2l-19.8 22.2c-6.8-1.1-13.8-1.7-20.9-1.7s-14.1 .6-20.9 1.7l-19.8-22.2c-6.3-7.1-16.2-9.9-25-6.2c-5.3 2.3-10.5 4.8-15.6 7.6l-5.2 3c-5.1 3-9.9 6.3-14.6 9.9c-7.6 5.7-10.1 15.7-7.1 24.7l9.3 28.2c-8.8 10.7-16 23-20.9 36.2L315.1 313c-9.3 1.9-16.7 9.1-17.8 18.5c-.8 6.7-1.2 13.5-1.2 20.4s.4 13.7 1.2 20.4c1.1 9.4 8.6 16.6 17.8 18.5l29.1 6.1c5 13.3 12.1 25.5 20.9 36.2l-9.3 28.2c-3 9-.5 19 7.1 24.7c4.7 3.5 9.5 6.8 14.6 9.8l5.4 3.1c5 2.8 10.2 5.3 15.5 7.6c8.7 3.7 18.6 .9 25-6.2l19.8-22.2c6.8 1.1 13.8 1.7 20.9 1.7s14.1-.6 20.9-1.7l19.8 22.2zM464 304a48 48 0 1 1 0 96 48 48 0 1 1 0-96z"],
12963
+ "sliders": [512, 512, [], "solid", "M0 416c0 17.7 14.3 32 32 32l54.7 0c12.3 28.3 40.5 48 73.3 48s61-19.7 73.3-48L480 448c17.7 0 32-14.3 32-32s-14.3-32-32-32l-246.7 0c-12.3-28.3-40.5-48-73.3-48s-61 19.7-73.3 48L32 384c-17.7 0-32 14.3-32 32zm128 0a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zM320 256a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm32-80c-32.8 0-61 19.7-73.3 48L32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l246.7 0c12.3 28.3 40.5 48 73.3 48s61-19.7 73.3-48l54.7 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-54.7 0c-12.3-28.3-40.5-48-73.3-48zM192 128a32 32 0 1 1 0-64 32 32 0 1 1 0 64zm73.3-64C253 35.7 224.8 16 192 16s-61 19.7-73.3 48L32 64C14.3 64 0 78.3 0 96s14.3 32 32 32l86.7 0c12.3 28.3 40.5 48 73.3 48s61-19.7 73.3-48L480 128c17.7 0 32-14.3 32-32s-14.3-32-32-32L265.3 64z"],
12750
12964
  "eye": [576, 512, [], "regular", "M288 80c-65.2 0-118.8 29.6-159.9 67.7C89.6 183.5 63 226 49.4 256c13.6 30 40.2 72.5 78.6 108.3C169.2 402.4 222.8 432 288 432s118.8-29.6 159.9-67.7C486.4 328.5 513 286 526.6 256c-13.6-30-40.2-72.5-78.6-108.3C406.8 109.6 353.2 80 288 80zM95.4 112.6C142.5 68.8 207.2 32 288 32s145.5 36.8 192.6 80.6c46.8 43.5 78.1 95.4 93 131.1c3.3 7.9 3.3 16.7 0 24.6c-14.9 35.7-46.2 87.7-93 131.1C433.5 443.2 368.8 480 288 480s-145.5-36.8-192.6-80.6C48.6 356 17.3 304 2.5 268.3c-3.3-7.9-3.3-16.7 0-24.6C17.3 208 48.6 156 95.4 112.6zM288 336c44.2 0 80-35.8 80-80s-35.8-80-80-80c-.7 0-1.3 0-2 0c1.3 5.1 2 10.5 2 16c0 35.3-28.7 64-64 64c-5.5 0-10.9-.7-16-2c0 .7 0 1.3 0 2c0 44.2 35.8 80 80 80zm0-208a128 128 0 1 1 0 256 128 128 0 1 1 0-256z"],
12751
12965
  "eye-slash": [640, 512, [], "regular", "M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zm151 118.3C226 97.7 269.5 80 320 80c65.2 0 118.8 29.6 159.9 67.7C518.4 183.5 545 226 558.6 256c-12.6 28-36.6 66.8-70.9 100.9l-53.8-42.2c9.1-17.6 14.2-37.5 14.2-58.7c0-70.7-57.3-128-128-128c-32.2 0-61.7 11.9-84.2 31.5l-46.1-36.1zM394.9 284.2l-81.5-63.9c4.2-8.5 6.6-18.2 6.6-28.3c0-5.5-.7-10.9-2-16c.7 0 1.3 0 2 0c44.2 0 80 35.8 80 80c0 9.9-1.8 19.4-5.1 28.2zm9.4 130.3C378.8 425.4 350.7 432 320 432c-65.2 0-118.8-29.6-159.9-67.7C121.6 328.5 95 286 81.4 256c8.3-18.4 21.5-41.5 39.4-64.8L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5l-41.9-33zM192 256c0 70.7 57.3 128 128 128c13.3 0 26.1-2 38.2-5.8L302 334c-23.5-5.4-43.1-21.2-53.7-42.3l-56.1-44.2c-.2 2.8-.3 5.6-.3 8.5z"],
12752
12966
  "comment": [512, 512, [], "regular", "M123.6 391.3c12.9-9.4 29.6-11.8 44.6-6.4c26.5 9.6 56.2 15.1 87.8 15.1c124.7 0 208-80.5 208-160s-83.3-160-208-160S48 160.5 48 240c0 32 12.4 62.8 35.7 89.2c8.6 9.7 12.8 22.5 11.8 35.5c-1.4 18.1-5.7 34.7-11.3 49.4c17-7.9 31.1-16.7 39.4-22.7zM21.2 431.9c1.8-2.7 3.5-5.4 5.1-8.1c10-16.6 19.5-38.4 21.4-62.9C17.7 326.8 0 285.1 0 240C0 125.1 114.6 32 256 32s256 93.1 256 208s-114.6 208-256 208c-37.1 0-72.3-6.4-104.1-17.9c-11.9 8.7-31.3 20.6-54.3 30.6c-15.1 6.6-32.3 12.6-50.1 16.1c-.8 .2-1.6 .3-2.4 .5c-4.4 .8-8.7 1.5-13.2 1.9c-.2 0-.5 .1-.7 .1c-5.1 .5-10.2 .8-15.3 .8c-6.5 0-12.3-3.9-14.8-9.9c-2.5-6-1.1-12.8 3.4-17.4c4.1-4.2 7.8-8.7 11.3-13.5c1.7-2.3 3.3-4.6 4.8-6.9l.3-.5z"],
@@ -12775,6 +12989,7 @@ LX.ICONS = {
12775
12989
  "minus": [448, 512, [], "solid", "M432 256c0 17.7-14.3 32-32 32L48 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l352 0c17.7 0 32 14.3 32 32z"],
12776
12990
  "more-horizontal": [448, 512, [], "solid", "M8 256a56 56 0 1 1 112 0A56 56 0 1 1 8 256zm160 0a56 56 0 1 1 112 0 56 56 0 1 1 -112 0zm216-56a56 56 0 1 1 0 112 56 56 0 1 1 0-112z"],
12777
12991
  "plus": [448, 512, [], "solid", "M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"],
12992
+ "circle-plus": [24, 24, [], "regular", "M12 8V16M8 12H16M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z", null, "fill=none stroke-width=2 stroke-linecap=round stroke-linejoin=round"],
12778
12993
  "search": [512, 512, [], "solid", "M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"],
12779
12994
  "compass": [512, 512, [], "regular", "M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm306.7 69.1L162.4 380.6c-19.4 7.5-38.5-11.6-31-31l55.5-144.3c3.3-8.5 9.9-15.1 18.4-18.4l144.3-55.5c19.4-7.5 38.5 11.6 31 31L325.1 306.7c-3.2 8.5-9.9 15.1-18.4 18.4zM288 256a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"],
12780
12995
  "sidebar": [512, 512, [], "regular", "M64 64h384a32 32 0 0 1 32 32v320a32 32 0 0 1-32 32H64a32 32 0 0 1-32-32V96a32 32 0 0 1 32-32zm128 0v384", null, "fill=none stroke=currentColor stroke-width=50 stroke-linejoin=round stroke-linecap=round"],