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.
package/build/lexgui.js CHANGED
@@ -12,7 +12,7 @@ console.warn( 'Script _build/lexgui.js_ is depracated and will be removed soon.
12
12
  */
13
13
 
14
14
  var LX = {
15
- version: "0.5.1",
15
+ version: "0.5.3",
16
16
  ready: false,
17
17
  components: [], // Specific pre-build components
18
18
  signals: {}, // Events and triggers
@@ -52,7 +52,7 @@ else if( typeof Date != "undefined" && Date.now )
52
52
  else if ( typeof process != "undefined" )
53
53
  {
54
54
  LX.getTime = function() {
55
- var t = process.hrtime();
55
+ const t = process.hrtime();
56
56
  return t[ 0 ] * 0.001 + t[ 1 ] * 1e-6;
57
57
  };
58
58
  }
@@ -154,7 +154,7 @@ LX.setTheme = setTheme;
154
154
  */
155
155
  function setThemeColor( colorName, color )
156
156
  {
157
- var r = document.querySelector( ':root' );
157
+ const r = document.querySelector( ':root' );
158
158
  r.style.setProperty( '--' + colorName, color );
159
159
  }
160
160
 
@@ -196,10 +196,10 @@ LX.getThemeColor = getThemeColor;
196
196
  */
197
197
  function getBase64Image( img )
198
198
  {
199
- var canvas = document.createElement( 'canvas' );
199
+ const canvas = document.createElement( 'canvas' );
200
200
  canvas.width = img.width;
201
201
  canvas.height = img.height;
202
- var ctx = canvas.getContext( '2d' );
202
+ const ctx = canvas.getContext( '2d' );
203
203
  ctx.drawImage( img, 0, 0 );
204
204
  return canvas.toDataURL( 'image/png' );
205
205
  }
@@ -964,8 +964,8 @@ function init( options = { } )
964
964
  this.root = root;
965
965
  this.container = document.body;
966
966
 
967
- this.modal.classList.add( 'hiddenOpacity' );
968
- this.modal.toggle = function( force ) { this.classList.toggle( 'hiddenOpacity', force ); };
967
+ this.modal.classList.add( 'hidden-opacity' );
968
+ this.modal.toggle = function( force ) { this.classList.toggle( 'hidden-opacity', force ); };
969
969
 
970
970
  if( options.container )
971
971
  {
@@ -1041,6 +1041,17 @@ function init( options = { } )
1041
1041
  this.DEFAULT_SPLITBAR_SIZE = 4;
1042
1042
  this.OPEN_CONTEXTMENU_ENTRY = 'click';
1043
1043
 
1044
+ this.widgetResizeObserver = new ResizeObserver( entries => {
1045
+ for ( const entry of entries )
1046
+ {
1047
+ const widget = entry.target?.jsInstance;
1048
+ if( widget && widget.onResize )
1049
+ {
1050
+ widget.onResize( entry.contentRect );
1051
+ }
1052
+ }
1053
+ });
1054
+
1044
1055
  this.ready = true;
1045
1056
  this.menubars = [ ];
1046
1057
 
@@ -1484,6 +1495,7 @@ class DropdownMenu {
1484
1495
  }
1485
1496
 
1486
1497
  this._trigger = trigger;
1498
+ trigger.classList.add( "triggered" );
1487
1499
  trigger.ddm = this;
1488
1500
 
1489
1501
  this._items = items;
@@ -1510,7 +1522,7 @@ class DropdownMenu {
1510
1522
  this.root.focus();
1511
1523
 
1512
1524
  this._onClick = e => {
1513
- if( e.target && ( e.target.className.includes( "lexdropdown" ) || e.target == this._trigger ) )
1525
+ if( e.target && ( this.root.contains( e.target ) || e.target == this._trigger ) )
1514
1526
  {
1515
1527
  return;
1516
1528
  }
@@ -1523,6 +1535,8 @@ class DropdownMenu {
1523
1535
 
1524
1536
  destroy() {
1525
1537
 
1538
+ this._trigger.classList.remove( "triggered" );
1539
+
1526
1540
  delete this._trigger.ddm;
1527
1541
 
1528
1542
  document.body.removeEventListener( "click", this._onClick );
@@ -1588,12 +1602,6 @@ class DropdownMenu {
1588
1602
  menuItem.id = pKey;
1589
1603
  menuItem.innerHTML = `<span>${ key }</span>`;
1590
1604
 
1591
- if( item.icon )
1592
- {
1593
- const icon = LX.makeIcon( item.icon );
1594
- menuItem.prepend( icon );
1595
- }
1596
-
1597
1605
  menuItem.tabIndex = "1";
1598
1606
  parentDom.appendChild( menuItem );
1599
1607
 
@@ -1609,15 +1617,41 @@ class DropdownMenu {
1609
1617
  menuItem.appendChild( submenuIcon );
1610
1618
  }
1611
1619
 
1612
- menuItem.addEventListener( "click", () => {
1613
- const f = item[ 'callback' ];
1614
- if( f )
1615
- {
1616
- f.call( this, key, menuItem );
1617
- }
1620
+ if( item.icon )
1621
+ {
1622
+ const icon = LX.makeIcon( item.icon );
1623
+ menuItem.prepend( icon );
1624
+ }
1618
1625
 
1619
- this.destroy();
1620
- } );
1626
+ if( item.checked != undefined )
1627
+ {
1628
+ const checkbox = new Checkbox( pKey + "_entryChecked", item.checked, (v) => {
1629
+ const f = item[ 'callback' ];
1630
+ if( f )
1631
+ {
1632
+ f.call( this, key, menuItem, v );
1633
+ }
1634
+ }, { className: "accent" });
1635
+ const input = checkbox.root.querySelector( "input" );
1636
+ menuItem.prepend( input );
1637
+
1638
+ menuItem.addEventListener( "click", (e) => {
1639
+ if( e.target.type == "checkbox" ) return;
1640
+ input.checked = !input.checked;
1641
+ checkbox.set( input.checked );
1642
+ } );
1643
+ }
1644
+ else
1645
+ {
1646
+ menuItem.addEventListener( "click", () => {
1647
+ const f = item[ 'callback' ];
1648
+ if( f )
1649
+ {
1650
+ f.call( this, key, menuItem );
1651
+ }
1652
+ this.destroy();
1653
+ } );
1654
+ }
1621
1655
 
1622
1656
  menuItem.addEventListener("mouseover", e => {
1623
1657
 
@@ -1761,7 +1795,7 @@ class Area {
1761
1795
  root.className += " " + options.className;
1762
1796
  }
1763
1797
 
1764
- var width = options.width || "calc( 100% )";
1798
+ var width = options.width || "100%";
1765
1799
  var height = options.height || "100%";
1766
1800
 
1767
1801
  // This has default options..
@@ -1787,7 +1821,7 @@ class Area {
1787
1821
 
1788
1822
  if( !options.skipAppend )
1789
1823
  {
1790
- var lexroot = document.getElementById("lexroot");
1824
+ let lexroot = document.getElementById("lexroot");
1791
1825
  lexroot.appendChild( this.root );
1792
1826
  }
1793
1827
 
@@ -1858,12 +1892,12 @@ class Area {
1858
1892
  this.splitBar.addEventListener("mousedown", innerMouseDown);
1859
1893
  this.root.appendChild( this.splitBar );
1860
1894
 
1861
- var that = this;
1862
- var lastMousePosition = [ 0, 0 ];
1895
+ const that = this;
1896
+ let lastMousePosition = [ 0, 0 ];
1863
1897
 
1864
1898
  function innerMouseDown( e )
1865
1899
  {
1866
- var doc = that.root.ownerDocument;
1900
+ const doc = that.root.ownerDocument;
1867
1901
  doc.addEventListener( 'mousemove', innerMouseMove );
1868
1902
  doc.addEventListener( 'mouseup', innerMouseUp );
1869
1903
  lastMousePosition[ 0 ] = e.x;
@@ -1916,7 +1950,7 @@ class Area {
1916
1950
 
1917
1951
  function innerMouseUp( e )
1918
1952
  {
1919
- var doc = that.root.ownerDocument;
1953
+ const doc = that.root.ownerDocument;
1920
1954
  doc.removeEventListener( 'mousemove', innerMouseMove );
1921
1955
  doc.removeEventListener( 'mouseup', innerMouseUp );
1922
1956
  document.body.classList.remove( 'nocursor' );
@@ -1968,9 +2002,9 @@ class Area {
1968
2002
  this.root = this.sections[ 1 ].root;
1969
2003
  }
1970
2004
 
1971
- var type = options.type || "horizontal";
1972
- var sizes = options.sizes || [ "50%", "50%" ];
1973
- var auto = (options.sizes === 'auto');
2005
+ const type = options.type || "horizontal";
2006
+ const sizes = options.sizes || [ "50%", "50%" ];
2007
+ const auto = (options.sizes === 'auto');
1974
2008
 
1975
2009
  if( !sizes[ 1 ] )
1976
2010
  {
@@ -1986,8 +2020,8 @@ class Area {
1986
2020
  }
1987
2021
 
1988
2022
  // Create areas
1989
- var area1 = new Area( { skipAppend: true, className: "split" + ( options.menubar || options.sidebar ? "" : " origin" ) } );
1990
- var area2 = new Area( { skipAppend: true, className: "split" } );
2023
+ let area1 = new Area( { skipAppend: true, className: "split" + ( options.menubar || options.sidebar ? "" : " origin" ) } );
2024
+ let area2 = new Area( { skipAppend: true, className: "split" } );
1991
2025
 
1992
2026
  area1.parentArea = this;
1993
2027
  area2.parentArea = this;
@@ -1995,7 +2029,7 @@ class Area {
1995
2029
  let minimizable = options.minimizable ?? false;
1996
2030
  let resize = ( options.resize ?? true ) || minimizable;
1997
2031
 
1998
- var data = "0px";
2032
+ let data = "0px";
1999
2033
  this.offset = 0;
2000
2034
 
2001
2035
  if( resize )
@@ -2042,7 +2076,7 @@ class Area {
2042
2076
 
2043
2077
  if( type == "horizontal" )
2044
2078
  {
2045
- var width1 = sizes[ 0 ],
2079
+ let width1 = sizes[ 0 ],
2046
2080
  width2 = sizes[ 1 ];
2047
2081
 
2048
2082
  if( width1.constructor == Number )
@@ -2083,7 +2117,7 @@ class Area {
2083
2117
  }
2084
2118
  else
2085
2119
  {
2086
- var height1 = sizes[ 0 ],
2120
+ let height1 = sizes[ 0 ],
2087
2121
  height2 = sizes[ 1 ];
2088
2122
 
2089
2123
  if( height1.constructor == Number )
@@ -2121,11 +2155,11 @@ class Area {
2121
2155
  return this.sections;
2122
2156
  }
2123
2157
 
2124
- var that = this;
2158
+ const that = this;
2125
2159
 
2126
2160
  function innerMouseDown( e )
2127
2161
  {
2128
- var doc = that.root.ownerDocument;
2162
+ const doc = that.root.ownerDocument;
2129
2163
  doc.addEventListener( 'mousemove', innerMouseMove );
2130
2164
  doc.addEventListener( 'mouseup', innerMouseUp );
2131
2165
  e.stopPropagation();
@@ -2145,26 +2179,13 @@ class Area {
2145
2179
  that._moveSplit( -e.movementY );
2146
2180
  }
2147
2181
 
2148
- const widgets = that.root.querySelectorAll( ".lexwidget" );
2149
-
2150
- // Send area resize to every widget in the area
2151
- for( let widget of widgets )
2152
- {
2153
- const jsInstance = widget.jsInstance;
2154
-
2155
- if( jsInstance.onresize )
2156
- {
2157
- jsInstance.onresize();
2158
- }
2159
- }
2160
-
2161
2182
  e.stopPropagation();
2162
2183
  e.preventDefault();
2163
2184
  }
2164
2185
 
2165
2186
  function innerMouseUp( e )
2166
2187
  {
2167
- var doc = that.root.ownerDocument;
2188
+ const doc = that.root.ownerDocument;
2168
2189
  doc.removeEventListener( 'mousemove', innerMouseMove );
2169
2190
  doc.removeEventListener( 'mouseup', innerMouseUp );
2170
2191
  document.body.classList.remove( 'nocursor' );
@@ -2312,7 +2333,7 @@ class Area {
2312
2333
 
2313
2334
  propagateEvent( eventName ) {
2314
2335
 
2315
- for( var i = 0; i < this.sections.length; i++ )
2336
+ for( let i = 0; i < this.sections.length; i++ )
2316
2337
  {
2317
2338
  const area = this.sections[ i ];
2318
2339
 
@@ -2366,7 +2387,7 @@ class Area {
2366
2387
 
2367
2388
  if( options.sticky ?? true )
2368
2389
  {
2369
- bar.root.classList.add( "sticky" );
2390
+ bar.root.className += " sticky top-0";
2370
2391
  }
2371
2392
 
2372
2393
  return menubar;
@@ -2438,7 +2459,7 @@ class Area {
2438
2459
 
2439
2460
  if( float )
2440
2461
  {
2441
- for( var i = 0; i < float.length; i++ )
2462
+ for( let i = 0; i < float.length; i++ )
2442
2463
  {
2443
2464
  const t = float[i];
2444
2465
  switch( t )
@@ -2463,7 +2484,8 @@ class Area {
2463
2484
  selected: b.selected,
2464
2485
  icon: b.icon,
2465
2486
  img: b.img,
2466
- className: b.class
2487
+ className: b.class ?? "",
2488
+ title: b.name
2467
2489
  };
2468
2490
 
2469
2491
  if( group )
@@ -2657,7 +2679,7 @@ class Area {
2657
2679
 
2658
2680
  for( var i = 0; i < this.sections.length; i++ )
2659
2681
  {
2660
- this.sections[i]._update();
2682
+ this.sections[ i ]._update();
2661
2683
  }
2662
2684
  }
2663
2685
  };
@@ -2766,6 +2788,12 @@ class Tabs {
2766
2788
 
2767
2789
  this.area = area.sections[1];
2768
2790
  this.area.root.className += " lexareatabscontent";
2791
+
2792
+ if( options.contentClass )
2793
+ {
2794
+ this.area.root.className += ` ${ options.contentClass }`;
2795
+ }
2796
+
2769
2797
  this.selected = null;
2770
2798
  this.root = container;
2771
2799
  this.tabs = {};
@@ -2785,8 +2813,8 @@ class Tabs {
2785
2813
  var transition = this.thumb.style.transition;
2786
2814
  this.thumb.style.transition = "none";
2787
2815
  this.thumb.style.transform = "translate( " + ( tabEl.childIndex * tabEl.offsetWidth ) + "px )";
2788
- this.thumb.style.width = ( tabEl.offsetWidth - 5 ) + "px";
2789
- this.thumb.style.height = ( tabEl.offsetHeight - 6 ) + "px";
2816
+ this.thumb.style.width = ( tabEl.offsetWidth ) + "px";
2817
+ this.thumb.style.height = ( tabEl.offsetHeight ) + "px";
2790
2818
  flushCss( this.thumb );
2791
2819
  this.thumb.style.transition = transition;
2792
2820
  });
@@ -2958,8 +2986,8 @@ class Tabs {
2958
2986
  if( isSelected && this.thumb )
2959
2987
  {
2960
2988
  this.thumb.style.transform = "translate( " + ( tabEl.childIndex * tabEl.offsetWidth ) + "px )";
2961
- this.thumb.style.width = ( tabEl.offsetWidth - 5 ) + "px";
2962
- this.thumb.style.height = ( tabEl.offsetHeight - 6 ) + "px";
2989
+ this.thumb.style.width = ( tabEl.offsetWidth ) + "px";
2990
+ this.thumb.style.height = ( tabEl.offsetHeight ) + "px";
2963
2991
  this.thumb.item = tabEl;
2964
2992
  }
2965
2993
 
@@ -3723,12 +3751,11 @@ class SideBar {
3723
3751
  // Entry filter
3724
3752
  if( ( options.filter ?? false ) )
3725
3753
  {
3726
- const panel = new Panel();
3727
- panel.addText(null, "", (value, event) => {
3754
+ const filterTextInput = new TextInput(null, "", (value, event) => {
3728
3755
  this.filterString = value;
3729
3756
  this.update();
3730
- }, { placeholder: "Search...", icon: "fa-solid fa-magnifying-glass" });
3731
- this.filter = panel.root.childNodes[ 0 ];
3757
+ }, { inputClass: "outline", placeholder: "Search...", icon: "fa-solid fa-magnifying-glass", className: "lexsidebarfilter" });
3758
+ this.filter = filterTextInput.root;
3732
3759
  this.root.appendChild( this.filter );
3733
3760
  }
3734
3761
 
@@ -3751,7 +3778,7 @@ class SideBar {
3751
3778
  // Set width depending on header/footer
3752
3779
  doAsync( () => {
3753
3780
  // This account for header, footer and all inner paddings
3754
- const contentOffset = 32 + ( this.header?.offsetHeight ?? 0 ) +
3781
+ const contentOffset = ( this.header?.offsetHeight ?? 0 ) +
3755
3782
  ( this.filter?.offsetHeight ?? 0 ) +
3756
3783
  ( this.footer?.offsetHeight ?? 0 );
3757
3784
  this.content.style.height = `calc(100% - ${ contentOffset }px)`;
@@ -4123,7 +4150,7 @@ class SideBar {
4123
4150
  const f = options.callback;
4124
4151
  item.value = value;
4125
4152
  if( f ) f.call( this, key, value, event );
4126
- }, { label: key, signal: ( "@checkbox_" + key ) });
4153
+ }, { className: "accent", label: key, signal: ( "@checkbox_" + key ) });
4127
4154
  itemDom.appendChild( panel.root.childNodes[ 0 ] );
4128
4155
  }
4129
4156
  else
@@ -4363,8 +4390,6 @@ class Widget {
4363
4390
 
4364
4391
  if( type != Widget.TITLE )
4365
4392
  {
4366
- // root.style.width = "calc(100% - " + (this._currentBranch || type == Widget.FILE || type == Widget.TREE ? 10 : 20) + "px)";
4367
-
4368
4393
  if( options.width )
4369
4394
  {
4370
4395
  root.style.width = root.style.minWidth = options.width;
@@ -4381,6 +4406,8 @@ class Widget {
4381
4406
  {
4382
4407
  root.style.height = root.style.minHeight = options.height;
4383
4408
  }
4409
+
4410
+ LX.widgetResizeObserver.observe( root );
4384
4411
  }
4385
4412
 
4386
4413
  if( name != undefined )
@@ -4398,6 +4425,7 @@ class Widget {
4398
4425
  domName.innerHTML = name;
4399
4426
  domName.title = options.title ?? domName.innerHTML;
4400
4427
  domName.style.width = options.nameWidth || LX.DEFAULT_NAME_WIDTH;
4428
+ domName.style.minWidth = domName.style.width;
4401
4429
 
4402
4430
  root.appendChild( domName );
4403
4431
  root.domName = domName;
@@ -4581,15 +4609,17 @@ LX.Widget = Widget;
4581
4609
 
4582
4610
  function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4583
4611
  {
4584
- let custom_idx = simple_guidGenerator();
4612
+ let customIdx = simple_guidGenerator();
4585
4613
 
4586
4614
  Panel.prototype[ 'add' + customWidgetName ] = function( name, instance, callback ) {
4587
4615
 
4616
+ options.nameWidth = "100%";
4617
+
4588
4618
  let widget = new Widget( Widget.CUSTOM, name, null, options );
4589
4619
  this._attachWidget( widget );
4590
4620
 
4591
4621
  widget.customName = customWidgetName;
4592
- widget.customIdx = custom_idx;
4622
+ widget.customIdx = customIdx;
4593
4623
 
4594
4624
  widget.onGetValue = () => {
4595
4625
  return instance;
@@ -4606,7 +4636,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4606
4636
  };
4607
4637
 
4608
4638
  const element = widget.root;
4609
- element.style.flexWrap = "wrap";
4610
4639
 
4611
4640
  let container, customWidgetsDom;
4612
4641
  let default_instance = options.default ?? {};
@@ -4625,20 +4654,20 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4625
4654
 
4626
4655
  container = document.createElement('div');
4627
4656
  container.className = "lexcustomcontainer";
4628
- doAsync( () => {
4629
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
4630
- container.style.width = `calc( 100% - ${ realNameWidth })`;
4631
- } );
4657
+ container.style.width = "100%";
4658
+ element.appendChild( container );
4659
+ element.dataset["opened"] = false;
4632
4660
 
4633
- let buttonName = "<a class='fa-solid " + (options.icon ?? "fa-cube") + "' style='float:left'></a>";
4661
+ let buttonName = "<a class='fa-solid " + (options.icon ?? "fa-cube") + "'></a>";
4634
4662
  buttonName += customWidgetName + (!instance ? " [empty]" : "");
4635
- // Add alwayis icon to keep spacing right
4636
- buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu' style='float:right; width:5%;'></a>";
4663
+ // Add always icon to keep spacing right
4664
+ buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu'></a>";
4637
4665
 
4638
4666
  let buttonEl = this.addButton(null, buttonName, (value, event) => {
4639
4667
  if( instance )
4640
4668
  {
4641
4669
  element.querySelector(".lexcustomitems").toggleAttribute('hidden');
4670
+ element.dataset["opened"] = !element.querySelector(".lexcustomitems").hasAttribute("hidden");
4642
4671
  }
4643
4672
  else
4644
4673
  {
@@ -4647,12 +4676,12 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4647
4676
  instance = {};
4648
4677
  refresh_widget();
4649
4678
  element.querySelector(".lexcustomitems").toggleAttribute('hidden', false);
4679
+ element.dataset["opened"] = !element.querySelector(".lexcustomitems").hasAttribute("hidden");
4650
4680
  });
4651
4681
  });
4652
4682
  }
4653
4683
 
4654
4684
  }, { buttonClass: 'custom' });
4655
-
4656
4685
  container.appendChild( buttonEl.root );
4657
4686
 
4658
4687
  if( instance )
@@ -4674,8 +4703,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4674
4703
  customWidgetsDom = document.createElement('div');
4675
4704
  customWidgetsDom.className = "lexcustomitems";
4676
4705
  customWidgetsDom.toggleAttribute('hidden', true);
4677
-
4678
- element.appendChild( container );
4679
4706
  element.appendChild( customWidgetsDom );
4680
4707
 
4681
4708
  if( instance )
@@ -4764,7 +4791,7 @@ class NodeTree {
4764
4791
  _createItem( parent, node, level = 0, selectedId ) {
4765
4792
 
4766
4793
  const that = this;
4767
- const nodeFilterInput = this.domEl.querySelector( "#lexnodetree_filter" );
4794
+ const nodeFilterInput = this.domEl.querySelector( ".lexnodetree_filter" );
4768
4795
 
4769
4796
  node.children = node.children ?? [];
4770
4797
  if( nodeFilterInput && nodeFilterInput.value != "" && !node.id.includes( nodeFilterInput.value ) )
@@ -5193,6 +5220,7 @@ class NodeTree {
5193
5220
  }
5194
5221
 
5195
5222
  const _hasChild = function( parent, id ) {
5223
+ if( !parent.length ) return;
5196
5224
  for( var c of parent.children )
5197
5225
  {
5198
5226
  if( c.id == id ) return true;
@@ -5342,14 +5370,7 @@ class TextInput extends Widget {
5342
5370
 
5343
5371
  this._lastValueTriggered = value = newValue;
5344
5372
 
5345
- if( options.disabled )
5346
- {
5347
- wValue.innerText = newValue;
5348
- }
5349
- else
5350
- {
5351
- wValue.value = newValue;
5352
- }
5373
+ wValue.value = newValue;
5353
5374
 
5354
5375
  if( !skipCallback )
5355
5376
  {
@@ -5357,6 +5378,11 @@ class TextInput extends Widget {
5357
5378
  }
5358
5379
  };
5359
5380
 
5381
+ this.onResize = ( rect ) => {
5382
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5383
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5384
+ };
5385
+
5360
5386
  this.valid = ( v ) => {
5361
5387
  v = v ?? this.value();
5362
5388
  if( !v.length || wValue.pattern == "" ) return true;
@@ -5365,17 +5391,9 @@ class TextInput extends Widget {
5365
5391
  };
5366
5392
 
5367
5393
  let container = document.createElement( 'div' );
5368
- container.className = "lextext" + ( options.warning ? " lexwarning" : "" );
5394
+ container.className = ( options.warning ? " lexwarning" : "" );
5369
5395
  container.style.display = "flex";
5370
- doAsync( () => {
5371
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5372
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5373
- } );
5374
-
5375
- if( options.textClass )
5376
- {
5377
- container.classList.add( options.textClass );
5378
- }
5396
+ this.root.appendChild( container );
5379
5397
 
5380
5398
  this.disabled = ( options.disabled || options.warning ) ?? ( options.url ? true : false );
5381
5399
  let wValue = null;
@@ -5383,6 +5401,7 @@ class TextInput extends Widget {
5383
5401
  if( !this.disabled )
5384
5402
  {
5385
5403
  wValue = document.createElement( 'input' );
5404
+ wValue.className = "lextext " + ( options.inputClass ?? "" );
5386
5405
  wValue.type = options.type || "";
5387
5406
  wValue.value = wValue.iValue = value || "";
5388
5407
  wValue.style.width = "100%";
@@ -5435,27 +5454,35 @@ class TextInput extends Widget {
5435
5454
  }
5436
5455
 
5437
5456
  }
5438
- else
5457
+ else if( options.url )
5439
5458
  {
5440
- wValue = document.createElement( options.url ? 'a' : 'div' );
5441
-
5442
- if( options.url )
5443
- {
5444
- wValue.href = options.url;
5445
- wValue.target = "_blank";
5446
- }
5459
+ wValue = document.createElement( 'a' );
5460
+ wValue.href = options.url;
5461
+ wValue.target = "_blank";
5447
5462
 
5448
5463
  const icon = options.warning ? '<i class="fa-solid fa-triangle-exclamation"></i>' : '';
5449
5464
  wValue.innerHTML = ( icon + value ) || "";
5450
5465
  wValue.style.width = "100%";
5451
5466
  wValue.style.textAlign = options.float ?? "";
5467
+ wValue.className = "lextext ellipsis-overflow";
5468
+ }
5469
+ else
5470
+ {
5471
+ wValue = document.createElement( 'input' );
5472
+
5473
+ const icon = options.warning ? '<i class="fa-solid fa-triangle-exclamation"></i>' : '';
5474
+ wValue.disabled = true;
5475
+ wValue.innerHTML = icon;
5476
+ wValue.value = value;
5477
+ wValue.style.width = "100%";
5478
+ wValue.style.textAlign = options.float ?? "";
5479
+ wValue.className = "lextext ellipsis-overflow " + ( options.inputClass ?? "" );
5452
5480
  }
5453
5481
 
5454
5482
  Object.assign( wValue.style, options.style ?? {} );
5455
-
5456
5483
  container.appendChild( wValue );
5457
5484
 
5458
- this.root.appendChild( container );
5485
+ doAsync( this.onResize.bind( this ) );
5459
5486
  }
5460
5487
  }
5461
5488
 
@@ -5486,26 +5513,22 @@ class TextArea extends Widget {
5486
5513
  }
5487
5514
  };
5488
5515
 
5516
+ this.onResize = ( rect ) => {
5517
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5518
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5519
+ };
5520
+
5489
5521
  let container = document.createElement( "div" );
5490
5522
  container.className = "lextextarea";
5491
5523
  container.style.display = "flex";
5492
- doAsync( () => {
5493
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5494
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5495
- container.style.height = options.height;
5496
-
5497
- if( options.fitHeight )
5498
- {
5499
- // Update height depending on the content
5500
- wValue.style.height = wValue.scrollHeight + "px";
5501
- }
5502
- } );
5524
+ this.root.appendChild( container );
5503
5525
 
5504
5526
  let wValue = document.createElement( "textarea" );
5505
5527
  wValue.value = wValue.iValue = value || "";
5506
5528
  wValue.style.width = "100%";
5507
5529
  wValue.style.textAlign = options.float ?? "";
5508
5530
  Object.assign( wValue.style, options.style ?? {} );
5531
+ container.appendChild( wValue );
5509
5532
 
5510
5533
  if( options.disabled ?? false ) wValue.setAttribute( "disabled", true );
5511
5534
  if( options.placeholder ) wValue.setAttribute( "placeholder", options.placeholder );
@@ -5539,9 +5562,17 @@ class TextArea extends Widget {
5539
5562
  container.appendChild( icon );
5540
5563
  }
5541
5564
 
5542
- container.appendChild( wValue );
5565
+ doAsync( () => {
5566
+ container.style.height = options.height;
5543
5567
 
5544
- this.root.appendChild( container );
5568
+ if( options.fitHeight )
5569
+ {
5570
+ // Update height depending on the content
5571
+ wValue.style.height = wValue.scrollHeight + "px";
5572
+ }
5573
+
5574
+ this.onResize();
5575
+ }, 10 );
5545
5576
  }
5546
5577
  }
5547
5578
 
@@ -5568,10 +5599,22 @@ class Button extends Widget {
5568
5599
  ( options.img ? "<img src='" + options.img + "'>" : "<span>" + ( newValue || "" ) + "</span>" ) );
5569
5600
  };
5570
5601
 
5602
+ this.onResize = ( rect ) => {
5603
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5604
+ wValue.style.width = `calc( 100% - ${ realNameWidth }px)`;
5605
+ };
5606
+
5571
5607
  var wValue = document.createElement( 'button' );
5572
5608
  wValue.title = options.title ?? "";
5573
5609
  wValue.className = "lexbutton " + ( options.buttonClass ?? "" );
5574
5610
 
5611
+ if( options.icon )
5612
+ {
5613
+ wValue.classList.add( "justify-center" );
5614
+ }
5615
+
5616
+ this.root.appendChild( wValue );
5617
+
5575
5618
  if( options.selected )
5576
5619
  {
5577
5620
  wValue.classList.add( "selected" );
@@ -5581,11 +5624,6 @@ class Button extends Widget {
5581
5624
  ( options.icon ? "<a class='" + options.icon + "'></a>" :
5582
5625
  ( options.img ? "<img src='" + options.img + "'>" : "<span>" + ( value || "" ) + "</span>" ) );
5583
5626
 
5584
- doAsync( () => {
5585
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5586
- wValue.style.width = `calc( 100% - ${ realNameWidth })`;
5587
- } );
5588
-
5589
5627
  if( options.disabled )
5590
5628
  {
5591
5629
  wValue.setAttribute( "disabled", true );
@@ -5605,15 +5643,7 @@ class Button extends Widget {
5605
5643
  this._trigger( new IEvent( name, value, e ), callback );
5606
5644
  });
5607
5645
 
5608
- this.root.appendChild( wValue );
5609
-
5610
- // Remove branch padding and
5611
- const useNameAsLabel = !( options.hideName ?? false ) && !( options.icon || options.img );
5612
- if( !useNameAsLabel )
5613
- {
5614
- wValue.className += " noname";
5615
- wValue.style.width = "100%";
5616
- }
5646
+ doAsync( this.onResize.bind( this ) );
5617
5647
  }
5618
5648
  }
5619
5649
 
@@ -5641,14 +5671,10 @@ class ComboButtons extends Widget {
5641
5671
  container.className += options.float;
5642
5672
  }
5643
5673
 
5644
- doAsync( () => {
5645
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5646
- container.style.width = `calc( 100% - ${ realNameWidth })`;
5647
- } );
5648
-
5649
5674
  let currentValue = [];
5650
5675
  let buttonsBox = document.createElement('div');
5651
5676
  buttonsBox.className = "lexcombobuttonsbox ";
5677
+ container.appendChild( buttonsBox );
5652
5678
 
5653
5679
  for( let b of values )
5654
5680
  {
@@ -5760,9 +5786,14 @@ class ComboButtons extends Widget {
5760
5786
  }
5761
5787
  };
5762
5788
 
5763
- container.appendChild( buttonsBox );
5789
+ this.onResize = ( rect ) => {
5790
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5791
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
5792
+ };
5764
5793
 
5765
5794
  this.root.appendChild( container );
5795
+
5796
+ doAsync( this.onResize.bind( this ) );
5766
5797
  }
5767
5798
  }
5768
5799
 
@@ -5784,6 +5815,7 @@ class Card extends Widget {
5784
5815
  let container = document.createElement('div');
5785
5816
  container.className = "lexcard";
5786
5817
  container.style.width = "100%";
5818
+ this.root.appendChild( container );
5787
5819
 
5788
5820
  if( options.img )
5789
5821
  {
@@ -5806,6 +5838,7 @@ class Card extends Widget {
5806
5838
 
5807
5839
  let cardNameDom = document.createElement('span');
5808
5840
  cardNameDom.innerText = name;
5841
+ container.appendChild( cardNameDom );
5809
5842
 
5810
5843
  if( options.link != undefined )
5811
5844
  {
@@ -5824,9 +5857,6 @@ class Card extends Widget {
5824
5857
  this._trigger( new IEvent( name, null, e ), options.callback );
5825
5858
  });
5826
5859
  }
5827
-
5828
- container.appendChild( cardNameDom );
5829
- this.root.appendChild( container );
5830
5860
  }
5831
5861
  }
5832
5862
 
@@ -5877,6 +5907,7 @@ class Form extends Widget {
5877
5907
  container.className = "lexformdata";
5878
5908
  container.style.width = "100%";
5879
5909
  container.formData = {};
5910
+ this.root.appendChild( container );
5880
5911
 
5881
5912
  for( let entry in data )
5882
5913
  {
@@ -5888,7 +5919,7 @@ class Form extends Widget {
5888
5919
  }
5889
5920
 
5890
5921
  entryData.placeholder = entryData.placeholder ?? entry;
5891
- entryData.width = "calc(100% - 10px)";
5922
+ entryData.width = "100%";
5892
5923
 
5893
5924
  // this.addLabel( entry, { textClass: "formlabel" } );
5894
5925
 
@@ -5918,11 +5949,9 @@ class Form extends Widget {
5918
5949
  {
5919
5950
  callback( container.formData, event );
5920
5951
  }
5921
- }, { buttonClass: "primary", width: "calc(100% - 10px)" } );
5952
+ }, { buttonClass: "primary" } );
5922
5953
 
5923
5954
  container.appendChild( submitButton.root );
5924
-
5925
- this.root.appendChild( container );
5926
5955
  }
5927
5956
  }
5928
5957
 
@@ -5963,7 +5992,7 @@ class Select extends Widget {
5963
5992
  // Reset filter
5964
5993
  if( filter )
5965
5994
  {
5966
- filter.querySelector( "input" ).value = "";
5995
+ filter.root.querySelector( "input" ).value = "";
5967
5996
  const filteredOptions = this._filterOptions( values, "" );
5968
5997
  list.refresh( filteredOptions );
5969
5998
  }
@@ -5974,12 +6003,14 @@ class Select extends Widget {
5974
6003
  }
5975
6004
  };
5976
6005
 
6006
+ this.onResize = ( rect ) => {
6007
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6008
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6009
+ };
6010
+
5977
6011
  let container = document.createElement( "div" );
5978
6012
  container.className = "lexselect";
5979
- doAsync( () => {
5980
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5981
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5982
- } );
6013
+ this.root.appendChild( container );
5983
6014
 
5984
6015
  let wValue = document.createElement( 'div' );
5985
6016
  wValue.className = "lexselect lexoption";
@@ -5988,7 +6019,7 @@ class Select extends Widget {
5988
6019
 
5989
6020
  // Add select widget button
5990
6021
  let buttonName = value;
5991
- buttonName += "<a class='fa-solid fa-angle-down' style='float:right; margin-right: 3px;'></a>";
6022
+ buttonName += "<a class='fa-solid fa-angle-down'></a>";
5992
6023
 
5993
6024
  const _placeOptions = ( parent ) => {
5994
6025
 
@@ -6014,6 +6045,7 @@ class Select extends Widget {
6014
6045
  {
6015
6046
  const rect = nestedDialog.getBoundingClientRect();
6016
6047
  topPosition -= rect.y;
6048
+ maxY -= rect.y;
6017
6049
  }
6018
6050
 
6019
6051
  parent.style.top = ( topPosition + selectRoot.offsetHeight ) + 'px';
@@ -6079,7 +6111,7 @@ class Select extends Widget {
6079
6111
 
6080
6112
  if( filter )
6081
6113
  {
6082
- filter.querySelector( "input" ).focus();
6114
+ filter.root.querySelector( "input" ).focus();
6083
6115
  }
6084
6116
 
6085
6117
  }, { buttonClass: "array", skipInlineCount: true, disabled: options.disabled } );
@@ -6118,7 +6150,7 @@ class Select extends Widget {
6118
6150
  this.unfocus_event = true;
6119
6151
  setTimeout( () => delete this.unfocus_event, 200 );
6120
6152
  }
6121
- else if ( e.relatedTarget && e.relatedTarget.tagName == "INPUT" )
6153
+ else if ( e.relatedTarget && ( e.relatedTarget.tagName == "INPUT" || e.relatedTarget.classList.contains("lexoptions") ) )
6122
6154
  {
6123
6155
  return;
6124
6156
  }
@@ -6138,13 +6170,14 @@ class Select extends Widget {
6138
6170
  filterOptions.skipWidget = filterOptions.skipWidget ?? true;
6139
6171
  filterOptions.trigger = "input";
6140
6172
  filterOptions.icon = "fa-solid fa-magnifying-glass";
6141
- filterOptions.className = "lexfilter noname";
6173
+ filterOptions.className = "lexfilter";
6174
+ filterOptions.inputClass = "outline";
6142
6175
 
6143
- let filter = new TextInput(null, options.filterValue ?? "", ( v ) => {
6176
+ filter = new TextInput(null, options.filterValue ?? "", ( v ) => {
6144
6177
  const filteredOptions = this._filterOptions( values, v );
6145
6178
  list.refresh( filteredOptions );
6146
6179
  }, filterOptions );
6147
- filter.root.querySelector( ".lextext" ).classList.remove( "lextext" );
6180
+ filter.root.querySelector( ".lextext" ).style.border = "1px solid transparent";
6148
6181
 
6149
6182
  const input = filter.root.querySelector( "input" );
6150
6183
 
@@ -6165,12 +6198,12 @@ class Select extends Widget {
6165
6198
  list.appendChild( listOptions );
6166
6199
 
6167
6200
  // Add select options list
6168
- list.refresh = ( options ) => {
6201
+ list.refresh = ( currentOptions ) => {
6169
6202
 
6170
6203
  // Empty list
6171
6204
  listOptions.innerHTML = "";
6172
6205
 
6173
- if( !options.length )
6206
+ if( !currentOptions.length )
6174
6207
  {
6175
6208
  let iValue = options.emptyMsg ?? "No options found.";
6176
6209
 
@@ -6186,9 +6219,9 @@ class Select extends Widget {
6186
6219
  return;
6187
6220
  }
6188
6221
 
6189
- for( let i = 0; i < options.length; i++ )
6222
+ for( let i = 0; i < currentOptions.length; i++ )
6190
6223
  {
6191
- let iValue = options[ i ];
6224
+ let iValue = currentOptions[ i ];
6192
6225
  let li = document.createElement( "li" );
6193
6226
  let option = document.createElement( "div" );
6194
6227
  option.className = "option";
@@ -6256,7 +6289,7 @@ class Select extends Widget {
6256
6289
 
6257
6290
  container.appendChild( listDialog );
6258
6291
 
6259
- this.root.appendChild( container );
6292
+ doAsync( this.onResize.bind( this ) );
6260
6293
  }
6261
6294
 
6262
6295
  _filterOptions( options, value ) {
@@ -6312,12 +6345,17 @@ class Curve extends Widget {
6312
6345
  }
6313
6346
  };
6314
6347
 
6348
+ this.onResize = ( rect ) => {
6349
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6350
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6351
+ flushCss( container );
6352
+ curveInstance.canvas.width = container.offsetWidth;
6353
+ curveInstance.redraw();
6354
+ };
6355
+
6315
6356
  var container = document.createElement( "div" );
6316
6357
  container.className = "lexcurve";
6317
- doAsync( () => {
6318
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6319
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6320
- } );
6358
+ this.root.appendChild( container );
6321
6359
 
6322
6360
  options.callback = (v, e) => {
6323
6361
  this._trigger( new IEvent( name, v, e ), callback );
@@ -6327,16 +6365,9 @@ class Curve extends Widget {
6327
6365
 
6328
6366
  let curveInstance = new CanvasCurve( values, options );
6329
6367
  container.appendChild( curveInstance.element );
6330
- this.root.appendChild( container );
6331
-
6332
- // Resize
6333
- this.onresize = curveInstance.redraw.bind( curveInstance );
6334
6368
  this.curveInstance = curveInstance;
6335
6369
 
6336
- doAsync(() => {
6337
- curveInstance.canvas.width = container.offsetWidth;
6338
- curveInstance.redraw();
6339
- });
6370
+ doAsync( this.onResize.bind( this ) );
6340
6371
  }
6341
6372
  }
6342
6373
 
@@ -6356,24 +6387,32 @@ class Dial extends Widget {
6356
6387
  super( Widget.DIAL, name, defaultValues, options );
6357
6388
 
6358
6389
  this.onGetValue = () => {
6359
- return JSON.parse( JSON.stringify( curveInstance.element.value ) );
6390
+ return JSON.parse( JSON.stringify( dialInstance.element.value ) );
6360
6391
  };
6361
6392
 
6362
6393
  this.onSetValue = ( newValue, skipCallback, event ) => {
6363
- curveInstance.element.value = JSON.parse( JSON.stringify( newValue ) );
6364
- curveInstance.redraw();
6394
+ dialInstance.element.value = JSON.parse( JSON.stringify( newValue ) );
6395
+ dialInstance.redraw();
6365
6396
  if( !skipCallback )
6366
6397
  {
6367
- this._trigger( new IEvent( name, curveInstance.element.value, event ), callback );
6398
+ this._trigger( new IEvent( name, dialInstance.element.value, event ), callback );
6368
6399
  }
6369
6400
  };
6370
6401
 
6402
+ this.onResize = ( rect ) => {
6403
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6404
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6405
+ flushCss( container );
6406
+ dialInstance.element.style.height = dialInstance.element.offsetWidth + "px";
6407
+ dialInstance.canvas.width = dialInstance.element.offsetWidth;
6408
+ container.style.width = dialInstance.element.offsetWidth + "px";
6409
+ dialInstance.canvas.height = dialInstance.canvas.width;
6410
+ dialInstance.redraw();
6411
+ };
6412
+
6371
6413
  var container = document.createElement( "div" );
6372
6414
  container.className = "lexcurve";
6373
- doAsync( () => {
6374
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6375
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6376
- } );
6415
+ this.root.appendChild( container );
6377
6416
 
6378
6417
  options.callback = ( v, e ) => {
6379
6418
  this._trigger( new IEvent( name, v, e ), callback );
@@ -6381,21 +6420,11 @@ class Dial extends Widget {
6381
6420
 
6382
6421
  options.name = name;
6383
6422
 
6384
- let curveInstance = new CanvasDial( this, values, options );
6385
- container.appendChild( curveInstance.element );
6386
- this.root.appendChild( container );
6423
+ let dialInstance = new CanvasDial( this, values, options );
6424
+ container.appendChild( dialInstance.element );
6425
+ this.dialInstance = dialInstance;
6387
6426
 
6388
- // Resize
6389
- this.onresize = curveInstance.redraw.bind( curveInstance );
6390
- this.curveInstance = curveInstance;
6391
-
6392
- doAsync(() => {
6393
- curveInstance.element.style.height = curveInstance.element.offsetWidth + "px";
6394
- curveInstance.canvas.width = curveInstance.element.offsetWidth;
6395
- container.style.width = curveInstance.element.offsetWidth + "px";
6396
- curveInstance.canvas.height = curveInstance.canvas.width;
6397
- curveInstance.redraw();
6398
- });
6427
+ doAsync( this.onResize.bind( this ) );
6399
6428
  }
6400
6429
  }
6401
6430
 
@@ -6418,25 +6447,27 @@ class Layers extends Widget {
6418
6447
 
6419
6448
  this.onSetValue = ( newValue, skipCallback, event ) => {
6420
6449
  value = newValue;
6421
- setLayers();
6450
+ this.setLayers( value );
6422
6451
  if( !skipCallback )
6423
6452
  {
6424
6453
  this._trigger( new IEvent(name, value, event), callback );
6425
6454
  }
6426
6455
  };
6427
6456
 
6457
+ this.onResize = ( rect ) => {
6458
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6459
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6460
+ };
6461
+
6428
6462
  var container = document.createElement( "div" );
6429
6463
  container.className = "lexlayers";
6430
- doAsync( () => {
6431
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6432
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6433
- } );
6464
+ this.root.appendChild( container );
6434
6465
 
6435
- const setLayers = () => {
6466
+ this.setLayers = ( val ) => {
6436
6467
 
6437
6468
  container.innerHTML = "";
6438
6469
 
6439
- let binary = value.toString( 2 );
6470
+ let binary = val.toString( 2 );
6440
6471
  let nbits = binary.length;
6441
6472
 
6442
6473
  // fill zeros
@@ -6450,7 +6481,7 @@ class Layers extends Widget {
6450
6481
  let layer = document.createElement( "div" );
6451
6482
  layer.className = "lexlayer";
6452
6483
 
6453
- if( value != undefined )
6484
+ if( val != undefined )
6454
6485
  {
6455
6486
  const valueBit = binary[ 16 - bit - 1 ];
6456
6487
  if( valueBit != undefined && valueBit == '1' )
@@ -6467,15 +6498,15 @@ class Layers extends Widget {
6467
6498
  e.stopPropagation();
6468
6499
  e.stopImmediatePropagation();
6469
6500
  e.target.classList.toggle( "selected" );
6470
- const newValue = value ^ ( 1 << bit );
6501
+ const newValue = val ^ ( 1 << bit );
6471
6502
  this.set( newValue, false, e );
6472
6503
  } );
6473
6504
  }
6474
6505
  };
6475
6506
 
6476
- setLayers();
6507
+ this.setLayers( value );
6477
6508
 
6478
- this.root.appendChild( container );
6509
+ doAsync( this.onResize.bind( this ) );
6479
6510
  }
6480
6511
  }
6481
6512
 
@@ -6490,6 +6521,8 @@ class ItemArray extends Widget {
6490
6521
 
6491
6522
  constructor( name, values = [], callback, options = {} ) {
6492
6523
 
6524
+ options.nameWidth = "100%";
6525
+
6493
6526
  super( Widget.ARRAY, name, null, options );
6494
6527
 
6495
6528
  this.onGetValue = () => {
@@ -6505,28 +6538,25 @@ class ItemArray extends Widget {
6505
6538
  }
6506
6539
  };
6507
6540
 
6508
- this.root.style.flexWrap = "wrap";
6509
-
6510
6541
  // Add open array button
6511
6542
 
6512
6543
  const itemNameWidth = "4%";
6513
6544
 
6514
6545
  var container = document.createElement('div');
6515
6546
  container.className = "lexarray";
6516
- doAsync( () => {
6517
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6518
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6519
- } );
6547
+ container.style.width = "100%";
6548
+ this.root.appendChild( container );
6549
+ this.root.dataset["opened"] = false;
6520
6550
 
6521
- const angleDown = `<a class='fa-solid fa-angle-down' style='float:right; margin-right: 3px;'></a>`;
6551
+ const angleDown = `<a class='fa-solid fa-angle-down'></a>`;
6522
6552
 
6523
6553
  let buttonName = "Array (size " + values.length + ")";
6524
6554
  buttonName += angleDown;
6525
6555
 
6526
6556
  const toggleButton = new Button(null, buttonName, () => {
6557
+ this.root.dataset["opened"] = this.root.dataset["opened"] == "true" ? false : true;
6527
6558
  this.root.querySelector(".lexarrayitems").toggleAttribute('hidden');
6528
6559
  }, { buttonClass: 'array' });
6529
-
6530
6560
  container.appendChild( toggleButton.root );
6531
6561
 
6532
6562
  // Show elements
@@ -6534,8 +6564,6 @@ class ItemArray extends Widget {
6534
6564
  let arrayItems = document.createElement( "div" );
6535
6565
  arrayItems.className = "lexarrayitems";
6536
6566
  arrayItems.toggleAttribute( "hidden", true );
6537
-
6538
- this.root.appendChild( container );
6539
6567
  this.root.appendChild( arrayItems );
6540
6568
 
6541
6569
  this._updateItems = () => {
@@ -6552,10 +6580,6 @@ class ItemArray extends Widget {
6552
6580
  {
6553
6581
  const value = values[ i ];
6554
6582
  let baseclass = options.innerValues ? 'select' : value.constructor;
6555
-
6556
- // TODO
6557
- // this.sameLine( 2 );
6558
-
6559
6583
  let widget = null;
6560
6584
 
6561
6585
  switch( baseclass )
@@ -6584,17 +6608,17 @@ class ItemArray extends Widget {
6584
6608
 
6585
6609
  arrayItems.appendChild( widget.root );
6586
6610
 
6587
- widget = new Button( null, "<a class='lexicon fa-solid fa-trash'></a>", ( v, event) => {
6611
+ const removeWidget = new Button( null, "<a class='lexicon fa-solid fa-trash'></a>", ( v, event) => {
6588
6612
  values.splice( values.indexOf( value ), 1 );
6589
6613
  this._updateItems();
6590
6614
  this._trigger( new IEvent(name, values, event), callback );
6591
6615
  }, { title: "Remove item", className: 'micro'} );
6592
6616
 
6593
- arrayItems.appendChild( widget.root );
6617
+ widget.root.appendChild( removeWidget.root );
6594
6618
  }
6595
6619
 
6596
6620
  buttonName = "Add item";
6597
- buttonName += "<a class='fa-solid fa-plus' style='float:right; margin-right: 3px; margin-top: 2px;'></a>";
6621
+ buttonName += "<a class='fa-solid fa-plus'></a>";
6598
6622
 
6599
6623
  const addButton = new Button(null, buttonName, (v, event) => {
6600
6624
  values.push( options.innerValues ? options.innerValues[ 0 ] : "" );
@@ -6655,6 +6679,11 @@ class List extends Widget {
6655
6679
  }
6656
6680
  };
6657
6681
 
6682
+ this.onResize = ( rect ) => {
6683
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6684
+ listContainer.style.width = `calc( 100% - ${ realNameWidth }px)`;
6685
+ };
6686
+
6658
6687
  this._updateValues = ( newValues ) => {
6659
6688
 
6660
6689
  values = newValues;
@@ -6690,14 +6719,11 @@ class List extends Widget {
6690
6719
 
6691
6720
  let listContainer = document.createElement( 'div' );
6692
6721
  listContainer.className = "lexlist";
6693
- doAsync( () => {
6694
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6695
- listContainer.style.width = `calc( 100% - ${ realNameWidth })`;
6696
- } );
6722
+ this.root.appendChild( listContainer );
6697
6723
 
6698
6724
  this._updateValues( values );
6699
6725
 
6700
- this.root.appendChild( listContainer );
6726
+ doAsync( this.onResize.bind( this ) );
6701
6727
  }
6702
6728
  }
6703
6729
 
@@ -6723,23 +6749,25 @@ class Tags extends Widget {
6723
6749
 
6724
6750
  this.onSetValue = ( newValue, skipCallback, event ) => {
6725
6751
  value = [].concat( newValue );
6726
- _generateTags();
6752
+ this.generateTags( value );
6727
6753
  if( !skipCallback )
6728
6754
  {
6729
6755
  this._trigger( new IEvent( name, value, event ), callback );
6730
6756
  }
6731
6757
  };
6732
6758
 
6759
+ this.onResize = ( rect ) => {
6760
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6761
+ tagsContainer.style.width = `calc( 100% - ${ realNameWidth }px)`;
6762
+ };
6763
+
6733
6764
  // Show tags
6734
6765
 
6735
6766
  const tagsContainer = document.createElement('div');
6736
6767
  tagsContainer.className = "lextags";
6737
- doAsync( () => {
6738
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6739
- tagsContainer.style.width = `calc( 100% - ${ realNameWidth })`;
6740
- } );
6768
+ this.root.appendChild( tagsContainer );
6741
6769
 
6742
- const _generateTags = () => {
6770
+ this.generateTags = ( value ) => {
6743
6771
 
6744
6772
  tagsContainer.innerHTML = "";
6745
6773
 
@@ -6783,9 +6811,9 @@ class Tags extends Widget {
6783
6811
  tagInput.focus();
6784
6812
  }
6785
6813
 
6786
- _generateTags();
6814
+ this.generateTags( value );
6787
6815
 
6788
- this.root.appendChild( tagsContainer );
6816
+ doAsync( this.onResize.bind( this ) );
6789
6817
  }
6790
6818
  }
6791
6819
 
@@ -6829,35 +6857,33 @@ class Checkbox extends Widget {
6829
6857
  }
6830
6858
  };
6831
6859
 
6860
+ this.onResize = ( rect ) => {
6861
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6862
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6863
+ };
6864
+
6832
6865
  var container = document.createElement( "div" );
6833
6866
  container.className = "lexcheckboxcont";
6834
- doAsync( () => {
6835
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6836
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
6837
- } );
6867
+ this.root.appendChild( container );
6838
6868
 
6839
6869
  let checkbox = document.createElement( "input" );
6840
6870
  checkbox.type = "checkbox";
6841
- checkbox.className = "lexcheckbox " + ( options.className ?? "" );
6871
+ checkbox.className = "lexcheckbox " + ( options.className ?? "primary" );
6842
6872
  checkbox.checked = value;
6843
6873
  checkbox.disabled = options.disabled ?? false;
6874
+ container.appendChild( checkbox );
6844
6875
 
6845
6876
  let valueName = document.createElement( "span" );
6846
6877
  valueName.className = "checkboxtext";
6847
6878
  valueName.innerHTML = options.label ?? "On";
6848
-
6849
- container.appendChild( checkbox );
6850
6879
  container.appendChild( valueName );
6851
6880
 
6852
6881
  checkbox.addEventListener( "change" , e => {
6853
6882
  this.set( checkbox.checked, false, e );
6854
6883
  });
6855
6884
 
6856
- this.root.appendChild( container );
6857
-
6858
6885
  if( options.suboptions )
6859
6886
  {
6860
- this.root.style.flexWrap = "wrap";
6861
6887
  let suboptions = document.createElement( "div" );
6862
6888
  suboptions.className = "lexcheckboxsubmenu";
6863
6889
  suboptions.toggleAttribute( "hidden", !checkbox.checked );
@@ -6869,6 +6895,8 @@ class Checkbox extends Widget {
6869
6895
 
6870
6896
  this.root.appendChild( suboptions );
6871
6897
  }
6898
+
6899
+ doAsync( this.onResize.bind( this ) );
6872
6900
  }
6873
6901
  }
6874
6902
 
@@ -6912,12 +6940,14 @@ class Toggle extends Widget {
6912
6940
  }
6913
6941
  };
6914
6942
 
6943
+ this.onResize = ( rect ) => {
6944
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6945
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6946
+ };
6947
+
6915
6948
  var container = document.createElement('div');
6916
6949
  container.className = "lextogglecont";
6917
- doAsync( () => {
6918
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6919
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
6920
- } );
6950
+ this.root.appendChild( container );
6921
6951
 
6922
6952
  let toggle = document.createElement('input');
6923
6953
  toggle.type = "checkbox";
@@ -6925,23 +6955,19 @@ class Toggle extends Widget {
6925
6955
  toggle.checked = value;
6926
6956
  toggle.iValue = value;
6927
6957
  toggle.disabled = options.disabled ?? false;
6958
+ container.appendChild( toggle );
6928
6959
 
6929
6960
  let valueName = document.createElement( 'span' );
6930
6961
  valueName.className = "toggletext";
6931
6962
  valueName.innerHTML = options.label ?? "On";
6932
-
6933
- container.appendChild( toggle );
6934
6963
  container.appendChild( valueName );
6935
6964
 
6936
6965
  toggle.addEventListener( "change" , e => {
6937
6966
  this.set( toggle.checked, false, e );
6938
6967
  });
6939
6968
 
6940
- this.root.appendChild( container );
6941
-
6942
6969
  if( options.suboptions )
6943
6970
  {
6944
- this.root.style.flexWrap = "wrap";
6945
6971
  let suboptions = document.createElement('div');
6946
6972
  suboptions.className = "lextogglesubmenu";
6947
6973
  suboptions.toggleAttribute( 'hidden', !toggle.checked );
@@ -6953,6 +6979,8 @@ class Toggle extends Widget {
6953
6979
 
6954
6980
  this.root.appendChild( suboptions );
6955
6981
  }
6982
+
6983
+ doAsync( this.onResize.bind( this ) );
6956
6984
  }
6957
6985
  }
6958
6986
 
@@ -6997,6 +7025,7 @@ class RadioGroup extends Widget {
6997
7025
 
6998
7026
  var container = document.createElement( 'div' );
6999
7027
  container.className = "lexradiogroup " + ( options.className ?? "" );
7028
+ this.root.appendChild( container );
7000
7029
 
7001
7030
  let labelSpan = document.createElement( 'span' );
7002
7031
  labelSpan.innerHTML = label;
@@ -7031,8 +7060,6 @@ class RadioGroup extends Widget {
7031
7060
  currentIndex = options.selected;
7032
7061
  this.set( currentIndex, true );
7033
7062
  }
7034
-
7035
- this.root.appendChild( container );
7036
7063
  }
7037
7064
  }
7038
7065
 
@@ -7062,8 +7089,7 @@ class ColorInput extends Widget {
7062
7089
  newValue = hexToRgb( newValue );
7063
7090
  }
7064
7091
 
7065
- // Means it was called from the color input listener, not the text
7066
- if( event )
7092
+ if( !this._skipTextUpdate )
7067
7093
  {
7068
7094
  textWidget.set( newValue, true, event );
7069
7095
  }
@@ -7076,20 +7102,22 @@ class ColorInput extends Widget {
7076
7102
  }
7077
7103
  };
7078
7104
 
7105
+ this.onResize = ( rect ) => {
7106
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7107
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7108
+ };
7109
+
7079
7110
  var container = document.createElement( 'span' );
7080
7111
  container.className = "lexcolor";
7081
- doAsync( () => {
7082
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7083
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7084
- } );
7112
+ this.root.appendChild( container );
7085
7113
 
7086
7114
  let color = document.createElement( 'input' );
7087
7115
  color.style.width = "32px";
7088
7116
  color.type = 'color';
7089
7117
  color.className = "colorinput";
7090
- color.id = "color" + simple_guidGenerator();
7091
7118
  color.useRGB = options.useRGB ?? false;
7092
- color.value = color.iValue = value;
7119
+ color.value = value;
7120
+ container.appendChild( color );
7093
7121
 
7094
7122
  if( options.disabled )
7095
7123
  {
@@ -7100,17 +7128,16 @@ class ColorInput extends Widget {
7100
7128
  this.set( e.target.value, false, e );
7101
7129
  }, false );
7102
7130
 
7103
- container.appendChild( color );
7104
-
7105
7131
  const textWidget = new TextInput( null, color.value, v => {
7132
+ this._skipTextUpdate = true;
7106
7133
  this.set( v );
7107
- }, { width: "calc( 100% - 32px )"});
7134
+ delete this._skipTextUpdate;
7135
+ }, { width: "calc( 100% - 32px )", disabled: options.disabled });
7108
7136
 
7109
7137
  textWidget.root.style.marginLeft = "4px";
7110
-
7111
7138
  container.appendChild( textWidget.root );
7112
7139
 
7113
- this.root.appendChild( container );
7140
+ doAsync( this.onResize.bind( this ) );
7114
7141
  }
7115
7142
  }
7116
7143
 
@@ -7146,22 +7173,36 @@ class RangeInput extends Widget {
7146
7173
  }
7147
7174
  };
7148
7175
 
7149
- var container = document.createElement( 'div' );
7176
+ this.onResize = ( rect ) => {
7177
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7178
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
7179
+ };
7180
+
7181
+ const container = document.createElement( 'div' );
7150
7182
  container.className = "lexrange";
7151
- doAsync( () => {
7152
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7153
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
7154
- } );
7183
+ this.root.appendChild( container );
7155
7184
 
7156
7185
  let slider = document.createElement( 'input' );
7157
7186
  slider.className = "lexrangeslider " + ( options.className ?? "" );
7158
- slider.value = slider.iValue = value;
7159
7187
  slider.min = options.min ?? 0;
7160
7188
  slider.max = options.max ?? 100;
7161
7189
  slider.step = options.step ?? 1;
7162
7190
  slider.type = "range";
7163
7191
  slider.disabled = options.disabled ?? false;
7164
7192
 
7193
+ if( value.constructor == Number )
7194
+ {
7195
+ value = clamp( value, +slider.min, +slider.max );
7196
+ }
7197
+
7198
+ if( options.left )
7199
+ {
7200
+ value = ( ( +slider.max ) - value + ( +slider.min ) );
7201
+ }
7202
+
7203
+ slider.value = value;
7204
+ container.appendChild( slider );
7205
+
7165
7206
  if( options.left ?? false )
7166
7207
  {
7167
7208
  slider.classList.add( "left" );
@@ -7198,14 +7239,7 @@ class RangeInput extends Widget {
7198
7239
  Widget._dispatchEvent( slider, "input", true );
7199
7240
  };
7200
7241
 
7201
- if( value.constructor == Number )
7202
- {
7203
- value = clamp( value, +slider.min, +slider.max );
7204
- }
7205
-
7206
- container.appendChild( slider );
7207
-
7208
- this.root.appendChild( container );
7242
+ doAsync( this.onResize.bind( this ) );
7209
7243
  }
7210
7244
  }
7211
7245
 
@@ -7253,15 +7287,18 @@ class NumberInput extends Widget {
7253
7287
  }
7254
7288
  };
7255
7289
 
7290
+ this.onResize = ( rect ) => {
7291
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7292
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
7293
+ };
7294
+
7256
7295
  var container = document.createElement( 'div' );
7257
7296
  container.className = "lexnumber";
7258
- doAsync( () => {
7259
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7260
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
7261
- } );
7297
+ this.root.appendChild( container );
7262
7298
 
7263
7299
  let box = document.createElement( 'div' );
7264
7300
  box.className = "numberbox";
7301
+ container.appendChild( box );
7265
7302
 
7266
7303
  let vecinput = document.createElement( 'input' );
7267
7304
  vecinput.id = "number_" + simple_guidGenerator();
@@ -7435,9 +7472,7 @@ class NumberInput extends Widget {
7435
7472
 
7436
7473
  vecinput.addEventListener( "mousedown", innerMouseDown );
7437
7474
 
7438
- container.appendChild( box );
7439
-
7440
- this.root.appendChild( container );
7475
+ doAsync( this.onResize.bind( this ) );
7441
7476
  }
7442
7477
  }
7443
7478
 
@@ -7489,14 +7524,16 @@ class Vector extends Widget {
7489
7524
  }
7490
7525
  };
7491
7526
 
7527
+ this.onResize = ( rect ) => {
7528
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7529
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7530
+ };
7531
+
7492
7532
  const vectorInputs = [];
7493
7533
 
7494
7534
  var container = document.createElement( 'div' );
7495
7535
  container.className = "lexvector";
7496
- doAsync( () => {
7497
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7498
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7499
- } );
7536
+ this.root.appendChild( container );
7500
7537
 
7501
7538
  const that = this;
7502
7539
 
@@ -7699,7 +7736,7 @@ class Vector extends Widget {
7699
7736
  }
7700
7737
  }, false );
7701
7738
 
7702
- this.root.appendChild( container );
7739
+ doAsync( this.onResize.bind( this ) );
7703
7740
  }
7704
7741
  }
7705
7742
 
@@ -7829,24 +7866,28 @@ class Pad extends Widget {
7829
7866
  }
7830
7867
  };
7831
7868
 
7869
+ this.onResize = ( rect ) => {
7870
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7871
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7872
+ };
7873
+
7832
7874
  var container = document.createElement( 'div' );
7833
7875
  container.className = "lexpad";
7834
- doAsync( () => {
7835
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7836
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7837
- } );
7876
+ this.root.appendChild( container );
7838
7877
 
7839
7878
  let pad = document.createElement('div');
7840
7879
  pad.id = "lexpad-" + name;
7841
7880
  pad.className = "lexinnerpad";
7842
7881
  pad.style.width = options.padSize ?? '96px';
7843
7882
  pad.style.height = options.padSize ?? '96px';
7883
+ container.appendChild( pad );
7844
7884
 
7845
7885
  let thumb = document.createElement('div');
7846
7886
  thumb.className = "lexpadthumb";
7847
7887
  thumb.value = new LX.vec2( value[ 0 ], value[ 1 ] );
7848
7888
  thumb.min = options.min ?? 0;
7849
7889
  thumb.max = options.max ?? 1;
7890
+ pad.appendChild( thumb );
7850
7891
 
7851
7892
  let _updateValue = v => {
7852
7893
  const [ w, h ] = [ pad.offsetWidth, pad.offsetHeight ];
@@ -7854,14 +7895,6 @@ class Pad extends Widget {
7854
7895
  thumb.style.transform = `translate(calc( ${ w * value0to1.x }px - 50% ), calc( ${ h * value0to1.y }px - 50%)`;
7855
7896
  }
7856
7897
 
7857
- doAsync( () => {
7858
- _updateValue( thumb.value )
7859
- } );
7860
-
7861
- pad.appendChild( thumb );
7862
- container.appendChild( pad );
7863
- this.root.appendChild( container );
7864
-
7865
7898
  pad.addEventListener( "mousedown", innerMouseDown );
7866
7899
 
7867
7900
  let that = this;
@@ -7880,6 +7913,7 @@ class Pad extends Widget {
7880
7913
  document.body.classList.add( 'noevents' );
7881
7914
  e.stopImmediatePropagation();
7882
7915
  e.stopPropagation();
7916
+ thumb.classList.add( "active" );
7883
7917
 
7884
7918
  if( options.onPress )
7885
7919
  {
@@ -7911,12 +7945,18 @@ class Pad extends Widget {
7911
7945
  doc.removeEventListener( 'mouseup', innerMouseUp );
7912
7946
  document.body.classList.remove( 'nocursor' );
7913
7947
  document.body.classList.remove( 'noevents' );
7948
+ thumb.classList.remove( "active" );
7914
7949
 
7915
7950
  if( options.onRelease )
7916
7951
  {
7917
7952
  options.onRelease.bind( thumb )( e, thumb );
7918
7953
  }
7919
7954
  }
7955
+
7956
+ doAsync( () => {
7957
+ this.onResize();
7958
+ _updateValue( thumb.value )
7959
+ } );
7920
7960
  }
7921
7961
  }
7922
7962
 
@@ -7946,12 +7986,14 @@ class Progress extends Widget {
7946
7986
  }
7947
7987
  };
7948
7988
 
7949
- var container = document.createElement('div');
7989
+ this.onResize = ( rect ) => {
7990
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7991
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7992
+ };
7993
+
7994
+ const container = document.createElement('div');
7950
7995
  container.className = "lexprogress";
7951
- doAsync( () => {
7952
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7953
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7954
- } );
7996
+ this.root.appendChild( container );
7955
7997
 
7956
7998
  // add slider (0-1 if not specified different )
7957
7999
 
@@ -7965,6 +8007,7 @@ class Progress extends Widget {
7965
8007
  progress.high = options.high ?? progress.high;
7966
8008
  progress.optimum = options.optimum ?? progress.optimum;
7967
8009
  progress.value = value;
8010
+ container.appendChild( progress );
7968
8011
 
7969
8012
  const _updateColor = () => {
7970
8013
 
@@ -7982,9 +8025,6 @@ class Progress extends Widget {
7982
8025
  progress.style.background = `color-mix(in srgb, ${backgroundColor} 20%, transparent)`;
7983
8026
  };
7984
8027
 
7985
- container.appendChild( progress );
7986
- this.root.appendChild( container );
7987
-
7988
8028
  if( options.showValue )
7989
8029
  {
7990
8030
  if( document.getElementById('progressvalue-' + name ) )
@@ -8051,6 +8091,8 @@ class Progress extends Widget {
8051
8091
  }
8052
8092
 
8053
8093
  _updateColor();
8094
+
8095
+ doAsync( this.onResize.bind( this ) );
8054
8096
  }
8055
8097
  }
8056
8098
 
@@ -8071,15 +8113,17 @@ class FileInput extends Widget {
8071
8113
  let type = options.type ?? 'text';
8072
8114
  let read = options.read ?? true;
8073
8115
 
8116
+ this.onResize = ( rect ) => {
8117
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
8118
+ input.style.width = `calc( 100% - ${ realNameWidth }px)`;
8119
+ };
8120
+
8074
8121
  // Create hidden input
8075
8122
  let input = document.createElement( 'input' );
8076
8123
  input.className = "lexfileinput";
8077
8124
  input.type = 'file';
8078
8125
  input.disabled = options.disabled ?? false;
8079
- doAsync( () => {
8080
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
8081
- input.style.width = `calc( 100% - ${ realNameWidth } - 10%)`;
8082
- } );
8126
+ this.root.appendChild( input );
8083
8127
 
8084
8128
  if( options.placeholder )
8085
8129
  {
@@ -8112,13 +8156,11 @@ class FileInput extends Widget {
8112
8156
  callback( null );
8113
8157
  });
8114
8158
 
8115
- this.root.appendChild( input );
8116
-
8117
8159
  if( local )
8118
8160
  {
8119
8161
  let settingsDialog = null;
8120
8162
 
8121
- const settingButton = new Button(null, "<a style='margin-top: 0px;' class='fa-solid fa-gear'></a>", () => {
8163
+ const settingButton = new Button(null, "", () => {
8122
8164
 
8123
8165
  if( settingsDialog )
8124
8166
  {
@@ -8130,10 +8172,12 @@ class FileInput extends Widget {
8130
8172
  p.addButton( null, "Reload", v => { input.dispatchEvent( new Event( 'change' ) ) } );
8131
8173
  }, { onclose: ( root ) => { root.remove(); settingsDialog = null; } } );
8132
8174
 
8133
- }, { className: "micro", skipInlineCount: true, title: "Settings" });
8175
+ }, { skipInlineCount: true, title: "Settings", disabled: options.disabled, icon: "fa-solid fa-gear" });
8134
8176
 
8135
8177
  this.root.appendChild( settingButton.root );
8136
8178
  }
8179
+
8180
+ doAsync( this.onResize.bind( this ) );
8137
8181
  }
8138
8182
  }
8139
8183
 
@@ -8191,9 +8235,9 @@ class Tree extends Widget {
8191
8235
  if( options.filter )
8192
8236
  {
8193
8237
  nodeFilterInput = document.createElement('input');
8194
- nodeFilterInput.id = "lexnodetree_filter";
8238
+ nodeFilterInput.className = "lexnodetree_filter";
8195
8239
  nodeFilterInput.setAttribute("placeholder", "Filter..");
8196
- nodeFilterInput.style.width = "calc( 100% - 17px )";
8240
+ nodeFilterInput.style.width = "100%";
8197
8241
  nodeFilterInput.addEventListener('input', () => {
8198
8242
  this.innerTree.refresh();
8199
8243
  });
@@ -8343,11 +8387,11 @@ class Counter extends Widget {
8343
8387
  container.className = "lexcounter";
8344
8388
  this.root.appendChild( container );
8345
8389
 
8346
- const substrButton = new Button(null, "<a style='margin-top: 0px;' class='fa-solid fa-minus'></a>", ( value, e ) => {
8390
+ const substrButton = new Button(null, "", ( value, e ) => {
8347
8391
  let mult = step ?? 1;
8348
8392
  if( e.shiftKey ) mult *= 10;
8349
8393
  this.set( counterText.count - mult, false, e );
8350
- }, { className: "micro", skipInlineCount: true, title: "Minus" });
8394
+ }, { skipInlineCount: true, title: "Minus", icon: "fa-solid fa-minus" });
8351
8395
 
8352
8396
  container.appendChild( substrButton.root );
8353
8397
 
@@ -8369,12 +8413,11 @@ class Counter extends Widget {
8369
8413
  containerBox.appendChild( counterLabel );
8370
8414
  }
8371
8415
 
8372
- const addButton = new Button(null, "<a style='margin-top: 0px;' class='fa-solid fa-plus'></a>", ( value, e ) => {
8416
+ const addButton = new Button(null, "", ( value, e ) => {
8373
8417
  let mult = step ?? 1;
8374
8418
  if( e.shiftKey ) mult *= 10;
8375
8419
  this.set( counterText.count + mult, false, e );
8376
- }, { className: "micro", skipInlineCount: true, title: "Plus" });
8377
-
8420
+ }, { skipInlineCount: true, title: "Plus", icon: "fa-solid fa-plus" });
8378
8421
  container.appendChild( addButton.root );
8379
8422
  }
8380
8423
  }
@@ -8397,12 +8440,14 @@ class Table extends Widget {
8397
8440
 
8398
8441
  super( Widget.TABLE, name, null, options );
8399
8442
 
8443
+ this.onResize = ( rect ) => {
8444
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
8445
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
8446
+ };
8447
+
8400
8448
  const container = document.createElement('div');
8401
8449
  container.className = "lextable";
8402
- doAsync( () => {
8403
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
8404
- container.style.width = `calc( 100% - ${ realNameWidth })`;
8405
- } );
8450
+ this.root.appendChild( container );
8406
8451
 
8407
8452
  this.centered = options.centered ?? false;
8408
8453
  if( this.centered === true )
@@ -8410,13 +8455,16 @@ class Table extends Widget {
8410
8455
  container.classList.add( "centered" );
8411
8456
  }
8412
8457
 
8413
- const table = document.createElement( 'table' );
8414
- container.appendChild( table );
8458
+ this.filter = options.filter ?? false;
8459
+ this.toggleColumns = options.toggleColumns ?? false;
8460
+ this.customFilters = options.customFilters ?? false;
8461
+ this.activeCustomFilters = {};
8415
8462
 
8416
8463
  data.head = data.head ?? [];
8417
8464
  data.body = data.body ?? [];
8418
- data.colVisibilityMap = { };
8419
8465
  data.checkMap = { };
8466
+ data.colVisibilityMap = { };
8467
+ data.head.forEach( (col, index) => { data.colVisibilityMap[ index ] = true; })
8420
8468
 
8421
8469
  const compareFn = ( idx, order, a, b) => {
8422
8470
  if (a[idx] < b[idx]) return -order;
@@ -8426,14 +8474,105 @@ class Table extends Widget {
8426
8474
 
8427
8475
  const sortFn = ( idx, sign ) => {
8428
8476
  data.body = data.body.sort( compareFn.bind( this, idx, sign ) );
8429
- this.refreshTable();
8477
+ this.refresh();
8478
+ }
8479
+
8480
+ // Append header
8481
+ if( this.filter || this.customFilters || this.toggleColumns )
8482
+ {
8483
+ const headerContainer = LX.makeContainer( [ "100%", "auto" ] );
8484
+
8485
+ if( this.filter )
8486
+ {
8487
+ const filterOptions = LX.deepCopy( options );
8488
+ filterOptions.placeholder = `Filter ${ this.filter }...`;
8489
+ filterOptions.skipWidget = true;
8490
+ filterOptions.trigger = "input";
8491
+ filterOptions.inputClass = "outline";
8492
+
8493
+ let filter = new TextInput(null, "", ( v ) => {
8494
+ this._currentFilter = v;
8495
+ this.refresh();
8496
+ }, filterOptions );
8497
+
8498
+ headerContainer.appendChild( filter.root );
8499
+ }
8500
+
8501
+ if( this.customFilters )
8502
+ {
8503
+ const icon = LX.makeIcon( "circle-plus", null, "sm" );
8504
+
8505
+ for( let f of this.customFilters )
8506
+ {
8507
+ const customFilterBtn = new Button(null, icon.innerHTML + f.name, ( v ) => {
8508
+
8509
+ const menuOptions = f.options.map( ( colName, idx ) => {
8510
+ const item = {
8511
+ name: colName,
8512
+ checked: !!this.activeCustomFilters[ colName ],
8513
+ callback: (key, dom, v) => {
8514
+ if( v ) { this.activeCustomFilters[ key ] = f.name; }
8515
+ else {
8516
+ delete this.activeCustomFilters[ key ];
8517
+ }
8518
+ this.refresh();
8519
+ }
8520
+ }
8521
+ return item;
8522
+ } );
8523
+ new DropdownMenu( customFilterBtn.root, menuOptions, { side: "bottom", align: "start" });
8524
+ }, { buttonClass: " primary dashed" } );
8525
+ headerContainer.appendChild( customFilterBtn.root );
8526
+ }
8527
+
8528
+ // const resetIcon = LX.makeIcon( "xmark", null, "sm" );
8529
+ this._resetCustomFiltersBtn = new Button(null, "resetButton", ( v ) => {
8530
+ this.activeCustomFilters = {};
8531
+ this.refresh();
8532
+ this._resetCustomFiltersBtn.root.classList.add( "hidden" );
8533
+ }, { title: "Reset filters", icon: "fa fa-xmark" } );
8534
+ headerContainer.appendChild( this._resetCustomFiltersBtn.root );
8535
+ this._resetCustomFiltersBtn.root.classList.add( "hidden" );
8536
+ }
8537
+
8538
+ if( this.toggleColumns )
8539
+ {
8540
+ const icon = LX.makeIcon( "sliders" );
8541
+ const toggleColumnsBtn = new Button( "toggleColumnsBtn", icon.innerHTML + "View", (value, e) => {
8542
+ const menuOptions = data.head.map( ( colName, idx ) => {
8543
+ const item = {
8544
+ name: colName,
8545
+ icon: "check",
8546
+ callback: () => {
8547
+ data.colVisibilityMap[ idx ] = !data.colVisibilityMap[ idx ];
8548
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8549
+ cells.forEach(cell => {
8550
+ cell.style.display = (cell.style.display === "none") ? "" : "none";
8551
+ });
8552
+ }
8553
+ }
8554
+ if( !data.colVisibilityMap[ idx ] ) delete item.icon;
8555
+ return item;
8556
+ } );
8557
+ new DropdownMenu( e.target, menuOptions, { side: "bottom", align: "end" });
8558
+ }, { hideName: true } );
8559
+ headerContainer.appendChild( toggleColumnsBtn.root );
8560
+ toggleColumnsBtn.root.style.marginLeft = "auto";
8561
+ }
8562
+
8563
+ container.appendChild( headerContainer );
8430
8564
  }
8431
8565
 
8432
- this.refreshTable = () => {
8566
+ const table = document.createElement( 'table' );
8567
+ container.appendChild( table );
8568
+
8569
+ this.refresh = () => {
8570
+
8571
+ this._currentFilter = this._currentFilter ?? "";
8433
8572
 
8434
8573
  table.innerHTML = "";
8435
8574
 
8436
- let rowOffsetCount = 0;
8575
+ this.rowOffsetCount = 0;
8437
8576
 
8438
8577
  // Head
8439
8578
  {
@@ -8448,7 +8587,7 @@ class Table extends Widget {
8448
8587
  const th = document.createElement( 'th' );
8449
8588
  th.style.width = "0px";
8450
8589
  hrow.appendChild( th );
8451
- rowOffsetCount++;
8590
+ this.rowOffsetCount++;
8452
8591
  }
8453
8592
 
8454
8593
  if( options.selectable )
@@ -8457,7 +8596,7 @@ class Table extends Widget {
8457
8596
  th.style.width = "0px";
8458
8597
  const input = document.createElement( 'input' );
8459
8598
  input.type = "checkbox";
8460
- input.className = "lexcheckbox";
8599
+ input.className = "lexcheckbox accent";
8461
8600
  input.checked = data.checkMap[ ":root" ] ?? false;
8462
8601
  th.appendChild( input );
8463
8602
 
@@ -8473,14 +8612,15 @@ class Table extends Widget {
8473
8612
  }
8474
8613
  });
8475
8614
 
8476
- rowOffsetCount++;
8615
+ this.rowOffsetCount++;
8477
8616
  hrow.appendChild( th );
8478
8617
  }
8479
8618
 
8480
8619
  for( const headData of data.head )
8481
8620
  {
8482
8621
  const th = document.createElement( 'th' );
8483
- th.innerHTML = `${ headData } <a class="fa-solid fa-sort"></a>`;
8622
+ th.innerHTML = `<span>${ headData }</span>`;
8623
+ th.querySelector( "span" ).appendChild( LX.makeIcon( "menu-arrows", null, "sm" ) );
8484
8624
 
8485
8625
  const idx = data.head.indexOf( headData );
8486
8626
  if( this.centered && this.centered.indexOf( idx ) > -1 )
@@ -8488,19 +8628,29 @@ class Table extends Widget {
8488
8628
  th.classList.add( "centered" );
8489
8629
  }
8490
8630
 
8491
- th.addEventListener( 'click', event => {
8492
- new LX.DropdownMenu( event.target, [
8493
- { name: "Asc", icon: "up", callback: sortFn.bind( this, idx, 1 ) },
8494
- { name: "Desc", icon: "down", callback: sortFn.bind( this, idx, -1 ) },
8631
+ const menuOptions = [
8632
+ { name: "Asc", icon: "up", callback: sortFn.bind( this, idx, 1 ) },
8633
+ { name: "Desc", icon: "down", callback: sortFn.bind( this, idx, -1 ) }
8634
+ ];
8635
+
8636
+ if( this.toggleColumns )
8637
+ {
8638
+ menuOptions.push(
8495
8639
  null,
8496
- { name: "Hide", icon: "eye-slash", callback: () => {
8497
- data.colVisibilityMap[ idx ] = 0;
8498
- const cells = table.querySelectorAll(`tr > *:nth-child(${idx + rowOffsetCount + 1})`);
8499
- cells.forEach(cell => {
8500
- cell.style.display = (cell.style.display === "none") ? "" : "none";
8501
- });
8502
- } }
8503
- ], { side: "bottom", align: "start" });
8640
+ {
8641
+ name: "Hide", icon: "eye-slash", callback: () => {
8642
+ data.colVisibilityMap[ idx ] = false;
8643
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8644
+ cells.forEach(cell => {
8645
+ cell.style.display = (cell.style.display === "none") ? "" : "none";
8646
+ });
8647
+ }
8648
+ }
8649
+ );
8650
+ }
8651
+
8652
+ th.addEventListener( 'click', event => {
8653
+ new DropdownMenu( event.target, menuOptions, { side: "bottom", align: "start" });
8504
8654
  });
8505
8655
 
8506
8656
  hrow.appendChild( th );
@@ -8538,15 +8688,23 @@ class Table extends Widget {
8538
8688
  v.style.transition = `none`;
8539
8689
  } );
8540
8690
  flushCss( fromRow );
8541
- rIdx = null;
8542
8691
 
8543
8692
  if( movePending )
8544
8693
  {
8694
+ // Modify inner data first
8695
+ const fromIdx = rIdx - 1;
8696
+ const targetIdx = movePending[ 1 ] - 1;
8697
+ var b = data.body[fromIdx];
8698
+ data.body[fromIdx] = data.body[targetIdx];
8699
+ data.body[targetIdx] = b;
8700
+
8545
8701
  const parent = movePending[ 0 ].parentNode;
8546
8702
  parent.insertChildAtIndex( movePending[ 0 ], movePending[ 1 ] );
8547
8703
  movePending = null;
8548
8704
  }
8549
8705
 
8706
+ rIdx = null;
8707
+
8550
8708
  doAsync( () => {
8551
8709
  Array.from( table.rows ).forEach( v => {
8552
8710
  v.style.transition = `transform 0.2s ease-in`;
@@ -8562,13 +8720,50 @@ class Table extends Widget {
8562
8720
  fromRow.style.transform = `translateY(${fromRow.dY}px)`;
8563
8721
  };
8564
8722
 
8565
-
8566
8723
  for( let r = 0; r < data.body.length; ++r )
8567
8724
  {
8568
8725
  const bodyData = data.body[ r ];
8726
+
8727
+ if( this.filter )
8728
+ {
8729
+ const filterColIndex = data.head.indexOf( this.filter );
8730
+ if( filterColIndex > -1 )
8731
+ {
8732
+ if( !bodyData[ filterColIndex ].toLowerCase().includes( this._currentFilter.toLowerCase() ) )
8733
+ {
8734
+ continue;
8735
+ }
8736
+ }
8737
+ }
8738
+
8739
+ if( Object.keys( this.activeCustomFilters ).length )
8740
+ {
8741
+ let acfMap = {};
8742
+
8743
+ this._resetCustomFiltersBtn.root.classList.remove( "hidden" );
8744
+
8745
+ for( let acfValue in this.activeCustomFilters )
8746
+ {
8747
+ const acfName = this.activeCustomFilters[ acfValue ];
8748
+ acfMap[ acfName ] = acfMap[ acfName ] ?? false;
8749
+
8750
+ const filterColIndex = data.head.indexOf( acfName );
8751
+ if( filterColIndex > -1 )
8752
+ {
8753
+ acfMap[ acfName ] |= ( bodyData[ filterColIndex ] === acfValue );
8754
+ }
8755
+ }
8756
+
8757
+ const show = Object.values( acfMap ).reduce( ( e, acc ) => acc *= e );
8758
+ if( !show )
8759
+ {
8760
+ continue;
8761
+ }
8762
+ }
8763
+
8569
8764
  const row = document.createElement( 'tr' );
8570
8765
  const rowId = LX.getSupportedDOMName( bodyData.join( '-' ) );
8571
- row.setAttribute( "rowId", rowId.substr(0, 16) );
8766
+ row.setAttribute( "rowId", rowId.substr(0, 32) );
8572
8767
 
8573
8768
  if( options.sortable )
8574
8769
  {
@@ -8619,7 +8814,7 @@ class Table extends Widget {
8619
8814
  const td = document.createElement( 'td' );
8620
8815
  const input = document.createElement( 'input' );
8621
8816
  input.type = "checkbox";
8622
- input.className = "lexcheckbox";
8817
+ input.className = "lexcheckbox accent";
8623
8818
  input.checked = data.checkMap[ rowId ];
8624
8819
  td.appendChild( input );
8625
8820
 
@@ -8676,14 +8871,15 @@ class Table extends Widget {
8676
8871
  {
8677
8872
  button = LX.makeIcon( "more-horizontal", "Menu" );
8678
8873
  button.addEventListener( 'click', function( event ) {
8679
- addContextMenu( null, event, c => {
8680
- if( options.onMenuAction )
8681
- {
8682
- options.onMenuAction( c );
8683
- return;
8684
- }
8685
- console.warn( "Using <Menu action> without action callbacks." );
8686
- } );
8874
+ if( !options.onMenuAction )
8875
+ {
8876
+ return;
8877
+ }
8878
+
8879
+ const menuOptions = options.onMenuAction( r, data );
8880
+ console.assert( menuOptions.length, "Add items to the Menu Action Dropdown!" );
8881
+
8882
+ new DropdownMenu( event.target, menuOptions, { side: "bottom", align: "end" });
8687
8883
  });
8688
8884
  }
8689
8885
  else // custom actions
@@ -8697,7 +8893,7 @@ class Table extends Widget {
8697
8893
  const mustRefresh = action.callback( bodyData, table, e );
8698
8894
  if( mustRefresh )
8699
8895
  {
8700
- this.refreshTable();
8896
+ this.refresh();
8701
8897
  }
8702
8898
  });
8703
8899
  }
@@ -8719,7 +8915,7 @@ class Table extends Widget {
8719
8915
  const idx = parseInt( v );
8720
8916
  if( !data.colVisibilityMap[ idx ] )
8721
8917
  {
8722
- const cells = table.querySelectorAll(`tr > *:nth-child(${idx + rowOffsetCount + 1})`);
8918
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8723
8919
  cells.forEach(cell => {
8724
8920
  cell.style.display = (cell.style.display === "none") ? "" : "none";
8725
8921
  });
@@ -8727,9 +8923,9 @@ class Table extends Widget {
8727
8923
  }
8728
8924
  }
8729
8925
 
8730
- this.refreshTable();
8926
+ this.refresh();
8731
8927
 
8732
- this.root.appendChild( container );
8928
+ doAsync( this.onResize.bind( this ) );
8733
8929
  }
8734
8930
  }
8735
8931
 
@@ -8765,7 +8961,7 @@ class Panel {
8765
8961
  root.className += " " + options.className;
8766
8962
  }
8767
8963
 
8768
- root.style.width = options.width || "calc( 100% - 6px )";
8964
+ root.style.width = options.width || "100%";
8769
8965
  root.style.height = options.height || "100%";
8770
8966
  Object.assign( root.style, options.style ?? {} );
8771
8967
 
@@ -8880,10 +9076,11 @@ class Panel {
8880
9076
 
8881
9077
  /**
8882
9078
  * @method endLine
9079
+ * @param {String} className Extra class to customize inline widgets parent container
8883
9080
  * @description Stop inlining widgets. Use it only if the number of widgets to be inlined is NOT specified.
8884
9081
  */
8885
9082
 
8886
- endLine( justifyContent ) {
9083
+ endLine( className ) {
8887
9084
 
8888
9085
  if( this._inlineWidgetsLeft == -1 )
8889
9086
  {
@@ -8898,9 +9095,9 @@ class Panel {
8898
9095
  this._inlineContainer = document.createElement('div');
8899
9096
  this._inlineContainer.className = "lexinlinewidgets";
8900
9097
 
8901
- if( justifyContent )
9098
+ if( className )
8902
9099
  {
8903
- this._inlineContainer.style.justifyContent = justifyContent;
9100
+ this._inlineContainer.className += ` ${ className }`;
8904
9101
  }
8905
9102
  }
8906
9103
 
@@ -9043,7 +9240,7 @@ class Panel {
9043
9240
  }
9044
9241
  else
9045
9242
  {
9046
- el.classList.add("nobranch");
9243
+ el.className += " nobranch w-full";
9047
9244
  this.root.appendChild( el );
9048
9245
  }
9049
9246
  }
@@ -9102,12 +9299,12 @@ class Panel {
9102
9299
 
9103
9300
  let widget = new TextInput( null, null, null, options )
9104
9301
  const element = widget.root;
9105
- element.className += " lexfilter noname";
9302
+ element.className += " lexfilter";
9106
9303
 
9107
9304
  let input = document.createElement('input');
9108
9305
  input.className = 'lexinput-filter';
9109
9306
  input.setAttribute( "placeholder", options.placeholder );
9110
- input.style.width = "calc( 100% - 17px )";
9307
+ input.style.width = "100%";
9111
9308
  input.value = options.filterValue || "";
9112
9309
 
9113
9310
  let searchIcon = document.createElement('a');
@@ -9115,7 +9312,7 @@ class Panel {
9115
9312
  element.appendChild( searchIcon );
9116
9313
  element.appendChild( input );
9117
9314
 
9118
- input.addEventListener("input", (e) => {
9315
+ input.addEventListener("input", e => {
9119
9316
  if( options.callback )
9120
9317
  {
9121
9318
  options.callback( input.value, e );
@@ -9285,6 +9482,7 @@ class Panel {
9285
9482
  * pattern: Regular expression that value must match
9286
9483
  * trigger: Choose onchange trigger (default, input) [default]
9287
9484
  * inputWidth: Width of the text input
9485
+ * inputClass: Class to add to the native input element
9288
9486
  * skipReset: Don't add the reset value button when value changes
9289
9487
  * float: Justify input text content
9290
9488
  * justifyName: Justify name content
@@ -9324,6 +9522,7 @@ class Panel {
9324
9522
 
9325
9523
  addLabel( value, options = {} ) {
9326
9524
  options.disabled = true;
9525
+ options.inputClass = ( options.inputClass ?? "" ) + " nobg";
9327
9526
  const widget = this.addText( null, value, null, options );
9328
9527
  widget.type = Widget.LABEL;
9329
9528
  return widget;
@@ -9340,6 +9539,7 @@ class Panel {
9340
9539
  * icon: Icon class to show as button value
9341
9540
  * img: Path to image to show as button value
9342
9541
  * title: Text to show in native Element title
9542
+ * buttonClass: Class to add to the native button element
9343
9543
  */
9344
9544
 
9345
9545
  addButton( name, value, callback, options = {} ) {
@@ -9879,7 +10079,6 @@ class Branch {
9879
10079
  root.className += " " + options.className;
9880
10080
  }
9881
10081
 
9882
- root.style.width = "calc(100% - 7px)";
9883
10082
  root.style.margin = "0 auto";
9884
10083
 
9885
10084
  var that = this;
@@ -9917,7 +10116,7 @@ class Branch {
9917
10116
  this.grabber.setAttribute( "hidden", true );
9918
10117
  doAsync( () => {
9919
10118
  this.content.setAttribute( "hidden", true );
9920
- }, 15 );
10119
+ }, 10 );
9921
10120
  }
9922
10121
 
9923
10122
  this.onclick = function( e ) {
@@ -10053,7 +10252,7 @@ class Branch {
10053
10252
  var size = this.grabber.style.marginLeft;
10054
10253
 
10055
10254
  // Update sizes of widgets inside
10056
- for( var i = 0; i < this.widgets.length; i++ )
10255
+ for( let i = 0; i < this.widgets.length; i++ )
10057
10256
  {
10058
10257
  let widget = this.widgets[ i ];
10059
10258
  const element = widget.root;
@@ -10063,26 +10262,22 @@ class Branch {
10063
10262
  continue;
10064
10263
  }
10065
10264
 
10066
- var name = element.children[ 0 ];
10067
- var value = element.children[ 1 ];
10265
+ let name = element.children[ 0 ];
10266
+ let value = element.children[ 1 ];
10068
10267
 
10069
10268
  name.style.width = size;
10070
- let padding = "0px";
10269
+ name.style.minWidth = size;
10270
+
10071
10271
  switch( widget.type )
10072
10272
  {
10073
- case Widget.FILE:
10074
- padding = "10%";
10075
- break;
10273
+ case Widget.CUSTOM:
10274
+ case Widget.ARRAY:
10275
+ continue;
10076
10276
  };
10077
10277
 
10078
- value.style.width = "-moz-calc( 100% - " + size + " - " + padding + " )";
10079
- value.style.width = "-webkit-calc( 100% - " + size + " - " + padding + " )";
10080
- value.style.width = "calc( 100% - " + size + " - " + padding + " )";
10081
-
10082
- if( widget.onresize )
10083
- {
10084
- widget.onresize();
10085
- }
10278
+ value.style.width = "-moz-calc( 100% - " + size + " )";
10279
+ value.style.width = "-webkit-calc( 100% - " + size + " )";
10280
+ value.style.width = "calc( 100% - " + size + " )";
10086
10281
  }
10087
10282
  }
10088
10283
  };
@@ -10106,7 +10301,8 @@ class Footer {
10106
10301
  root.className = "lexfooter";
10107
10302
 
10108
10303
  const wrapper = document.createElement( "div" );
10109
- wrapper.className = "wrapper";
10304
+ wrapper.style.minHeight = "48px";
10305
+ wrapper.className = "w-full";
10110
10306
  root.appendChild( wrapper );
10111
10307
 
10112
10308
  if( options.columns && options.columns.constructor == Array )
@@ -10181,6 +10377,10 @@ class Footer {
10181
10377
  // Append directly to body
10182
10378
  const parent = options.parent ?? document.body;
10183
10379
  parent.appendChild( root );
10380
+
10381
+ // Set always at bottom
10382
+ root.previousElementSibling.style.height = "unset";
10383
+ root.previousElementSibling.style.flexGrow = "1";
10184
10384
  }
10185
10385
 
10186
10386
  }
@@ -10210,7 +10410,7 @@ class Dialog {
10210
10410
  draggable = options.draggable ?? true,
10211
10411
  modal = options.modal ?? false;
10212
10412
 
10213
- var root = document.createElement('dialog');
10413
+ let root = document.createElement('dialog');
10214
10414
  root.className = "lexdialog " + (options.className ?? "");
10215
10415
  root.id = options.id ?? "dialog" + Dialog._last_id++;
10216
10416
  LX.root.appendChild( root );
@@ -10221,7 +10421,7 @@ class Dialog {
10221
10421
 
10222
10422
  let that = this;
10223
10423
 
10224
- var titleDiv = document.createElement('div');
10424
+ const titleDiv = document.createElement('div');
10225
10425
 
10226
10426
  if( title )
10227
10427
  {
@@ -10286,7 +10486,7 @@ class Dialog {
10286
10486
  }, { icon: "fa-regular fa-window-restore" });
10287
10487
  };
10288
10488
 
10289
- root.appendChild(titleDiv);
10489
+ root.appendChild( titleDiv );
10290
10490
  }
10291
10491
 
10292
10492
  if( options.closable ?? true )
@@ -10379,7 +10579,6 @@ class Dialog {
10379
10579
  root.style.left = position[ 0 ] ?? "50%";
10380
10580
  root.style.top = position[ 1 ] ?? "50%";
10381
10581
 
10382
- panel.root.style.width = "calc( 100% - 30px )";
10383
10582
  panel.root.style.height = title ? "calc( 100% - " + ( titleDiv.offsetHeight + 30 ) + "px )" : "calc( 100% - 51px )";
10384
10583
  }
10385
10584
 
@@ -10451,8 +10650,8 @@ class PocketDialog extends Dialog {
10451
10650
  this.root.style.top = dragMargin + "px";
10452
10651
  }
10453
10652
 
10454
- this.panel.root.style.width = "calc( 100% - 12px )";
10455
- this.panel.root.style.height = "calc( 100% - 40px )";
10653
+ this.panel.root.style.width = "100%";
10654
+ this.panel.root.style.height = "100%";
10456
10655
  this.dock_pos = PocketDialog.TOP;
10457
10656
 
10458
10657
  this.minimized = false;
@@ -10485,7 +10684,7 @@ class PocketDialog extends Dialog {
10485
10684
 
10486
10685
  if( float )
10487
10686
  {
10488
- for( var i = 0; i < float.length; i++ )
10687
+ for( let i = 0; i < float.length; i++ )
10489
10688
  {
10490
10689
  const t = float[i];
10491
10690
  switch( t )
@@ -10618,14 +10817,14 @@ class ContextMenu {
10618
10817
  contextmenu.className = "lexcontextmenu";
10619
10818
  c.appendChild( contextmenu );
10620
10819
 
10621
- for( var i = 0; i < o[k].length; ++i )
10820
+ for( let i = 0; i < o[k].length; ++i )
10622
10821
  {
10623
10822
  const subitem = o[ k ][ i ];
10624
10823
  const subkey = Object.keys( subitem )[ 0 ];
10625
10824
  this._createEntry(subitem, subkey, contextmenu, d);
10626
10825
  }
10627
10826
 
10628
- var rect = c.getBoundingClientRect();
10827
+ const rect = c.getBoundingClientRect();
10629
10828
  contextmenu.style.left = rect.width + "px";
10630
10829
  contextmenu.style.marginTop = 3.5 - c.offsetHeight + "px";
10631
10830
 
@@ -10778,10 +10977,10 @@ class ContextMenu {
10778
10977
  _item[ key ].unshift( parent );
10779
10978
  }
10780
10979
 
10781
- for( var child of _item[ key ] )
10980
+ for( let child of _item[ key ] )
10782
10981
  {
10783
10982
  let k = Object.keys( child )[ 0 ];
10784
- for( var i = 0; i < child[ k ].length; ++i )
10983
+ for( let i = 0; i < child[ k ].length; ++i )
10785
10984
  {
10786
10985
  setParent( child );
10787
10986
  }
@@ -10822,7 +11021,7 @@ LX.ContextMenu = ContextMenu;
10822
11021
 
10823
11022
  function addContextMenu( title, event, callback, options )
10824
11023
  {
10825
- var menu = new ContextMenu( event, title, options );
11024
+ const menu = new ContextMenu( event, title, options );
10826
11025
  LX.root.appendChild( menu.root );
10827
11026
 
10828
11027
  if( callback )
@@ -10853,7 +11052,8 @@ class CanvasCurve {
10853
11052
  element.style.minHeight = "20px";
10854
11053
 
10855
11054
  element.bgcolor = options.bgColor || LX.getThemeColor( "global-intense-background" );
10856
- element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected-light" );
11055
+ element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected" );
11056
+ element.activepointscolor = options.activePointsColor || LX.getThemeColor( "global-selected-light" );
10857
11057
  element.linecolor = options.lineColor || "#555";
10858
11058
  element.value = value || [];
10859
11059
  element.xrange = options.xrange || [ 0, 1 ]; // min, max
@@ -10869,7 +11069,8 @@ class CanvasCurve {
10869
11069
 
10870
11070
  LX.addSignal( "@on_new_color_scheme", (el, value) => {
10871
11071
  element.bgcolor = options.bgColor || LX.getThemeColor( "global-intense-background" );
10872
- element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected-light" );
11072
+ element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected" );
11073
+ element.activepointscolor = options.activePointsColor || LX.getThemeColor( "global-selected-light" );
10873
11074
  this.redraw();
10874
11075
  } );
10875
11076
 
@@ -10890,11 +11091,11 @@ class CanvasCurve {
10890
11091
  return element.defaulty;
10891
11092
  }
10892
11093
 
10893
- var last = [ element.xrange[ 0 ], element.defaulty ];
10894
- var f = 0;
10895
- for( var i = 0; i < element.value.length; i += 1 )
11094
+ let last = [ element.xrange[ 0 ], element.defaulty ];
11095
+ let f = 0;
11096
+ for( let i = 0; i < element.value.length; i += 1 )
10896
11097
  {
10897
- var v = element.value[ i ];
11098
+ let v = element.value[ i ];
10898
11099
  if( x == v[ 0 ] ) return v[ 1 ];
10899
11100
  if( x < v[ 0 ] )
10900
11101
  {
@@ -10912,9 +11113,9 @@ class CanvasCurve {
10912
11113
 
10913
11114
  element.resample = function( samples ) {
10914
11115
 
10915
- var r = [];
10916
- var dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
10917
- for( var i = element.xrange[0]; i <= element.xrange[1]; i += dx )
11116
+ let r = [];
11117
+ let dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
11118
+ for( let i = element.xrange[0]; i <= element.xrange[1]; i += dx )
10918
11119
  {
10919
11120
  r.push( element.getValueAt(i) );
10920
11121
  }
@@ -10923,9 +11124,9 @@ class CanvasCurve {
10923
11124
 
10924
11125
  element.addValue = function(v) {
10925
11126
 
10926
- for( var i = 0; i < element.value; i++ )
11127
+ for( let i = 0; i < element.value; i++ )
10927
11128
  {
10928
- var value = element.value[i];
11129
+ let value = element.value[i];
10929
11130
  if(value[0] < v[0]) continue;
10930
11131
  element.value.splice(i,0,v);
10931
11132
  redraw();
@@ -10948,7 +11149,7 @@ class CanvasCurve {
10948
11149
  (v[1] * element.yrange[1] / canvas.height + element.yrange[0])];
10949
11150
  }
10950
11151
 
10951
- var selected = -1;
11152
+ let selected = -1;
10952
11153
 
10953
11154
  element.redraw = function( o = {} ) {
10954
11155
 
@@ -11010,7 +11211,7 @@ class CanvasCurve {
11010
11211
  var value = element.value[ i ];
11011
11212
  pos = convert( value );
11012
11213
  if( selected == i )
11013
- ctx.fillStyle = "white";
11214
+ ctx.fillStyle = element.activepointscolor;
11014
11215
  else
11015
11216
  ctx.fillStyle = element.pointscolor;
11016
11217
  ctx.beginPath();
@@ -11856,11 +12057,15 @@ class AssetView {
11856
12057
  this.rightPanel.sameLine();
11857
12058
  this.rightPanel.addSelect( "Filter", this.allowedTypes, this.allowedTypes[ 0 ], v => this._refreshContent.call(this, null, v), { width: "30%", minWidth: "128px" } );
11858
12059
  this.rightPanel.addText( null, this.searchValue ?? "", v => this._refreshContent.call(this, v, null), { placeholder: "Search assets.." } );
11859
- this.rightPanel.addButton( null, "<a class='fa fa-arrow-up-short-wide'></a>", on_sort.bind(this), { className: "micro", title: "Sort" } );
11860
- this.rightPanel.addButton( null, "<a class='fa-solid fa-grip'></a>", on_change_view.bind(this), { className: "micro", title: "View" } );
12060
+ this.rightPanel.addButton( null, "<a class='fa fa-arrow-up-short-wide'></a>", on_sort.bind(this), { title: "Sort" } );
12061
+ this.rightPanel.addButton( null, "<a class='fa-solid fa-grip'></a>", on_change_view.bind(this), { title: "View" } );
11861
12062
  // Content Pages
11862
- this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-left'></a>", on_change_page.bind(this, -1), { className: "micro", title: "Previous Page" } );
11863
- this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-right'></a>", on_change_page.bind(this, 1), { className: "micro", title: "Next Page" } );
12063
+ this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-left'></a>", on_change_page.bind(this, -1), { title: "Previous Page", className: "ml-auto" } );
12064
+ this.rightPanel.addButton( null, "<a class='fa-solid fa-angles-right'></a>", on_change_page.bind(this, 1), { title: "Next Page" } );
12065
+ const textString = "Page " + this.contentPage + " / " + ((((this.currentData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1);
12066
+ this.rightPanel.addText(null, textString, null, {
12067
+ inputClass: "nobg", disabled: true, signal: "@on_page_change", maxWidth: "16ch" }
12068
+ );
11864
12069
  this.rightPanel.endLine();
11865
12070
 
11866
12071
  if( !this.skipBrowser )
@@ -11894,9 +12099,13 @@ class AssetView {
11894
12099
  icon: "fa-solid fa-arrows-rotate",
11895
12100
  callback: domEl => { this._refreshContent(); }
11896
12101
  }
11897
- ], { width: "20%", minWidth: "164px", noSelection: true } );
11898
- 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" } });
11899
- this.rightPanel.addText(null, "Page " + this.contentPage + " / " + ((((this.currentData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1), null, {disabled: true, signal: "@on_page_change", width: "fit-content"})
12102
+ ], { noSelection: true } );
12103
+
12104
+ this.rightPanel.addText(null, this.path.join('/'), null, {
12105
+ inputClass: "nobg", disabled: true, signal: "@on_folder_change",
12106
+ style: { fontWeight: "600", fontSize: "15px" }
12107
+ });
12108
+
11900
12109
  this.rightPanel.endLine();
11901
12110
  }
11902
12111
 
@@ -12174,7 +12383,9 @@ class AssetView {
12174
12383
  }
12175
12384
 
12176
12385
  this.allowNextPage = filteredData.length - 1 > AssetView.MAX_PAGE_ELEMENTS;
12177
- LX.emit("@on_page_change", "Page " + this.contentPage + " / " + ((((filteredData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1));
12386
+
12387
+ const textString = "Page " + this.contentPage + " / " + ((((filteredData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1);
12388
+ LX.emit( "@on_page_change", textString );
12178
12389
 
12179
12390
  if( this.onRefreshContent )
12180
12391
  {
@@ -12198,7 +12409,7 @@ class AssetView {
12198
12409
  const hasImage = ['png', 'jpg'].indexOf( getExtension( file.src ) ) > -1 || is_base_64;
12199
12410
  if( hasImage )
12200
12411
  {
12201
- this.previewPanel.addImage( file.src, { style: { width: "100%" } } );
12412
+ this.previewPanel.addImage( null, file.src, { style: { width: "100%" } } );
12202
12413
  }
12203
12414
  }
12204
12415
 
@@ -12753,6 +12964,9 @@ LX.ICONS = {
12753
12964
  "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"],
12754
12965
  "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"],
12755
12966
  "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"],
12967
+ "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"],
12968
+ "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"],
12969
+ "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"],
12756
12970
  "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"],
12757
12971
  "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"],
12758
12972
  "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"],
@@ -12781,6 +12995,7 @@ LX.ICONS = {
12781
12995
  "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"],
12782
12996
  "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"],
12783
12997
  "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"],
12998
+ "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"],
12784
12999
  "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"],
12785
13000
  "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"],
12786
13001
  "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"],