lexgui 0.5.1 → 0.5.2

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.2",
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
+ });
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
 
@@ -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
 
@@ -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 )
@@ -2657,7 +2678,7 @@ class Area {
2657
2678
 
2658
2679
  for( var i = 0; i < this.sections.length; i++ )
2659
2680
  {
2660
- this.sections[i]._update();
2681
+ this.sections[ i ]._update();
2661
2682
  }
2662
2683
  }
2663
2684
  };
@@ -4381,6 +4402,8 @@ class Widget {
4381
4402
  {
4382
4403
  root.style.height = root.style.minHeight = options.height;
4383
4404
  }
4405
+
4406
+ LX.widgetResizeObserver.observe( root );
4384
4407
  }
4385
4408
 
4386
4409
  if( name != undefined )
@@ -4581,15 +4604,17 @@ LX.Widget = Widget;
4581
4604
 
4582
4605
  function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4583
4606
  {
4584
- let custom_idx = simple_guidGenerator();
4607
+ let customIdx = simple_guidGenerator();
4585
4608
 
4586
4609
  Panel.prototype[ 'add' + customWidgetName ] = function( name, instance, callback ) {
4587
4610
 
4611
+ options.nameWidth = "100%";
4612
+
4588
4613
  let widget = new Widget( Widget.CUSTOM, name, null, options );
4589
4614
  this._attachWidget( widget );
4590
4615
 
4591
4616
  widget.customName = customWidgetName;
4592
- widget.customIdx = custom_idx;
4617
+ widget.customIdx = customIdx;
4593
4618
 
4594
4619
  widget.onGetValue = () => {
4595
4620
  return instance;
@@ -4606,7 +4631,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4606
4631
  };
4607
4632
 
4608
4633
  const element = widget.root;
4609
- element.style.flexWrap = "wrap";
4610
4634
 
4611
4635
  let container, customWidgetsDom;
4612
4636
  let default_instance = options.default ?? {};
@@ -4625,14 +4649,12 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4625
4649
 
4626
4650
  container = document.createElement('div');
4627
4651
  container.className = "lexcustomcontainer";
4628
- doAsync( () => {
4629
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
4630
- container.style.width = `calc( 100% - ${ realNameWidth })`;
4631
- } );
4652
+ container.style.width = "100%";
4653
+ element.appendChild( container );
4632
4654
 
4633
4655
  let buttonName = "<a class='fa-solid " + (options.icon ?? "fa-cube") + "' style='float:left'></a>";
4634
4656
  buttonName += customWidgetName + (!instance ? " [empty]" : "");
4635
- // Add alwayis icon to keep spacing right
4657
+ // Add always icon to keep spacing right
4636
4658
  buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu' style='float:right; width:5%;'></a>";
4637
4659
 
4638
4660
  let buttonEl = this.addButton(null, buttonName, (value, event) => {
@@ -4652,7 +4674,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4652
4674
  }
4653
4675
 
4654
4676
  }, { buttonClass: 'custom' });
4655
-
4656
4677
  container.appendChild( buttonEl.root );
4657
4678
 
4658
4679
  if( instance )
@@ -4674,8 +4695,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4674
4695
  customWidgetsDom = document.createElement('div');
4675
4696
  customWidgetsDom.className = "lexcustomitems";
4676
4697
  customWidgetsDom.toggleAttribute('hidden', true);
4677
-
4678
- element.appendChild( container );
4679
4698
  element.appendChild( customWidgetsDom );
4680
4699
 
4681
4700
  if( instance )
@@ -5193,6 +5212,7 @@ class NodeTree {
5193
5212
  }
5194
5213
 
5195
5214
  const _hasChild = function( parent, id ) {
5215
+ if( !parent.length ) return;
5196
5216
  for( var c of parent.children )
5197
5217
  {
5198
5218
  if( c.id == id ) return true;
@@ -5357,6 +5377,11 @@ class TextInput extends Widget {
5357
5377
  }
5358
5378
  };
5359
5379
 
5380
+ this.onResize = ( rect ) => {
5381
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5382
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5383
+ };
5384
+
5360
5385
  this.valid = ( v ) => {
5361
5386
  v = v ?? this.value();
5362
5387
  if( !v.length || wValue.pattern == "" ) return true;
@@ -5367,10 +5392,7 @@ class TextInput extends Widget {
5367
5392
  let container = document.createElement( 'div' );
5368
5393
  container.className = "lextext" + ( options.warning ? " lexwarning" : "" );
5369
5394
  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
- } );
5395
+ this.root.appendChild( container );
5374
5396
 
5375
5397
  if( options.textClass )
5376
5398
  {
@@ -5449,13 +5471,13 @@ class TextInput extends Widget {
5449
5471
  wValue.innerHTML = ( icon + value ) || "";
5450
5472
  wValue.style.width = "100%";
5451
5473
  wValue.style.textAlign = options.float ?? "";
5474
+ wValue.className = "ellipsis-overflow";
5452
5475
  }
5453
5476
 
5454
5477
  Object.assign( wValue.style, options.style ?? {} );
5455
-
5456
5478
  container.appendChild( wValue );
5457
5479
 
5458
- this.root.appendChild( container );
5480
+ doAsync( this.onResize.bind( this ) );
5459
5481
  }
5460
5482
  }
5461
5483
 
@@ -5486,26 +5508,22 @@ class TextArea extends Widget {
5486
5508
  }
5487
5509
  };
5488
5510
 
5511
+ this.onResize = ( rect ) => {
5512
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5513
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5514
+ };
5515
+
5489
5516
  let container = document.createElement( "div" );
5490
5517
  container.className = "lextextarea";
5491
5518
  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
- } );
5519
+ this.root.appendChild( container );
5503
5520
 
5504
5521
  let wValue = document.createElement( "textarea" );
5505
5522
  wValue.value = wValue.iValue = value || "";
5506
5523
  wValue.style.width = "100%";
5507
5524
  wValue.style.textAlign = options.float ?? "";
5508
5525
  Object.assign( wValue.style, options.style ?? {} );
5526
+ container.appendChild( wValue );
5509
5527
 
5510
5528
  if( options.disabled ?? false ) wValue.setAttribute( "disabled", true );
5511
5529
  if( options.placeholder ) wValue.setAttribute( "placeholder", options.placeholder );
@@ -5539,9 +5557,17 @@ class TextArea extends Widget {
5539
5557
  container.appendChild( icon );
5540
5558
  }
5541
5559
 
5542
- container.appendChild( wValue );
5560
+ doAsync( () => {
5561
+ container.style.height = options.height;
5543
5562
 
5544
- this.root.appendChild( container );
5563
+ if( options.fitHeight )
5564
+ {
5565
+ // Update height depending on the content
5566
+ wValue.style.height = wValue.scrollHeight + "px";
5567
+ }
5568
+
5569
+ this.onResize();
5570
+ }, 10 );
5545
5571
  }
5546
5572
  }
5547
5573
 
@@ -5568,9 +5594,15 @@ class Button extends Widget {
5568
5594
  ( options.img ? "<img src='" + options.img + "'>" : "<span>" + ( newValue || "" ) + "</span>" ) );
5569
5595
  };
5570
5596
 
5597
+ this.onResize = ( rect ) => {
5598
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5599
+ wValue.style.width = `calc( 100% - ${ realNameWidth }px)`;
5600
+ };
5601
+
5571
5602
  var wValue = document.createElement( 'button' );
5572
5603
  wValue.title = options.title ?? "";
5573
5604
  wValue.className = "lexbutton " + ( options.buttonClass ?? "" );
5605
+ this.root.appendChild( wValue );
5574
5606
 
5575
5607
  if( options.selected )
5576
5608
  {
@@ -5581,11 +5613,6 @@ class Button extends Widget {
5581
5613
  ( options.icon ? "<a class='" + options.icon + "'></a>" :
5582
5614
  ( options.img ? "<img src='" + options.img + "'>" : "<span>" + ( value || "" ) + "</span>" ) );
5583
5615
 
5584
- doAsync( () => {
5585
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5586
- wValue.style.width = `calc( 100% - ${ realNameWidth })`;
5587
- } );
5588
-
5589
5616
  if( options.disabled )
5590
5617
  {
5591
5618
  wValue.setAttribute( "disabled", true );
@@ -5605,15 +5632,7 @@ class Button extends Widget {
5605
5632
  this._trigger( new IEvent( name, value, e ), callback );
5606
5633
  });
5607
5634
 
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
- }
5635
+ doAsync( this.onResize.bind( this ) );
5617
5636
  }
5618
5637
  }
5619
5638
 
@@ -5641,14 +5660,10 @@ class ComboButtons extends Widget {
5641
5660
  container.className += options.float;
5642
5661
  }
5643
5662
 
5644
- doAsync( () => {
5645
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5646
- container.style.width = `calc( 100% - ${ realNameWidth })`;
5647
- } );
5648
-
5649
5663
  let currentValue = [];
5650
5664
  let buttonsBox = document.createElement('div');
5651
5665
  buttonsBox.className = "lexcombobuttonsbox ";
5666
+ container.appendChild( buttonsBox );
5652
5667
 
5653
5668
  for( let b of values )
5654
5669
  {
@@ -5760,9 +5775,14 @@ class ComboButtons extends Widget {
5760
5775
  }
5761
5776
  };
5762
5777
 
5763
- container.appendChild( buttonsBox );
5778
+ this.onResize = ( rect ) => {
5779
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5780
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
5781
+ };
5764
5782
 
5765
5783
  this.root.appendChild( container );
5784
+
5785
+ doAsync( this.onResize.bind( this ) );
5766
5786
  }
5767
5787
  }
5768
5788
 
@@ -5784,6 +5804,7 @@ class Card extends Widget {
5784
5804
  let container = document.createElement('div');
5785
5805
  container.className = "lexcard";
5786
5806
  container.style.width = "100%";
5807
+ this.root.appendChild( container );
5787
5808
 
5788
5809
  if( options.img )
5789
5810
  {
@@ -5806,6 +5827,7 @@ class Card extends Widget {
5806
5827
 
5807
5828
  let cardNameDom = document.createElement('span');
5808
5829
  cardNameDom.innerText = name;
5830
+ container.appendChild( cardNameDom );
5809
5831
 
5810
5832
  if( options.link != undefined )
5811
5833
  {
@@ -5824,9 +5846,6 @@ class Card extends Widget {
5824
5846
  this._trigger( new IEvent( name, null, e ), options.callback );
5825
5847
  });
5826
5848
  }
5827
-
5828
- container.appendChild( cardNameDom );
5829
- this.root.appendChild( container );
5830
5849
  }
5831
5850
  }
5832
5851
 
@@ -5877,6 +5896,7 @@ class Form extends Widget {
5877
5896
  container.className = "lexformdata";
5878
5897
  container.style.width = "100%";
5879
5898
  container.formData = {};
5899
+ this.root.appendChild( container );
5880
5900
 
5881
5901
  for( let entry in data )
5882
5902
  {
@@ -5921,8 +5941,6 @@ class Form extends Widget {
5921
5941
  }, { buttonClass: "primary", width: "calc(100% - 10px)" } );
5922
5942
 
5923
5943
  container.appendChild( submitButton.root );
5924
-
5925
- this.root.appendChild( container );
5926
5944
  }
5927
5945
  }
5928
5946
 
@@ -5974,12 +5992,14 @@ class Select extends Widget {
5974
5992
  }
5975
5993
  };
5976
5994
 
5995
+ this.onResize = ( rect ) => {
5996
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5997
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5998
+ };
5999
+
5977
6000
  let container = document.createElement( "div" );
5978
6001
  container.className = "lexselect";
5979
- doAsync( () => {
5980
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5981
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5982
- } );
6002
+ this.root.appendChild( container );
5983
6003
 
5984
6004
  let wValue = document.createElement( 'div' );
5985
6005
  wValue.className = "lexselect lexoption";
@@ -6138,7 +6158,7 @@ class Select extends Widget {
6138
6158
  filterOptions.skipWidget = filterOptions.skipWidget ?? true;
6139
6159
  filterOptions.trigger = "input";
6140
6160
  filterOptions.icon = "fa-solid fa-magnifying-glass";
6141
- filterOptions.className = "lexfilter noname";
6161
+ filterOptions.className = "lexfilter";
6142
6162
 
6143
6163
  let filter = new TextInput(null, options.filterValue ?? "", ( v ) => {
6144
6164
  const filteredOptions = this._filterOptions( values, v );
@@ -6256,7 +6276,7 @@ class Select extends Widget {
6256
6276
 
6257
6277
  container.appendChild( listDialog );
6258
6278
 
6259
- this.root.appendChild( container );
6279
+ doAsync( this.onResize.bind( this ) );
6260
6280
  }
6261
6281
 
6262
6282
  _filterOptions( options, value ) {
@@ -6312,12 +6332,17 @@ class Curve extends Widget {
6312
6332
  }
6313
6333
  };
6314
6334
 
6335
+ this.onResize = ( rect ) => {
6336
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6337
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6338
+ flushCss( container );
6339
+ curveInstance.canvas.width = container.offsetWidth;
6340
+ curveInstance.redraw();
6341
+ };
6342
+
6315
6343
  var container = document.createElement( "div" );
6316
6344
  container.className = "lexcurve";
6317
- doAsync( () => {
6318
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6319
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6320
- } );
6345
+ this.root.appendChild( container );
6321
6346
 
6322
6347
  options.callback = (v, e) => {
6323
6348
  this._trigger( new IEvent( name, v, e ), callback );
@@ -6327,16 +6352,9 @@ class Curve extends Widget {
6327
6352
 
6328
6353
  let curveInstance = new CanvasCurve( values, options );
6329
6354
  container.appendChild( curveInstance.element );
6330
- this.root.appendChild( container );
6331
-
6332
- // Resize
6333
- this.onresize = curveInstance.redraw.bind( curveInstance );
6334
6355
  this.curveInstance = curveInstance;
6335
6356
 
6336
- doAsync(() => {
6337
- curveInstance.canvas.width = container.offsetWidth;
6338
- curveInstance.redraw();
6339
- });
6357
+ doAsync( this.onResize.bind( this ) );
6340
6358
  }
6341
6359
  }
6342
6360
 
@@ -6356,24 +6374,32 @@ class Dial extends Widget {
6356
6374
  super( Widget.DIAL, name, defaultValues, options );
6357
6375
 
6358
6376
  this.onGetValue = () => {
6359
- return JSON.parse( JSON.stringify( curveInstance.element.value ) );
6377
+ return JSON.parse( JSON.stringify( dialInstance.element.value ) );
6360
6378
  };
6361
6379
 
6362
6380
  this.onSetValue = ( newValue, skipCallback, event ) => {
6363
- curveInstance.element.value = JSON.parse( JSON.stringify( newValue ) );
6364
- curveInstance.redraw();
6381
+ dialInstance.element.value = JSON.parse( JSON.stringify( newValue ) );
6382
+ dialInstance.redraw();
6365
6383
  if( !skipCallback )
6366
6384
  {
6367
- this._trigger( new IEvent( name, curveInstance.element.value, event ), callback );
6385
+ this._trigger( new IEvent( name, dialInstance.element.value, event ), callback );
6368
6386
  }
6369
6387
  };
6370
6388
 
6389
+ this.onResize = ( rect ) => {
6390
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6391
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6392
+ flushCss( container );
6393
+ dialInstance.element.style.height = dialInstance.element.offsetWidth + "px";
6394
+ dialInstance.canvas.width = dialInstance.element.offsetWidth;
6395
+ container.style.width = dialInstance.element.offsetWidth + "px";
6396
+ dialInstance.canvas.height = dialInstance.canvas.width;
6397
+ dialInstance.redraw();
6398
+ };
6399
+
6371
6400
  var container = document.createElement( "div" );
6372
6401
  container.className = "lexcurve";
6373
- doAsync( () => {
6374
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6375
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6376
- } );
6402
+ this.root.appendChild( container );
6377
6403
 
6378
6404
  options.callback = ( v, e ) => {
6379
6405
  this._trigger( new IEvent( name, v, e ), callback );
@@ -6381,21 +6407,11 @@ class Dial extends Widget {
6381
6407
 
6382
6408
  options.name = name;
6383
6409
 
6384
- let curveInstance = new CanvasDial( this, values, options );
6385
- container.appendChild( curveInstance.element );
6386
- this.root.appendChild( container );
6387
-
6388
- // Resize
6389
- this.onresize = curveInstance.redraw.bind( curveInstance );
6390
- this.curveInstance = curveInstance;
6410
+ let dialInstance = new CanvasDial( this, values, options );
6411
+ container.appendChild( dialInstance.element );
6412
+ this.dialInstance = dialInstance;
6391
6413
 
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
- });
6414
+ doAsync( this.onResize.bind( this ) );
6399
6415
  }
6400
6416
  }
6401
6417
 
@@ -6418,25 +6434,27 @@ class Layers extends Widget {
6418
6434
 
6419
6435
  this.onSetValue = ( newValue, skipCallback, event ) => {
6420
6436
  value = newValue;
6421
- setLayers();
6437
+ this.setLayers( value );
6422
6438
  if( !skipCallback )
6423
6439
  {
6424
6440
  this._trigger( new IEvent(name, value, event), callback );
6425
6441
  }
6426
6442
  };
6427
6443
 
6444
+ this.onResize = ( rect ) => {
6445
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6446
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6447
+ };
6448
+
6428
6449
  var container = document.createElement( "div" );
6429
6450
  container.className = "lexlayers";
6430
- doAsync( () => {
6431
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6432
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6433
- } );
6451
+ this.root.appendChild( container );
6434
6452
 
6435
- const setLayers = () => {
6453
+ this.setLayers = ( val ) => {
6436
6454
 
6437
6455
  container.innerHTML = "";
6438
6456
 
6439
- let binary = value.toString( 2 );
6457
+ let binary = val.toString( 2 );
6440
6458
  let nbits = binary.length;
6441
6459
 
6442
6460
  // fill zeros
@@ -6450,7 +6468,7 @@ class Layers extends Widget {
6450
6468
  let layer = document.createElement( "div" );
6451
6469
  layer.className = "lexlayer";
6452
6470
 
6453
- if( value != undefined )
6471
+ if( val != undefined )
6454
6472
  {
6455
6473
  const valueBit = binary[ 16 - bit - 1 ];
6456
6474
  if( valueBit != undefined && valueBit == '1' )
@@ -6467,15 +6485,15 @@ class Layers extends Widget {
6467
6485
  e.stopPropagation();
6468
6486
  e.stopImmediatePropagation();
6469
6487
  e.target.classList.toggle( "selected" );
6470
- const newValue = value ^ ( 1 << bit );
6488
+ const newValue = val ^ ( 1 << bit );
6471
6489
  this.set( newValue, false, e );
6472
6490
  } );
6473
6491
  }
6474
6492
  };
6475
6493
 
6476
- setLayers();
6494
+ this.setLayers( value );
6477
6495
 
6478
- this.root.appendChild( container );
6496
+ doAsync( this.onResize.bind( this ) );
6479
6497
  }
6480
6498
  }
6481
6499
 
@@ -6490,6 +6508,8 @@ class ItemArray extends Widget {
6490
6508
 
6491
6509
  constructor( name, values = [], callback, options = {} ) {
6492
6510
 
6511
+ options.nameWidth = "100%";
6512
+
6493
6513
  super( Widget.ARRAY, name, null, options );
6494
6514
 
6495
6515
  this.onGetValue = () => {
@@ -6505,18 +6525,14 @@ class ItemArray extends Widget {
6505
6525
  }
6506
6526
  };
6507
6527
 
6508
- this.root.style.flexWrap = "wrap";
6509
-
6510
6528
  // Add open array button
6511
6529
 
6512
6530
  const itemNameWidth = "4%";
6513
6531
 
6514
6532
  var container = document.createElement('div');
6515
6533
  container.className = "lexarray";
6516
- doAsync( () => {
6517
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6518
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6519
- } );
6534
+ container.style.width = "100%";
6535
+ this.root.appendChild( container );
6520
6536
 
6521
6537
  const angleDown = `<a class='fa-solid fa-angle-down' style='float:right; margin-right: 3px;'></a>`;
6522
6538
 
@@ -6526,7 +6542,6 @@ class ItemArray extends Widget {
6526
6542
  const toggleButton = new Button(null, buttonName, () => {
6527
6543
  this.root.querySelector(".lexarrayitems").toggleAttribute('hidden');
6528
6544
  }, { buttonClass: 'array' });
6529
-
6530
6545
  container.appendChild( toggleButton.root );
6531
6546
 
6532
6547
  // Show elements
@@ -6534,8 +6549,6 @@ class ItemArray extends Widget {
6534
6549
  let arrayItems = document.createElement( "div" );
6535
6550
  arrayItems.className = "lexarrayitems";
6536
6551
  arrayItems.toggleAttribute( "hidden", true );
6537
-
6538
- this.root.appendChild( container );
6539
6552
  this.root.appendChild( arrayItems );
6540
6553
 
6541
6554
  this._updateItems = () => {
@@ -6552,10 +6565,6 @@ class ItemArray extends Widget {
6552
6565
  {
6553
6566
  const value = values[ i ];
6554
6567
  let baseclass = options.innerValues ? 'select' : value.constructor;
6555
-
6556
- // TODO
6557
- // this.sameLine( 2 );
6558
-
6559
6568
  let widget = null;
6560
6569
 
6561
6570
  switch( baseclass )
@@ -6584,13 +6593,13 @@ class ItemArray extends Widget {
6584
6593
 
6585
6594
  arrayItems.appendChild( widget.root );
6586
6595
 
6587
- widget = new Button( null, "<a class='lexicon fa-solid fa-trash'></a>", ( v, event) => {
6596
+ const removeWidget = new Button( null, "<a class='lexicon fa-solid fa-trash'></a>", ( v, event) => {
6588
6597
  values.splice( values.indexOf( value ), 1 );
6589
6598
  this._updateItems();
6590
6599
  this._trigger( new IEvent(name, values, event), callback );
6591
6600
  }, { title: "Remove item", className: 'micro'} );
6592
6601
 
6593
- arrayItems.appendChild( widget.root );
6602
+ widget.root.appendChild( removeWidget.root );
6594
6603
  }
6595
6604
 
6596
6605
  buttonName = "Add item";
@@ -6655,6 +6664,11 @@ class List extends Widget {
6655
6664
  }
6656
6665
  };
6657
6666
 
6667
+ this.onResize = ( rect ) => {
6668
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6669
+ listContainer.style.width = `calc( 100% - ${ realNameWidth }px)`;
6670
+ };
6671
+
6658
6672
  this._updateValues = ( newValues ) => {
6659
6673
 
6660
6674
  values = newValues;
@@ -6690,14 +6704,11 @@ class List extends Widget {
6690
6704
 
6691
6705
  let listContainer = document.createElement( 'div' );
6692
6706
  listContainer.className = "lexlist";
6693
- doAsync( () => {
6694
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6695
- listContainer.style.width = `calc( 100% - ${ realNameWidth })`;
6696
- } );
6707
+ this.root.appendChild( listContainer );
6697
6708
 
6698
6709
  this._updateValues( values );
6699
6710
 
6700
- this.root.appendChild( listContainer );
6711
+ doAsync( this.onResize.bind( this ) );
6701
6712
  }
6702
6713
  }
6703
6714
 
@@ -6723,23 +6734,25 @@ class Tags extends Widget {
6723
6734
 
6724
6735
  this.onSetValue = ( newValue, skipCallback, event ) => {
6725
6736
  value = [].concat( newValue );
6726
- _generateTags();
6737
+ this.generateTags( value );
6727
6738
  if( !skipCallback )
6728
6739
  {
6729
6740
  this._trigger( new IEvent( name, value, event ), callback );
6730
6741
  }
6731
6742
  };
6732
6743
 
6744
+ this.onResize = ( rect ) => {
6745
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6746
+ tagsContainer.style.width = `calc( 100% - ${ realNameWidth }px)`;
6747
+ };
6748
+
6733
6749
  // Show tags
6734
6750
 
6735
6751
  const tagsContainer = document.createElement('div');
6736
6752
  tagsContainer.className = "lextags";
6737
- doAsync( () => {
6738
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6739
- tagsContainer.style.width = `calc( 100% - ${ realNameWidth })`;
6740
- } );
6753
+ this.root.appendChild( tagsContainer );
6741
6754
 
6742
- const _generateTags = () => {
6755
+ this.generateTags = ( value ) => {
6743
6756
 
6744
6757
  tagsContainer.innerHTML = "";
6745
6758
 
@@ -6783,9 +6796,9 @@ class Tags extends Widget {
6783
6796
  tagInput.focus();
6784
6797
  }
6785
6798
 
6786
- _generateTags();
6799
+ this.generateTags( value );
6787
6800
 
6788
- this.root.appendChild( tagsContainer );
6801
+ doAsync( this.onResize.bind( this ) );
6789
6802
  }
6790
6803
  }
6791
6804
 
@@ -6829,35 +6842,33 @@ class Checkbox extends Widget {
6829
6842
  }
6830
6843
  };
6831
6844
 
6845
+ this.onResize = ( rect ) => {
6846
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6847
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6848
+ };
6849
+
6832
6850
  var container = document.createElement( "div" );
6833
6851
  container.className = "lexcheckboxcont";
6834
- doAsync( () => {
6835
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6836
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
6837
- } );
6852
+ this.root.appendChild( container );
6838
6853
 
6839
6854
  let checkbox = document.createElement( "input" );
6840
6855
  checkbox.type = "checkbox";
6841
6856
  checkbox.className = "lexcheckbox " + ( options.className ?? "" );
6842
6857
  checkbox.checked = value;
6843
6858
  checkbox.disabled = options.disabled ?? false;
6859
+ container.appendChild( checkbox );
6844
6860
 
6845
6861
  let valueName = document.createElement( "span" );
6846
6862
  valueName.className = "checkboxtext";
6847
6863
  valueName.innerHTML = options.label ?? "On";
6848
-
6849
- container.appendChild( checkbox );
6850
6864
  container.appendChild( valueName );
6851
6865
 
6852
6866
  checkbox.addEventListener( "change" , e => {
6853
6867
  this.set( checkbox.checked, false, e );
6854
6868
  });
6855
6869
 
6856
- this.root.appendChild( container );
6857
-
6858
6870
  if( options.suboptions )
6859
6871
  {
6860
- this.root.style.flexWrap = "wrap";
6861
6872
  let suboptions = document.createElement( "div" );
6862
6873
  suboptions.className = "lexcheckboxsubmenu";
6863
6874
  suboptions.toggleAttribute( "hidden", !checkbox.checked );
@@ -6869,6 +6880,8 @@ class Checkbox extends Widget {
6869
6880
 
6870
6881
  this.root.appendChild( suboptions );
6871
6882
  }
6883
+
6884
+ doAsync( this.onResize.bind( this ) );
6872
6885
  }
6873
6886
  }
6874
6887
 
@@ -6912,12 +6925,14 @@ class Toggle extends Widget {
6912
6925
  }
6913
6926
  };
6914
6927
 
6928
+ this.onResize = ( rect ) => {
6929
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6930
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6931
+ };
6932
+
6915
6933
  var container = document.createElement('div');
6916
6934
  container.className = "lextogglecont";
6917
- doAsync( () => {
6918
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6919
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
6920
- } );
6935
+ this.root.appendChild( container );
6921
6936
 
6922
6937
  let toggle = document.createElement('input');
6923
6938
  toggle.type = "checkbox";
@@ -6925,23 +6940,19 @@ class Toggle extends Widget {
6925
6940
  toggle.checked = value;
6926
6941
  toggle.iValue = value;
6927
6942
  toggle.disabled = options.disabled ?? false;
6943
+ container.appendChild( toggle );
6928
6944
 
6929
6945
  let valueName = document.createElement( 'span' );
6930
6946
  valueName.className = "toggletext";
6931
6947
  valueName.innerHTML = options.label ?? "On";
6932
-
6933
- container.appendChild( toggle );
6934
6948
  container.appendChild( valueName );
6935
6949
 
6936
6950
  toggle.addEventListener( "change" , e => {
6937
6951
  this.set( toggle.checked, false, e );
6938
6952
  });
6939
6953
 
6940
- this.root.appendChild( container );
6941
-
6942
6954
  if( options.suboptions )
6943
6955
  {
6944
- this.root.style.flexWrap = "wrap";
6945
6956
  let suboptions = document.createElement('div');
6946
6957
  suboptions.className = "lextogglesubmenu";
6947
6958
  suboptions.toggleAttribute( 'hidden', !toggle.checked );
@@ -6953,6 +6964,8 @@ class Toggle extends Widget {
6953
6964
 
6954
6965
  this.root.appendChild( suboptions );
6955
6966
  }
6967
+
6968
+ doAsync( this.onResize.bind( this ) );
6956
6969
  }
6957
6970
  }
6958
6971
 
@@ -6997,6 +7010,7 @@ class RadioGroup extends Widget {
6997
7010
 
6998
7011
  var container = document.createElement( 'div' );
6999
7012
  container.className = "lexradiogroup " + ( options.className ?? "" );
7013
+ this.root.appendChild( container );
7000
7014
 
7001
7015
  let labelSpan = document.createElement( 'span' );
7002
7016
  labelSpan.innerHTML = label;
@@ -7031,8 +7045,6 @@ class RadioGroup extends Widget {
7031
7045
  currentIndex = options.selected;
7032
7046
  this.set( currentIndex, true );
7033
7047
  }
7034
-
7035
- this.root.appendChild( container );
7036
7048
  }
7037
7049
  }
7038
7050
 
@@ -7076,12 +7088,14 @@ class ColorInput extends Widget {
7076
7088
  }
7077
7089
  };
7078
7090
 
7091
+ this.onResize = ( rect ) => {
7092
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7093
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7094
+ };
7095
+
7079
7096
  var container = document.createElement( 'span' );
7080
7097
  container.className = "lexcolor";
7081
- doAsync( () => {
7082
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7083
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7084
- } );
7098
+ this.root.appendChild( container );
7085
7099
 
7086
7100
  let color = document.createElement( 'input' );
7087
7101
  color.style.width = "32px";
@@ -7090,6 +7104,7 @@ class ColorInput extends Widget {
7090
7104
  color.id = "color" + simple_guidGenerator();
7091
7105
  color.useRGB = options.useRGB ?? false;
7092
7106
  color.value = color.iValue = value;
7107
+ container.appendChild( color );
7093
7108
 
7094
7109
  if( options.disabled )
7095
7110
  {
@@ -7100,17 +7115,14 @@ class ColorInput extends Widget {
7100
7115
  this.set( e.target.value, false, e );
7101
7116
  }, false );
7102
7117
 
7103
- container.appendChild( color );
7104
-
7105
7118
  const textWidget = new TextInput( null, color.value, v => {
7106
7119
  this.set( v );
7107
7120
  }, { width: "calc( 100% - 32px )"});
7108
7121
 
7109
7122
  textWidget.root.style.marginLeft = "4px";
7110
-
7111
7123
  container.appendChild( textWidget.root );
7112
7124
 
7113
- this.root.appendChild( container );
7125
+ doAsync( this.onResize.bind( this ) );
7114
7126
  }
7115
7127
  }
7116
7128
 
@@ -7146,12 +7158,14 @@ class RangeInput extends Widget {
7146
7158
  }
7147
7159
  };
7148
7160
 
7149
- var container = document.createElement( 'div' );
7161
+ this.onResize = ( rect ) => {
7162
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7163
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
7164
+ };
7165
+
7166
+ const container = document.createElement( 'div' );
7150
7167
  container.className = "lexrange";
7151
- doAsync( () => {
7152
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7153
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
7154
- } );
7168
+ this.root.appendChild( container );
7155
7169
 
7156
7170
  let slider = document.createElement( 'input' );
7157
7171
  slider.className = "lexrangeslider " + ( options.className ?? "" );
@@ -7161,6 +7175,7 @@ class RangeInput extends Widget {
7161
7175
  slider.step = options.step ?? 1;
7162
7176
  slider.type = "range";
7163
7177
  slider.disabled = options.disabled ?? false;
7178
+ container.appendChild( slider );
7164
7179
 
7165
7180
  if( options.left ?? false )
7166
7181
  {
@@ -7203,9 +7218,7 @@ class RangeInput extends Widget {
7203
7218
  value = clamp( value, +slider.min, +slider.max );
7204
7219
  }
7205
7220
 
7206
- container.appendChild( slider );
7207
-
7208
- this.root.appendChild( container );
7221
+ doAsync( this.onResize.bind( this ) );
7209
7222
  }
7210
7223
  }
7211
7224
 
@@ -7253,15 +7266,18 @@ class NumberInput extends Widget {
7253
7266
  }
7254
7267
  };
7255
7268
 
7269
+ this.onResize = ( rect ) => {
7270
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7271
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
7272
+ };
7273
+
7256
7274
  var container = document.createElement( 'div' );
7257
7275
  container.className = "lexnumber";
7258
- doAsync( () => {
7259
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7260
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
7261
- } );
7276
+ this.root.appendChild( container );
7262
7277
 
7263
7278
  let box = document.createElement( 'div' );
7264
7279
  box.className = "numberbox";
7280
+ container.appendChild( box );
7265
7281
 
7266
7282
  let vecinput = document.createElement( 'input' );
7267
7283
  vecinput.id = "number_" + simple_guidGenerator();
@@ -7435,9 +7451,7 @@ class NumberInput extends Widget {
7435
7451
 
7436
7452
  vecinput.addEventListener( "mousedown", innerMouseDown );
7437
7453
 
7438
- container.appendChild( box );
7439
-
7440
- this.root.appendChild( container );
7454
+ doAsync( this.onResize.bind( this ) );
7441
7455
  }
7442
7456
  }
7443
7457
 
@@ -7489,14 +7503,16 @@ class Vector extends Widget {
7489
7503
  }
7490
7504
  };
7491
7505
 
7506
+ this.onResize = ( rect ) => {
7507
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7508
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7509
+ };
7510
+
7492
7511
  const vectorInputs = [];
7493
7512
 
7494
7513
  var container = document.createElement( 'div' );
7495
7514
  container.className = "lexvector";
7496
- doAsync( () => {
7497
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7498
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7499
- } );
7515
+ this.root.appendChild( container );
7500
7516
 
7501
7517
  const that = this;
7502
7518
 
@@ -7699,7 +7715,7 @@ class Vector extends Widget {
7699
7715
  }
7700
7716
  }, false );
7701
7717
 
7702
- this.root.appendChild( container );
7718
+ doAsync( this.onResize.bind( this ) );
7703
7719
  }
7704
7720
  }
7705
7721
 
@@ -7829,24 +7845,28 @@ class Pad extends Widget {
7829
7845
  }
7830
7846
  };
7831
7847
 
7848
+ this.onResize = ( rect ) => {
7849
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7850
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7851
+ };
7852
+
7832
7853
  var container = document.createElement( 'div' );
7833
7854
  container.className = "lexpad";
7834
- doAsync( () => {
7835
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7836
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7837
- } );
7855
+ this.root.appendChild( container );
7838
7856
 
7839
7857
  let pad = document.createElement('div');
7840
7858
  pad.id = "lexpad-" + name;
7841
7859
  pad.className = "lexinnerpad";
7842
7860
  pad.style.width = options.padSize ?? '96px';
7843
7861
  pad.style.height = options.padSize ?? '96px';
7862
+ container.appendChild( pad );
7844
7863
 
7845
7864
  let thumb = document.createElement('div');
7846
7865
  thumb.className = "lexpadthumb";
7847
7866
  thumb.value = new LX.vec2( value[ 0 ], value[ 1 ] );
7848
7867
  thumb.min = options.min ?? 0;
7849
7868
  thumb.max = options.max ?? 1;
7869
+ pad.appendChild( thumb );
7850
7870
 
7851
7871
  let _updateValue = v => {
7852
7872
  const [ w, h ] = [ pad.offsetWidth, pad.offsetHeight ];
@@ -7854,14 +7874,6 @@ class Pad extends Widget {
7854
7874
  thumb.style.transform = `translate(calc( ${ w * value0to1.x }px - 50% ), calc( ${ h * value0to1.y }px - 50%)`;
7855
7875
  }
7856
7876
 
7857
- doAsync( () => {
7858
- _updateValue( thumb.value )
7859
- } );
7860
-
7861
- pad.appendChild( thumb );
7862
- container.appendChild( pad );
7863
- this.root.appendChild( container );
7864
-
7865
7877
  pad.addEventListener( "mousedown", innerMouseDown );
7866
7878
 
7867
7879
  let that = this;
@@ -7880,6 +7892,7 @@ class Pad extends Widget {
7880
7892
  document.body.classList.add( 'noevents' );
7881
7893
  e.stopImmediatePropagation();
7882
7894
  e.stopPropagation();
7895
+ thumb.classList.add( "active" );
7883
7896
 
7884
7897
  if( options.onPress )
7885
7898
  {
@@ -7911,12 +7924,18 @@ class Pad extends Widget {
7911
7924
  doc.removeEventListener( 'mouseup', innerMouseUp );
7912
7925
  document.body.classList.remove( 'nocursor' );
7913
7926
  document.body.classList.remove( 'noevents' );
7927
+ thumb.classList.remove( "active" );
7914
7928
 
7915
7929
  if( options.onRelease )
7916
7930
  {
7917
7931
  options.onRelease.bind( thumb )( e, thumb );
7918
7932
  }
7919
7933
  }
7934
+
7935
+ doAsync( () => {
7936
+ this.onResize();
7937
+ _updateValue( thumb.value )
7938
+ } );
7920
7939
  }
7921
7940
  }
7922
7941
 
@@ -7946,12 +7965,14 @@ class Progress extends Widget {
7946
7965
  }
7947
7966
  };
7948
7967
 
7949
- var container = document.createElement('div');
7968
+ this.onResize = ( rect ) => {
7969
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7970
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7971
+ };
7972
+
7973
+ const container = document.createElement('div');
7950
7974
  container.className = "lexprogress";
7951
- doAsync( () => {
7952
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7953
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7954
- } );
7975
+ this.root.appendChild( container );
7955
7976
 
7956
7977
  // add slider (0-1 if not specified different )
7957
7978
 
@@ -7965,6 +7986,7 @@ class Progress extends Widget {
7965
7986
  progress.high = options.high ?? progress.high;
7966
7987
  progress.optimum = options.optimum ?? progress.optimum;
7967
7988
  progress.value = value;
7989
+ container.appendChild( progress );
7968
7990
 
7969
7991
  const _updateColor = () => {
7970
7992
 
@@ -7982,9 +8004,6 @@ class Progress extends Widget {
7982
8004
  progress.style.background = `color-mix(in srgb, ${backgroundColor} 20%, transparent)`;
7983
8005
  };
7984
8006
 
7985
- container.appendChild( progress );
7986
- this.root.appendChild( container );
7987
-
7988
8007
  if( options.showValue )
7989
8008
  {
7990
8009
  if( document.getElementById('progressvalue-' + name ) )
@@ -8051,6 +8070,8 @@ class Progress extends Widget {
8051
8070
  }
8052
8071
 
8053
8072
  _updateColor();
8073
+
8074
+ doAsync( this.onResize.bind( this ) );
8054
8075
  }
8055
8076
  }
8056
8077
 
@@ -8071,15 +8092,17 @@ class FileInput extends Widget {
8071
8092
  let type = options.type ?? 'text';
8072
8093
  let read = options.read ?? true;
8073
8094
 
8095
+ this.onResize = ( rect ) => {
8096
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
8097
+ input.style.width = `calc( 100% - ${ realNameWidth }px)`;
8098
+ };
8099
+
8074
8100
  // Create hidden input
8075
8101
  let input = document.createElement( 'input' );
8076
8102
  input.className = "lexfileinput";
8077
8103
  input.type = 'file';
8078
8104
  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
- } );
8105
+ this.root.appendChild( input );
8083
8106
 
8084
8107
  if( options.placeholder )
8085
8108
  {
@@ -8112,8 +8135,6 @@ class FileInput extends Widget {
8112
8135
  callback( null );
8113
8136
  });
8114
8137
 
8115
- this.root.appendChild( input );
8116
-
8117
8138
  if( local )
8118
8139
  {
8119
8140
  let settingsDialog = null;
@@ -8134,6 +8155,8 @@ class FileInput extends Widget {
8134
8155
 
8135
8156
  this.root.appendChild( settingButton.root );
8136
8157
  }
8158
+
8159
+ doAsync( this.onResize.bind( this ) );
8137
8160
  }
8138
8161
  }
8139
8162
 
@@ -8374,7 +8397,6 @@ class Counter extends Widget {
8374
8397
  if( e.shiftKey ) mult *= 10;
8375
8398
  this.set( counterText.count + mult, false, e );
8376
8399
  }, { className: "micro", skipInlineCount: true, title: "Plus" });
8377
-
8378
8400
  container.appendChild( addButton.root );
8379
8401
  }
8380
8402
  }
@@ -8397,12 +8419,14 @@ class Table extends Widget {
8397
8419
 
8398
8420
  super( Widget.TABLE, name, null, options );
8399
8421
 
8422
+ this.onResize = ( rect ) => {
8423
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
8424
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
8425
+ };
8426
+
8400
8427
  const container = document.createElement('div');
8401
8428
  container.className = "lextable";
8402
- doAsync( () => {
8403
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
8404
- container.style.width = `calc( 100% - ${ realNameWidth })`;
8405
- } );
8429
+ this.root.appendChild( container );
8406
8430
 
8407
8431
  this.centered = options.centered ?? false;
8408
8432
  if( this.centered === true )
@@ -8410,13 +8434,16 @@ class Table extends Widget {
8410
8434
  container.classList.add( "centered" );
8411
8435
  }
8412
8436
 
8413
- const table = document.createElement( 'table' );
8414
- container.appendChild( table );
8437
+ this.filter = options.filter ?? false;
8438
+ this.toggleColumns = options.toggleColumns ?? false;
8439
+ this.customFilters = options.customFilters ?? false;
8440
+ this.activeCustomFilters = {};
8415
8441
 
8416
8442
  data.head = data.head ?? [];
8417
8443
  data.body = data.body ?? [];
8418
- data.colVisibilityMap = { };
8419
8444
  data.checkMap = { };
8445
+ data.colVisibilityMap = { };
8446
+ data.head.forEach( (col, index) => { data.colVisibilityMap[ index ] = true; })
8420
8447
 
8421
8448
  const compareFn = ( idx, order, a, b) => {
8422
8449
  if (a[idx] < b[idx]) return -order;
@@ -8426,14 +8453,105 @@ class Table extends Widget {
8426
8453
 
8427
8454
  const sortFn = ( idx, sign ) => {
8428
8455
  data.body = data.body.sort( compareFn.bind( this, idx, sign ) );
8429
- this.refreshTable();
8456
+ this.refresh();
8457
+ }
8458
+
8459
+ // Append header
8460
+ if( this.filter || this.customFilters || this.toggleColumns )
8461
+ {
8462
+ const headerContainer = LX.makeContainer( [ "100%", "auto" ] );
8463
+
8464
+ if( this.filter )
8465
+ {
8466
+ const filterOptions = LX.deepCopy( options );
8467
+ filterOptions.placeholder = `Filter ${ this.filter }...`;
8468
+ filterOptions.skipWidget = true;
8469
+ filterOptions.trigger = "input";
8470
+ filterOptions.textClass = "outline";
8471
+
8472
+ let filter = new TextInput(null, "", ( v ) => {
8473
+ this._currentFilter = v;
8474
+ this.refresh();
8475
+ }, filterOptions );
8476
+
8477
+ headerContainer.appendChild( filter.root );
8478
+ }
8479
+
8480
+ if( this.customFilters )
8481
+ {
8482
+ const icon = LX.makeIcon( "circle-plus", null, "sm" );
8483
+
8484
+ for( let f of this.customFilters )
8485
+ {
8486
+ const customFilterBtn = new Button(null, icon.innerHTML + f.name, ( v ) => {
8487
+
8488
+ const menuOptions = f.options.map( ( colName, idx ) => {
8489
+ const item = {
8490
+ name: colName,
8491
+ checked: !!this.activeCustomFilters[ colName ],
8492
+ callback: (key, dom, v) => {
8493
+ if( v ) { this.activeCustomFilters[ key ] = f.name; }
8494
+ else {
8495
+ delete this.activeCustomFilters[ key ];
8496
+ }
8497
+ this.refresh();
8498
+ }
8499
+ }
8500
+ return item;
8501
+ } );
8502
+ new DropdownMenu( customFilterBtn.root, menuOptions, { side: "bottom", align: "start" });
8503
+ }, { buttonClass: "dashed" } );
8504
+ headerContainer.appendChild( customFilterBtn.root );
8505
+ }
8506
+
8507
+ // const resetIcon = LX.makeIcon( "xmark", null, "sm" );
8508
+ this._resetCustomFiltersBtn = new Button(null, "resetButton", ( v ) => {
8509
+ this.activeCustomFilters = {};
8510
+ this.refresh();
8511
+ this._resetCustomFiltersBtn.root.classList.add( "hidden" );
8512
+ }, { title: "Reset filters", icon: "fa fa-xmark" } );
8513
+ headerContainer.appendChild( this._resetCustomFiltersBtn.root );
8514
+ this._resetCustomFiltersBtn.root.classList.add( "hidden" );
8515
+ }
8516
+
8517
+ if( this.toggleColumns )
8518
+ {
8519
+ const icon = LX.makeIcon( "sliders" );
8520
+ const toggleColumnsBtn = new Button( "toggleColumnsBtn", icon.innerHTML + "View", (value, e) => {
8521
+ const menuOptions = data.head.map( ( colName, idx ) => {
8522
+ const item = {
8523
+ name: colName,
8524
+ icon: "check",
8525
+ callback: () => {
8526
+ data.colVisibilityMap[ idx ] = !data.colVisibilityMap[ idx ];
8527
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8528
+ cells.forEach(cell => {
8529
+ cell.style.display = (cell.style.display === "none") ? "" : "none";
8530
+ });
8531
+ }
8532
+ }
8533
+ if( !data.colVisibilityMap[ idx ] ) delete item.icon;
8534
+ return item;
8535
+ } );
8536
+ new DropdownMenu( e.target, menuOptions, { side: "bottom", align: "end" });
8537
+ }, { hideName: true } );
8538
+ headerContainer.appendChild( toggleColumnsBtn.root );
8539
+ toggleColumnsBtn.root.style.marginLeft = "auto";
8540
+ }
8541
+
8542
+ container.appendChild( headerContainer );
8430
8543
  }
8431
8544
 
8432
- this.refreshTable = () => {
8545
+ const table = document.createElement( 'table' );
8546
+ container.appendChild( table );
8547
+
8548
+ this.refresh = () => {
8549
+
8550
+ this._currentFilter = this._currentFilter ?? "";
8433
8551
 
8434
8552
  table.innerHTML = "";
8435
8553
 
8436
- let rowOffsetCount = 0;
8554
+ this.rowOffsetCount = 0;
8437
8555
 
8438
8556
  // Head
8439
8557
  {
@@ -8448,7 +8566,7 @@ class Table extends Widget {
8448
8566
  const th = document.createElement( 'th' );
8449
8567
  th.style.width = "0px";
8450
8568
  hrow.appendChild( th );
8451
- rowOffsetCount++;
8569
+ this.rowOffsetCount++;
8452
8570
  }
8453
8571
 
8454
8572
  if( options.selectable )
@@ -8473,14 +8591,15 @@ class Table extends Widget {
8473
8591
  }
8474
8592
  });
8475
8593
 
8476
- rowOffsetCount++;
8594
+ this.rowOffsetCount++;
8477
8595
  hrow.appendChild( th );
8478
8596
  }
8479
8597
 
8480
8598
  for( const headData of data.head )
8481
8599
  {
8482
8600
  const th = document.createElement( 'th' );
8483
- th.innerHTML = `${ headData } <a class="fa-solid fa-sort"></a>`;
8601
+ th.innerHTML = `<span>${ headData }</span>`;
8602
+ th.querySelector( "span" ).appendChild( LX.makeIcon( "menu-arrows", null, "sm" ) );
8484
8603
 
8485
8604
  const idx = data.head.indexOf( headData );
8486
8605
  if( this.centered && this.centered.indexOf( idx ) > -1 )
@@ -8488,19 +8607,29 @@ class Table extends Widget {
8488
8607
  th.classList.add( "centered" );
8489
8608
  }
8490
8609
 
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 ) },
8610
+ const menuOptions = [
8611
+ { name: "Asc", icon: "up", callback: sortFn.bind( this, idx, 1 ) },
8612
+ { name: "Desc", icon: "down", callback: sortFn.bind( this, idx, -1 ) }
8613
+ ];
8614
+
8615
+ if( this.toggleColumns )
8616
+ {
8617
+ menuOptions.push(
8495
8618
  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" });
8619
+ {
8620
+ name: "Hide", icon: "eye-slash", callback: () => {
8621
+ data.colVisibilityMap[ idx ] = false;
8622
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8623
+ cells.forEach(cell => {
8624
+ cell.style.display = (cell.style.display === "none") ? "" : "none";
8625
+ });
8626
+ }
8627
+ }
8628
+ );
8629
+ }
8630
+
8631
+ th.addEventListener( 'click', event => {
8632
+ new DropdownMenu( event.target, menuOptions, { side: "bottom", align: "start" });
8504
8633
  });
8505
8634
 
8506
8635
  hrow.appendChild( th );
@@ -8538,15 +8667,23 @@ class Table extends Widget {
8538
8667
  v.style.transition = `none`;
8539
8668
  } );
8540
8669
  flushCss( fromRow );
8541
- rIdx = null;
8542
8670
 
8543
8671
  if( movePending )
8544
8672
  {
8673
+ // Modify inner data first
8674
+ const fromIdx = rIdx - 1;
8675
+ const targetIdx = movePending[ 1 ] - 1;
8676
+ var b = data.body[fromIdx];
8677
+ data.body[fromIdx] = data.body[targetIdx];
8678
+ data.body[targetIdx] = b;
8679
+
8545
8680
  const parent = movePending[ 0 ].parentNode;
8546
8681
  parent.insertChildAtIndex( movePending[ 0 ], movePending[ 1 ] );
8547
8682
  movePending = null;
8548
8683
  }
8549
8684
 
8685
+ rIdx = null;
8686
+
8550
8687
  doAsync( () => {
8551
8688
  Array.from( table.rows ).forEach( v => {
8552
8689
  v.style.transition = `transform 0.2s ease-in`;
@@ -8562,10 +8699,47 @@ class Table extends Widget {
8562
8699
  fromRow.style.transform = `translateY(${fromRow.dY}px)`;
8563
8700
  };
8564
8701
 
8565
-
8566
8702
  for( let r = 0; r < data.body.length; ++r )
8567
8703
  {
8568
8704
  const bodyData = data.body[ r ];
8705
+
8706
+ if( this.filter )
8707
+ {
8708
+ const filterColIndex = data.head.indexOf( this.filter );
8709
+ if( filterColIndex > -1 )
8710
+ {
8711
+ if( !bodyData[ filterColIndex ].toLowerCase().includes( this._currentFilter.toLowerCase() ) )
8712
+ {
8713
+ continue;
8714
+ }
8715
+ }
8716
+ }
8717
+
8718
+ if( Object.keys( this.activeCustomFilters ).length )
8719
+ {
8720
+ let acfMap = {};
8721
+
8722
+ this._resetCustomFiltersBtn.root.classList.remove( "hidden" );
8723
+
8724
+ for( let acfValue in this.activeCustomFilters )
8725
+ {
8726
+ const acfName = this.activeCustomFilters[ acfValue ];
8727
+ acfMap[ acfName ] = acfMap[ acfName ] ?? false;
8728
+
8729
+ const filterColIndex = data.head.indexOf( acfName );
8730
+ if( filterColIndex > -1 )
8731
+ {
8732
+ acfMap[ acfName ] |= ( bodyData[ filterColIndex ] === acfValue );
8733
+ }
8734
+ }
8735
+
8736
+ const show = Object.values( acfMap ).reduce( ( e, acc ) => acc *= e );
8737
+ if( !show )
8738
+ {
8739
+ continue;
8740
+ }
8741
+ }
8742
+
8569
8743
  const row = document.createElement( 'tr' );
8570
8744
  const rowId = LX.getSupportedDOMName( bodyData.join( '-' ) );
8571
8745
  row.setAttribute( "rowId", rowId.substr(0, 16) );
@@ -8676,14 +8850,15 @@ class Table extends Widget {
8676
8850
  {
8677
8851
  button = LX.makeIcon( "more-horizontal", "Menu" );
8678
8852
  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
- } );
8853
+ if( !options.onMenuAction )
8854
+ {
8855
+ return;
8856
+ }
8857
+
8858
+ const menuOptions = options.onMenuAction( r, data );
8859
+ console.assert( menuOptions.length, "Add items to the Menu Action Dropdown!" );
8860
+
8861
+ new DropdownMenu( event.target, menuOptions, { side: "bottom", align: "end" });
8687
8862
  });
8688
8863
  }
8689
8864
  else // custom actions
@@ -8697,7 +8872,7 @@ class Table extends Widget {
8697
8872
  const mustRefresh = action.callback( bodyData, table, e );
8698
8873
  if( mustRefresh )
8699
8874
  {
8700
- this.refreshTable();
8875
+ this.refresh();
8701
8876
  }
8702
8877
  });
8703
8878
  }
@@ -8719,7 +8894,7 @@ class Table extends Widget {
8719
8894
  const idx = parseInt( v );
8720
8895
  if( !data.colVisibilityMap[ idx ] )
8721
8896
  {
8722
- const cells = table.querySelectorAll(`tr > *:nth-child(${idx + rowOffsetCount + 1})`);
8897
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8723
8898
  cells.forEach(cell => {
8724
8899
  cell.style.display = (cell.style.display === "none") ? "" : "none";
8725
8900
  });
@@ -8727,9 +8902,9 @@ class Table extends Widget {
8727
8902
  }
8728
8903
  }
8729
8904
 
8730
- this.refreshTable();
8905
+ this.refresh();
8731
8906
 
8732
- this.root.appendChild( container );
8907
+ doAsync( this.onResize.bind( this ) );
8733
8908
  }
8734
8909
  }
8735
8910
 
@@ -9102,7 +9277,7 @@ class Panel {
9102
9277
 
9103
9278
  let widget = new TextInput( null, null, null, options )
9104
9279
  const element = widget.root;
9105
- element.className += " lexfilter noname";
9280
+ element.className += " lexfilter";
9106
9281
 
9107
9282
  let input = document.createElement('input');
9108
9283
  input.className = 'lexinput-filter';
@@ -9115,7 +9290,7 @@ class Panel {
9115
9290
  element.appendChild( searchIcon );
9116
9291
  element.appendChild( input );
9117
9292
 
9118
- input.addEventListener("input", (e) => {
9293
+ input.addEventListener("input", e => {
9119
9294
  if( options.callback )
9120
9295
  {
9121
9296
  options.callback( input.value, e );
@@ -10053,7 +10228,7 @@ class Branch {
10053
10228
  var size = this.grabber.style.marginLeft;
10054
10229
 
10055
10230
  // Update sizes of widgets inside
10056
- for( var i = 0; i < this.widgets.length; i++ )
10231
+ for( let i = 0; i < this.widgets.length; i++ )
10057
10232
  {
10058
10233
  let widget = this.widgets[ i ];
10059
10234
  const element = widget.root;
@@ -10063,26 +10238,21 @@ class Branch {
10063
10238
  continue;
10064
10239
  }
10065
10240
 
10066
- var name = element.children[ 0 ];
10067
- var value = element.children[ 1 ];
10241
+ let name = element.children[ 0 ];
10242
+ let value = element.children[ 1 ];
10068
10243
 
10069
10244
  name.style.width = size;
10070
- let padding = "0px";
10245
+
10071
10246
  switch( widget.type )
10072
10247
  {
10073
- case Widget.FILE:
10074
- padding = "10%";
10075
- break;
10248
+ case Widget.CUSTOM:
10249
+ case Widget.ARRAY:
10250
+ continue;
10076
10251
  };
10077
10252
 
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
- }
10253
+ value.style.width = "-moz-calc( 100% - " + size + " )";
10254
+ value.style.width = "-webkit-calc( 100% - " + size + " )";
10255
+ value.style.width = "calc( 100% - " + size + " )";
10086
10256
  }
10087
10257
  }
10088
10258
  };
@@ -10210,7 +10380,7 @@ class Dialog {
10210
10380
  draggable = options.draggable ?? true,
10211
10381
  modal = options.modal ?? false;
10212
10382
 
10213
- var root = document.createElement('dialog');
10383
+ let root = document.createElement('dialog');
10214
10384
  root.className = "lexdialog " + (options.className ?? "");
10215
10385
  root.id = options.id ?? "dialog" + Dialog._last_id++;
10216
10386
  LX.root.appendChild( root );
@@ -10221,7 +10391,7 @@ class Dialog {
10221
10391
 
10222
10392
  let that = this;
10223
10393
 
10224
- var titleDiv = document.createElement('div');
10394
+ const titleDiv = document.createElement('div');
10225
10395
 
10226
10396
  if( title )
10227
10397
  {
@@ -10286,7 +10456,7 @@ class Dialog {
10286
10456
  }, { icon: "fa-regular fa-window-restore" });
10287
10457
  };
10288
10458
 
10289
- root.appendChild(titleDiv);
10459
+ root.appendChild( titleDiv );
10290
10460
  }
10291
10461
 
10292
10462
  if( options.closable ?? true )
@@ -10485,7 +10655,7 @@ class PocketDialog extends Dialog {
10485
10655
 
10486
10656
  if( float )
10487
10657
  {
10488
- for( var i = 0; i < float.length; i++ )
10658
+ for( let i = 0; i < float.length; i++ )
10489
10659
  {
10490
10660
  const t = float[i];
10491
10661
  switch( t )
@@ -10618,14 +10788,14 @@ class ContextMenu {
10618
10788
  contextmenu.className = "lexcontextmenu";
10619
10789
  c.appendChild( contextmenu );
10620
10790
 
10621
- for( var i = 0; i < o[k].length; ++i )
10791
+ for( let i = 0; i < o[k].length; ++i )
10622
10792
  {
10623
10793
  const subitem = o[ k ][ i ];
10624
10794
  const subkey = Object.keys( subitem )[ 0 ];
10625
10795
  this._createEntry(subitem, subkey, contextmenu, d);
10626
10796
  }
10627
10797
 
10628
- var rect = c.getBoundingClientRect();
10798
+ const rect = c.getBoundingClientRect();
10629
10799
  contextmenu.style.left = rect.width + "px";
10630
10800
  contextmenu.style.marginTop = 3.5 - c.offsetHeight + "px";
10631
10801
 
@@ -10778,10 +10948,10 @@ class ContextMenu {
10778
10948
  _item[ key ].unshift( parent );
10779
10949
  }
10780
10950
 
10781
- for( var child of _item[ key ] )
10951
+ for( let child of _item[ key ] )
10782
10952
  {
10783
10953
  let k = Object.keys( child )[ 0 ];
10784
- for( var i = 0; i < child[ k ].length; ++i )
10954
+ for( let i = 0; i < child[ k ].length; ++i )
10785
10955
  {
10786
10956
  setParent( child );
10787
10957
  }
@@ -10822,7 +10992,7 @@ LX.ContextMenu = ContextMenu;
10822
10992
 
10823
10993
  function addContextMenu( title, event, callback, options )
10824
10994
  {
10825
- var menu = new ContextMenu( event, title, options );
10995
+ const menu = new ContextMenu( event, title, options );
10826
10996
  LX.root.appendChild( menu.root );
10827
10997
 
10828
10998
  if( callback )
@@ -10853,7 +11023,8 @@ class CanvasCurve {
10853
11023
  element.style.minHeight = "20px";
10854
11024
 
10855
11025
  element.bgcolor = options.bgColor || LX.getThemeColor( "global-intense-background" );
10856
- element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected-light" );
11026
+ element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected" );
11027
+ element.activepointscolor = options.activePointsColor || LX.getThemeColor( "global-selected-light" );
10857
11028
  element.linecolor = options.lineColor || "#555";
10858
11029
  element.value = value || [];
10859
11030
  element.xrange = options.xrange || [ 0, 1 ]; // min, max
@@ -10869,7 +11040,8 @@ class CanvasCurve {
10869
11040
 
10870
11041
  LX.addSignal( "@on_new_color_scheme", (el, value) => {
10871
11042
  element.bgcolor = options.bgColor || LX.getThemeColor( "global-intense-background" );
10872
- element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected-light" );
11043
+ element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected" );
11044
+ element.activepointscolor = options.activePointsColor || LX.getThemeColor( "global-selected-light" );
10873
11045
  this.redraw();
10874
11046
  } );
10875
11047
 
@@ -10890,11 +11062,11 @@ class CanvasCurve {
10890
11062
  return element.defaulty;
10891
11063
  }
10892
11064
 
10893
- var last = [ element.xrange[ 0 ], element.defaulty ];
10894
- var f = 0;
10895
- for( var i = 0; i < element.value.length; i += 1 )
11065
+ let last = [ element.xrange[ 0 ], element.defaulty ];
11066
+ let f = 0;
11067
+ for( let i = 0; i < element.value.length; i += 1 )
10896
11068
  {
10897
- var v = element.value[ i ];
11069
+ let v = element.value[ i ];
10898
11070
  if( x == v[ 0 ] ) return v[ 1 ];
10899
11071
  if( x < v[ 0 ] )
10900
11072
  {
@@ -10912,9 +11084,9 @@ class CanvasCurve {
10912
11084
 
10913
11085
  element.resample = function( samples ) {
10914
11086
 
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 )
11087
+ let r = [];
11088
+ let dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
11089
+ for( let i = element.xrange[0]; i <= element.xrange[1]; i += dx )
10918
11090
  {
10919
11091
  r.push( element.getValueAt(i) );
10920
11092
  }
@@ -10923,9 +11095,9 @@ class CanvasCurve {
10923
11095
 
10924
11096
  element.addValue = function(v) {
10925
11097
 
10926
- for( var i = 0; i < element.value; i++ )
11098
+ for( let i = 0; i < element.value; i++ )
10927
11099
  {
10928
- var value = element.value[i];
11100
+ let value = element.value[i];
10929
11101
  if(value[0] < v[0]) continue;
10930
11102
  element.value.splice(i,0,v);
10931
11103
  redraw();
@@ -10948,7 +11120,7 @@ class CanvasCurve {
10948
11120
  (v[1] * element.yrange[1] / canvas.height + element.yrange[0])];
10949
11121
  }
10950
11122
 
10951
- var selected = -1;
11123
+ let selected = -1;
10952
11124
 
10953
11125
  element.redraw = function( o = {} ) {
10954
11126
 
@@ -11010,7 +11182,7 @@ class CanvasCurve {
11010
11182
  var value = element.value[ i ];
11011
11183
  pos = convert( value );
11012
11184
  if( selected == i )
11013
- ctx.fillStyle = "white";
11185
+ ctx.fillStyle = element.activepointscolor;
11014
11186
  else
11015
11187
  ctx.fillStyle = element.pointscolor;
11016
11188
  ctx.beginPath();
@@ -12198,7 +12370,7 @@ class AssetView {
12198
12370
  const hasImage = ['png', 'jpg'].indexOf( getExtension( file.src ) ) > -1 || is_base_64;
12199
12371
  if( hasImage )
12200
12372
  {
12201
- this.previewPanel.addImage( file.src, { style: { width: "100%" } } );
12373
+ this.previewPanel.addImage( null, file.src, { style: { width: "100%" } } );
12202
12374
  }
12203
12375
  }
12204
12376
 
@@ -12753,6 +12925,9 @@ LX.ICONS = {
12753
12925
  "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
12926
  "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
12927
  "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"],
12928
+ "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"],
12929
+ "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"],
12930
+ "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
12931
  "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
12932
  "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
12933
  "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 +12956,7 @@ LX.ICONS = {
12781
12956
  "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
12957
  "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
12958
  "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"],
12959
+ "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
12960
  "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
12961
  "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
12962
  "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"],