lexgui 0.6.10 → 0.6.11

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/README.md CHANGED
@@ -6,15 +6,15 @@ NPM Package: [npmjs.com/package/lexgui](https://www.npmjs.com/package/lexgui)
6
6
 
7
7
  <table>
8
8
  <tr>
9
- <td valign="top"><img src="data/Screenshot.png"/></td>
10
- <td valign="top"><img src="data/Screenshot_Godot.png"/></td>
9
+ <td valign="top"><img src="data/Screenshot_Editor.png"/></td>
10
+ <td valign="top"><img src="data/Screenshot_Examples.png"/></td>
11
11
  </tr>
12
12
  </table>
13
13
 
14
14
  <table>
15
15
  <tr>
16
16
  <td valign="top"><h3>Code Editor</h3><img src="data/Screenshot_Code.png"/></td>
17
- <td valign="top"><h3>Node Graph Editor (WIP)</h3><img src="data/Screenshot_Graph.png"/></td>
17
+ <td valign="top"><h3>Node Graph Editor</h3><img src="data/Screenshot_Graph.png"/></td>
18
18
  </tr>
19
19
  </table>
20
20
 
@@ -7,9 +7,9 @@ if( !LX )
7
7
  throw( "lexgui.js missing!" );
8
8
  }
9
9
 
10
- const CPP_KEY_WORDS = ['int', 'float', 'double', 'bool', 'char', 'wchar_t', 'const', 'static_cast', 'dynamic_cast', 'new', 'delete', 'void', 'true', 'false', 'auto', 'struct', 'typedef', 'nullptr', 'NULL', 'unsigned', 'namespace'];
10
+ const CPP_KEY_WORDS = ['int', 'float', 'double', 'bool', 'char', 'wchar_t', 'const', 'static_cast', 'dynamic_cast', 'new', 'delete', 'void', 'true', 'false', 'auto', 'struct', 'typedef', 'nullptr', 'NULL', 'unsigned', 'namespace', 'auto'];
11
11
  const CLASS_WORDS = ['uint32_t', 'uint64_t', 'uint8_t'];
12
- const STATEMENT_WORDS = ['for', 'if', 'else', 'return', 'continue', 'break', 'case', 'switch', 'while', 'import', 'from'];
12
+ const STATEMENT_WORDS = ['for', 'if', 'else', 'return', 'continue', 'break', 'case', 'switch', 'while', 'import', 'from', 'await'];
13
13
 
14
14
  const JS_KEY_WORDS = ['var', 'let', 'const', 'static', 'function', 'null', 'undefined', 'new', 'delete', 'true', 'false', 'NaN', 'this'];
15
15
  const HTML_ATTRIBUTES = ['html', 'charset', 'rel', 'src', 'href', 'crossorigin', 'type', 'lang'];
@@ -5,8 +5,6 @@
5
5
  }
6
6
 
7
7
  :root {
8
- color-scheme: light dark;
9
-
10
8
  --border-style: 1px solid #444;
11
9
  --panel-width: 300px;
12
10
  --page-padding: 24px;
package/build/lexgui.css CHANGED
@@ -4771,6 +4771,39 @@ ul.lexassetscontent {
4771
4771
  transform: scale(1.12);
4772
4772
  }
4773
4773
 
4774
+ /* Tour */
4775
+
4776
+ .tour-mask {
4777
+ position: absolute;
4778
+ top: 0; left: 0; right: 0; bottom: 0;
4779
+ background-color: #1f1f1fe7;
4780
+ --webkit-backdrop-filter: blur(2px);
4781
+ backdrop-filter: blur(2px);
4782
+ z-index: 99;
4783
+ clip-path: url(#svgTourClipPath);
4784
+ }
4785
+
4786
+ .tour-ref-mask {
4787
+ position: absolute;
4788
+ background-color: #1f1f1fe7;
4789
+ --webkit-backdrop-filter: blur(2px);
4790
+ backdrop-filter: blur(2px);
4791
+ z-index: 100;
4792
+ mask: url(#svgTourReferenceMask);
4793
+ }
4794
+
4795
+ .tour-step-indicator {
4796
+ width: 10px;
4797
+ height: 10px;
4798
+ border-radius: 5px;
4799
+ background-color: var(--global-text-quaternary);
4800
+ display: inline-flex;
4801
+ }
4802
+
4803
+ .tour-step-indicator.active {
4804
+ background-color: var(--global-text-primary);
4805
+ }
4806
+
4774
4807
  /* Code Editor */
4775
4808
  .codebasearea {
4776
4809
  display: flex;
package/build/lexgui.js CHANGED
@@ -14,7 +14,7 @@ console.warn( 'Script _build/lexgui.js_ is depracated and will be removed soon.
14
14
  */
15
15
 
16
16
  const LX = {
17
- version: "0.6.10",
17
+ version: "0.6.11",
18
18
  ready: false,
19
19
  components: [], // Specific pre-build components
20
20
  signals: {}, // Events and triggers
@@ -725,8 +725,6 @@ class Popover {
725
725
 
726
726
  constructor( trigger, content, options = {} ) {
727
727
 
728
- console.assert( trigger, "Popover needs a DOM element as trigger!" );
729
-
730
728
  if( Popover.activeElement )
731
729
  {
732
730
  Popover.activeElement.destroy();
@@ -734,13 +732,20 @@ class Popover {
734
732
  }
735
733
 
736
734
  this._trigger = trigger;
737
- trigger.classList.add( "triggered" );
738
- trigger.active = this;
735
+
736
+ if( trigger )
737
+ {
738
+ trigger.classList.add( "triggered" );
739
+ trigger.active = this;
740
+ }
739
741
 
740
742
  this._windowPadding = 4;
741
743
  this.side = options.side ?? "bottom";
742
744
  this.align = options.align ?? "center";
745
+ this.sideOffset = options.sideOffset ?? 0;
746
+ this.alignOffset = options.alignOffset ?? 0;
743
747
  this.avoidCollisions = options.avoidCollisions ?? true;
748
+ this.reference = options.reference;
744
749
 
745
750
  this.root = document.createElement( "div" );
746
751
  this.root.dataset["side"] = this.side;
@@ -775,29 +780,35 @@ class Popover {
775
780
  LX.doAsync( () => {
776
781
  this._adjustPosition();
777
782
 
778
- this.root.focus();
783
+ if( this._trigger )
784
+ {
785
+ this.root.focus();
779
786
 
780
- this._onClick = e => {
781
- if( e.target && ( this.root.contains( e.target ) || e.target == this._trigger ) )
782
- {
783
- return;
784
- }
785
- this.destroy();
786
- };
787
+ this._onClick = e => {
788
+ if( e.target && ( this.root.contains( e.target ) || e.target == this._trigger ) )
789
+ {
790
+ return;
791
+ }
792
+ this.destroy();
793
+ };
794
+
795
+ document.body.addEventListener( "mousedown", this._onClick, true );
796
+ document.body.addEventListener( "focusin", this._onClick, true );
797
+ }
787
798
 
788
- document.body.addEventListener( "mousedown", this._onClick, true );
789
- document.body.addEventListener( "focusin", this._onClick, true );
790
799
  }, 10 );
791
800
  }
792
801
 
793
802
  destroy() {
794
803
 
795
- this._trigger.classList.remove( "triggered" );
796
-
797
- delete this._trigger.active;
804
+ if( this._trigger )
805
+ {
806
+ this._trigger.classList.remove( "triggered" );
807
+ delete this._trigger.active;
798
808
 
799
- document.body.removeEventListener( "mousedown", this._onClick, true );
800
- document.body.removeEventListener( "focusin", this._onClick, true );
809
+ document.body.removeEventListener( "mousedown", this._onClick, true );
810
+ document.body.removeEventListener( "focusin", this._onClick, true );
811
+ }
801
812
 
802
813
  this.root.remove();
803
814
 
@@ -810,26 +821,28 @@ class Popover {
810
821
 
811
822
  // Place menu using trigger position and user options
812
823
  {
813
- const rect = this._trigger.getBoundingClientRect();
824
+ const el = this.reference ?? this._trigger;
825
+ console.assert( el, "Popover needs a trigger or reference element!" );
826
+ const rect = el.getBoundingClientRect();
814
827
 
815
828
  let alignWidth = true;
816
829
 
817
830
  switch( this.side )
818
831
  {
819
832
  case "left":
820
- position[ 0 ] += ( rect.x - this.root.offsetWidth );
833
+ position[ 0 ] += ( rect.x - this.root.offsetWidth - this.sideOffset );
821
834
  alignWidth = false;
822
835
  break;
823
836
  case "right":
824
- position[ 0 ] += ( rect.x + rect.width );
837
+ position[ 0 ] += ( rect.x + rect.width + this.sideOffset );
825
838
  alignWidth = false;
826
839
  break;
827
840
  case "top":
828
- position[ 1 ] += ( rect.y - this.root.offsetHeight );
841
+ position[ 1 ] += ( rect.y - this.root.offsetHeight - this.sideOffset );
829
842
  alignWidth = true;
830
843
  break;
831
844
  case "bottom":
832
- position[ 1 ] += ( rect.y + rect.height );
845
+ position[ 1 ] += ( rect.y + rect.height + this.sideOffset );
833
846
  alignWidth = true;
834
847
  break;
835
848
  }
@@ -849,6 +862,9 @@ class Popover {
849
862
  else { position[ 1 ] += rect.y - this.root.offsetHeight + rect.height; }
850
863
  break;
851
864
  }
865
+
866
+ if( alignWidth ) { position[ 0 ] += this.alignOffset; }
867
+ else { position[ 1 ] += this.alignOffset; }
852
868
  }
853
869
 
854
870
  if( this.avoidCollisions )
@@ -985,6 +1001,8 @@ class DropdownMenu {
985
1001
  this._windowPadding = 4;
986
1002
  this.side = options.side ?? "bottom";
987
1003
  this.align = options.align ?? "center";
1004
+ this.sideOffset = options.sideOffset ?? 0;
1005
+ this.alignOffset = options.alignOffset ?? 0;
988
1006
  this.avoidCollisions = options.avoidCollisions ?? true;
989
1007
  this.onBlur = options.onBlur;
990
1008
  this.inPlace = false;
@@ -1227,19 +1245,19 @@ class DropdownMenu {
1227
1245
  switch( this.side )
1228
1246
  {
1229
1247
  case "left":
1230
- position[ 0 ] += ( rect.x - this.root.offsetWidth );
1248
+ position[ 0 ] += ( rect.x - this.root.offsetWidth - this.sideOffset );
1231
1249
  alignWidth = false;
1232
1250
  break;
1233
1251
  case "right":
1234
- position[ 0 ] += ( rect.x + rect.width );
1252
+ position[ 0 ] += ( rect.x + rect.width + this.sideOffset );
1235
1253
  alignWidth = false;
1236
1254
  break;
1237
1255
  case "top":
1238
- position[ 1 ] += ( rect.y - this.root.offsetHeight );
1256
+ position[ 1 ] += ( rect.y - this.root.offsetHeight - this.sideOffset );
1239
1257
  alignWidth = true;
1240
1258
  break;
1241
1259
  case "bottom":
1242
- position[ 1 ] += ( rect.y + rect.height );
1260
+ position[ 1 ] += ( rect.y + rect.height + this.sideOffset );
1243
1261
  alignWidth = true;
1244
1262
  break;
1245
1263
  }
@@ -1259,6 +1277,9 @@ class DropdownMenu {
1259
1277
  else { position[ 1 ] += rect.y - this.root.offsetHeight + rect.height; }
1260
1278
  break;
1261
1279
  }
1280
+
1281
+ if( alignWidth ) { position[ 0 ] += this.alignOffset; }
1282
+ else { position[ 1 ] += this.alignOffset; }
1262
1283
  }
1263
1284
 
1264
1285
  if( this.avoidCollisions )
@@ -8962,16 +8983,17 @@ class Form extends Widget {
8962
8983
 
8963
8984
  if( entryData.constructor != Object )
8964
8985
  {
8965
- entryData = { };
8986
+ const oldValue = JSON.parse( JSON.stringify( entryData ) );
8987
+ entryData = { value: oldValue };
8966
8988
  data[ entry ] = entryData;
8967
8989
  }
8968
8990
 
8969
- entryData.placeholder = entryData.placeholder ?? entry;
8991
+ entryData.placeholder = entryData.placeholder ?? ( entryData.label ?? `Enter ${ entry }` );
8970
8992
  entryData.width = "100%";
8971
8993
 
8972
8994
  if( !( options.skipLabels ?? false ) )
8973
8995
  {
8974
- const label = new LX.TextInput( null, entry, null, { disabled: true, inputClass: "formlabel nobg" } );
8996
+ const label = new LX.TextInput( null, entryData.label ?? entry, null, { disabled: true, inputClass: "formlabel nobg" } );
8975
8997
  container.appendChild( label.root );
8976
8998
  }
8977
8999
 
@@ -10666,15 +10688,15 @@ class Vector extends Widget {
10666
10688
 
10667
10689
  for( let i = 0; i < vectorInputs.length; ++i )
10668
10690
  {
10669
- let value = newValue[ i ];
10670
- value = LX.clamp( value, +vectorInputs[ i ].min, +vectorInputs[ i ].max );
10671
- value = LX.round( value, options.precision ) ?? 0;
10672
- vectorInputs[ i ].value = newValue[ i ] = value;
10691
+ let vecValue = newValue[ i ];
10692
+ vecValue = LX.clamp( vecValue, +vectorInputs[ i ].min, +vectorInputs[ i ].max );
10693
+ vecValue = LX.round( vecValue, options.precision ) ?? 0;
10694
+ vectorInputs[ i ].value = value[ i ] = vecValue;
10673
10695
  }
10674
10696
 
10675
10697
  if( !skipCallback )
10676
10698
  {
10677
- this._trigger( new LX.IEvent( name, newValue, event ), callback );
10699
+ this._trigger( new LX.IEvent( name, value, event ), callback );
10678
10700
  }
10679
10701
  };
10680
10702
 
@@ -11264,12 +11286,18 @@ class Progress extends Widget {
11264
11286
  };
11265
11287
 
11266
11288
  this.onSetValue = ( newValue, skipCallback, event ) => {
11289
+ newValue = LX.clamp( newValue, progress.min, progress.max );
11267
11290
  this.root.querySelector("meter").value = newValue;
11268
11291
  _updateColor();
11269
11292
  if( this.root.querySelector("span") )
11270
11293
  {
11271
11294
  this.root.querySelector("span").innerText = newValue;
11272
11295
  }
11296
+
11297
+ if( !skipCallback )
11298
+ {
11299
+ this._trigger( new LX.IEvent( name, newValue, event ), options.callback );
11300
+ }
11273
11301
  };
11274
11302
 
11275
11303
  this.onResize = ( rect ) => {
@@ -11353,11 +11381,6 @@ class Progress extends Widget {
11353
11381
  const rect = progress.getBoundingClientRect();
11354
11382
  const newValue = LX.round( LX.remapRange( e.offsetX - rect.x, 0, rect.width, progress.min, progress.max ) );
11355
11383
  this.set( newValue, false, e );
11356
-
11357
- if( options.callback )
11358
- {
11359
- options.callback( newValue, e );
11360
- }
11361
11384
  }
11362
11385
 
11363
11386
  e.stopPropagation();
@@ -15828,4 +15851,281 @@ class AssetView {
15828
15851
 
15829
15852
  LX.AssetView = AssetView;
15830
15853
 
15854
+ // tour.js @jxarco
15855
+
15856
+ class Tour {
15857
+
15858
+ /**
15859
+ * @constructor Tour
15860
+ * @param {Array} steps
15861
+ * @param {Object} options
15862
+ * useModal: Use a modal to highlight the tour step [true]
15863
+ * offset: Horizontal and vertical margin offset [0]
15864
+ * horizontalOffset: Horizontal offset [0]
15865
+ * verticalOffset: Vertical offset [0]
15866
+ * radius: Radius for the tour step highlight [8]
15867
+ */
15868
+
15869
+ constructor( steps, options = {} ) {
15870
+
15871
+ this.steps = steps || [];
15872
+ this.currentStep = 0;
15873
+
15874
+ this.useModal = options.useModal ?? true;
15875
+ this.offset = options.offset ?? 8;
15876
+ this.horizontalOffset = options.horizontalOffset;
15877
+ this.verticalOffset = options.verticalOffset;
15878
+ this.radius = options.radius ?? 12;
15879
+
15880
+ this.tourContainer = LX.makeContainer( ["100%", "100%"], "tour-container" );
15881
+ this.tourContainer.style.display = "none";
15882
+ document.body.appendChild( this.tourContainer );
15883
+
15884
+ this.tourMask = LX.makeContainer( ["100%", "100%"], "tour-mask" );
15885
+ }
15886
+
15887
+ /**
15888
+ * @method begin
15889
+ */
15890
+
15891
+ begin() {
15892
+
15893
+ this.currentStep = 0;
15894
+
15895
+ if ( this.useModal )
15896
+ {
15897
+ this.tourMask.style.display = "block";
15898
+ this.tourContainer.appendChild( this.tourMask );
15899
+ }
15900
+
15901
+ this.tourContainer.style.display = "block";
15902
+
15903
+ this._showStep( 0 );
15904
+ }
15905
+
15906
+ /**
15907
+ * @method stop
15908
+ */
15909
+
15910
+ stop() {
15911
+
15912
+ if( this.useModal )
15913
+ {
15914
+ this.tourMask.style.display = "none";
15915
+ this.tourContainer.removeChild( this.tourMask );
15916
+ }
15917
+
15918
+ this._popover?.destroy();
15919
+
15920
+ this.tourContainer.style.display = "none";
15921
+ }
15922
+
15923
+ // Show the current step of the tour
15924
+ _showStep( stepOffset = 1 ) {
15925
+
15926
+ this.currentStep += stepOffset;
15927
+
15928
+ const step = this.steps[ this.currentStep ];
15929
+ if ( !step ) {
15930
+ this.stop();
15931
+ return;
15932
+ }
15933
+
15934
+ const prevStep = this.steps[ this.currentStep - 1 ];
15935
+ const nextStep = this.steps[ this.currentStep + 1 ];
15936
+
15937
+ this._generateMask( step.reference );
15938
+ this._createHighlight( step, prevStep, nextStep );
15939
+ }
15940
+
15941
+ // Generate mask for the specific step reference
15942
+ // using a fullscreen SVG with "rect" elements
15943
+ _generateMask( reference ) {
15944
+
15945
+ this.tourMask.innerHTML = ""; // Clear previous content
15946
+
15947
+ const svg = document.createElementNS( "http://www.w3.org/2000/svg", "svg" );
15948
+ svg.style.width = "100%";
15949
+ svg.style.height = "100%";
15950
+ this.tourMask.appendChild( svg );
15951
+
15952
+ const clipPath = document.createElementNS( "http://www.w3.org/2000/svg", "clipPath" );
15953
+ clipPath.setAttribute( "id", "svgTourClipPath" );
15954
+ svg.appendChild( clipPath );
15955
+
15956
+ function ceilAndShiftRect( p, s ) {
15957
+ const cp = Math.ceil( p );
15958
+ const delta = cp - p;
15959
+ const ds = s - delta;
15960
+ return [ cp, ds ];
15961
+ }
15962
+
15963
+ const refBounding = reference.getBoundingClientRect();
15964
+ const [ boundingX, boundingWidth ] = ceilAndShiftRect( refBounding.x, refBounding.width );
15965
+ const [ boundingY, boundingHeight ] = ceilAndShiftRect( refBounding.y, refBounding.height );
15966
+
15967
+ const vOffset = this.verticalOffset ?? this.offset;
15968
+ const hOffset = this.horizontalOffset ?? this.offset;
15969
+
15970
+ // Left
15971
+ {
15972
+ const rect = document.createElementNS( "http://www.w3.org/2000/svg", "rect" );
15973
+ rect.setAttribute( "x", 0 );
15974
+ rect.setAttribute( "y", 0 );
15975
+ rect.setAttribute( "width", boundingX - hOffset );
15976
+ rect.setAttribute( "height", window.innerHeight );
15977
+ rect.setAttribute( "stroke", "none" );
15978
+ clipPath.appendChild( rect );
15979
+ }
15980
+
15981
+ // Top
15982
+ {
15983
+ const rect = document.createElementNS( "http://www.w3.org/2000/svg", "rect" );
15984
+ rect.setAttribute( "x", boundingX - hOffset );
15985
+ rect.setAttribute( "y", 0 );
15986
+ rect.setAttribute( "width", boundingWidth + hOffset * 2 );
15987
+ rect.setAttribute( "height", boundingY - vOffset );
15988
+ rect.setAttribute( "stroke", "none" );
15989
+ clipPath.appendChild( rect );
15990
+ }
15991
+
15992
+ // Bottom
15993
+ {
15994
+ const rect = document.createElementNS( "http://www.w3.org/2000/svg", "rect" );
15995
+ rect.setAttribute( "x", boundingX - hOffset );
15996
+ rect.setAttribute( "y", boundingY + boundingHeight + vOffset );
15997
+ rect.setAttribute( "width", boundingWidth + hOffset * 2 );
15998
+ rect.setAttribute( "height", window.innerHeight - boundingY - boundingHeight - vOffset );
15999
+ rect.setAttribute( "stroke", "none" );
16000
+ clipPath.appendChild( rect );
16001
+ }
16002
+
16003
+ // Right
16004
+ {
16005
+ const rect = document.createElementNS( "http://www.w3.org/2000/svg", "rect" );
16006
+ rect.setAttribute( "x", boundingX + boundingWidth + hOffset );
16007
+ rect.setAttribute( "y", 0 );
16008
+ rect.setAttribute( "width", window.innerWidth - boundingX - boundingWidth );
16009
+ rect.setAttribute( "height", window.innerHeight );
16010
+ rect.setAttribute( "stroke", "none" );
16011
+ clipPath.appendChild( rect );
16012
+ }
16013
+
16014
+ // Reference Highlight
16015
+ const refContainer = LX.makeContainer( ["0", "0"], "tour-ref-mask" );
16016
+ refContainer.style.left = `${ boundingX - hOffset - 1 }px`;
16017
+ refContainer.style.top = `${ boundingY - vOffset - 1 }px`;
16018
+ refContainer.style.width = `${ boundingWidth + hOffset * 2 + 2 }px`;
16019
+ refContainer.style.height = `${ boundingHeight + vOffset * 2 + 2}px`;
16020
+ this.tourContainer.appendChild( refContainer );
16021
+
16022
+ const referenceMask = document.createElementNS( "http://www.w3.org/2000/svg", "mask" );
16023
+ referenceMask.setAttribute( "id", "svgTourReferenceMask" );
16024
+ svg.appendChild( referenceMask );
16025
+
16026
+ // Reference Mask
16027
+ {
16028
+ const rectWhite = document.createElementNS( "http://www.w3.org/2000/svg", "rect" );
16029
+ rectWhite.setAttribute( "width", boundingWidth + hOffset * 2 + 2 );
16030
+ rectWhite.setAttribute( "height", boundingHeight + vOffset * 2 + 2);
16031
+ rectWhite.setAttribute( "stroke", "none" );
16032
+ rectWhite.setAttribute( "fill", "white" );
16033
+ referenceMask.appendChild( rectWhite );
16034
+
16035
+ const rectBlack = document.createElementNS( "http://www.w3.org/2000/svg", "rect" );
16036
+ rectBlack.setAttribute( "rx", this.radius );
16037
+ rectBlack.setAttribute( "width", boundingWidth + hOffset * 2 + 2);
16038
+ rectBlack.setAttribute( "height", boundingHeight + vOffset * 2 + 2);
16039
+ rectBlack.setAttribute( "stroke", "none" );
16040
+ rectBlack.setAttribute( "fill", "black" );
16041
+ referenceMask.appendChild( rectBlack );
16042
+ }
16043
+ }
16044
+
16045
+ // Create the container with the user hints
16046
+ _createHighlight( step, previousStep, nextStep ) {
16047
+
16048
+ const popoverContainer = LX.makeContainer( ["auto", "auto"], "tour-step-container" );
16049
+
16050
+ {
16051
+ const header = LX.makeContainer( ["100%", "auto"], "flex flex-row", "", popoverContainer );
16052
+ LX.makeContainer( ["70%", "auto"], "p-2 font-medium", step.title, header );
16053
+ const closer = LX.makeContainer( ["30%", "auto"], "flex flex-row p-2 justify-end", "", header );
16054
+ const closeIcon = LX.makeIcon( "X" );
16055
+ closer.appendChild( closeIcon );
16056
+
16057
+ closeIcon.listen( "click", () => {
16058
+ this.stop();
16059
+ } );
16060
+ }
16061
+
16062
+ LX.makeContainer( ["100%", "auto"], "p-2 text-md", step.content, popoverContainer, { maxWidth: "400px" } );
16063
+ const footer = LX.makeContainer( ["100%", "auto"], "flex flex-row text-md", "", popoverContainer );
16064
+
16065
+ {
16066
+ const footerSteps = LX.makeContainer( ["50%", "auto"], "p-2 gap-1 self-center flex flex-row text-md", "", footer );
16067
+ for( let i = 0; i < this.steps.length; i++ )
16068
+ {
16069
+ const stepIndicator = document.createElement( "span" );
16070
+ stepIndicator.className = "tour-step-indicator";
16071
+ if( i === this.currentStep )
16072
+ {
16073
+ stepIndicator.classList.add( "active" );
16074
+ }
16075
+ footerSteps.appendChild( stepIndicator );
16076
+ }
16077
+ }
16078
+
16079
+ const footerButtons = LX.makeContainer( ["50%", "auto"], "text-md", "", footer );
16080
+ const footerPanel = new LX.Panel();
16081
+
16082
+ let numButtons = 1;
16083
+
16084
+ if( previousStep )
16085
+ {
16086
+ numButtons++;
16087
+ }
16088
+
16089
+ if( numButtons > 1 )
16090
+ {
16091
+ footerPanel.sameLine( 2, "justify-end" );
16092
+ }
16093
+
16094
+ if( previousStep )
16095
+ {
16096
+ footerPanel.addButton( null, "Previous", () => {
16097
+ this._showStep( -1 );
16098
+ }, { buttonClass: "contrast" } );
16099
+ }
16100
+
16101
+ if( nextStep )
16102
+ {
16103
+ footerPanel.addButton( null, "Next", () => {
16104
+ this._showStep( 1 );
16105
+ }, { buttonClass: "accent" } );
16106
+ }
16107
+ else
16108
+ {
16109
+ footerPanel.addButton( null, "Finish", () => {
16110
+ this.stop();
16111
+ } );
16112
+ }
16113
+
16114
+ footerButtons.appendChild( footerPanel.root );
16115
+
16116
+ const sideOffset = ( step.side === "left" || step.side === "right" ? this.horizontalOffset : this.verticalOffset ) ?? this.offset;
16117
+ const alignOffset = ( step.align === "start" || step.align === "end" ? sideOffset : 0 );
16118
+
16119
+ this._popover?.destroy();
16120
+ this._popover = new LX.Popover( null, [ popoverContainer ], {
16121
+ reference: step.reference,
16122
+ side: step.side,
16123
+ align: step.align,
16124
+ sideOffset,
16125
+ alignOffset: step.align === "start" ? -alignOffset : alignOffset,
16126
+ } );
16127
+ }
16128
+ }
16129
+ LX.Tour = Tour;
16130
+
15831
16131
  })( typeof(window) != 'undefined' ? window : (typeof(self) != 'undefined' ? self : global ) );