lexgui 0.6.0 → 0.6.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.6.0",
15
+ version: "0.6.2",
16
16
  ready: false,
17
17
  components: [], // Specific pre-build components
18
18
  signals: {}, // Events and triggers
@@ -91,7 +91,21 @@ LX.doAsync = doAsync;
91
91
  */
92
92
  function getSupportedDOMName( text )
93
93
  {
94
- return text.replace( /\s/g, '' ).replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll( '.', '' );
94
+ console.assert( typeof text == "string", "getSupportedDOMName: Text is not a string!" );
95
+
96
+ let name = text.trim();
97
+
98
+ // Replace specific known symbols
99
+ name = name.replace( /@/g, '_at_' ).replace( /\+/g, '_plus_' ).replace( /\./g, '_dot_' );
100
+ name = name.replace( /[^a-zA-Z0-9_-]/g, '_' );
101
+
102
+ // prefix with an underscore if needed
103
+ if( /^[0-9]/.test( name ) )
104
+ {
105
+ name = '_' + name;
106
+ }
107
+
108
+ return name;
95
109
  }
96
110
 
97
111
  LX.getSupportedDOMName = getSupportedDOMName;
@@ -2302,7 +2316,7 @@ class DropdownMenu {
2302
2316
 
2303
2317
  console.assert( trigger, "DropdownMenu needs a DOM element as trigger!" );
2304
2318
 
2305
- if( DropdownMenu.currentMenu )
2319
+ if( DropdownMenu.currentMenu || !items?.length )
2306
2320
  {
2307
2321
  DropdownMenu.currentMenu.destroy();
2308
2322
  this.invalid = true;
@@ -2320,6 +2334,7 @@ class DropdownMenu {
2320
2334
  this.align = options.align ?? "center";
2321
2335
  this.avoidCollisions = options.avoidCollisions ?? true;
2322
2336
  this.onBlur = options.onBlur;
2337
+ this.inPlace = false;
2323
2338
 
2324
2339
  this.root = document.createElement( "div" );
2325
2340
  this.root.id = "root";
@@ -2339,7 +2354,8 @@ class DropdownMenu {
2339
2354
 
2340
2355
  this._onClick = e => {
2341
2356
 
2342
- if( e.target && ( this.root.contains( e.target ) || e.target == this._trigger ) )
2357
+ // Check if the click is inside a menu or on the trigger
2358
+ if( e.target && ( e.target.closest( ".lexdropdownmenu" ) != undefined || e.target == this._trigger ) )
2343
2359
  {
2344
2360
  return;
2345
2361
  }
@@ -2347,7 +2363,8 @@ class DropdownMenu {
2347
2363
  this.destroy( true );
2348
2364
  };
2349
2365
 
2350
- document.body.addEventListener( "click", this._onClick );
2366
+ document.body.addEventListener( "mousedown", this._onClick, true );
2367
+ document.body.addEventListener( "focusin", this._onClick, true );
2351
2368
  }, 10 );
2352
2369
  }
2353
2370
 
@@ -2357,7 +2374,8 @@ class DropdownMenu {
2357
2374
 
2358
2375
  delete this._trigger.ddm;
2359
2376
 
2360
- document.body.removeEventListener( "click", this._onClick );
2377
+ document.body.removeEventListener( "mousedown", this._onClick, true );
2378
+ document.body.removeEventListener( "focusin", this._onClick, true );
2361
2379
 
2362
2380
  LX.root.querySelectorAll( ".lexdropdownmenu" ).forEach( m => { m.remove(); } );
2363
2381
 
@@ -2382,7 +2400,7 @@ class DropdownMenu {
2382
2400
  let newParent = document.createElement( "div" );
2383
2401
  newParent.tabIndex = "1";
2384
2402
  newParent.className = "lexdropdownmenu";
2385
- newParent.id = parentDom.id;
2403
+ newParent.dataset["id"] = parentDom.dataset["id"];
2386
2404
  newParent.dataset["side"] = "right"; // submenus always come from the right
2387
2405
  LX.root.appendChild( newParent );
2388
2406
 
@@ -2414,7 +2432,7 @@ class DropdownMenu {
2414
2432
  }
2415
2433
 
2416
2434
  const key = item.name ?? item;
2417
- const pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
2435
+ const pKey = LX.getSupportedDOMName( key );
2418
2436
 
2419
2437
  // Item already created
2420
2438
  if( parentDom.querySelector( "#" + pKey ) )
@@ -2424,7 +2442,7 @@ class DropdownMenu {
2424
2442
 
2425
2443
  const menuItem = document.createElement('div');
2426
2444
  menuItem.className = "lexdropdownmenuitem" + ( item.name ? "" : " label" ) + ( item.disabled ?? false ? " disabled" : "" ) + ( ` ${ item.className ?? "" }` );
2427
- menuItem.id = pKey;
2445
+ menuItem.dataset["id"] = pKey;
2428
2446
  menuItem.innerHTML = `<span>${ key }</span>`;
2429
2447
  menuItem.tabIndex = "1";
2430
2448
  parentDom.appendChild( menuItem );
@@ -2510,24 +2528,24 @@ class DropdownMenu {
2510
2528
 
2511
2529
  menuItem.addEventListener("mouseover", e => {
2512
2530
 
2513
- let path = menuItem.id;
2531
+ let path = menuItem.dataset["id"];
2514
2532
  let p = parentDom;
2515
2533
 
2516
2534
  while( p )
2517
2535
  {
2518
- path += "/" + p.id;
2536
+ path += "/" + p.dataset["id"];
2519
2537
  p = p.currentParent?.parentElement;
2520
2538
  }
2521
2539
 
2522
2540
  LX.root.querySelectorAll( ".lexdropdownmenu" ).forEach( m => {
2523
- if( !path.includes( m.id ) )
2541
+ if( !path.includes( m.dataset["id"] ) )
2524
2542
  {
2525
2543
  m.currentParent.built = false;
2526
2544
  m.remove();
2527
2545
  }
2528
2546
  } );
2529
2547
 
2530
- if( item.submenu )
2548
+ if( item.submenu && this.inPlace )
2531
2549
  {
2532
2550
  if( menuItem.built )
2533
2551
  {
@@ -2601,6 +2619,7 @@ class DropdownMenu {
2601
2619
 
2602
2620
  this.root.style.left = `${ position[ 0 ] }px`;
2603
2621
  this.root.style.top = `${ position[ 1 ] }px`;
2622
+ this.inPlace = true;
2604
2623
  }
2605
2624
 
2606
2625
  _addSeparator( parent ) {
@@ -3462,6 +3481,7 @@ class Area {
3462
3481
  const type = options.type ?? "horizontal";
3463
3482
  const sizes = options.sizes || [ "50%", "50%" ];
3464
3483
  const auto = (options.sizes === 'auto') || ( options.sizes && options.sizes[ 0 ] == "auto" && options.sizes[ 1 ] == "auto" );
3484
+ const rect = this.root.getBoundingClientRect();
3465
3485
 
3466
3486
  // Secondary area fills space
3467
3487
  if( !sizes[ 1 ] || ( sizes[ 0 ] != "auto" && sizes[ 1 ] == "auto" ) )
@@ -3512,7 +3532,7 @@ class Area {
3512
3532
 
3513
3533
  if( !fixedSize )
3514
3534
  {
3515
- const parentWidth = this.root.offsetWidth;
3535
+ const parentWidth = rect.width;
3516
3536
  const leftPx = parsePixelSize( sizes[ 0 ], parentWidth );
3517
3537
  const rightPx = parsePixelSize( sizes[ 1 ], parentWidth );
3518
3538
  const leftPercent = ( leftPx / parentWidth ) * 100;
@@ -3536,10 +3556,11 @@ class Area {
3536
3556
  if( auto )
3537
3557
  {
3538
3558
  primarySize[ 1 ] = "auto";
3559
+ secondarySize[ 1 ] = "auto";
3539
3560
  }
3540
3561
  else if( !fixedSize )
3541
3562
  {
3542
- const parentHeight = this.root.offsetHeight;
3563
+ const parentHeight = rect.height;
3543
3564
  const topPx = parsePixelSize( sizes[ 0 ], parentHeight );
3544
3565
  const bottomPx = parsePixelSize( sizes[ 1 ], parentHeight );
3545
3566
  const topPercent = ( topPx / parentHeight ) * 100;
@@ -3562,6 +3583,72 @@ class Area {
3562
3583
  let area1 = new Area( { width: primarySize[ 0 ], height: primarySize[ 1 ], skipAppend: true, className: "split" + ( options.menubar || options.sidebar ? "" : " origin" ) } );
3563
3584
  let area2 = new Area( { width: secondarySize[ 0 ], height: secondarySize[ 1 ], skipAppend: true, className: "split" } );
3564
3585
 
3586
+ /*
3587
+ If the parent area is not in the DOM, we need to wait for the resize event to get the its correct size
3588
+ and set the sizes of the split areas accordingly.
3589
+ */
3590
+ if( !fixedSize && ( !rect.width || !rect.height ) )
3591
+ {
3592
+ const observer = new ResizeObserver( entries => {
3593
+
3594
+ console.assert( entries.length == 1, "AreaResizeObserver: more than one entry" );
3595
+
3596
+ const rect = entries[ 0 ].contentRect;
3597
+ if( !rect.width || !rect.height )
3598
+ {
3599
+ return;
3600
+ }
3601
+
3602
+ this._update( [ rect.width, rect.height ], false );
3603
+
3604
+ // On auto splits, we only need to set the size of the parent area
3605
+ if( !auto )
3606
+ {
3607
+ if( type == "horizontal" )
3608
+ {
3609
+ const parentWidth = rect.width;
3610
+ const leftPx = parsePixelSize( sizes[ 0 ], parentWidth );
3611
+ const rightPx = parsePixelSize( sizes[ 1 ], parentWidth );
3612
+ const leftPercent = ( leftPx / parentWidth ) * 100;
3613
+ const rightPercent = ( rightPx / parentWidth ) * 100;
3614
+
3615
+ // Style using percentages
3616
+ primarySize[ 0 ] = `calc(${ leftPercent }% - ${ splitbarOffset }px)`;
3617
+ secondarySize[ 0 ] = `calc(${ rightPercent }% - ${ splitbarOffset }px)`;
3618
+ }
3619
+ else // vertical
3620
+ {
3621
+ const parentHeight = rect.height;
3622
+ const topPx = parsePixelSize( sizes[ 0 ], parentHeight );
3623
+ const bottomPx = parsePixelSize( sizes[ 1 ], parentHeight );
3624
+ const topPercent = ( topPx / parentHeight ) * 100;
3625
+ const bottomPercent = ( bottomPx / parentHeight ) * 100;
3626
+
3627
+ primarySize[ 1 ] = ( sizes[ 0 ] == "auto" ? "auto" : `calc(${ topPercent }% - ${ splitbarOffset }px)`);
3628
+ secondarySize[ 1 ] = ( sizes[ 1 ] == "auto" ? "auto" : `calc(${ bottomPercent }% - ${ splitbarOffset }px)`);
3629
+ }
3630
+
3631
+ area1.root.style.width = primarySize[ 0 ];
3632
+ area1.root.style.height = primarySize[ 1 ];
3633
+
3634
+ area2.root.style.width = secondarySize[ 0 ];
3635
+ area2.root.style.height = secondarySize[ 1 ];
3636
+ }
3637
+
3638
+ area1._update();
3639
+ area2._update();
3640
+
3641
+ // Stop observing
3642
+ observer.disconnect();
3643
+ });
3644
+
3645
+ // Observe the parent area until the DOM is ready
3646
+ // and the size is set correctly.
3647
+ doAsync( () => {
3648
+ observer.observe( this.root );
3649
+ }, 100 );
3650
+ }
3651
+
3565
3652
  if( auto && type == "vertical" )
3566
3653
  {
3567
3654
  // Listen resize event on first area
@@ -3571,6 +3658,7 @@ class Area {
3571
3658
  const size = entry.target.getComputedSize();
3572
3659
  area2.root.style.height = "calc(100% - " + ( size.height ) + "px )";
3573
3660
  }
3661
+ resizeObserver.disconnect();
3574
3662
  });
3575
3663
 
3576
3664
  resizeObserver.observe( area1.root );
@@ -3614,7 +3702,7 @@ class Area {
3614
3702
  this.type = type;
3615
3703
 
3616
3704
  // Update sizes
3617
- this._update();
3705
+ this._update( rect.width || rect.height ? [ rect.width, rect.height ] : undefined );
3618
3706
 
3619
3707
  if( !resize )
3620
3708
  {
@@ -3671,6 +3759,11 @@ class Area {
3671
3759
  this.minHeight = minh;
3672
3760
  this.maxWidth = maxw;
3673
3761
  this.maxHeight = maxh;
3762
+
3763
+ if( minw != 0 ) this.root.style.minWidth = `${ minw }px`;
3764
+ if( minh != 0 ) this.root.style.minHeight = `${ minh }px`;
3765
+ if( maxw != Infinity ) this.root.style.maxWidth = `${ maxw }px`;
3766
+ if( maxh != Infinity ) this.root.style.maxHeight = `${ maxh }px`;
3674
3767
  }
3675
3768
 
3676
3769
  /**
@@ -3730,7 +3823,7 @@ class Area {
3730
3823
  {
3731
3824
  this.offset = area2.root.offsetHeight;
3732
3825
  area2.root.classList.add("fadeout-vertical");
3733
- this._moveSplit(-Infinity, true);
3826
+ this._moveSplit( -Infinity, true );
3734
3827
 
3735
3828
  }
3736
3829
  else
@@ -4038,7 +4131,6 @@ class Area {
4038
4131
  {
4039
4132
  _addButton( b );
4040
4133
  }
4041
-
4042
4134
  }
4043
4135
 
4044
4136
  // Add floating info
@@ -4130,12 +4222,12 @@ class Area {
4130
4222
 
4131
4223
  if( a1.maxWidth != Infinity )
4132
4224
  {
4133
- a2Root.style.minWidth = "calc( 100% - " + parseInt( a1.maxWidth ) + "px" + " )";
4225
+ a2Root.style.minWidth = `calc( 100% - ${ parseInt( a1.maxWidth ) }px )`;
4134
4226
  }
4135
4227
  }
4136
4228
  else
4137
4229
  {
4138
- var size = Math.max( ( a2Root.offsetHeight + dt ) + a2.offset, parseInt(a2.minHeight) );
4230
+ var size = Math.max( ( a2Root.offsetHeight + dt ) + a2.offset, parseInt( a2.minHeight ) );
4139
4231
  if( forceWidth ) size = forceWidth;
4140
4232
 
4141
4233
  const parentHeight = this.size[ 1 ];
@@ -4149,7 +4241,10 @@ class Area {
4149
4241
  a2Root.style.height = `${ bottomPercent }%`;
4150
4242
  a2Root.style.height = `${ bottomPercent }%`;
4151
4243
 
4152
- a1Root.style.minHeight = a1.minHeight + "px";
4244
+ if( a1.maxHeight != Infinity )
4245
+ {
4246
+ a2Root.style.minHeight = `calc( 100% - ${ parseInt( a1.maxHeight ) }px )`;
4247
+ }
4153
4248
  }
4154
4249
 
4155
4250
  if( !forceAnimation )
@@ -4171,15 +4266,24 @@ class Area {
4171
4266
  delete this.splitBar;
4172
4267
  }
4173
4268
 
4174
- _update() {
4175
-
4176
- const rect = this.root.getBoundingClientRect();
4269
+ _update( newSize, propagate = true ) {
4177
4270
 
4178
- this.size = [ rect.width, rect.height ];
4271
+ if( !newSize )
4272
+ {
4273
+ const rect = this.root.getBoundingClientRect();
4274
+ this.size = [ rect.width, rect.height ];
4275
+ }
4276
+ else
4277
+ {
4278
+ this.size = newSize;
4279
+ }
4179
4280
 
4180
- for( var i = 0; i < this.sections.length; i++ )
4281
+ if( propagate )
4181
4282
  {
4182
- this.sections[ i ]._update();
4283
+ for( var i = 0; i < this.sections.length; i++ )
4284
+ {
4285
+ this.sections[ i ]._update();
4286
+ }
4183
4287
  }
4184
4288
  }
4185
4289
  };
@@ -4579,7 +4683,7 @@ class Menubar {
4579
4683
 
4580
4684
  this.root.querySelectorAll(".lexmenuentry").forEach( e => {
4581
4685
  e.classList.remove( 'selected' );
4582
- e.built = false;
4686
+ delete e.dataset[ "built" ];
4583
4687
  } );
4584
4688
 
4585
4689
  if( this._currentDropdown )
@@ -4601,7 +4705,7 @@ class Menubar {
4601
4705
  for( let item of this.items )
4602
4706
  {
4603
4707
  let key = item.name;
4604
- let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
4708
+ let pKey = LX.getSupportedDOMName( key );
4605
4709
 
4606
4710
  // Item already created
4607
4711
  if( this.root.querySelector( "#" + pKey ) )
@@ -4620,8 +4724,8 @@ class Menubar {
4620
4724
  const _showEntry = () => {
4621
4725
  this._resetMenubar(true);
4622
4726
  entry.classList.add( "selected" );
4623
- entry.built = true;
4624
- this._currentDropdown = addDropdownMenu( entry, item.submenu, { side: "bottom", align: "start", onBlur: () => {
4727
+ entry.dataset["built"] = "true";
4728
+ this._currentDropdown = addDropdownMenu( entry, item.submenu ?? [], { side: "bottom", align: "start", onBlur: () => {
4625
4729
  this._resetMenubar();
4626
4730
  } });
4627
4731
  };
@@ -4641,7 +4745,7 @@ class Menubar {
4641
4745
 
4642
4746
  entry.addEventListener( "mouseover", (e) => {
4643
4747
 
4644
- if( this.focused && !entry.built )
4748
+ if( this.focused && !( entry.dataset[ "built" ] ?? false ) )
4645
4749
  {
4646
4750
  _showEntry();
4647
4751
  }
@@ -5234,7 +5338,7 @@ class SideBar {
5234
5338
 
5235
5339
  select( name ) {
5236
5340
 
5237
- let pKey = name.replace( /\s/g, '' ).replaceAll( '.', '' );
5341
+ let pKey = LX.getSupportedDOMName( name );
5238
5342
 
5239
5343
  const entry = this.items.find( v => v.name === pKey );
5240
5344
 
@@ -5272,7 +5376,7 @@ class SideBar {
5272
5376
  continue;
5273
5377
  }
5274
5378
 
5275
- let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
5379
+ let pKey = LX.getSupportedDOMName( key );
5276
5380
  let currentGroup = null;
5277
5381
 
5278
5382
  let entry = document.createElement( 'div' );
@@ -6538,7 +6642,7 @@ class Title extends Widget {
6538
6642
  // Note: Titles are not registered in Panel.widgets by now
6539
6643
  super( Widget.TITLE, null, null, options );
6540
6644
 
6541
- this.root.className = "lextitle";
6645
+ this.root.className = `lextitle ${ this.root.className }`;
6542
6646
 
6543
6647
  if( options.icon )
6544
6648
  {
@@ -6852,7 +6956,7 @@ class Button extends Widget {
6852
6956
 
6853
6957
  var wValue = document.createElement( 'button' );
6854
6958
  wValue.title = options.tooltip ? "" : ( options.title ?? "" );
6855
- wValue.className = "lexbutton " + ( options.buttonClass ?? "" );
6959
+ wValue.className = "lexbutton p-1 " + ( options.buttonClass ?? "" );
6856
6960
 
6857
6961
  this.root.appendChild( wValue );
6858
6962
 
@@ -6989,7 +7093,7 @@ class ComboButtons extends Widget {
6989
7093
  buttonEl.classList.add( options.buttonClass );
6990
7094
  }
6991
7095
 
6992
- if( shouldSelect && b.selected )
7096
+ if( shouldSelect && ( b.selected || options.selected?.includes( b.value ) ) )
6993
7097
  {
6994
7098
  buttonEl.classList.add("selected");
6995
7099
  currentValue = ( currentValue ).concat( [ b.value ] );
@@ -7038,7 +7142,7 @@ class ComboButtons extends Widget {
7038
7142
 
7039
7143
  if( !shouldToggle && currentValue.length > 1 )
7040
7144
  {
7041
- console.error( `Enable _options.toggle_ to allow selecting multiple options in ComboButtons.` )
7145
+ console.error( `Enable _options.toggle_ to allow selecting multiple options in ComboButtons.` );
7042
7146
  return;
7043
7147
  }
7044
7148
 
@@ -7052,9 +7156,12 @@ class ComboButtons extends Widget {
7052
7156
 
7053
7157
  if( currentValue.length > 1 )
7054
7158
  {
7055
- options.toggle = true;
7056
- shouldToggle = shouldSelect;
7057
- console.warn( `Multiple options selected in '${ name }' ComboButtons. Enabling _toggle_ mode.` );
7159
+ if( !shouldToggle )
7160
+ {
7161
+ options.toggle = true;
7162
+ shouldToggle = shouldSelect;
7163
+ console.warn( `Multiple options selected in '${ name }' ComboButtons. Enabling _toggle_ mode.` );
7164
+ }
7058
7165
  }
7059
7166
  else
7060
7167
  {
@@ -7473,7 +7580,7 @@ class Select extends Widget {
7473
7580
  this.unfocus_event = true;
7474
7581
  setTimeout( () => delete this.unfocus_event, 200 );
7475
7582
  }
7476
- else if ( e.relatedTarget && ( e.relatedTarget.tagName == "INPUT" || e.relatedTarget.classList.contains("lexoptions") ) )
7583
+ else if ( e.relatedTarget && listDialog.contains( e.relatedTarget ) )
7477
7584
  {
7478
7585
  return;
7479
7586
  }
@@ -8369,7 +8476,7 @@ class RadioGroup extends Widget {
8369
8476
  container.appendChild( optionItem );
8370
8477
 
8371
8478
  const optionButton = document.createElement( 'button' );
8372
- optionButton.className = "lexbutton";
8479
+ optionButton.className = "flex p-0 rounded-lg cursor-pointer";
8373
8480
  optionButton.disabled = options.disabled ?? false;
8374
8481
  optionItem.appendChild( optionButton );
8375
8482
 
@@ -8672,7 +8779,7 @@ class NumberInput extends Widget {
8672
8779
  box.className = "numberbox";
8673
8780
  container.appendChild( box );
8674
8781
 
8675
- let valueBox = LX.makeContainer( [ "auto", "100%" ], "relative flex flex-row", "", box );
8782
+ let valueBox = LX.makeContainer( [ "auto", "100%" ], "relative flex flex-row cursor-text", "", box );
8676
8783
 
8677
8784
  let vecinput = document.createElement( 'input' );
8678
8785
  vecinput.id = "number_" + simple_guidGenerator();
@@ -8691,7 +8798,7 @@ class NumberInput extends Widget {
8691
8798
  vecinput.value = vecinput.iValue = value;
8692
8799
  valueBox.appendChild( vecinput );
8693
8800
 
8694
- const dragIcon = LX.makeIcon( "MoveVertical", { iconClass: "drag-icon hidden", svgClass: "sm" } );
8801
+ const dragIcon = LX.makeIcon( "MoveVertical", { iconClass: "drag-icon hidden-opacity", svgClass: "sm" } );
8695
8802
  valueBox.appendChild( dragIcon );
8696
8803
 
8697
8804
  if( options.units )
@@ -8775,7 +8882,7 @@ class NumberInput extends Widget {
8775
8882
 
8776
8883
  let innerMouseDown = e => {
8777
8884
 
8778
- if( document.activeElement == vecinput )
8885
+ if( ( document.activeElement == vecinput ) || ( e.button != LX.MOUSE_LEFT_CLICK ) )
8779
8886
  {
8780
8887
  return;
8781
8888
  }
@@ -8784,13 +8891,13 @@ class NumberInput extends Widget {
8784
8891
  doc.addEventListener( 'mousemove', innerMouseMove );
8785
8892
  doc.addEventListener( 'mouseup', innerMouseUp );
8786
8893
  document.body.classList.add( 'noevents' );
8787
- dragIcon.classList.remove( 'hidden' );
8894
+ dragIcon.classList.remove( 'hidden-opacity' );
8788
8895
  e.stopImmediatePropagation();
8789
8896
  e.stopPropagation();
8790
8897
 
8791
8898
  if( !document.pointerLockElement )
8792
8899
  {
8793
- vecinput.requestPointerLock();
8900
+ valueBox.requestPointerLock();
8794
8901
  }
8795
8902
 
8796
8903
  if( options.onPress )
@@ -8822,7 +8929,7 @@ class NumberInput extends Widget {
8822
8929
  doc.removeEventListener( 'mousemove', innerMouseMove );
8823
8930
  doc.removeEventListener( 'mouseup', innerMouseUp );
8824
8931
  document.body.classList.remove( 'noevents' );
8825
- dragIcon.classList.add( 'hidden' );
8932
+ dragIcon.classList.add( 'hidden-opacity' );
8826
8933
 
8827
8934
  if( document.pointerLockElement )
8828
8935
  {
@@ -8835,7 +8942,7 @@ class NumberInput extends Widget {
8835
8942
  }
8836
8943
  }
8837
8944
 
8838
- vecinput.addEventListener( "mousedown", innerMouseDown );
8945
+ valueBox.addEventListener( "mousedown", innerMouseDown );
8839
8946
 
8840
8947
  doAsync( this.onResize.bind( this ) );
8841
8948
  }
@@ -8917,6 +9024,7 @@ class Vector extends Widget {
8917
9024
  vecinput.id = "vec" + numComponents + "_" + simple_guidGenerator();
8918
9025
  vecinput.idx = i;
8919
9026
  vectorInputs[ i ] = vecinput;
9027
+ box.appendChild( vecinput );
8920
9028
 
8921
9029
  if( value[ i ].constructor == Number )
8922
9030
  {
@@ -8926,7 +9034,7 @@ class Vector extends Widget {
8926
9034
 
8927
9035
  vecinput.value = vecinput.iValue = value[ i ];
8928
9036
 
8929
- const dragIcon = LX.makeIcon( "MoveVertical", { iconClass: "drag-icon hidden", svgClass: "sm" } );
9037
+ const dragIcon = LX.makeIcon( "MoveVertical", { iconClass: "drag-icon hidden-opacity", svgClass: "sm" } );
8930
9038
  box.appendChild( dragIcon );
8931
9039
 
8932
9040
  if( options.disabled )
@@ -8989,7 +9097,7 @@ class Vector extends Widget {
8989
9097
 
8990
9098
  function innerMouseDown( e )
8991
9099
  {
8992
- if( document.activeElement == vecinput )
9100
+ if( ( document.activeElement == vecinput ) || ( e.button != LX.MOUSE_LEFT_CLICK ) )
8993
9101
  {
8994
9102
  return;
8995
9103
  }
@@ -8998,13 +9106,13 @@ class Vector extends Widget {
8998
9106
  doc.addEventListener( 'mousemove', innerMouseMove );
8999
9107
  doc.addEventListener( 'mouseup', innerMouseUp );
9000
9108
  document.body.classList.add( 'noevents' );
9001
- dragIcon.classList.remove( 'hidden' );
9109
+ dragIcon.classList.remove( 'hidden-opacity' );
9002
9110
  e.stopImmediatePropagation();
9003
9111
  e.stopPropagation();
9004
9112
 
9005
9113
  if( !document.pointerLockElement )
9006
9114
  {
9007
- vecinput.requestPointerLock();
9115
+ box.requestPointerLock();
9008
9116
  }
9009
9117
 
9010
9118
  if( options.onPress )
@@ -9048,7 +9156,7 @@ class Vector extends Widget {
9048
9156
  doc.removeEventListener( 'mousemove', innerMouseMove );
9049
9157
  doc.removeEventListener( 'mouseup', innerMouseUp );
9050
9158
  document.body.classList.remove( 'noevents' );
9051
- dragIcon.classList.add('hidden');
9159
+ dragIcon.classList.add('hidden-opacity');
9052
9160
 
9053
9161
  if( document.pointerLockElement )
9054
9162
  {
@@ -9061,9 +9169,7 @@ class Vector extends Widget {
9061
9169
  }
9062
9170
  }
9063
9171
 
9064
- vecinput.addEventListener( "mousedown", innerMouseDown );
9065
-
9066
- box.appendChild( vecinput );
9172
+ box.addEventListener( "mousedown", innerMouseDown );
9067
9173
  container.appendChild( box );
9068
9174
  }
9069
9175
 
@@ -9996,34 +10102,90 @@ class Table extends Widget {
9996
10102
  if( this.customFilters )
9997
10103
  {
9998
10104
  const icon = LX.makeIcon( "CirclePlus", { svgClass: "sm" } );
10105
+ const separatorHtml = `<div class="lexcontainer border-right self-center mx-1" style="width: 1px; height: 70%;"></div>`;
9999
10106
 
10000
10107
  for( let f of this.customFilters )
10001
10108
  {
10002
- const customFilterBtn = new Button(null, icon.innerHTML + f.name, ( v ) => {
10109
+ f.widget = new Button(null, icon.innerHTML + f.name, ( v ) => {
10003
10110
 
10004
- const menuOptions = f.options.map( ( colName, idx ) => {
10005
- const item = {
10006
- name: colName,
10007
- checked: !!this.activeCustomFilters[ colName ],
10008
- callback: (key, v, dom) => {
10009
- if( v ) { this.activeCustomFilters[ key ] = f.name; }
10010
- else {
10011
- delete this.activeCustomFilters[ key ];
10111
+ const spanName = f.widget.root.querySelector( "span" );
10112
+
10113
+ if( f.options )
10114
+ {
10115
+ const menuOptions = f.options.map( ( colName, idx ) => {
10116
+ const item = {
10117
+ name: colName,
10118
+ checked: !!this.activeCustomFilters[ colName ],
10119
+ callback: (key, v, dom) => {
10120
+ if( v ) { this.activeCustomFilters[ key ] = f.name; }
10121
+ else {
10122
+ delete this.activeCustomFilters[ key ];
10123
+ }
10124
+ const activeFilters = Object.keys( this.activeCustomFilters ).filter( k => this.activeCustomFilters[ k ] == f.name );
10125
+ const filterBadgesHtml = activeFilters.reduce( ( acc, key ) => acc += LX.badge( key, "bg-tertiary text-sm" ), "" );
10126
+ spanName.innerHTML = icon.innerHTML + f.name + ( activeFilters.length ? separatorHtml : "" ) + filterBadgesHtml;
10127
+ this.refresh();
10012
10128
  }
10013
- this.refresh();
10014
10129
  }
10130
+ return item;
10131
+ } );
10132
+ new DropdownMenu( f.widget.root, menuOptions, { side: "bottom", align: "start" });
10133
+ }
10134
+ else if( f.type == "range" )
10135
+ {
10136
+ console.assert( f.min != undefined && f.max != undefined, "Range filter needs min and max values!" );
10137
+ const container = LX.makeContainer( ["240px", "auto"], "border bg-primary rounded-lg text-md" );
10138
+ const panel = new Panel();
10139
+ LX.makeContainer( ["100%", "auto"], "px-3 p-2 pb-0 text-md font-medium", f.name, container );
10140
+
10141
+ f.start = f.start ?? f.min;
10142
+ f.end = f.end ?? f.max;
10143
+
10144
+ panel.refresh = () => {
10145
+ panel.clear();
10146
+ panel.sameLine( 2, "justify-center" );
10147
+ panel.addNumber( null, f.start, (v) => {
10148
+ f.start = v;
10149
+ const inUse = ( f.start != f.min || f.end != f.max );
10150
+ spanName.innerHTML = icon.innerHTML + f.name + ( inUse ? separatorHtml + LX.badge( `${ f.start } - ${ f.end } ${ f.units ?? "" }`, "bg-tertiary text-sm" ) : "" );
10151
+ this.refresh();
10152
+ }, { skipSlider: true, min: f.min, max: f.max, step: f.step, units: f.units } );
10153
+ panel.addNumber( null, f.end, (v) => {
10154
+ f.end = v;
10155
+ const inUse = ( f.start != f.min || f.end != f.max );
10156
+ spanName.innerHTML = icon.innerHTML + f.name + ( inUse ? separatorHtml + LX.badge( `${ f.start } - ${ f.end } ${ f.units ?? "" }`, "bg-tertiary text-sm" ) : "" );
10157
+ this.refresh();
10158
+ }, { skipSlider: true, min: f.min, max: f.max, step: f.step, units: f.units } );
10159
+ panel.addButton( null, "Reset", () => {
10160
+ f.start = f.min;
10161
+ f.end = f.max;
10162
+ spanName.innerHTML = icon.innerHTML + f.name;
10163
+ panel.refresh();
10164
+ this.refresh();
10165
+ }, { buttonClass: "contrast" } );
10015
10166
  }
10016
- return item;
10017
- } );
10018
- new DropdownMenu( customFilterBtn.root, menuOptions, { side: "bottom", align: "start" });
10019
- }, { buttonClass: " primary dashed" } );
10020
- headerContainer.appendChild( customFilterBtn.root );
10167
+ panel.refresh();
10168
+ container.appendChild( panel.root );
10169
+ new Popover( f.widget.root, [ container ], { side: "bottom" } );
10170
+ }
10171
+
10172
+ }, { buttonClass: "px-2 primary dashed" } );
10173
+ headerContainer.appendChild( f.widget.root );
10021
10174
  }
10022
10175
 
10023
10176
  this._resetCustomFiltersBtn = new Button(null, "resetButton", ( v ) => {
10024
10177
  this.activeCustomFilters = {};
10025
- this.refresh();
10026
10178
  this._resetCustomFiltersBtn.root.classList.add( "hidden" );
10179
+ for( let f of this.customFilters )
10180
+ {
10181
+ f.widget.root.querySelector( "span" ).innerHTML = ( icon.innerHTML + f.name );
10182
+ if( f.type == "range" )
10183
+ {
10184
+ f.start = f.min;
10185
+ f.end = f.max;
10186
+ }
10187
+ }
10188
+ this.refresh();
10027
10189
  }, { title: "Reset filters", icon: "X" } );
10028
10190
  headerContainer.appendChild( this._resetCustomFiltersBtn.root );
10029
10191
  this._resetCustomFiltersBtn.root.classList.add( "hidden" );
@@ -10256,6 +10418,41 @@ class Table extends Widget {
10256
10418
  }
10257
10419
  }
10258
10420
 
10421
+ // Check range/date filters
10422
+ if( this.customFilters )
10423
+ {
10424
+ let acfMap = {};
10425
+
10426
+ for( let f of this.customFilters )
10427
+ {
10428
+ const acfName = f.name;
10429
+
10430
+ if( f.type == "range" )
10431
+ {
10432
+ acfMap[ acfName ] = acfMap[ acfName ] ?? false;
10433
+
10434
+ const filterColIndex = data.head.indexOf( acfName );
10435
+ if( filterColIndex > -1 )
10436
+ {
10437
+ const validRowValue = parseFloat( bodyData[ filterColIndex ] );
10438
+ const min = f.start ?? f.min;
10439
+ const max = f.end ?? f.max;
10440
+ acfMap[ acfName ] |= ( validRowValue >= min ) && ( validRowValue <= max );
10441
+ }
10442
+ }
10443
+ else if( f.type == "date" )
10444
+ {
10445
+ // TODO
10446
+ }
10447
+ }
10448
+
10449
+ const show = Object.values( acfMap ).reduce( ( e, acc ) => acc *= e );
10450
+ if( !show )
10451
+ {
10452
+ continue;
10453
+ }
10454
+ }
10455
+
10259
10456
  const row = document.createElement( 'tr' );
10260
10457
  const rowId = LX.getSupportedDOMName( bodyData.join( '-' ) );
10261
10458
  row.setAttribute( "rowId", rowId.substr(0, 32) );
@@ -11133,6 +11330,7 @@ class Panel {
11133
11330
  * @param {Object} options:
11134
11331
  * hideName: Don't use name as label [false]
11135
11332
  * float: Justify content (left, center, right) [center]
11333
+ * selected: Selected button by default (String|Array)
11136
11334
  * noSelection: Buttons can be clicked, but they are not selectable
11137
11335
  * toggle: Buttons can be toggled insted of selecting only one
11138
11336
  */
@@ -13415,7 +13613,7 @@ class AssetView {
13415
13613
 
13416
13614
  if( !this.skipBrowser )
13417
13615
  {
13418
- [left, right] = area.split({ type: "horizontal", sizes: ["15%", "85%"]});
13616
+ [ left, right ] = area.split({ type: "horizontal", sizes: ["15%", "85%"]});
13419
13617
  contentArea = right;
13420
13618
 
13421
13619
  left.setLimitBox( 210, 0 );
@@ -13625,7 +13823,7 @@ class AssetView {
13625
13823
  }
13626
13824
  else
13627
13825
  {
13628
- this.rightPanel = area.addPanel({ className: 'lexassetcontentpanel' });
13826
+ this.rightPanel = area.addPanel({ className: 'lexassetcontentpanel flex flex-col overflow-hidden' });
13629
13827
  }
13630
13828
 
13631
13829
  const on_sort = ( value, event ) => {
@@ -14669,26 +14867,31 @@ LX.ICONS = {
14669
14867
  "Folder": [512, 512, [], "solid", "M64 480H448c35.3 0 64-28.7 64-64V160c0-35.3-28.7-64-64-64H288c-10.1 0-19.6-4.7-25.6-12.8L243.2 57.6C231.1 41.5 212.1 32 192 32H64C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64z"],
14670
14868
  "FolderOpen": [576, 512, [], "solid", "M384 480l48 0c11.4 0 21.9-6 27.6-15.9l112-192c5.8-9.9 5.8-22.1 .1-32.1S555.5 224 544 224l-400 0c-11.4 0-21.9 6-27.6 15.9L48 357.1 48 96c0-8.8 7.2-16 16-16l117.5 0c4.2 0 8.3 1.7 11.3 4.7l26.5 26.5c21 21 49.5 32.8 79.2 32.8L416 144c8.8 0 16 7.2 16 16l0 32 48 0 0-32c0-35.3-28.7-64-64-64L298.5 96c-17 0-33.3-6.7-45.3-18.7L226.7 50.7c-12-12-28.3-18.7-45.3-18.7L64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l23.7 0L384 480z"],
14671
14869
  "FolderClosed": [512, 512, [], "solid", "M448 480L64 480c-35.3 0-64-28.7-64-64L0 192l512 0 0 224c0 35.3-28.7 64-64 64zm64-320L0 160 0 96C0 60.7 28.7 32 64 32l128 0c20.1 0 39.1 9.5 51.2 25.6l19.2 25.6c6 8.1 15.5 12.8 25.6 12.8l160 0c35.3 0 64 28.7 64 64z"],
14672
- "Play": [384, 512, [], "solid", "M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80L0 432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z"],
14673
- "Pause": [320, 512, [], "solid", "M48 64C21.5 64 0 85.5 0 112L0 400c0 26.5 21.5 48 48 48l32 0c26.5 0 48-21.5 48-48l0-288c0-26.5-21.5-48-48-48L48 64zm192 0c-26.5 0-48 21.5-48 48l0 288c0 26.5 21.5 48 48 48l32 0c26.5 0 48-21.5 48-48l0-288c0-26.5-21.5-48-48-48l-32 0z"],
14870
+ "Function": [384, 512, [], "solid", "M314.7 32c-38.8 0-73.7 23.3-88.6 59.1L170.7 224 64 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l80 0L98.9 396.3c-5 11.9-16.6 19.7-29.5 19.7L32 416c-17.7 0-32 14.3-32 32s14.3 32 32 32l37.3 0c38.8 0 73.7-23.3 88.6-59.1L213.3 288 320 288c17.7 0 32-14.3 32-32s-14.3-32-32-32l-80 0 45.1-108.3c5-11.9 16.6-19.7 29.5-19.7L352 96c17.7 0 32-14.3 32-32s-14.3-32-32-32l-37.3 0z"],
14674
14871
  "Stop": [384, 512, [], "solid", "M0 128C0 92.7 28.7 64 64 64H320c35.3 0 64 28.7 64 64V384c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V128z"],
14675
14872
  "Image": [512, 512, [], "solid", "M448 80c8.8 0 16 7.2 16 16l0 319.8-5-6.5-136-176c-4.5-5.9-11.6-9.3-19-9.3s-14.4 3.4-19 9.3L202 340.7l-30.5-42.7C167 291.7 159.8 288 152 288s-15 3.7-19.5 10.1l-80 112L48 416.3l0-.3L48 96c0-8.8 7.2-16 16-16l384 0zM64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-320c0-35.3-28.7-64-64-64L64 32zm80 192a48 48 0 1 0 0-96 48 48 0 1 0 0 96z"],
14676
14873
  "Images": [576, 512, [], "solid", "M160 80l352 0c8.8 0 16 7.2 16 16l0 224c0 8.8-7.2 16-16 16l-21.2 0L388.1 178.9c-4.4-6.8-12-10.9-20.1-10.9s-15.7 4.1-20.1 10.9l-52.2 79.8-12.4-16.9c-4.5-6.2-11.7-9.8-19.4-9.8s-14.8 3.6-19.4 9.8L175.6 336 160 336c-8.8 0-16-7.2-16-16l0-224c0-8.8 7.2-16 16-16zM96 96l0 224c0 35.3 28.7 64 64 64l352 0c35.3 0 64-28.7 64-64l0-224c0-35.3-28.7-64-64-64L160 32c-35.3 0-64 28.7-64 64zM48 120c0-13.3-10.7-24-24-24S0 106.7 0 120L0 344c0 75.1 60.9 136 136 136l320 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-320 0c-48.6 0-88-39.4-88-88l0-224zm208 24a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"],
14677
- "Function": [384, 512, [], "solid", "M314.7 32c-38.8 0-73.7 23.3-88.6 59.1L170.7 224 64 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l80 0L98.9 396.3c-5 11.9-16.6 19.7-29.5 19.7L32 416c-17.7 0-32 14.3-32 32s14.3 32 32 32l37.3 0c38.8 0 73.7-23.3 88.6-59.1L213.3 288 320 288c17.7 0 32-14.3 32-32s-14.3-32-32-32l-80 0 45.1-108.3c5-11.9 16.6-19.7 29.5-19.7L352 96c17.7 0 32-14.3 32-32s-14.3-32-32-32l-37.3 0z"],
14874
+ "Info": [512, 512, [], "solid", "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336l24 0 0-64-24 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l48 0c13.3 0 24 10.7 24 24l0 88 8 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"],
14678
14875
  "Bone": [576, 512, [], "solid", "M153.7 144.8c6.9 16.3 20.6 31.2 38.3 31.2l192 0c17.7 0 31.4-14.9 38.3-31.2C434.4 116.1 462.9 96 496 96c44.2 0 80 35.8 80 80c0 30.4-17 56.9-42 70.4c-3.6 1.9-6 5.5-6 9.6s2.4 7.7 6 9.6c25 13.5 42 40 42 70.4c0 44.2-35.8 80-80 80c-33.1 0-61.6-20.1-73.7-48.8C415.4 350.9 401.7 336 384 336l-192 0c-17.7 0-31.4 14.9-38.3 31.2C141.6 395.9 113.1 416 80 416c-44.2 0-80-35.8-80-80c0-30.4 17-56.9 42-70.4c3.6-1.9 6-5.5 6-9.6s-2.4-7.7-6-9.6C17 232.9 0 206.4 0 176c0-44.2 35.8-80 80-80c33.1 0 61.6 20.1 73.7 48.8z"],
14679
14876
  "Puzzle": [512, 512, [], "solid", "M192 104.8c0-9.2-5.8-17.3-13.2-22.8C167.2 73.3 160 61.3 160 48c0-26.5 28.7-48 64-48s64 21.5 64 48c0 13.3-7.2 25.3-18.8 34c-7.4 5.5-13.2 13.6-13.2 22.8c0 12.8 10.4 23.2 23.2 23.2l56.8 0c26.5 0 48 21.5 48 48l0 56.8c0 12.8 10.4 23.2 23.2 23.2c9.2 0 17.3-5.8 22.8-13.2c8.7-11.6 20.7-18.8 34-18.8c26.5 0 48 28.7 48 64s-21.5 64-48 64c-13.3 0-25.3-7.2-34-18.8c-5.5-7.4-13.6-13.2-22.8-13.2c-12.8 0-23.2 10.4-23.2 23.2L384 464c0 26.5-21.5 48-48 48l-56.8 0c-12.8 0-23.2-10.4-23.2-23.2c0-9.2 5.8-17.3 13.2-22.8c11.6-8.7 18.8-20.7 18.8-34c0-26.5-28.7-48-64-48s-64 21.5-64 48c0 13.3 7.2 25.3 18.8 34c7.4 5.5 13.2 13.6 13.2 22.8c0 12.8-10.4 23.2-23.2 23.2L48 512c-26.5 0-48-21.5-48-48L0 343.2C0 330.4 10.4 320 23.2 320c9.2 0 17.3 5.8 22.8 13.2C54.7 344.8 66.7 352 80 352c26.5 0 48-28.7 48-64s-21.5-64-48-64c-13.3 0-25.3 7.2-34 18.8C40.5 250.2 32.4 256 23.2 256C10.4 256 0 245.6 0 232.8L0 176c0-26.5 21.5-48 48-48l120.8 0c12.8 0 23.2-10.4 23.2-23.2z"],
14680
14877
  "Lock": [448, 512, [], "solid", "M144 144l0 48 160 0 0-48c0-44.2-35.8-80-80-80s-80 35.8-80 80zM80 192l0-48C80 64.5 144.5 0 224 0s144 64.5 144 144l0 48 16 0c35.3 0 64 28.7 64 64l0 192c0 35.3-28.7 64-64 64L64 512c-35.3 0-64-28.7-64-64L0 256c0-35.3 28.7-64 64-64l16 0z"],
14681
14878
  "LockOpen": [576, 512, [], "solid", "M352 144c0-44.2 35.8-80 80-80s80 35.8 80 80l0 48c0 17.7 14.3 32 32 32s32-14.3 32-32l0-48C576 64.5 511.5 0 432 0S288 64.5 288 144l0 48L64 192c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-192c0-35.3-28.7-64-64-64l-32 0 0-48z"],
14682
14879
  "Shuffle": [512, 512, [], "solid", "M403.8 34.4c12-5 25.7-2.2 34.9 6.9l64 64c6 6 9.4 14.1 9.4 22.6s-3.4 16.6-9.4 22.6l-64 64c-9.2 9.2-22.9 11.9-34.9 6.9s-19.8-16.6-19.8-29.6l0-32-32 0c-10.1 0-19.6 4.7-25.6 12.8L284 229.3 244 176l31.2-41.6C293.3 110.2 321.8 96 352 96l32 0 0-32c0-12.9 7.8-24.6 19.8-29.6zM164 282.7L204 336l-31.2 41.6C154.7 401.8 126.2 416 96 416l-64 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l64 0c10.1 0 19.6-4.7 25.6-12.8L164 282.7zm274.6 188c-9.2 9.2-22.9 11.9-34.9 6.9s-19.8-16.6-19.8-29.6l0-32-32 0c-30.2 0-58.7-14.2-76.8-38.4L121.6 172.8c-6-8.1-15.5-12.8-25.6-12.8l-64 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l64 0c30.2 0 58.7 14.2 76.8 38.4L326.4 339.2c6 8.1 15.5 12.8 25.6 12.8l32 0 0-32c0-12.9 7.8-24.6 19.8-29.6s25.7-2.2 34.9 6.9l64 64c6 6 9.4 14.1 9.4 22.6s-3.4 16.6-9.4 22.6l-64 64z"],
14880
+ "Play": [384, 512, [], "solid", "M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80L0 432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z"],
14881
+ "Pause": [320, 512, [], "solid", "M48 64C21.5 64 0 85.5 0 112L0 400c0 26.5 21.5 48 48 48l32 0c26.5 0 48-21.5 48-48l0-288c0-26.5-21.5-48-48-48L48 64zm192 0c-26.5 0-48 21.5-48 48l0 288c0 26.5 21.5 48 48 48l32 0c26.5 0 48-21.5 48-48l0-288c0-26.5-21.5-48-48-48l-32 0z"],
14882
+ "PlusCircle": [512, 512, [], "solid", "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM232 344l0-64-64 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l64 0 0-64c0-13.3 10.7-24 24-24s24 10.7 24 24l0 64 64 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-64 0 0 64c0 13.3-10.7 24-24 24s-24-10.7-24-24z"],
14683
14883
  "LogIn": [512, 512, [], "solid", "M352 96l64 0c17.7 0 32 14.3 32 32l0 256c0 17.7-14.3 32-32 32l-64 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l64 0c53 0 96-43 96-96l0-256c0-53-43-96-96-96l-64 0c-17.7 0-32 14.3-32 32s14.3 32 32 32zm-9.4 182.6c12.5-12.5 12.5-32.8 0-45.3l-128-128c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L242.7 224 32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l210.7 0-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l128-128z"],
14684
14884
  "LogOut": [512, 512, [], "solid", "M502.6 278.6c12.5-12.5 12.5-32.8 0-45.3l-128-128c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L402.7 224 192 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l210.7 0-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l128-128zM160 96c17.7 0 32-14.3 32-32s-14.3-32-32-32L96 32C43 32 0 75 0 128L0 384c0 53 43 96 96 96l64 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-64 0c-17.7 0-32-14.3-32-32l0-256c0-17.7 14.3-32 32-32l64 0z"],
14685
14885
  "MousePointer": [320, 512, [], "solid", "M0 55.2L0 426c0 12.2 9.9 22 22 22c6.3 0 12.4-2.7 16.6-7.5L121.2 346l58.1 116.3c7.9 15.8 27.1 22.2 42.9 14.3s22.2-27.1 14.3-42.9L179.8 320l118.1 0c12.2 0 22.1-9.9 22.1-22.1c0-6.3-2.7-12.3-7.4-16.5L38.6 37.9C34.3 34.1 28.9 32 23.2 32C10.4 32 0 42.4 0 55.2z"],
14686
14886
  "User": [512, 512, [], "solid", "M256 288A144 144 0 1 0 256 0a144 144 0 1 0 0 288zm-94.7 32C72.2 320 0 392.2 0 481.3c0 17 13.8 30.7 30.7 30.7l450.6 0c17 0 30.7-13.8 30.7-30.7C512 392.2 439.8 320 350.7 320l-189.4 0z"],
14687
14887
  "HardDriveDownload": [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"],
14688
14888
  "HardDriveUpload": [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"],
14689
- "CirclePlay": [512, 512, [], "solid", "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 256zM188.3 147.1c7.6-4.2 16.8-4.1 24.3 .5l144 88c7.1 4.4 11.5 12.1 11.5 20.5s-4.4 16.1-11.5 20.5l-144 88c-7.4 4.5-16.7 4.7-24.3 .5s-12.3-12.2-12.3-20.9l0-176c0-8.7 4.7-16.7 12.3-20.9z"],
14690
- "CircleStop": [512, 512, [], "solid", "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 256zm192-96l128 0c17.7 0 32 14.3 32 32l0 128c0 17.7-14.3 32-32 32l-128 0c-17.7 0-32-14.3-32-32l0-128c0-17.7 14.3-32 32-32z"],
14889
+ "CircleCheck": [512, 512, ["CheckCircle2"], "solid", "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"],
14890
+ "CirclePlay": [512, 512, [], "solid", "M0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zM188.3 147.1c-7.6 4.2-12.3 12.3-12.3 20.9l0 176c0 8.7 4.7 16.7 12.3 20.9s16.8 4.1 24.3-.5l144-88c7.1-4.4 11.5-12.1 11.5-20.5s-4.4-16.1-11.5-20.5l-144-88c-7.4-4.5-16.7-4.7-24.3-.5z"],
14891
+ "CirclePause": [512, 512, [], "solid", "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM224 192l0 128c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-128c0-17.7 14.3-32 32-32s32 14.3 32 32zm128 0l0 128c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-128c0-17.7 14.3-32 32-32s32 14.3 32 32z"],
14892
+ "CircleStop": [512, 512, [], "solid", "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM192 160l128 0c17.7 0 32 14.3 32 32l0 128c0 17.7-14.3 32-32 32l-128 0c-17.7 0-32-14.3-32-32l0-128c0-17.7 14.3-32 32-32z"],
14691
14893
  "CircleDot": [512, 512, [], "solid", "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 256zm256-96a96 96 0 1 1 0 192 96 96 0 1 1 0-192z"],
14894
+ "CircleHelp": [512, 512, ["HelpCircle"], "solid", "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM169.8 165.3c7.9-22.3 29.1-37.3 52.8-37.3l58.3 0c34.9 0 63.1 28.3 63.1 63.1c0 22.6-12.1 43.5-31.7 54.8L280 264.4c-.2 13-10.9 23.6-24 23.6c-13.3 0-24-10.7-24-24l0-13.5c0-8.6 4.6-16.5 12.1-20.8l44.3-25.4c4.7-2.7 7.6-7.7 7.6-13.1c0-8.4-6.8-15.1-15.1-15.1l-58.3 0c-3.4 0-6.4 2.1-7.5 5.3l-.4 1.2c-4.4 12.5-18.2 19-30.6 14.6s-19-18.2-14.6-30.6l.4-1.2zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"],
14692
14895
  "Apple": [384, 512, [], "solid", "M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"],
14693
14896
  "Chrome": [512, 512, [], "solid", "M0 256C0 209.4 12.47 165.6 34.27 127.1L144.1 318.3C166 357.5 207.9 384 256 384C270.3 384 283.1 381.7 296.8 377.4L220.5 509.6C95.9 492.3 0 385.3 0 256zM365.1 321.6C377.4 302.4 384 279.1 384 256C384 217.8 367.2 183.5 340.7 160H493.4C505.4 189.6 512 222.1 512 256C512 397.4 397.4 511.1 256 512L365.1 321.6zM477.8 128H256C193.1 128 142.3 172.1 130.5 230.7L54.19 98.47C101 38.53 174 0 256 0C350.8 0 433.5 51.48 477.8 128V128zM168 256C168 207.4 207.4 168 256 168C304.6 168 344 207.4 344 256C344 304.6 304.6 344 256 344C207.4 344 168 304.6 168 256z"],
14694
14897
  "Facebook": [512, 512, [], "solid", "M512 256C512 114.6 397.4 0 256 0S0 114.6 0 256C0 376 82.7 476.8 194.2 504.5V334.2H141.4V256h52.8V222.3c0-87.1 39.4-127.5 125-127.5c16.2 0 44.2 3.2 55.7 6.4V172c-6-.6-16.5-1-29.6-1c-42 0-58.2 15.9-58.2 57.2V256h83.6l-14.4 78.2H287V510.1C413.8 494.8 512 386.9 512 256h0z"],
@@ -14704,7 +14907,9 @@ LX.ICONS = {
14704
14907
  "Chain": "Link",
14705
14908
  "ChainBroken": "LinkOff",
14706
14909
  "ChainOff": "LinkOff",
14707
- "Unlink": "LinkOff"
14910
+ "Unlink": "LinkOff",
14911
+ "HelpCircle": "CircleHelp",
14912
+ "CheckCircle2": "CircleCheck"
14708
14913
  }
14709
14914
 
14710
14915
  // Alias for Lucide Icons