lexgui 0.7.4 → 0.7.6

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.
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  const LX = {
10
- version: "0.7.4",
10
+ version: "0.7.6",
11
11
  ready: false,
12
12
  extensions: [], // Store extensions used
13
13
  signals: {}, // Events and triggers
@@ -536,16 +536,30 @@ async function init( options = { } )
536
536
  this.main_area = new LX.Area( { id: options.id ?? 'mainarea' } );
537
537
  }
538
538
 
539
- if( ( options.autoTheme ?? true ) )
539
+ // Initial or automatic changes don't force color scheme
540
+ // to be stored in localStorage
541
+
542
+ this._onChangeSystemTheme = function( event ) {
543
+ const storedcolorScheme = localStorage.getItem( "lxColorScheme" );
544
+ if( storedcolorScheme ) return;
545
+ LX.setTheme( event.matches ? "dark" : "light", false );
546
+ };
547
+
548
+ this._mqlPrefersDarkScheme = window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null;
549
+
550
+ const storedcolorScheme = localStorage.getItem( "lxColorScheme" );
551
+ if( storedcolorScheme )
540
552
  {
541
- if( window.matchMedia && window.matchMedia( "(prefers-color-scheme: light)" ).matches )
553
+ LX.setTheme( storedcolorScheme );
554
+ }
555
+ else if( this._mqlPrefersDarkScheme && ( options.autoTheme ?? true ) )
556
+ {
557
+ if( window.matchMedia( "(prefers-color-scheme: light)" ).matches )
542
558
  {
543
- LX.setTheme( "light" );
559
+ LX.setTheme( "light", false );
544
560
  }
545
561
 
546
- window.matchMedia( "(prefers-color-scheme: dark)" ).addEventListener( "change", event => {
547
- LX.setTheme( event.matches ? "dark" : "light" );
548
- });
562
+ this._mqlPrefersDarkScheme.addEventListener( "change", this._onChangeSystemTheme );
549
563
  }
550
564
 
551
565
  return this.main_area;
@@ -1092,6 +1106,7 @@ class DropdownMenu {
1092
1106
  this.alignOffset = options.alignOffset ?? 0;
1093
1107
  this.avoidCollisions = options.avoidCollisions ?? true;
1094
1108
  this.onBlur = options.onBlur;
1109
+ this.event = options.event;
1095
1110
  this.inPlace = false;
1096
1111
 
1097
1112
  this.root = document.createElement( "div" );
@@ -1382,11 +1397,11 @@ class DropdownMenu {
1382
1397
  _adjustPosition() {
1383
1398
 
1384
1399
  const position = [ 0, 0 ];
1400
+ const rect = this._trigger.getBoundingClientRect();
1385
1401
 
1386
1402
  // Place menu using trigger position and user options
1403
+ if( !this.event )
1387
1404
  {
1388
- const rect = this._trigger.getBoundingClientRect();
1389
-
1390
1405
  let alignWidth = true;
1391
1406
 
1392
1407
  switch( this.side )
@@ -1428,11 +1443,11 @@ class DropdownMenu {
1428
1443
  if( alignWidth ) { position[ 0 ] += this.alignOffset; }
1429
1444
  else { position[ 1 ] += this.alignOffset; }
1430
1445
  }
1431
-
1432
- if( this.avoidCollisions )
1446
+ // Offset position based on event
1447
+ else
1433
1448
  {
1434
- position[ 0 ] = LX.clamp( position[ 0 ], 0, window.innerWidth - this.root.offsetWidth - this._windowPadding );
1435
- position[ 1 ] = LX.clamp( position[ 1 ], 0, window.innerHeight - this.root.offsetHeight - this._windowPadding );
1449
+ position[ 0 ] = this.event.x;
1450
+ position[ 1 ] = this.event.y;
1436
1451
  }
1437
1452
 
1438
1453
  if( this._parent instanceof HTMLDialogElement )
@@ -1442,6 +1457,12 @@ class DropdownMenu {
1442
1457
  position[ 1 ] -= parentRect.y;
1443
1458
  }
1444
1459
 
1460
+ if( this.avoidCollisions )
1461
+ {
1462
+ position[ 0 ] = LX.clamp( position[ 0 ], 0, window.innerWidth - this.root.offsetWidth - this._windowPadding );
1463
+ position[ 1 ] = LX.clamp( position[ 1 ], 0, window.innerHeight - this.root.offsetHeight - this._windowPadding );
1464
+ }
1465
+
1445
1466
  this.root.style.left = `${ position[ 0 ] }px`;
1446
1467
  this.root.style.top = `${ position[ 1 ] }px`;
1447
1468
  this.inPlace = true;
@@ -2538,8 +2559,9 @@ class Tabs {
2538
2559
  });
2539
2560
 
2540
2561
  // Attach content
2541
- tabEl.childIndex = ( this.root.childElementCount - 1 );
2542
- this.root.appendChild( tabEl );
2562
+ const indexOffset = options.indexOffset ?? -1;
2563
+ tabEl.childIndex = ( this.root.childElementCount + indexOffset );
2564
+ this.root.insertChildAtIndex( tabEl, tabEl.childIndex + 1 );
2543
2565
  this.area.attach( contentEl );
2544
2566
  this.tabDOMs[ name ] = tabEl;
2545
2567
  this.tabs[ name ] = content;
@@ -4964,11 +4986,13 @@ LX.deepCopy = deepCopy;
4964
4986
  * @method setTheme
4965
4987
  * @description Set dark or light theme
4966
4988
  * @param {String} colorScheme Name of the scheme
4989
+ * @param {Boolean} storeLocal Store in localStorage
4967
4990
  */
4968
- function setTheme( colorScheme )
4991
+ function setTheme( colorScheme, storeLocal = true )
4969
4992
  {
4970
4993
  colorScheme = ( colorScheme == "light" ) ? "light" : "dark";
4971
4994
  document.documentElement.setAttribute( "data-theme", colorScheme );
4995
+ if( storeLocal ) localStorage.setItem( "lxColorScheme", colorScheme );
4972
4996
  LX.emit( "@on_new_color_scheme", colorScheme );
4973
4997
  }
4974
4998
 
@@ -4997,6 +5021,26 @@ function switchTheme()
4997
5021
 
4998
5022
  LX.switchTheme = switchTheme;
4999
5023
 
5024
+ /**
5025
+ * @method setSystemTheme
5026
+ * @description Sets back the system theme
5027
+ */
5028
+ function setSystemTheme()
5029
+ {
5030
+ const currentTheme = ( window.matchMedia && window.matchMedia( "(prefers-color-scheme: light)" ).matches ) ? "light" : "dark";
5031
+ setTheme( currentTheme );
5032
+ localStorage.removeItem( "lxColorScheme" );
5033
+
5034
+ // Reapply listener
5035
+ if( this._mqlPrefersDarkScheme )
5036
+ {
5037
+ this._mqlPrefersDarkScheme.removeEventListener( "change", this._onChangeSystemTheme );
5038
+ this._mqlPrefersDarkScheme.addEventListener( "change", this._onChangeSystemTheme );
5039
+ }
5040
+ }
5041
+
5042
+ LX.setSystemTheme = setSystemTheme;
5043
+
5000
5044
  /**
5001
5045
  * @method setThemeColor
5002
5046
  * @description Sets a new value for one of the main theme variables
@@ -8979,7 +9023,7 @@ class TextInput extends BaseComponent {
8979
9023
 
8980
9024
  this.valid = ( v ) => {
8981
9025
  v = v ?? this.value();
8982
- if( !v.length || wValue.pattern == "" ) return true;
9026
+ if( ( wValue.pattern ?? "" ) == "" ) return true;
8983
9027
  const regexp = new RegExp( wValue.pattern );
8984
9028
  return regexp.test( v );
8985
9029
  };
@@ -9718,19 +9762,21 @@ class Form extends BaseComponent {
9718
9762
 
9719
9763
  const primaryButton = new LX.Button( null, options.primaryActionName ?? "Submit", ( value, event ) => {
9720
9764
 
9765
+ const errors = [];
9766
+
9721
9767
  for( let entry in data )
9722
9768
  {
9723
9769
  let entryData = data[ entry ];
9724
9770
 
9725
9771
  if( !entryData.textComponent.valid() )
9726
9772
  {
9727
- return;
9773
+ errors.push( { type: "input_not_valid", entry } );
9728
9774
  }
9729
9775
  }
9730
9776
 
9731
9777
  if( callback )
9732
9778
  {
9733
- callback( container.formData, event );
9779
+ callback( container.formData, errors, event );
9734
9780
  }
9735
9781
  }, { width: "100%", minWidth: "0", buttonClass: options.primaryButtonClass ?? "contrast" } );
9736
9782
 
@@ -15935,8 +15981,7 @@ class Sidebar {
15935
15981
  return;
15936
15982
  }
15937
15983
 
15938
- const f = options.callback;
15939
- if( f ) f.call( this, key, item.value, e );
15984
+ let value = undefined;
15940
15985
 
15941
15986
  if( isCollapsable )
15942
15987
  {
@@ -15946,14 +15991,18 @@ class Sidebar {
15946
15991
  {
15947
15992
  item.value = !item.value;
15948
15993
  item.checkbox.set( item.value, true );
15994
+ value = item.value;
15949
15995
  }
15950
-
15951
- if( options.swap && !( e.target instanceof HTMLInputElement ) )
15996
+ else if( options.swap && !( e.target instanceof HTMLInputElement ) )
15952
15997
  {
15953
15998
  const swapInput = itemDom.querySelector( "input" );
15954
15999
  swapInput.checked = !swapInput.checked;
16000
+ value = swapInput.checked;
15955
16001
  }
15956
16002
 
16003
+ const f = options.callback;
16004
+ if( f ) f.call( this, key, value ?? entry, e );
16005
+
15957
16006
  // Manage selected
15958
16007
  if( this.displaySelected && !options.skipSelection )
15959
16008
  {