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.
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  var LX = {
9
- version: "0.5.1",
9
+ version: "0.5.2",
10
10
  ready: false,
11
11
  components: [], // Specific pre-build components
12
12
  signals: {}, // Events and triggers
@@ -46,7 +46,7 @@ else if( typeof Date != "undefined" && Date.now )
46
46
  else if ( typeof process != "undefined" )
47
47
  {
48
48
  LX.getTime = function() {
49
- var t = process.hrtime();
49
+ const t = process.hrtime();
50
50
  return t[ 0 ] * 0.001 + t[ 1 ] * 1e-6;
51
51
  };
52
52
  }
@@ -148,7 +148,7 @@ LX.setTheme = setTheme;
148
148
  */
149
149
  function setThemeColor( colorName, color )
150
150
  {
151
- var r = document.querySelector( ':root' );
151
+ const r = document.querySelector( ':root' );
152
152
  r.style.setProperty( '--' + colorName, color );
153
153
  }
154
154
 
@@ -190,10 +190,10 @@ LX.getThemeColor = getThemeColor;
190
190
  */
191
191
  function getBase64Image( img )
192
192
  {
193
- var canvas = document.createElement( 'canvas' );
193
+ const canvas = document.createElement( 'canvas' );
194
194
  canvas.width = img.width;
195
195
  canvas.height = img.height;
196
- var ctx = canvas.getContext( '2d' );
196
+ const ctx = canvas.getContext( '2d' );
197
197
  ctx.drawImage( img, 0, 0 );
198
198
  return canvas.toDataURL( 'image/png' );
199
199
  }
@@ -958,8 +958,8 @@ function init( options = { } )
958
958
  this.root = root;
959
959
  this.container = document.body;
960
960
 
961
- this.modal.classList.add( 'hiddenOpacity' );
962
- this.modal.toggle = function( force ) { this.classList.toggle( 'hiddenOpacity', force ); };
961
+ this.modal.classList.add( 'hidden-opacity' );
962
+ this.modal.toggle = function( force ) { this.classList.toggle( 'hidden-opacity', force ); };
963
963
 
964
964
  if( options.container )
965
965
  {
@@ -1035,6 +1035,17 @@ function init( options = { } )
1035
1035
  this.DEFAULT_SPLITBAR_SIZE = 4;
1036
1036
  this.OPEN_CONTEXTMENU_ENTRY = 'click';
1037
1037
 
1038
+ this.widgetResizeObserver = new ResizeObserver( entries => {
1039
+ for ( const entry of entries )
1040
+ {
1041
+ const widget = entry.target?.jsInstance;
1042
+ if( widget && widget.onResize )
1043
+ {
1044
+ widget.onResize( entry.contentRect );
1045
+ }
1046
+ }
1047
+ });
1048
+
1038
1049
  this.ready = true;
1039
1050
  this.menubars = [ ];
1040
1051
 
@@ -1478,6 +1489,7 @@ class DropdownMenu {
1478
1489
  }
1479
1490
 
1480
1491
  this._trigger = trigger;
1492
+ trigger.classList.add( "triggered" );
1481
1493
  trigger.ddm = this;
1482
1494
 
1483
1495
  this._items = items;
@@ -1504,7 +1516,7 @@ class DropdownMenu {
1504
1516
  this.root.focus();
1505
1517
 
1506
1518
  this._onClick = e => {
1507
- if( e.target && ( e.target.className.includes( "lexdropdown" ) || e.target == this._trigger ) )
1519
+ if( e.target && ( this.root.contains( e.target ) || e.target == this._trigger ) )
1508
1520
  {
1509
1521
  return;
1510
1522
  }
@@ -1517,6 +1529,8 @@ class DropdownMenu {
1517
1529
 
1518
1530
  destroy() {
1519
1531
 
1532
+ this._trigger.classList.remove( "triggered" );
1533
+
1520
1534
  delete this._trigger.ddm;
1521
1535
 
1522
1536
  document.body.removeEventListener( "click", this._onClick );
@@ -1582,12 +1596,6 @@ class DropdownMenu {
1582
1596
  menuItem.id = pKey;
1583
1597
  menuItem.innerHTML = `<span>${ key }</span>`;
1584
1598
 
1585
- if( item.icon )
1586
- {
1587
- const icon = LX.makeIcon( item.icon );
1588
- menuItem.prepend( icon );
1589
- }
1590
-
1591
1599
  menuItem.tabIndex = "1";
1592
1600
  parentDom.appendChild( menuItem );
1593
1601
 
@@ -1603,15 +1611,41 @@ class DropdownMenu {
1603
1611
  menuItem.appendChild( submenuIcon );
1604
1612
  }
1605
1613
 
1606
- menuItem.addEventListener( "click", () => {
1607
- const f = item[ 'callback' ];
1608
- if( f )
1609
- {
1610
- f.call( this, key, menuItem );
1611
- }
1614
+ if( item.icon )
1615
+ {
1616
+ const icon = LX.makeIcon( item.icon );
1617
+ menuItem.prepend( icon );
1618
+ }
1612
1619
 
1613
- this.destroy();
1614
- } );
1620
+ if( item.checked != undefined )
1621
+ {
1622
+ const checkbox = new Checkbox( pKey + "_entryChecked", item.checked, (v) => {
1623
+ const f = item[ 'callback' ];
1624
+ if( f )
1625
+ {
1626
+ f.call( this, key, menuItem, v );
1627
+ }
1628
+ });
1629
+ const input = checkbox.root.querySelector( "input" );
1630
+ menuItem.prepend( input );
1631
+
1632
+ menuItem.addEventListener( "click", (e) => {
1633
+ if( e.target.type == "checkbox" ) return;
1634
+ input.checked = !input.checked;
1635
+ checkbox.set( input.checked );
1636
+ } );
1637
+ }
1638
+ else
1639
+ {
1640
+ menuItem.addEventListener( "click", () => {
1641
+ const f = item[ 'callback' ];
1642
+ if( f )
1643
+ {
1644
+ f.call( this, key, menuItem );
1645
+ }
1646
+ this.destroy();
1647
+ } );
1648
+ }
1615
1649
 
1616
1650
  menuItem.addEventListener("mouseover", e => {
1617
1651
 
@@ -1781,7 +1815,7 @@ class Area {
1781
1815
 
1782
1816
  if( !options.skipAppend )
1783
1817
  {
1784
- var lexroot = document.getElementById("lexroot");
1818
+ let lexroot = document.getElementById("lexroot");
1785
1819
  lexroot.appendChild( this.root );
1786
1820
  }
1787
1821
 
@@ -1852,12 +1886,12 @@ class Area {
1852
1886
  this.splitBar.addEventListener("mousedown", innerMouseDown);
1853
1887
  this.root.appendChild( this.splitBar );
1854
1888
 
1855
- var that = this;
1856
- var lastMousePosition = [ 0, 0 ];
1889
+ const that = this;
1890
+ let lastMousePosition = [ 0, 0 ];
1857
1891
 
1858
1892
  function innerMouseDown( e )
1859
1893
  {
1860
- var doc = that.root.ownerDocument;
1894
+ const doc = that.root.ownerDocument;
1861
1895
  doc.addEventListener( 'mousemove', innerMouseMove );
1862
1896
  doc.addEventListener( 'mouseup', innerMouseUp );
1863
1897
  lastMousePosition[ 0 ] = e.x;
@@ -1910,7 +1944,7 @@ class Area {
1910
1944
 
1911
1945
  function innerMouseUp( e )
1912
1946
  {
1913
- var doc = that.root.ownerDocument;
1947
+ const doc = that.root.ownerDocument;
1914
1948
  doc.removeEventListener( 'mousemove', innerMouseMove );
1915
1949
  doc.removeEventListener( 'mouseup', innerMouseUp );
1916
1950
  document.body.classList.remove( 'nocursor' );
@@ -1962,9 +1996,9 @@ class Area {
1962
1996
  this.root = this.sections[ 1 ].root;
1963
1997
  }
1964
1998
 
1965
- var type = options.type || "horizontal";
1966
- var sizes = options.sizes || [ "50%", "50%" ];
1967
- var auto = (options.sizes === 'auto');
1999
+ const type = options.type || "horizontal";
2000
+ const sizes = options.sizes || [ "50%", "50%" ];
2001
+ const auto = (options.sizes === 'auto');
1968
2002
 
1969
2003
  if( !sizes[ 1 ] )
1970
2004
  {
@@ -1980,8 +2014,8 @@ class Area {
1980
2014
  }
1981
2015
 
1982
2016
  // Create areas
1983
- var area1 = new Area( { skipAppend: true, className: "split" + ( options.menubar || options.sidebar ? "" : " origin" ) } );
1984
- var area2 = new Area( { skipAppend: true, className: "split" } );
2017
+ let area1 = new Area( { skipAppend: true, className: "split" + ( options.menubar || options.sidebar ? "" : " origin" ) } );
2018
+ let area2 = new Area( { skipAppend: true, className: "split" } );
1985
2019
 
1986
2020
  area1.parentArea = this;
1987
2021
  area2.parentArea = this;
@@ -1989,7 +2023,7 @@ class Area {
1989
2023
  let minimizable = options.minimizable ?? false;
1990
2024
  let resize = ( options.resize ?? true ) || minimizable;
1991
2025
 
1992
- var data = "0px";
2026
+ let data = "0px";
1993
2027
  this.offset = 0;
1994
2028
 
1995
2029
  if( resize )
@@ -2036,7 +2070,7 @@ class Area {
2036
2070
 
2037
2071
  if( type == "horizontal" )
2038
2072
  {
2039
- var width1 = sizes[ 0 ],
2073
+ let width1 = sizes[ 0 ],
2040
2074
  width2 = sizes[ 1 ];
2041
2075
 
2042
2076
  if( width1.constructor == Number )
@@ -2077,7 +2111,7 @@ class Area {
2077
2111
  }
2078
2112
  else
2079
2113
  {
2080
- var height1 = sizes[ 0 ],
2114
+ let height1 = sizes[ 0 ],
2081
2115
  height2 = sizes[ 1 ];
2082
2116
 
2083
2117
  if( height1.constructor == Number )
@@ -2115,11 +2149,11 @@ class Area {
2115
2149
  return this.sections;
2116
2150
  }
2117
2151
 
2118
- var that = this;
2152
+ const that = this;
2119
2153
 
2120
2154
  function innerMouseDown( e )
2121
2155
  {
2122
- var doc = that.root.ownerDocument;
2156
+ const doc = that.root.ownerDocument;
2123
2157
  doc.addEventListener( 'mousemove', innerMouseMove );
2124
2158
  doc.addEventListener( 'mouseup', innerMouseUp );
2125
2159
  e.stopPropagation();
@@ -2139,26 +2173,13 @@ class Area {
2139
2173
  that._moveSplit( -e.movementY );
2140
2174
  }
2141
2175
 
2142
- const widgets = that.root.querySelectorAll( ".lexwidget" );
2143
-
2144
- // Send area resize to every widget in the area
2145
- for( let widget of widgets )
2146
- {
2147
- const jsInstance = widget.jsInstance;
2148
-
2149
- if( jsInstance.onresize )
2150
- {
2151
- jsInstance.onresize();
2152
- }
2153
- }
2154
-
2155
2176
  e.stopPropagation();
2156
2177
  e.preventDefault();
2157
2178
  }
2158
2179
 
2159
2180
  function innerMouseUp( e )
2160
2181
  {
2161
- var doc = that.root.ownerDocument;
2182
+ const doc = that.root.ownerDocument;
2162
2183
  doc.removeEventListener( 'mousemove', innerMouseMove );
2163
2184
  doc.removeEventListener( 'mouseup', innerMouseUp );
2164
2185
  document.body.classList.remove( 'nocursor' );
@@ -2306,7 +2327,7 @@ class Area {
2306
2327
 
2307
2328
  propagateEvent( eventName ) {
2308
2329
 
2309
- for( var i = 0; i < this.sections.length; i++ )
2330
+ for( let i = 0; i < this.sections.length; i++ )
2310
2331
  {
2311
2332
  const area = this.sections[ i ];
2312
2333
 
@@ -2432,7 +2453,7 @@ class Area {
2432
2453
 
2433
2454
  if( float )
2434
2455
  {
2435
- for( var i = 0; i < float.length; i++ )
2456
+ for( let i = 0; i < float.length; i++ )
2436
2457
  {
2437
2458
  const t = float[i];
2438
2459
  switch( t )
@@ -2651,7 +2672,7 @@ class Area {
2651
2672
 
2652
2673
  for( var i = 0; i < this.sections.length; i++ )
2653
2674
  {
2654
- this.sections[i]._update();
2675
+ this.sections[ i ]._update();
2655
2676
  }
2656
2677
  }
2657
2678
  };
@@ -4375,6 +4396,8 @@ class Widget {
4375
4396
  {
4376
4397
  root.style.height = root.style.minHeight = options.height;
4377
4398
  }
4399
+
4400
+ LX.widgetResizeObserver.observe( root );
4378
4401
  }
4379
4402
 
4380
4403
  if( name != undefined )
@@ -4575,15 +4598,17 @@ LX.Widget = Widget;
4575
4598
 
4576
4599
  function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4577
4600
  {
4578
- let custom_idx = simple_guidGenerator();
4601
+ let customIdx = simple_guidGenerator();
4579
4602
 
4580
4603
  Panel.prototype[ 'add' + customWidgetName ] = function( name, instance, callback ) {
4581
4604
 
4605
+ options.nameWidth = "100%";
4606
+
4582
4607
  let widget = new Widget( Widget.CUSTOM, name, null, options );
4583
4608
  this._attachWidget( widget );
4584
4609
 
4585
4610
  widget.customName = customWidgetName;
4586
- widget.customIdx = custom_idx;
4611
+ widget.customIdx = customIdx;
4587
4612
 
4588
4613
  widget.onGetValue = () => {
4589
4614
  return instance;
@@ -4600,7 +4625,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4600
4625
  };
4601
4626
 
4602
4627
  const element = widget.root;
4603
- element.style.flexWrap = "wrap";
4604
4628
 
4605
4629
  let container, customWidgetsDom;
4606
4630
  let default_instance = options.default ?? {};
@@ -4619,14 +4643,12 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4619
4643
 
4620
4644
  container = document.createElement('div');
4621
4645
  container.className = "lexcustomcontainer";
4622
- doAsync( () => {
4623
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
4624
- container.style.width = `calc( 100% - ${ realNameWidth })`;
4625
- } );
4646
+ container.style.width = "100%";
4647
+ element.appendChild( container );
4626
4648
 
4627
4649
  let buttonName = "<a class='fa-solid " + (options.icon ?? "fa-cube") + "' style='float:left'></a>";
4628
4650
  buttonName += customWidgetName + (!instance ? " [empty]" : "");
4629
- // Add alwayis icon to keep spacing right
4651
+ // Add always icon to keep spacing right
4630
4652
  buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu' style='float:right; width:5%;'></a>";
4631
4653
 
4632
4654
  let buttonEl = this.addButton(null, buttonName, (value, event) => {
@@ -4646,7 +4668,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4646
4668
  }
4647
4669
 
4648
4670
  }, { buttonClass: 'custom' });
4649
-
4650
4671
  container.appendChild( buttonEl.root );
4651
4672
 
4652
4673
  if( instance )
@@ -4668,8 +4689,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
4668
4689
  customWidgetsDom = document.createElement('div');
4669
4690
  customWidgetsDom.className = "lexcustomitems";
4670
4691
  customWidgetsDom.toggleAttribute('hidden', true);
4671
-
4672
- element.appendChild( container );
4673
4692
  element.appendChild( customWidgetsDom );
4674
4693
 
4675
4694
  if( instance )
@@ -5187,6 +5206,7 @@ class NodeTree {
5187
5206
  }
5188
5207
 
5189
5208
  const _hasChild = function( parent, id ) {
5209
+ if( !parent.length ) return;
5190
5210
  for( var c of parent.children )
5191
5211
  {
5192
5212
  if( c.id == id ) return true;
@@ -5351,6 +5371,11 @@ class TextInput extends Widget {
5351
5371
  }
5352
5372
  };
5353
5373
 
5374
+ this.onResize = ( rect ) => {
5375
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5376
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5377
+ };
5378
+
5354
5379
  this.valid = ( v ) => {
5355
5380
  v = v ?? this.value();
5356
5381
  if( !v.length || wValue.pattern == "" ) return true;
@@ -5361,10 +5386,7 @@ class TextInput extends Widget {
5361
5386
  let container = document.createElement( 'div' );
5362
5387
  container.className = "lextext" + ( options.warning ? " lexwarning" : "" );
5363
5388
  container.style.display = "flex";
5364
- doAsync( () => {
5365
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5366
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5367
- } );
5389
+ this.root.appendChild( container );
5368
5390
 
5369
5391
  if( options.textClass )
5370
5392
  {
@@ -5443,13 +5465,13 @@ class TextInput extends Widget {
5443
5465
  wValue.innerHTML = ( icon + value ) || "";
5444
5466
  wValue.style.width = "100%";
5445
5467
  wValue.style.textAlign = options.float ?? "";
5468
+ wValue.className = "ellipsis-overflow";
5446
5469
  }
5447
5470
 
5448
5471
  Object.assign( wValue.style, options.style ?? {} );
5449
-
5450
5472
  container.appendChild( wValue );
5451
5473
 
5452
- this.root.appendChild( container );
5474
+ doAsync( this.onResize.bind( this ) );
5453
5475
  }
5454
5476
  }
5455
5477
 
@@ -5480,26 +5502,22 @@ class TextArea extends Widget {
5480
5502
  }
5481
5503
  };
5482
5504
 
5505
+ this.onResize = ( rect ) => {
5506
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5507
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5508
+ };
5509
+
5483
5510
  let container = document.createElement( "div" );
5484
5511
  container.className = "lextextarea";
5485
5512
  container.style.display = "flex";
5486
- doAsync( () => {
5487
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5488
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5489
- container.style.height = options.height;
5490
-
5491
- if( options.fitHeight )
5492
- {
5493
- // Update height depending on the content
5494
- wValue.style.height = wValue.scrollHeight + "px";
5495
- }
5496
- } );
5513
+ this.root.appendChild( container );
5497
5514
 
5498
5515
  let wValue = document.createElement( "textarea" );
5499
5516
  wValue.value = wValue.iValue = value || "";
5500
5517
  wValue.style.width = "100%";
5501
5518
  wValue.style.textAlign = options.float ?? "";
5502
5519
  Object.assign( wValue.style, options.style ?? {} );
5520
+ container.appendChild( wValue );
5503
5521
 
5504
5522
  if( options.disabled ?? false ) wValue.setAttribute( "disabled", true );
5505
5523
  if( options.placeholder ) wValue.setAttribute( "placeholder", options.placeholder );
@@ -5533,9 +5551,17 @@ class TextArea extends Widget {
5533
5551
  container.appendChild( icon );
5534
5552
  }
5535
5553
 
5536
- container.appendChild( wValue );
5554
+ doAsync( () => {
5555
+ container.style.height = options.height;
5537
5556
 
5538
- this.root.appendChild( container );
5557
+ if( options.fitHeight )
5558
+ {
5559
+ // Update height depending on the content
5560
+ wValue.style.height = wValue.scrollHeight + "px";
5561
+ }
5562
+
5563
+ this.onResize();
5564
+ }, 10 );
5539
5565
  }
5540
5566
  }
5541
5567
 
@@ -5562,9 +5588,15 @@ class Button extends Widget {
5562
5588
  ( options.img ? "<img src='" + options.img + "'>" : "<span>" + ( newValue || "" ) + "</span>" ) );
5563
5589
  };
5564
5590
 
5591
+ this.onResize = ( rect ) => {
5592
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5593
+ wValue.style.width = `calc( 100% - ${ realNameWidth }px)`;
5594
+ };
5595
+
5565
5596
  var wValue = document.createElement( 'button' );
5566
5597
  wValue.title = options.title ?? "";
5567
5598
  wValue.className = "lexbutton " + ( options.buttonClass ?? "" );
5599
+ this.root.appendChild( wValue );
5568
5600
 
5569
5601
  if( options.selected )
5570
5602
  {
@@ -5575,11 +5607,6 @@ class Button extends Widget {
5575
5607
  ( options.icon ? "<a class='" + options.icon + "'></a>" :
5576
5608
  ( options.img ? "<img src='" + options.img + "'>" : "<span>" + ( value || "" ) + "</span>" ) );
5577
5609
 
5578
- doAsync( () => {
5579
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5580
- wValue.style.width = `calc( 100% - ${ realNameWidth })`;
5581
- } );
5582
-
5583
5610
  if( options.disabled )
5584
5611
  {
5585
5612
  wValue.setAttribute( "disabled", true );
@@ -5599,15 +5626,7 @@ class Button extends Widget {
5599
5626
  this._trigger( new IEvent( name, value, e ), callback );
5600
5627
  });
5601
5628
 
5602
- this.root.appendChild( wValue );
5603
-
5604
- // Remove branch padding and
5605
- const useNameAsLabel = !( options.hideName ?? false ) && !( options.icon || options.img );
5606
- if( !useNameAsLabel )
5607
- {
5608
- wValue.className += " noname";
5609
- wValue.style.width = "100%";
5610
- }
5629
+ doAsync( this.onResize.bind( this ) );
5611
5630
  }
5612
5631
  }
5613
5632
 
@@ -5635,14 +5654,10 @@ class ComboButtons extends Widget {
5635
5654
  container.className += options.float;
5636
5655
  }
5637
5656
 
5638
- doAsync( () => {
5639
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5640
- container.style.width = `calc( 100% - ${ realNameWidth })`;
5641
- } );
5642
-
5643
5657
  let currentValue = [];
5644
5658
  let buttonsBox = document.createElement('div');
5645
5659
  buttonsBox.className = "lexcombobuttonsbox ";
5660
+ container.appendChild( buttonsBox );
5646
5661
 
5647
5662
  for( let b of values )
5648
5663
  {
@@ -5754,9 +5769,14 @@ class ComboButtons extends Widget {
5754
5769
  }
5755
5770
  };
5756
5771
 
5757
- container.appendChild( buttonsBox );
5772
+ this.onResize = ( rect ) => {
5773
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5774
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
5775
+ };
5758
5776
 
5759
5777
  this.root.appendChild( container );
5778
+
5779
+ doAsync( this.onResize.bind( this ) );
5760
5780
  }
5761
5781
  }
5762
5782
 
@@ -5778,6 +5798,7 @@ class Card extends Widget {
5778
5798
  let container = document.createElement('div');
5779
5799
  container.className = "lexcard";
5780
5800
  container.style.width = "100%";
5801
+ this.root.appendChild( container );
5781
5802
 
5782
5803
  if( options.img )
5783
5804
  {
@@ -5800,6 +5821,7 @@ class Card extends Widget {
5800
5821
 
5801
5822
  let cardNameDom = document.createElement('span');
5802
5823
  cardNameDom.innerText = name;
5824
+ container.appendChild( cardNameDom );
5803
5825
 
5804
5826
  if( options.link != undefined )
5805
5827
  {
@@ -5818,9 +5840,6 @@ class Card extends Widget {
5818
5840
  this._trigger( new IEvent( name, null, e ), options.callback );
5819
5841
  });
5820
5842
  }
5821
-
5822
- container.appendChild( cardNameDom );
5823
- this.root.appendChild( container );
5824
5843
  }
5825
5844
  }
5826
5845
 
@@ -5871,6 +5890,7 @@ class Form extends Widget {
5871
5890
  container.className = "lexformdata";
5872
5891
  container.style.width = "100%";
5873
5892
  container.formData = {};
5893
+ this.root.appendChild( container );
5874
5894
 
5875
5895
  for( let entry in data )
5876
5896
  {
@@ -5915,8 +5935,6 @@ class Form extends Widget {
5915
5935
  }, { buttonClass: "primary", width: "calc(100% - 10px)" } );
5916
5936
 
5917
5937
  container.appendChild( submitButton.root );
5918
-
5919
- this.root.appendChild( container );
5920
5938
  }
5921
5939
  }
5922
5940
 
@@ -5968,12 +5986,14 @@ class Select extends Widget {
5968
5986
  }
5969
5987
  };
5970
5988
 
5989
+ this.onResize = ( rect ) => {
5990
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
5991
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
5992
+ };
5993
+
5971
5994
  let container = document.createElement( "div" );
5972
5995
  container.className = "lexselect";
5973
- doAsync( () => {
5974
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
5975
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
5976
- } );
5996
+ this.root.appendChild( container );
5977
5997
 
5978
5998
  let wValue = document.createElement( 'div' );
5979
5999
  wValue.className = "lexselect lexoption";
@@ -6132,7 +6152,7 @@ class Select extends Widget {
6132
6152
  filterOptions.skipWidget = filterOptions.skipWidget ?? true;
6133
6153
  filterOptions.trigger = "input";
6134
6154
  filterOptions.icon = "fa-solid fa-magnifying-glass";
6135
- filterOptions.className = "lexfilter noname";
6155
+ filterOptions.className = "lexfilter";
6136
6156
 
6137
6157
  let filter = new TextInput(null, options.filterValue ?? "", ( v ) => {
6138
6158
  const filteredOptions = this._filterOptions( values, v );
@@ -6250,7 +6270,7 @@ class Select extends Widget {
6250
6270
 
6251
6271
  container.appendChild( listDialog );
6252
6272
 
6253
- this.root.appendChild( container );
6273
+ doAsync( this.onResize.bind( this ) );
6254
6274
  }
6255
6275
 
6256
6276
  _filterOptions( options, value ) {
@@ -6306,12 +6326,17 @@ class Curve extends Widget {
6306
6326
  }
6307
6327
  };
6308
6328
 
6329
+ this.onResize = ( rect ) => {
6330
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6331
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6332
+ flushCss( container );
6333
+ curveInstance.canvas.width = container.offsetWidth;
6334
+ curveInstance.redraw();
6335
+ };
6336
+
6309
6337
  var container = document.createElement( "div" );
6310
6338
  container.className = "lexcurve";
6311
- doAsync( () => {
6312
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6313
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6314
- } );
6339
+ this.root.appendChild( container );
6315
6340
 
6316
6341
  options.callback = (v, e) => {
6317
6342
  this._trigger( new IEvent( name, v, e ), callback );
@@ -6321,16 +6346,9 @@ class Curve extends Widget {
6321
6346
 
6322
6347
  let curveInstance = new CanvasCurve( values, options );
6323
6348
  container.appendChild( curveInstance.element );
6324
- this.root.appendChild( container );
6325
-
6326
- // Resize
6327
- this.onresize = curveInstance.redraw.bind( curveInstance );
6328
6349
  this.curveInstance = curveInstance;
6329
6350
 
6330
- doAsync(() => {
6331
- curveInstance.canvas.width = container.offsetWidth;
6332
- curveInstance.redraw();
6333
- });
6351
+ doAsync( this.onResize.bind( this ) );
6334
6352
  }
6335
6353
  }
6336
6354
 
@@ -6350,24 +6368,32 @@ class Dial extends Widget {
6350
6368
  super( Widget.DIAL, name, defaultValues, options );
6351
6369
 
6352
6370
  this.onGetValue = () => {
6353
- return JSON.parse( JSON.stringify( curveInstance.element.value ) );
6371
+ return JSON.parse( JSON.stringify( dialInstance.element.value ) );
6354
6372
  };
6355
6373
 
6356
6374
  this.onSetValue = ( newValue, skipCallback, event ) => {
6357
- curveInstance.element.value = JSON.parse( JSON.stringify( newValue ) );
6358
- curveInstance.redraw();
6375
+ dialInstance.element.value = JSON.parse( JSON.stringify( newValue ) );
6376
+ dialInstance.redraw();
6359
6377
  if( !skipCallback )
6360
6378
  {
6361
- this._trigger( new IEvent( name, curveInstance.element.value, event ), callback );
6379
+ this._trigger( new IEvent( name, dialInstance.element.value, event ), callback );
6362
6380
  }
6363
6381
  };
6364
6382
 
6383
+ this.onResize = ( rect ) => {
6384
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6385
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6386
+ flushCss( container );
6387
+ dialInstance.element.style.height = dialInstance.element.offsetWidth + "px";
6388
+ dialInstance.canvas.width = dialInstance.element.offsetWidth;
6389
+ container.style.width = dialInstance.element.offsetWidth + "px";
6390
+ dialInstance.canvas.height = dialInstance.canvas.width;
6391
+ dialInstance.redraw();
6392
+ };
6393
+
6365
6394
  var container = document.createElement( "div" );
6366
6395
  container.className = "lexcurve";
6367
- doAsync( () => {
6368
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6369
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6370
- } );
6396
+ this.root.appendChild( container );
6371
6397
 
6372
6398
  options.callback = ( v, e ) => {
6373
6399
  this._trigger( new IEvent( name, v, e ), callback );
@@ -6375,21 +6401,11 @@ class Dial extends Widget {
6375
6401
 
6376
6402
  options.name = name;
6377
6403
 
6378
- let curveInstance = new CanvasDial( this, values, options );
6379
- container.appendChild( curveInstance.element );
6380
- this.root.appendChild( container );
6381
-
6382
- // Resize
6383
- this.onresize = curveInstance.redraw.bind( curveInstance );
6384
- this.curveInstance = curveInstance;
6404
+ let dialInstance = new CanvasDial( this, values, options );
6405
+ container.appendChild( dialInstance.element );
6406
+ this.dialInstance = dialInstance;
6385
6407
 
6386
- doAsync(() => {
6387
- curveInstance.element.style.height = curveInstance.element.offsetWidth + "px";
6388
- curveInstance.canvas.width = curveInstance.element.offsetWidth;
6389
- container.style.width = curveInstance.element.offsetWidth + "px";
6390
- curveInstance.canvas.height = curveInstance.canvas.width;
6391
- curveInstance.redraw();
6392
- });
6408
+ doAsync( this.onResize.bind( this ) );
6393
6409
  }
6394
6410
  }
6395
6411
 
@@ -6412,25 +6428,27 @@ class Layers extends Widget {
6412
6428
 
6413
6429
  this.onSetValue = ( newValue, skipCallback, event ) => {
6414
6430
  value = newValue;
6415
- setLayers();
6431
+ this.setLayers( value );
6416
6432
  if( !skipCallback )
6417
6433
  {
6418
6434
  this._trigger( new IEvent(name, value, event), callback );
6419
6435
  }
6420
6436
  };
6421
6437
 
6438
+ this.onResize = ( rect ) => {
6439
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6440
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
6441
+ };
6442
+
6422
6443
  var container = document.createElement( "div" );
6423
6444
  container.className = "lexlayers";
6424
- doAsync( () => {
6425
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6426
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6427
- } );
6445
+ this.root.appendChild( container );
6428
6446
 
6429
- const setLayers = () => {
6447
+ this.setLayers = ( val ) => {
6430
6448
 
6431
6449
  container.innerHTML = "";
6432
6450
 
6433
- let binary = value.toString( 2 );
6451
+ let binary = val.toString( 2 );
6434
6452
  let nbits = binary.length;
6435
6453
 
6436
6454
  // fill zeros
@@ -6444,7 +6462,7 @@ class Layers extends Widget {
6444
6462
  let layer = document.createElement( "div" );
6445
6463
  layer.className = "lexlayer";
6446
6464
 
6447
- if( value != undefined )
6465
+ if( val != undefined )
6448
6466
  {
6449
6467
  const valueBit = binary[ 16 - bit - 1 ];
6450
6468
  if( valueBit != undefined && valueBit == '1' )
@@ -6461,15 +6479,15 @@ class Layers extends Widget {
6461
6479
  e.stopPropagation();
6462
6480
  e.stopImmediatePropagation();
6463
6481
  e.target.classList.toggle( "selected" );
6464
- const newValue = value ^ ( 1 << bit );
6482
+ const newValue = val ^ ( 1 << bit );
6465
6483
  this.set( newValue, false, e );
6466
6484
  } );
6467
6485
  }
6468
6486
  };
6469
6487
 
6470
- setLayers();
6488
+ this.setLayers( value );
6471
6489
 
6472
- this.root.appendChild( container );
6490
+ doAsync( this.onResize.bind( this ) );
6473
6491
  }
6474
6492
  }
6475
6493
 
@@ -6484,6 +6502,8 @@ class ItemArray extends Widget {
6484
6502
 
6485
6503
  constructor( name, values = [], callback, options = {} ) {
6486
6504
 
6505
+ options.nameWidth = "100%";
6506
+
6487
6507
  super( Widget.ARRAY, name, null, options );
6488
6508
 
6489
6509
  this.onGetValue = () => {
@@ -6499,18 +6519,14 @@ class ItemArray extends Widget {
6499
6519
  }
6500
6520
  };
6501
6521
 
6502
- this.root.style.flexWrap = "wrap";
6503
-
6504
6522
  // Add open array button
6505
6523
 
6506
6524
  const itemNameWidth = "4%";
6507
6525
 
6508
6526
  var container = document.createElement('div');
6509
6527
  container.className = "lexarray";
6510
- doAsync( () => {
6511
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6512
- container.style.width = `calc( 100% - ${ realNameWidth })`;
6513
- } );
6528
+ container.style.width = "100%";
6529
+ this.root.appendChild( container );
6514
6530
 
6515
6531
  const angleDown = `<a class='fa-solid fa-angle-down' style='float:right; margin-right: 3px;'></a>`;
6516
6532
 
@@ -6520,7 +6536,6 @@ class ItemArray extends Widget {
6520
6536
  const toggleButton = new Button(null, buttonName, () => {
6521
6537
  this.root.querySelector(".lexarrayitems").toggleAttribute('hidden');
6522
6538
  }, { buttonClass: 'array' });
6523
-
6524
6539
  container.appendChild( toggleButton.root );
6525
6540
 
6526
6541
  // Show elements
@@ -6528,8 +6543,6 @@ class ItemArray extends Widget {
6528
6543
  let arrayItems = document.createElement( "div" );
6529
6544
  arrayItems.className = "lexarrayitems";
6530
6545
  arrayItems.toggleAttribute( "hidden", true );
6531
-
6532
- this.root.appendChild( container );
6533
6546
  this.root.appendChild( arrayItems );
6534
6547
 
6535
6548
  this._updateItems = () => {
@@ -6546,10 +6559,6 @@ class ItemArray extends Widget {
6546
6559
  {
6547
6560
  const value = values[ i ];
6548
6561
  let baseclass = options.innerValues ? 'select' : value.constructor;
6549
-
6550
- // TODO
6551
- // this.sameLine( 2 );
6552
-
6553
6562
  let widget = null;
6554
6563
 
6555
6564
  switch( baseclass )
@@ -6578,13 +6587,13 @@ class ItemArray extends Widget {
6578
6587
 
6579
6588
  arrayItems.appendChild( widget.root );
6580
6589
 
6581
- widget = new Button( null, "<a class='lexicon fa-solid fa-trash'></a>", ( v, event) => {
6590
+ const removeWidget = new Button( null, "<a class='lexicon fa-solid fa-trash'></a>", ( v, event) => {
6582
6591
  values.splice( values.indexOf( value ), 1 );
6583
6592
  this._updateItems();
6584
6593
  this._trigger( new IEvent(name, values, event), callback );
6585
6594
  }, { title: "Remove item", className: 'micro'} );
6586
6595
 
6587
- arrayItems.appendChild( widget.root );
6596
+ widget.root.appendChild( removeWidget.root );
6588
6597
  }
6589
6598
 
6590
6599
  buttonName = "Add item";
@@ -6649,6 +6658,11 @@ class List extends Widget {
6649
6658
  }
6650
6659
  };
6651
6660
 
6661
+ this.onResize = ( rect ) => {
6662
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6663
+ listContainer.style.width = `calc( 100% - ${ realNameWidth }px)`;
6664
+ };
6665
+
6652
6666
  this._updateValues = ( newValues ) => {
6653
6667
 
6654
6668
  values = newValues;
@@ -6684,14 +6698,11 @@ class List extends Widget {
6684
6698
 
6685
6699
  let listContainer = document.createElement( 'div' );
6686
6700
  listContainer.className = "lexlist";
6687
- doAsync( () => {
6688
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6689
- listContainer.style.width = `calc( 100% - ${ realNameWidth })`;
6690
- } );
6701
+ this.root.appendChild( listContainer );
6691
6702
 
6692
6703
  this._updateValues( values );
6693
6704
 
6694
- this.root.appendChild( listContainer );
6705
+ doAsync( this.onResize.bind( this ) );
6695
6706
  }
6696
6707
  }
6697
6708
 
@@ -6717,23 +6728,25 @@ class Tags extends Widget {
6717
6728
 
6718
6729
  this.onSetValue = ( newValue, skipCallback, event ) => {
6719
6730
  value = [].concat( newValue );
6720
- _generateTags();
6731
+ this.generateTags( value );
6721
6732
  if( !skipCallback )
6722
6733
  {
6723
6734
  this._trigger( new IEvent( name, value, event ), callback );
6724
6735
  }
6725
6736
  };
6726
6737
 
6738
+ this.onResize = ( rect ) => {
6739
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6740
+ tagsContainer.style.width = `calc( 100% - ${ realNameWidth }px)`;
6741
+ };
6742
+
6727
6743
  // Show tags
6728
6744
 
6729
6745
  const tagsContainer = document.createElement('div');
6730
6746
  tagsContainer.className = "lextags";
6731
- doAsync( () => {
6732
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6733
- tagsContainer.style.width = `calc( 100% - ${ realNameWidth })`;
6734
- } );
6747
+ this.root.appendChild( tagsContainer );
6735
6748
 
6736
- const _generateTags = () => {
6749
+ this.generateTags = ( value ) => {
6737
6750
 
6738
6751
  tagsContainer.innerHTML = "";
6739
6752
 
@@ -6777,9 +6790,9 @@ class Tags extends Widget {
6777
6790
  tagInput.focus();
6778
6791
  }
6779
6792
 
6780
- _generateTags();
6793
+ this.generateTags( value );
6781
6794
 
6782
- this.root.appendChild( tagsContainer );
6795
+ doAsync( this.onResize.bind( this ) );
6783
6796
  }
6784
6797
  }
6785
6798
 
@@ -6823,35 +6836,33 @@ class Checkbox extends Widget {
6823
6836
  }
6824
6837
  };
6825
6838
 
6839
+ this.onResize = ( rect ) => {
6840
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6841
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6842
+ };
6843
+
6826
6844
  var container = document.createElement( "div" );
6827
6845
  container.className = "lexcheckboxcont";
6828
- doAsync( () => {
6829
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6830
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
6831
- } );
6846
+ this.root.appendChild( container );
6832
6847
 
6833
6848
  let checkbox = document.createElement( "input" );
6834
6849
  checkbox.type = "checkbox";
6835
6850
  checkbox.className = "lexcheckbox " + ( options.className ?? "" );
6836
6851
  checkbox.checked = value;
6837
6852
  checkbox.disabled = options.disabled ?? false;
6853
+ container.appendChild( checkbox );
6838
6854
 
6839
6855
  let valueName = document.createElement( "span" );
6840
6856
  valueName.className = "checkboxtext";
6841
6857
  valueName.innerHTML = options.label ?? "On";
6842
-
6843
- container.appendChild( checkbox );
6844
6858
  container.appendChild( valueName );
6845
6859
 
6846
6860
  checkbox.addEventListener( "change" , e => {
6847
6861
  this.set( checkbox.checked, false, e );
6848
6862
  });
6849
6863
 
6850
- this.root.appendChild( container );
6851
-
6852
6864
  if( options.suboptions )
6853
6865
  {
6854
- this.root.style.flexWrap = "wrap";
6855
6866
  let suboptions = document.createElement( "div" );
6856
6867
  suboptions.className = "lexcheckboxsubmenu";
6857
6868
  suboptions.toggleAttribute( "hidden", !checkbox.checked );
@@ -6863,6 +6874,8 @@ class Checkbox extends Widget {
6863
6874
 
6864
6875
  this.root.appendChild( suboptions );
6865
6876
  }
6877
+
6878
+ doAsync( this.onResize.bind( this ) );
6866
6879
  }
6867
6880
  }
6868
6881
 
@@ -6906,12 +6919,14 @@ class Toggle extends Widget {
6906
6919
  }
6907
6920
  };
6908
6921
 
6922
+ this.onResize = ( rect ) => {
6923
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
6924
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
6925
+ };
6926
+
6909
6927
  var container = document.createElement('div');
6910
6928
  container.className = "lextogglecont";
6911
- doAsync( () => {
6912
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
6913
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
6914
- } );
6929
+ this.root.appendChild( container );
6915
6930
 
6916
6931
  let toggle = document.createElement('input');
6917
6932
  toggle.type = "checkbox";
@@ -6919,23 +6934,19 @@ class Toggle extends Widget {
6919
6934
  toggle.checked = value;
6920
6935
  toggle.iValue = value;
6921
6936
  toggle.disabled = options.disabled ?? false;
6937
+ container.appendChild( toggle );
6922
6938
 
6923
6939
  let valueName = document.createElement( 'span' );
6924
6940
  valueName.className = "toggletext";
6925
6941
  valueName.innerHTML = options.label ?? "On";
6926
-
6927
- container.appendChild( toggle );
6928
6942
  container.appendChild( valueName );
6929
6943
 
6930
6944
  toggle.addEventListener( "change" , e => {
6931
6945
  this.set( toggle.checked, false, e );
6932
6946
  });
6933
6947
 
6934
- this.root.appendChild( container );
6935
-
6936
6948
  if( options.suboptions )
6937
6949
  {
6938
- this.root.style.flexWrap = "wrap";
6939
6950
  let suboptions = document.createElement('div');
6940
6951
  suboptions.className = "lextogglesubmenu";
6941
6952
  suboptions.toggleAttribute( 'hidden', !toggle.checked );
@@ -6947,6 +6958,8 @@ class Toggle extends Widget {
6947
6958
 
6948
6959
  this.root.appendChild( suboptions );
6949
6960
  }
6961
+
6962
+ doAsync( this.onResize.bind( this ) );
6950
6963
  }
6951
6964
  }
6952
6965
 
@@ -6991,6 +7004,7 @@ class RadioGroup extends Widget {
6991
7004
 
6992
7005
  var container = document.createElement( 'div' );
6993
7006
  container.className = "lexradiogroup " + ( options.className ?? "" );
7007
+ this.root.appendChild( container );
6994
7008
 
6995
7009
  let labelSpan = document.createElement( 'span' );
6996
7010
  labelSpan.innerHTML = label;
@@ -7025,8 +7039,6 @@ class RadioGroup extends Widget {
7025
7039
  currentIndex = options.selected;
7026
7040
  this.set( currentIndex, true );
7027
7041
  }
7028
-
7029
- this.root.appendChild( container );
7030
7042
  }
7031
7043
  }
7032
7044
 
@@ -7070,12 +7082,14 @@ class ColorInput extends Widget {
7070
7082
  }
7071
7083
  };
7072
7084
 
7085
+ this.onResize = ( rect ) => {
7086
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7087
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7088
+ };
7089
+
7073
7090
  var container = document.createElement( 'span' );
7074
7091
  container.className = "lexcolor";
7075
- doAsync( () => {
7076
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7077
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7078
- } );
7092
+ this.root.appendChild( container );
7079
7093
 
7080
7094
  let color = document.createElement( 'input' );
7081
7095
  color.style.width = "32px";
@@ -7084,6 +7098,7 @@ class ColorInput extends Widget {
7084
7098
  color.id = "color" + simple_guidGenerator();
7085
7099
  color.useRGB = options.useRGB ?? false;
7086
7100
  color.value = color.iValue = value;
7101
+ container.appendChild( color );
7087
7102
 
7088
7103
  if( options.disabled )
7089
7104
  {
@@ -7094,17 +7109,14 @@ class ColorInput extends Widget {
7094
7109
  this.set( e.target.value, false, e );
7095
7110
  }, false );
7096
7111
 
7097
- container.appendChild( color );
7098
-
7099
7112
  const textWidget = new TextInput( null, color.value, v => {
7100
7113
  this.set( v );
7101
7114
  }, { width: "calc( 100% - 32px )"});
7102
7115
 
7103
7116
  textWidget.root.style.marginLeft = "4px";
7104
-
7105
7117
  container.appendChild( textWidget.root );
7106
7118
 
7107
- this.root.appendChild( container );
7119
+ doAsync( this.onResize.bind( this ) );
7108
7120
  }
7109
7121
  }
7110
7122
 
@@ -7140,12 +7152,14 @@ class RangeInput extends Widget {
7140
7152
  }
7141
7153
  };
7142
7154
 
7143
- var container = document.createElement( 'div' );
7155
+ this.onResize = ( rect ) => {
7156
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7157
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
7158
+ };
7159
+
7160
+ const container = document.createElement( 'div' );
7144
7161
  container.className = "lexrange";
7145
- doAsync( () => {
7146
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7147
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
7148
- } );
7162
+ this.root.appendChild( container );
7149
7163
 
7150
7164
  let slider = document.createElement( 'input' );
7151
7165
  slider.className = "lexrangeslider " + ( options.className ?? "" );
@@ -7155,6 +7169,7 @@ class RangeInput extends Widget {
7155
7169
  slider.step = options.step ?? 1;
7156
7170
  slider.type = "range";
7157
7171
  slider.disabled = options.disabled ?? false;
7172
+ container.appendChild( slider );
7158
7173
 
7159
7174
  if( options.left ?? false )
7160
7175
  {
@@ -7197,9 +7212,7 @@ class RangeInput extends Widget {
7197
7212
  value = clamp( value, +slider.min, +slider.max );
7198
7213
  }
7199
7214
 
7200
- container.appendChild( slider );
7201
-
7202
- this.root.appendChild( container );
7215
+ doAsync( this.onResize.bind( this ) );
7203
7216
  }
7204
7217
  }
7205
7218
 
@@ -7247,15 +7260,18 @@ class NumberInput extends Widget {
7247
7260
  }
7248
7261
  };
7249
7262
 
7263
+ this.onResize = ( rect ) => {
7264
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7265
+ container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth }px)`;
7266
+ };
7267
+
7250
7268
  var container = document.createElement( 'div' );
7251
7269
  container.className = "lexnumber";
7252
- doAsync( () => {
7253
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7254
- container.style.width = options.inputWidth ?? `calc( 100% - ${ realNameWidth })`;
7255
- } );
7270
+ this.root.appendChild( container );
7256
7271
 
7257
7272
  let box = document.createElement( 'div' );
7258
7273
  box.className = "numberbox";
7274
+ container.appendChild( box );
7259
7275
 
7260
7276
  let vecinput = document.createElement( 'input' );
7261
7277
  vecinput.id = "number_" + simple_guidGenerator();
@@ -7429,9 +7445,7 @@ class NumberInput extends Widget {
7429
7445
 
7430
7446
  vecinput.addEventListener( "mousedown", innerMouseDown );
7431
7447
 
7432
- container.appendChild( box );
7433
-
7434
- this.root.appendChild( container );
7448
+ doAsync( this.onResize.bind( this ) );
7435
7449
  }
7436
7450
  }
7437
7451
 
@@ -7483,14 +7497,16 @@ class Vector extends Widget {
7483
7497
  }
7484
7498
  };
7485
7499
 
7500
+ this.onResize = ( rect ) => {
7501
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7502
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7503
+ };
7504
+
7486
7505
  const vectorInputs = [];
7487
7506
 
7488
7507
  var container = document.createElement( 'div' );
7489
7508
  container.className = "lexvector";
7490
- doAsync( () => {
7491
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7492
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7493
- } );
7509
+ this.root.appendChild( container );
7494
7510
 
7495
7511
  const that = this;
7496
7512
 
@@ -7693,7 +7709,7 @@ class Vector extends Widget {
7693
7709
  }
7694
7710
  }, false );
7695
7711
 
7696
- this.root.appendChild( container );
7712
+ doAsync( this.onResize.bind( this ) );
7697
7713
  }
7698
7714
  }
7699
7715
 
@@ -7823,24 +7839,28 @@ class Pad extends Widget {
7823
7839
  }
7824
7840
  };
7825
7841
 
7842
+ this.onResize = ( rect ) => {
7843
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7844
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7845
+ };
7846
+
7826
7847
  var container = document.createElement( 'div' );
7827
7848
  container.className = "lexpad";
7828
- doAsync( () => {
7829
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7830
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7831
- } );
7849
+ this.root.appendChild( container );
7832
7850
 
7833
7851
  let pad = document.createElement('div');
7834
7852
  pad.id = "lexpad-" + name;
7835
7853
  pad.className = "lexinnerpad";
7836
7854
  pad.style.width = options.padSize ?? '96px';
7837
7855
  pad.style.height = options.padSize ?? '96px';
7856
+ container.appendChild( pad );
7838
7857
 
7839
7858
  let thumb = document.createElement('div');
7840
7859
  thumb.className = "lexpadthumb";
7841
7860
  thumb.value = new LX.vec2( value[ 0 ], value[ 1 ] );
7842
7861
  thumb.min = options.min ?? 0;
7843
7862
  thumb.max = options.max ?? 1;
7863
+ pad.appendChild( thumb );
7844
7864
 
7845
7865
  let _updateValue = v => {
7846
7866
  const [ w, h ] = [ pad.offsetWidth, pad.offsetHeight ];
@@ -7848,14 +7868,6 @@ class Pad extends Widget {
7848
7868
  thumb.style.transform = `translate(calc( ${ w * value0to1.x }px - 50% ), calc( ${ h * value0to1.y }px - 50%)`;
7849
7869
  }
7850
7870
 
7851
- doAsync( () => {
7852
- _updateValue( thumb.value )
7853
- } );
7854
-
7855
- pad.appendChild( thumb );
7856
- container.appendChild( pad );
7857
- this.root.appendChild( container );
7858
-
7859
7871
  pad.addEventListener( "mousedown", innerMouseDown );
7860
7872
 
7861
7873
  let that = this;
@@ -7874,6 +7886,7 @@ class Pad extends Widget {
7874
7886
  document.body.classList.add( 'noevents' );
7875
7887
  e.stopImmediatePropagation();
7876
7888
  e.stopPropagation();
7889
+ thumb.classList.add( "active" );
7877
7890
 
7878
7891
  if( options.onPress )
7879
7892
  {
@@ -7905,12 +7918,18 @@ class Pad extends Widget {
7905
7918
  doc.removeEventListener( 'mouseup', innerMouseUp );
7906
7919
  document.body.classList.remove( 'nocursor' );
7907
7920
  document.body.classList.remove( 'noevents' );
7921
+ thumb.classList.remove( "active" );
7908
7922
 
7909
7923
  if( options.onRelease )
7910
7924
  {
7911
7925
  options.onRelease.bind( thumb )( e, thumb );
7912
7926
  }
7913
7927
  }
7928
+
7929
+ doAsync( () => {
7930
+ this.onResize();
7931
+ _updateValue( thumb.value )
7932
+ } );
7914
7933
  }
7915
7934
  }
7916
7935
 
@@ -7940,12 +7959,14 @@ class Progress extends Widget {
7940
7959
  }
7941
7960
  };
7942
7961
 
7943
- var container = document.createElement('div');
7962
+ this.onResize = ( rect ) => {
7963
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
7964
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
7965
+ };
7966
+
7967
+ const container = document.createElement('div');
7944
7968
  container.className = "lexprogress";
7945
- doAsync( () => {
7946
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
7947
- container.style.width = `calc( 100% - ${ realNameWidth })`;
7948
- } );
7969
+ this.root.appendChild( container );
7949
7970
 
7950
7971
  // add slider (0-1 if not specified different )
7951
7972
 
@@ -7959,6 +7980,7 @@ class Progress extends Widget {
7959
7980
  progress.high = options.high ?? progress.high;
7960
7981
  progress.optimum = options.optimum ?? progress.optimum;
7961
7982
  progress.value = value;
7983
+ container.appendChild( progress );
7962
7984
 
7963
7985
  const _updateColor = () => {
7964
7986
 
@@ -7976,9 +7998,6 @@ class Progress extends Widget {
7976
7998
  progress.style.background = `color-mix(in srgb, ${backgroundColor} 20%, transparent)`;
7977
7999
  };
7978
8000
 
7979
- container.appendChild( progress );
7980
- this.root.appendChild( container );
7981
-
7982
8001
  if( options.showValue )
7983
8002
  {
7984
8003
  if( document.getElementById('progressvalue-' + name ) )
@@ -8045,6 +8064,8 @@ class Progress extends Widget {
8045
8064
  }
8046
8065
 
8047
8066
  _updateColor();
8067
+
8068
+ doAsync( this.onResize.bind( this ) );
8048
8069
  }
8049
8070
  }
8050
8071
 
@@ -8065,15 +8086,17 @@ class FileInput extends Widget {
8065
8086
  let type = options.type ?? 'text';
8066
8087
  let read = options.read ?? true;
8067
8088
 
8089
+ this.onResize = ( rect ) => {
8090
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
8091
+ input.style.width = `calc( 100% - ${ realNameWidth }px)`;
8092
+ };
8093
+
8068
8094
  // Create hidden input
8069
8095
  let input = document.createElement( 'input' );
8070
8096
  input.className = "lexfileinput";
8071
8097
  input.type = 'file';
8072
8098
  input.disabled = options.disabled ?? false;
8073
- doAsync( () => {
8074
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
8075
- input.style.width = `calc( 100% - ${ realNameWidth } - 10%)`;
8076
- } );
8099
+ this.root.appendChild( input );
8077
8100
 
8078
8101
  if( options.placeholder )
8079
8102
  {
@@ -8106,8 +8129,6 @@ class FileInput extends Widget {
8106
8129
  callback( null );
8107
8130
  });
8108
8131
 
8109
- this.root.appendChild( input );
8110
-
8111
8132
  if( local )
8112
8133
  {
8113
8134
  let settingsDialog = null;
@@ -8128,6 +8149,8 @@ class FileInput extends Widget {
8128
8149
 
8129
8150
  this.root.appendChild( settingButton.root );
8130
8151
  }
8152
+
8153
+ doAsync( this.onResize.bind( this ) );
8131
8154
  }
8132
8155
  }
8133
8156
 
@@ -8368,7 +8391,6 @@ class Counter extends Widget {
8368
8391
  if( e.shiftKey ) mult *= 10;
8369
8392
  this.set( counterText.count + mult, false, e );
8370
8393
  }, { className: "micro", skipInlineCount: true, title: "Plus" });
8371
-
8372
8394
  container.appendChild( addButton.root );
8373
8395
  }
8374
8396
  }
@@ -8391,12 +8413,14 @@ class Table extends Widget {
8391
8413
 
8392
8414
  super( Widget.TABLE, name, null, options );
8393
8415
 
8416
+ this.onResize = ( rect ) => {
8417
+ const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 );
8418
+ container.style.width = `calc( 100% - ${ realNameWidth }px)`;
8419
+ };
8420
+
8394
8421
  const container = document.createElement('div');
8395
8422
  container.className = "lextable";
8396
- doAsync( () => {
8397
- const realNameWidth = ( this.root.domName?.offsetWidth ?? 0 ) + "px";
8398
- container.style.width = `calc( 100% - ${ realNameWidth })`;
8399
- } );
8423
+ this.root.appendChild( container );
8400
8424
 
8401
8425
  this.centered = options.centered ?? false;
8402
8426
  if( this.centered === true )
@@ -8404,13 +8428,16 @@ class Table extends Widget {
8404
8428
  container.classList.add( "centered" );
8405
8429
  }
8406
8430
 
8407
- const table = document.createElement( 'table' );
8408
- container.appendChild( table );
8431
+ this.filter = options.filter ?? false;
8432
+ this.toggleColumns = options.toggleColumns ?? false;
8433
+ this.customFilters = options.customFilters ?? false;
8434
+ this.activeCustomFilters = {};
8409
8435
 
8410
8436
  data.head = data.head ?? [];
8411
8437
  data.body = data.body ?? [];
8412
- data.colVisibilityMap = { };
8413
8438
  data.checkMap = { };
8439
+ data.colVisibilityMap = { };
8440
+ data.head.forEach( (col, index) => { data.colVisibilityMap[ index ] = true; })
8414
8441
 
8415
8442
  const compareFn = ( idx, order, a, b) => {
8416
8443
  if (a[idx] < b[idx]) return -order;
@@ -8420,14 +8447,105 @@ class Table extends Widget {
8420
8447
 
8421
8448
  const sortFn = ( idx, sign ) => {
8422
8449
  data.body = data.body.sort( compareFn.bind( this, idx, sign ) );
8423
- this.refreshTable();
8450
+ this.refresh();
8451
+ }
8452
+
8453
+ // Append header
8454
+ if( this.filter || this.customFilters || this.toggleColumns )
8455
+ {
8456
+ const headerContainer = LX.makeContainer( [ "100%", "auto" ] );
8457
+
8458
+ if( this.filter )
8459
+ {
8460
+ const filterOptions = LX.deepCopy( options );
8461
+ filterOptions.placeholder = `Filter ${ this.filter }...`;
8462
+ filterOptions.skipWidget = true;
8463
+ filterOptions.trigger = "input";
8464
+ filterOptions.textClass = "outline";
8465
+
8466
+ let filter = new TextInput(null, "", ( v ) => {
8467
+ this._currentFilter = v;
8468
+ this.refresh();
8469
+ }, filterOptions );
8470
+
8471
+ headerContainer.appendChild( filter.root );
8472
+ }
8473
+
8474
+ if( this.customFilters )
8475
+ {
8476
+ const icon = LX.makeIcon( "circle-plus", null, "sm" );
8477
+
8478
+ for( let f of this.customFilters )
8479
+ {
8480
+ const customFilterBtn = new Button(null, icon.innerHTML + f.name, ( v ) => {
8481
+
8482
+ const menuOptions = f.options.map( ( colName, idx ) => {
8483
+ const item = {
8484
+ name: colName,
8485
+ checked: !!this.activeCustomFilters[ colName ],
8486
+ callback: (key, dom, v) => {
8487
+ if( v ) { this.activeCustomFilters[ key ] = f.name; }
8488
+ else {
8489
+ delete this.activeCustomFilters[ key ];
8490
+ }
8491
+ this.refresh();
8492
+ }
8493
+ }
8494
+ return item;
8495
+ } );
8496
+ new DropdownMenu( customFilterBtn.root, menuOptions, { side: "bottom", align: "start" });
8497
+ }, { buttonClass: "dashed" } );
8498
+ headerContainer.appendChild( customFilterBtn.root );
8499
+ }
8500
+
8501
+ // const resetIcon = LX.makeIcon( "xmark", null, "sm" );
8502
+ this._resetCustomFiltersBtn = new Button(null, "resetButton", ( v ) => {
8503
+ this.activeCustomFilters = {};
8504
+ this.refresh();
8505
+ this._resetCustomFiltersBtn.root.classList.add( "hidden" );
8506
+ }, { title: "Reset filters", icon: "fa fa-xmark" } );
8507
+ headerContainer.appendChild( this._resetCustomFiltersBtn.root );
8508
+ this._resetCustomFiltersBtn.root.classList.add( "hidden" );
8509
+ }
8510
+
8511
+ if( this.toggleColumns )
8512
+ {
8513
+ const icon = LX.makeIcon( "sliders" );
8514
+ const toggleColumnsBtn = new Button( "toggleColumnsBtn", icon.innerHTML + "View", (value, e) => {
8515
+ const menuOptions = data.head.map( ( colName, idx ) => {
8516
+ const item = {
8517
+ name: colName,
8518
+ icon: "check",
8519
+ callback: () => {
8520
+ data.colVisibilityMap[ idx ] = !data.colVisibilityMap[ idx ];
8521
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8522
+ cells.forEach(cell => {
8523
+ cell.style.display = (cell.style.display === "none") ? "" : "none";
8524
+ });
8525
+ }
8526
+ }
8527
+ if( !data.colVisibilityMap[ idx ] ) delete item.icon;
8528
+ return item;
8529
+ } );
8530
+ new DropdownMenu( e.target, menuOptions, { side: "bottom", align: "end" });
8531
+ }, { hideName: true } );
8532
+ headerContainer.appendChild( toggleColumnsBtn.root );
8533
+ toggleColumnsBtn.root.style.marginLeft = "auto";
8534
+ }
8535
+
8536
+ container.appendChild( headerContainer );
8424
8537
  }
8425
8538
 
8426
- this.refreshTable = () => {
8539
+ const table = document.createElement( 'table' );
8540
+ container.appendChild( table );
8541
+
8542
+ this.refresh = () => {
8543
+
8544
+ this._currentFilter = this._currentFilter ?? "";
8427
8545
 
8428
8546
  table.innerHTML = "";
8429
8547
 
8430
- let rowOffsetCount = 0;
8548
+ this.rowOffsetCount = 0;
8431
8549
 
8432
8550
  // Head
8433
8551
  {
@@ -8442,7 +8560,7 @@ class Table extends Widget {
8442
8560
  const th = document.createElement( 'th' );
8443
8561
  th.style.width = "0px";
8444
8562
  hrow.appendChild( th );
8445
- rowOffsetCount++;
8563
+ this.rowOffsetCount++;
8446
8564
  }
8447
8565
 
8448
8566
  if( options.selectable )
@@ -8467,14 +8585,15 @@ class Table extends Widget {
8467
8585
  }
8468
8586
  });
8469
8587
 
8470
- rowOffsetCount++;
8588
+ this.rowOffsetCount++;
8471
8589
  hrow.appendChild( th );
8472
8590
  }
8473
8591
 
8474
8592
  for( const headData of data.head )
8475
8593
  {
8476
8594
  const th = document.createElement( 'th' );
8477
- th.innerHTML = `${ headData } <a class="fa-solid fa-sort"></a>`;
8595
+ th.innerHTML = `<span>${ headData }</span>`;
8596
+ th.querySelector( "span" ).appendChild( LX.makeIcon( "menu-arrows", null, "sm" ) );
8478
8597
 
8479
8598
  const idx = data.head.indexOf( headData );
8480
8599
  if( this.centered && this.centered.indexOf( idx ) > -1 )
@@ -8482,19 +8601,29 @@ class Table extends Widget {
8482
8601
  th.classList.add( "centered" );
8483
8602
  }
8484
8603
 
8485
- th.addEventListener( 'click', event => {
8486
- new LX.DropdownMenu( event.target, [
8487
- { name: "Asc", icon: "up", callback: sortFn.bind( this, idx, 1 ) },
8488
- { name: "Desc", icon: "down", callback: sortFn.bind( this, idx, -1 ) },
8604
+ const menuOptions = [
8605
+ { name: "Asc", icon: "up", callback: sortFn.bind( this, idx, 1 ) },
8606
+ { name: "Desc", icon: "down", callback: sortFn.bind( this, idx, -1 ) }
8607
+ ];
8608
+
8609
+ if( this.toggleColumns )
8610
+ {
8611
+ menuOptions.push(
8489
8612
  null,
8490
- { name: "Hide", icon: "eye-slash", callback: () => {
8491
- data.colVisibilityMap[ idx ] = 0;
8492
- const cells = table.querySelectorAll(`tr > *:nth-child(${idx + rowOffsetCount + 1})`);
8493
- cells.forEach(cell => {
8494
- cell.style.display = (cell.style.display === "none") ? "" : "none";
8495
- });
8496
- } }
8497
- ], { side: "bottom", align: "start" });
8613
+ {
8614
+ name: "Hide", icon: "eye-slash", callback: () => {
8615
+ data.colVisibilityMap[ idx ] = false;
8616
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8617
+ cells.forEach(cell => {
8618
+ cell.style.display = (cell.style.display === "none") ? "" : "none";
8619
+ });
8620
+ }
8621
+ }
8622
+ );
8623
+ }
8624
+
8625
+ th.addEventListener( 'click', event => {
8626
+ new DropdownMenu( event.target, menuOptions, { side: "bottom", align: "start" });
8498
8627
  });
8499
8628
 
8500
8629
  hrow.appendChild( th );
@@ -8532,15 +8661,23 @@ class Table extends Widget {
8532
8661
  v.style.transition = `none`;
8533
8662
  } );
8534
8663
  flushCss( fromRow );
8535
- rIdx = null;
8536
8664
 
8537
8665
  if( movePending )
8538
8666
  {
8667
+ // Modify inner data first
8668
+ const fromIdx = rIdx - 1;
8669
+ const targetIdx = movePending[ 1 ] - 1;
8670
+ var b = data.body[fromIdx];
8671
+ data.body[fromIdx] = data.body[targetIdx];
8672
+ data.body[targetIdx] = b;
8673
+
8539
8674
  const parent = movePending[ 0 ].parentNode;
8540
8675
  parent.insertChildAtIndex( movePending[ 0 ], movePending[ 1 ] );
8541
8676
  movePending = null;
8542
8677
  }
8543
8678
 
8679
+ rIdx = null;
8680
+
8544
8681
  doAsync( () => {
8545
8682
  Array.from( table.rows ).forEach( v => {
8546
8683
  v.style.transition = `transform 0.2s ease-in`;
@@ -8556,10 +8693,47 @@ class Table extends Widget {
8556
8693
  fromRow.style.transform = `translateY(${fromRow.dY}px)`;
8557
8694
  };
8558
8695
 
8559
-
8560
8696
  for( let r = 0; r < data.body.length; ++r )
8561
8697
  {
8562
8698
  const bodyData = data.body[ r ];
8699
+
8700
+ if( this.filter )
8701
+ {
8702
+ const filterColIndex = data.head.indexOf( this.filter );
8703
+ if( filterColIndex > -1 )
8704
+ {
8705
+ if( !bodyData[ filterColIndex ].toLowerCase().includes( this._currentFilter.toLowerCase() ) )
8706
+ {
8707
+ continue;
8708
+ }
8709
+ }
8710
+ }
8711
+
8712
+ if( Object.keys( this.activeCustomFilters ).length )
8713
+ {
8714
+ let acfMap = {};
8715
+
8716
+ this._resetCustomFiltersBtn.root.classList.remove( "hidden" );
8717
+
8718
+ for( let acfValue in this.activeCustomFilters )
8719
+ {
8720
+ const acfName = this.activeCustomFilters[ acfValue ];
8721
+ acfMap[ acfName ] = acfMap[ acfName ] ?? false;
8722
+
8723
+ const filterColIndex = data.head.indexOf( acfName );
8724
+ if( filterColIndex > -1 )
8725
+ {
8726
+ acfMap[ acfName ] |= ( bodyData[ filterColIndex ] === acfValue );
8727
+ }
8728
+ }
8729
+
8730
+ const show = Object.values( acfMap ).reduce( ( e, acc ) => acc *= e );
8731
+ if( !show )
8732
+ {
8733
+ continue;
8734
+ }
8735
+ }
8736
+
8563
8737
  const row = document.createElement( 'tr' );
8564
8738
  const rowId = LX.getSupportedDOMName( bodyData.join( '-' ) );
8565
8739
  row.setAttribute( "rowId", rowId.substr(0, 16) );
@@ -8670,14 +8844,15 @@ class Table extends Widget {
8670
8844
  {
8671
8845
  button = LX.makeIcon( "more-horizontal", "Menu" );
8672
8846
  button.addEventListener( 'click', function( event ) {
8673
- addContextMenu( null, event, c => {
8674
- if( options.onMenuAction )
8675
- {
8676
- options.onMenuAction( c );
8677
- return;
8678
- }
8679
- console.warn( "Using <Menu action> without action callbacks." );
8680
- } );
8847
+ if( !options.onMenuAction )
8848
+ {
8849
+ return;
8850
+ }
8851
+
8852
+ const menuOptions = options.onMenuAction( r, data );
8853
+ console.assert( menuOptions.length, "Add items to the Menu Action Dropdown!" );
8854
+
8855
+ new DropdownMenu( event.target, menuOptions, { side: "bottom", align: "end" });
8681
8856
  });
8682
8857
  }
8683
8858
  else // custom actions
@@ -8691,7 +8866,7 @@ class Table extends Widget {
8691
8866
  const mustRefresh = action.callback( bodyData, table, e );
8692
8867
  if( mustRefresh )
8693
8868
  {
8694
- this.refreshTable();
8869
+ this.refresh();
8695
8870
  }
8696
8871
  });
8697
8872
  }
@@ -8713,7 +8888,7 @@ class Table extends Widget {
8713
8888
  const idx = parseInt( v );
8714
8889
  if( !data.colVisibilityMap[ idx ] )
8715
8890
  {
8716
- const cells = table.querySelectorAll(`tr > *:nth-child(${idx + rowOffsetCount + 1})`);
8891
+ const cells = table.querySelectorAll(`tr > *:nth-child(${idx + this.rowOffsetCount + 1})`);
8717
8892
  cells.forEach(cell => {
8718
8893
  cell.style.display = (cell.style.display === "none") ? "" : "none";
8719
8894
  });
@@ -8721,9 +8896,9 @@ class Table extends Widget {
8721
8896
  }
8722
8897
  }
8723
8898
 
8724
- this.refreshTable();
8899
+ this.refresh();
8725
8900
 
8726
- this.root.appendChild( container );
8901
+ doAsync( this.onResize.bind( this ) );
8727
8902
  }
8728
8903
  }
8729
8904
 
@@ -9096,7 +9271,7 @@ class Panel {
9096
9271
 
9097
9272
  let widget = new TextInput( null, null, null, options )
9098
9273
  const element = widget.root;
9099
- element.className += " lexfilter noname";
9274
+ element.className += " lexfilter";
9100
9275
 
9101
9276
  let input = document.createElement('input');
9102
9277
  input.className = 'lexinput-filter';
@@ -9109,7 +9284,7 @@ class Panel {
9109
9284
  element.appendChild( searchIcon );
9110
9285
  element.appendChild( input );
9111
9286
 
9112
- input.addEventListener("input", (e) => {
9287
+ input.addEventListener("input", e => {
9113
9288
  if( options.callback )
9114
9289
  {
9115
9290
  options.callback( input.value, e );
@@ -10047,7 +10222,7 @@ class Branch {
10047
10222
  var size = this.grabber.style.marginLeft;
10048
10223
 
10049
10224
  // Update sizes of widgets inside
10050
- for( var i = 0; i < this.widgets.length; i++ )
10225
+ for( let i = 0; i < this.widgets.length; i++ )
10051
10226
  {
10052
10227
  let widget = this.widgets[ i ];
10053
10228
  const element = widget.root;
@@ -10057,26 +10232,21 @@ class Branch {
10057
10232
  continue;
10058
10233
  }
10059
10234
 
10060
- var name = element.children[ 0 ];
10061
- var value = element.children[ 1 ];
10235
+ let name = element.children[ 0 ];
10236
+ let value = element.children[ 1 ];
10062
10237
 
10063
10238
  name.style.width = size;
10064
- let padding = "0px";
10239
+
10065
10240
  switch( widget.type )
10066
10241
  {
10067
- case Widget.FILE:
10068
- padding = "10%";
10069
- break;
10242
+ case Widget.CUSTOM:
10243
+ case Widget.ARRAY:
10244
+ continue;
10070
10245
  };
10071
10246
 
10072
- value.style.width = "-moz-calc( 100% - " + size + " - " + padding + " )";
10073
- value.style.width = "-webkit-calc( 100% - " + size + " - " + padding + " )";
10074
- value.style.width = "calc( 100% - " + size + " - " + padding + " )";
10075
-
10076
- if( widget.onresize )
10077
- {
10078
- widget.onresize();
10079
- }
10247
+ value.style.width = "-moz-calc( 100% - " + size + " )";
10248
+ value.style.width = "-webkit-calc( 100% - " + size + " )";
10249
+ value.style.width = "calc( 100% - " + size + " )";
10080
10250
  }
10081
10251
  }
10082
10252
  };
@@ -10204,7 +10374,7 @@ class Dialog {
10204
10374
  draggable = options.draggable ?? true,
10205
10375
  modal = options.modal ?? false;
10206
10376
 
10207
- var root = document.createElement('dialog');
10377
+ let root = document.createElement('dialog');
10208
10378
  root.className = "lexdialog " + (options.className ?? "");
10209
10379
  root.id = options.id ?? "dialog" + Dialog._last_id++;
10210
10380
  LX.root.appendChild( root );
@@ -10215,7 +10385,7 @@ class Dialog {
10215
10385
 
10216
10386
  let that = this;
10217
10387
 
10218
- var titleDiv = document.createElement('div');
10388
+ const titleDiv = document.createElement('div');
10219
10389
 
10220
10390
  if( title )
10221
10391
  {
@@ -10280,7 +10450,7 @@ class Dialog {
10280
10450
  }, { icon: "fa-regular fa-window-restore" });
10281
10451
  };
10282
10452
 
10283
- root.appendChild(titleDiv);
10453
+ root.appendChild( titleDiv );
10284
10454
  }
10285
10455
 
10286
10456
  if( options.closable ?? true )
@@ -10479,7 +10649,7 @@ class PocketDialog extends Dialog {
10479
10649
 
10480
10650
  if( float )
10481
10651
  {
10482
- for( var i = 0; i < float.length; i++ )
10652
+ for( let i = 0; i < float.length; i++ )
10483
10653
  {
10484
10654
  const t = float[i];
10485
10655
  switch( t )
@@ -10612,14 +10782,14 @@ class ContextMenu {
10612
10782
  contextmenu.className = "lexcontextmenu";
10613
10783
  c.appendChild( contextmenu );
10614
10784
 
10615
- for( var i = 0; i < o[k].length; ++i )
10785
+ for( let i = 0; i < o[k].length; ++i )
10616
10786
  {
10617
10787
  const subitem = o[ k ][ i ];
10618
10788
  const subkey = Object.keys( subitem )[ 0 ];
10619
10789
  this._createEntry(subitem, subkey, contextmenu, d);
10620
10790
  }
10621
10791
 
10622
- var rect = c.getBoundingClientRect();
10792
+ const rect = c.getBoundingClientRect();
10623
10793
  contextmenu.style.left = rect.width + "px";
10624
10794
  contextmenu.style.marginTop = 3.5 - c.offsetHeight + "px";
10625
10795
 
@@ -10772,10 +10942,10 @@ class ContextMenu {
10772
10942
  _item[ key ].unshift( parent );
10773
10943
  }
10774
10944
 
10775
- for( var child of _item[ key ] )
10945
+ for( let child of _item[ key ] )
10776
10946
  {
10777
10947
  let k = Object.keys( child )[ 0 ];
10778
- for( var i = 0; i < child[ k ].length; ++i )
10948
+ for( let i = 0; i < child[ k ].length; ++i )
10779
10949
  {
10780
10950
  setParent( child );
10781
10951
  }
@@ -10816,7 +10986,7 @@ LX.ContextMenu = ContextMenu;
10816
10986
 
10817
10987
  function addContextMenu( title, event, callback, options )
10818
10988
  {
10819
- var menu = new ContextMenu( event, title, options );
10989
+ const menu = new ContextMenu( event, title, options );
10820
10990
  LX.root.appendChild( menu.root );
10821
10991
 
10822
10992
  if( callback )
@@ -10847,7 +11017,8 @@ class CanvasCurve {
10847
11017
  element.style.minHeight = "20px";
10848
11018
 
10849
11019
  element.bgcolor = options.bgColor || LX.getThemeColor( "global-intense-background" );
10850
- element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected-light" );
11020
+ element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected" );
11021
+ element.activepointscolor = options.activePointsColor || LX.getThemeColor( "global-selected-light" );
10851
11022
  element.linecolor = options.lineColor || "#555";
10852
11023
  element.value = value || [];
10853
11024
  element.xrange = options.xrange || [ 0, 1 ]; // min, max
@@ -10863,7 +11034,8 @@ class CanvasCurve {
10863
11034
 
10864
11035
  LX.addSignal( "@on_new_color_scheme", (el, value) => {
10865
11036
  element.bgcolor = options.bgColor || LX.getThemeColor( "global-intense-background" );
10866
- element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected-light" );
11037
+ element.pointscolor = options.pointsColor || LX.getThemeColor( "global-selected" );
11038
+ element.activepointscolor = options.activePointsColor || LX.getThemeColor( "global-selected-light" );
10867
11039
  this.redraw();
10868
11040
  } );
10869
11041
 
@@ -10884,11 +11056,11 @@ class CanvasCurve {
10884
11056
  return element.defaulty;
10885
11057
  }
10886
11058
 
10887
- var last = [ element.xrange[ 0 ], element.defaulty ];
10888
- var f = 0;
10889
- for( var i = 0; i < element.value.length; i += 1 )
11059
+ let last = [ element.xrange[ 0 ], element.defaulty ];
11060
+ let f = 0;
11061
+ for( let i = 0; i < element.value.length; i += 1 )
10890
11062
  {
10891
- var v = element.value[ i ];
11063
+ let v = element.value[ i ];
10892
11064
  if( x == v[ 0 ] ) return v[ 1 ];
10893
11065
  if( x < v[ 0 ] )
10894
11066
  {
@@ -10906,9 +11078,9 @@ class CanvasCurve {
10906
11078
 
10907
11079
  element.resample = function( samples ) {
10908
11080
 
10909
- var r = [];
10910
- var dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
10911
- for( var i = element.xrange[0]; i <= element.xrange[1]; i += dx )
11081
+ let r = [];
11082
+ let dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
11083
+ for( let i = element.xrange[0]; i <= element.xrange[1]; i += dx )
10912
11084
  {
10913
11085
  r.push( element.getValueAt(i) );
10914
11086
  }
@@ -10917,9 +11089,9 @@ class CanvasCurve {
10917
11089
 
10918
11090
  element.addValue = function(v) {
10919
11091
 
10920
- for( var i = 0; i < element.value; i++ )
11092
+ for( let i = 0; i < element.value; i++ )
10921
11093
  {
10922
- var value = element.value[i];
11094
+ let value = element.value[i];
10923
11095
  if(value[0] < v[0]) continue;
10924
11096
  element.value.splice(i,0,v);
10925
11097
  redraw();
@@ -10942,7 +11114,7 @@ class CanvasCurve {
10942
11114
  (v[1] * element.yrange[1] / canvas.height + element.yrange[0])];
10943
11115
  }
10944
11116
 
10945
- var selected = -1;
11117
+ let selected = -1;
10946
11118
 
10947
11119
  element.redraw = function( o = {} ) {
10948
11120
 
@@ -11004,7 +11176,7 @@ class CanvasCurve {
11004
11176
  var value = element.value[ i ];
11005
11177
  pos = convert( value );
11006
11178
  if( selected == i )
11007
- ctx.fillStyle = "white";
11179
+ ctx.fillStyle = element.activepointscolor;
11008
11180
  else
11009
11181
  ctx.fillStyle = element.pointscolor;
11010
11182
  ctx.beginPath();
@@ -12192,7 +12364,7 @@ class AssetView {
12192
12364
  const hasImage = ['png', 'jpg'].indexOf( getExtension( file.src ) ) > -1 || is_base_64;
12193
12365
  if( hasImage )
12194
12366
  {
12195
- this.previewPanel.addImage( file.src, { style: { width: "100%" } } );
12367
+ this.previewPanel.addImage( null, file.src, { style: { width: "100%" } } );
12196
12368
  }
12197
12369
  }
12198
12370
 
@@ -12747,6 +12919,9 @@ LX.ICONS = {
12747
12919
  "floppy-disk": [448, 512, ["save"], "regular", "M48 96l0 320c0 8.8 7.2 16 16 16l320 0c8.8 0 16-7.2 16-16l0-245.5c0-4.2-1.7-8.3-4.7-11.3l33.9-33.9c12 12 18.7 28.3 18.7 45.3L448 416c0 35.3-28.7 64-64 64L64 480c-35.3 0-64-28.7-64-64L0 96C0 60.7 28.7 32 64 32l245.5 0c17 0 33.3 6.7 45.3 18.7l74.5 74.5-33.9 33.9L320.8 84.7c-.3-.3-.5-.5-.8-.8L320 184c0 13.3-10.7 24-24 24l-192 0c-13.3 0-24-10.7-24-24L80 80 64 80c-8.8 0-16 7.2-16 16zm80-16l0 80 144 0 0-80L128 80zm32 240a64 64 0 1 1 128 0 64 64 0 1 1 -128 0z"],
12748
12920
  "download": [512, 512, [], "solid", "M288 32c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 242.7-73.4-73.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l128 128c12.5 12.5 32.8 12.5 45.3 0l128-128c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L288 274.7 288 32zM64 352c-35.3 0-64 28.7-64 64l0 32c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-32c0-35.3-28.7-64-64-64l-101.5 0-45.3 45.3c-25 25-65.5 25-90.5 0L165.5 352 64 352zm368 56a24 24 0 1 1 0 48 24 24 0 1 1 0-48z"],
12749
12921
  "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"],
12922
+ "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"],
12923
+ "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"],
12924
+ "sliders": [512, 512, [], "solid", "M0 416c0 17.7 14.3 32 32 32l54.7 0c12.3 28.3 40.5 48 73.3 48s61-19.7 73.3-48L480 448c17.7 0 32-14.3 32-32s-14.3-32-32-32l-246.7 0c-12.3-28.3-40.5-48-73.3-48s-61 19.7-73.3 48L32 384c-17.7 0-32 14.3-32 32zm128 0a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zM320 256a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm32-80c-32.8 0-61 19.7-73.3 48L32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l246.7 0c12.3 28.3 40.5 48 73.3 48s61-19.7 73.3-48l54.7 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-54.7 0c-12.3-28.3-40.5-48-73.3-48zM192 128a32 32 0 1 1 0-64 32 32 0 1 1 0 64zm73.3-64C253 35.7 224.8 16 192 16s-61 19.7-73.3 48L32 64C14.3 64 0 78.3 0 96s14.3 32 32 32l86.7 0c12.3 28.3 40.5 48 73.3 48s61-19.7 73.3-48L480 128c17.7 0 32-14.3 32-32s-14.3-32-32-32L265.3 64z"],
12750
12925
  "eye": [576, 512, [], "regular", "M288 80c-65.2 0-118.8 29.6-159.9 67.7C89.6 183.5 63 226 49.4 256c13.6 30 40.2 72.5 78.6 108.3C169.2 402.4 222.8 432 288 432s118.8-29.6 159.9-67.7C486.4 328.5 513 286 526.6 256c-13.6-30-40.2-72.5-78.6-108.3C406.8 109.6 353.2 80 288 80zM95.4 112.6C142.5 68.8 207.2 32 288 32s145.5 36.8 192.6 80.6c46.8 43.5 78.1 95.4 93 131.1c3.3 7.9 3.3 16.7 0 24.6c-14.9 35.7-46.2 87.7-93 131.1C433.5 443.2 368.8 480 288 480s-145.5-36.8-192.6-80.6C48.6 356 17.3 304 2.5 268.3c-3.3-7.9-3.3-16.7 0-24.6C17.3 208 48.6 156 95.4 112.6zM288 336c44.2 0 80-35.8 80-80s-35.8-80-80-80c-.7 0-1.3 0-2 0c1.3 5.1 2 10.5 2 16c0 35.3-28.7 64-64 64c-5.5 0-10.9-.7-16-2c0 .7 0 1.3 0 2c0 44.2 35.8 80 80 80zm0-208a128 128 0 1 1 0 256 128 128 0 1 1 0-256z"],
12751
12926
  "eye-slash": [640, 512, [], "regular", "M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zm151 118.3C226 97.7 269.5 80 320 80c65.2 0 118.8 29.6 159.9 67.7C518.4 183.5 545 226 558.6 256c-12.6 28-36.6 66.8-70.9 100.9l-53.8-42.2c9.1-17.6 14.2-37.5 14.2-58.7c0-70.7-57.3-128-128-128c-32.2 0-61.7 11.9-84.2 31.5l-46.1-36.1zM394.9 284.2l-81.5-63.9c4.2-8.5 6.6-18.2 6.6-28.3c0-5.5-.7-10.9-2-16c.7 0 1.3 0 2 0c44.2 0 80 35.8 80 80c0 9.9-1.8 19.4-5.1 28.2zm9.4 130.3C378.8 425.4 350.7 432 320 432c-65.2 0-118.8-29.6-159.9-67.7C121.6 328.5 95 286 81.4 256c8.3-18.4 21.5-41.5 39.4-64.8L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5l-41.9-33zM192 256c0 70.7 57.3 128 128 128c13.3 0 26.1-2 38.2-5.8L302 334c-23.5-5.4-43.1-21.2-53.7-42.3l-56.1-44.2c-.2 2.8-.3 5.6-.3 8.5z"],
12752
12927
  "comment": [512, 512, [], "regular", "M123.6 391.3c12.9-9.4 29.6-11.8 44.6-6.4c26.5 9.6 56.2 15.1 87.8 15.1c124.7 0 208-80.5 208-160s-83.3-160-208-160S48 160.5 48 240c0 32 12.4 62.8 35.7 89.2c8.6 9.7 12.8 22.5 11.8 35.5c-1.4 18.1-5.7 34.7-11.3 49.4c17-7.9 31.1-16.7 39.4-22.7zM21.2 431.9c1.8-2.7 3.5-5.4 5.1-8.1c10-16.6 19.5-38.4 21.4-62.9C17.7 326.8 0 285.1 0 240C0 125.1 114.6 32 256 32s256 93.1 256 208s-114.6 208-256 208c-37.1 0-72.3-6.4-104.1-17.9c-11.9 8.7-31.3 20.6-54.3 30.6c-15.1 6.6-32.3 12.6-50.1 16.1c-.8 .2-1.6 .3-2.4 .5c-4.4 .8-8.7 1.5-13.2 1.9c-.2 0-.5 .1-.7 .1c-5.1 .5-10.2 .8-15.3 .8c-6.5 0-12.3-3.9-14.8-9.9c-2.5-6-1.1-12.8 3.4-17.4c4.1-4.2 7.8-8.7 11.3-13.5c1.7-2.3 3.3-4.6 4.8-6.9l.3-.5z"],
@@ -12775,6 +12950,7 @@ LX.ICONS = {
12775
12950
  "minus": [448, 512, [], "solid", "M432 256c0 17.7-14.3 32-32 32L48 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l352 0c17.7 0 32 14.3 32 32z"],
12776
12951
  "more-horizontal": [448, 512, [], "solid", "M8 256a56 56 0 1 1 112 0A56 56 0 1 1 8 256zm160 0a56 56 0 1 1 112 0 56 56 0 1 1 -112 0zm216-56a56 56 0 1 1 0 112 56 56 0 1 1 0-112z"],
12777
12952
  "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"],
12953
+ "circle-plus": [24, 24, [], "regular", "M12 8V16M8 12H16M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z", null, "fill=none stroke-width=2 stroke-linecap=round stroke-linejoin=round"],
12778
12954
  "search": [512, 512, [], "solid", "M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"],
12779
12955
  "compass": [512, 512, [], "regular", "M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm306.7 69.1L162.4 380.6c-19.4 7.5-38.5-11.6-31-31l55.5-144.3c3.3-8.5 9.9-15.1 18.4-18.4l144.3-55.5c19.4-7.5 38.5 11.6 31 31L325.1 306.7c-3.2 8.5-9.9 15.1-18.4 18.4zM288 256a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"],
12780
12956
  "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"],