lexgui 0.6.9 → 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 +3 -3
- package/build/components/docmaker.js +2 -2
- package/build/components/timeline.js +102 -73
- package/build/lexgui-docs.css +0 -2
- package/build/lexgui.css +39 -4
- package/build/lexgui.js +640 -259
- package/build/lexgui.min.css +1 -1
- package/build/lexgui.min.js +1 -1
- package/build/lexgui.module.js +682 -301
- package/build/lexgui.module.min.js +1 -1
- package/changelog.md +33 -1
- package/demo.js +27 -0
- package/examples/editor.html +11 -6
- package/package.json +3 -2
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.
|
|
17
|
+
version: "0.6.11",
|
|
18
18
|
ready: false,
|
|
19
19
|
components: [], // Specific pre-build components
|
|
20
20
|
signals: {}, // Events and triggers
|
|
@@ -318,7 +318,7 @@ function _createCommandbar( root )
|
|
|
318
318
|
|
|
319
319
|
const _propagateAdd = ( item, filter, path, skipPropagation ) => {
|
|
320
320
|
|
|
321
|
-
if( !item )
|
|
321
|
+
if( !item || ( item.constructor != Object ) )
|
|
322
322
|
{
|
|
323
323
|
return;
|
|
324
324
|
}
|
|
@@ -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
|
-
|
|
738
|
-
trigger
|
|
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.
|
|
783
|
+
if( this._trigger )
|
|
784
|
+
{
|
|
785
|
+
this.root.focus();
|
|
779
786
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
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
|
|
796
|
-
|
|
797
|
-
|
|
804
|
+
if( this._trigger )
|
|
805
|
+
{
|
|
806
|
+
this._trigger.classList.remove( "triggered" );
|
|
807
|
+
delete this._trigger.active;
|
|
798
808
|
|
|
799
|
-
|
|
800
|
-
|
|
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
|
|
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 )
|
|
@@ -1537,7 +1558,7 @@ class ColorPicker {
|
|
|
1537
1558
|
copyButtonWidget.root.querySelector( "input[type='checkbox']" ).style.pointerEvents = "none";
|
|
1538
1559
|
|
|
1539
1560
|
LX.doAsync( () => {
|
|
1540
|
-
copyButtonWidget.
|
|
1561
|
+
copyButtonWidget.swap( true );
|
|
1541
1562
|
copyButtonWidget.root.querySelector( "input[type='checkbox']" ).style.pointerEvents = "auto";
|
|
1542
1563
|
}, 3000 );
|
|
1543
1564
|
|
|
@@ -6020,6 +6041,176 @@ LX.drawSpline = drawSpline;
|
|
|
6020
6041
|
|
|
6021
6042
|
// area.js @jxarco
|
|
6022
6043
|
|
|
6044
|
+
class AreaOverlayButtons {
|
|
6045
|
+
|
|
6046
|
+
/**
|
|
6047
|
+
* @constructor AreaOverlayButtons
|
|
6048
|
+
*/
|
|
6049
|
+
|
|
6050
|
+
constructor( area, buttonsArray, options = {} ) {
|
|
6051
|
+
|
|
6052
|
+
this.area = area;
|
|
6053
|
+
this.options = options;
|
|
6054
|
+
|
|
6055
|
+
this.buttons = {};
|
|
6056
|
+
|
|
6057
|
+
this._buildButtons( buttonsArray, options );
|
|
6058
|
+
}
|
|
6059
|
+
|
|
6060
|
+
_buildButtons( buttonsArray, options ) {
|
|
6061
|
+
|
|
6062
|
+
options.className = "lexoverlaybuttons";
|
|
6063
|
+
|
|
6064
|
+
let overlayPanel = this.area.addPanel( options );
|
|
6065
|
+
let overlayGroup = null;
|
|
6066
|
+
|
|
6067
|
+
const container = document.createElement( "div" );
|
|
6068
|
+
container.className = "lexoverlaybuttonscontainer";
|
|
6069
|
+
container.appendChild( overlayPanel.root );
|
|
6070
|
+
this.area.attach( container );
|
|
6071
|
+
|
|
6072
|
+
const float = options.float;
|
|
6073
|
+
let floatClass = "";
|
|
6074
|
+
|
|
6075
|
+
if( float )
|
|
6076
|
+
{
|
|
6077
|
+
for( let i = 0; i < float.length; i++ )
|
|
6078
|
+
{
|
|
6079
|
+
const t = float[ i ];
|
|
6080
|
+
switch( t )
|
|
6081
|
+
{
|
|
6082
|
+
case 'h': break;
|
|
6083
|
+
case 'v': floatClass += " vertical"; break;
|
|
6084
|
+
case 't': break;
|
|
6085
|
+
case 'm': floatClass += " middle"; break;
|
|
6086
|
+
case 'b': floatClass += " bottom"; break;
|
|
6087
|
+
case 'l': break;
|
|
6088
|
+
case 'c': floatClass += " center"; break;
|
|
6089
|
+
case 'r': floatClass += " right"; break;
|
|
6090
|
+
}
|
|
6091
|
+
}
|
|
6092
|
+
|
|
6093
|
+
container.className += ` ${ floatClass }`;
|
|
6094
|
+
}
|
|
6095
|
+
|
|
6096
|
+
const _addButton = ( b, group, last ) => {
|
|
6097
|
+
|
|
6098
|
+
const _options = {
|
|
6099
|
+
width: "auto",
|
|
6100
|
+
selectable: b.selectable,
|
|
6101
|
+
selected: b.selected,
|
|
6102
|
+
icon: b.icon,
|
|
6103
|
+
img: b.img,
|
|
6104
|
+
className: b.class ?? "",
|
|
6105
|
+
title: b.name,
|
|
6106
|
+
overflowContainerX: overlayPanel.root,
|
|
6107
|
+
swap: b.swap
|
|
6108
|
+
};
|
|
6109
|
+
|
|
6110
|
+
if( group )
|
|
6111
|
+
{
|
|
6112
|
+
if( !overlayGroup )
|
|
6113
|
+
{
|
|
6114
|
+
overlayGroup = document.createElement('div');
|
|
6115
|
+
overlayGroup.className = "lexoverlaygroup";
|
|
6116
|
+
overlayPanel.queuedContainer = overlayGroup;
|
|
6117
|
+
}
|
|
6118
|
+
|
|
6119
|
+
_options.parent = overlayGroup;
|
|
6120
|
+
}
|
|
6121
|
+
|
|
6122
|
+
let callback = b.callback;
|
|
6123
|
+
let widget = null;
|
|
6124
|
+
|
|
6125
|
+
if( b.options )
|
|
6126
|
+
{
|
|
6127
|
+
widget = overlayPanel.addSelect( null, b.options, b.value ?? b.name, callback, _options );
|
|
6128
|
+
}
|
|
6129
|
+
else
|
|
6130
|
+
{
|
|
6131
|
+
widget = overlayPanel.addButton( null, b.name, function( value, event ) {
|
|
6132
|
+
if( b.selectable )
|
|
6133
|
+
{
|
|
6134
|
+
if( b.group )
|
|
6135
|
+
{
|
|
6136
|
+
let _prev = b.selected;
|
|
6137
|
+
b.group.forEach( sub => sub.selected = false );
|
|
6138
|
+
b.selected = !_prev;
|
|
6139
|
+
}
|
|
6140
|
+
else
|
|
6141
|
+
{
|
|
6142
|
+
b.selected = !b.selected;
|
|
6143
|
+
}
|
|
6144
|
+
}
|
|
6145
|
+
|
|
6146
|
+
if( callback )
|
|
6147
|
+
{
|
|
6148
|
+
callback( value, event, widget.root );
|
|
6149
|
+
}
|
|
6150
|
+
|
|
6151
|
+
}, _options );
|
|
6152
|
+
}
|
|
6153
|
+
|
|
6154
|
+
this.buttons[ b.name ] = widget;
|
|
6155
|
+
|
|
6156
|
+
// ends the group
|
|
6157
|
+
if( overlayGroup && last )
|
|
6158
|
+
{
|
|
6159
|
+
overlayPanel.root.appendChild( overlayGroup );
|
|
6160
|
+
overlayGroup = null;
|
|
6161
|
+
overlayPanel.clearQueue();
|
|
6162
|
+
}
|
|
6163
|
+
};
|
|
6164
|
+
|
|
6165
|
+
const _refreshPanel = function() {
|
|
6166
|
+
|
|
6167
|
+
overlayPanel.clear();
|
|
6168
|
+
|
|
6169
|
+
for( let b of buttonsArray )
|
|
6170
|
+
{
|
|
6171
|
+
if( b === null )
|
|
6172
|
+
{
|
|
6173
|
+
// Add a separator
|
|
6174
|
+
const separator = document.createElement("div");
|
|
6175
|
+
separator.className = "lexoverlayseparator" + floatClass;
|
|
6176
|
+
overlayPanel.root.appendChild( separator );
|
|
6177
|
+
continue;
|
|
6178
|
+
}
|
|
6179
|
+
|
|
6180
|
+
if( b.constructor === Array )
|
|
6181
|
+
{
|
|
6182
|
+
for( let i = 0; i < b.length; ++i )
|
|
6183
|
+
{
|
|
6184
|
+
let sub = b[ i ];
|
|
6185
|
+
sub.group = b;
|
|
6186
|
+
_addButton( sub, true, i == ( b.length - 1 ) );
|
|
6187
|
+
}
|
|
6188
|
+
}
|
|
6189
|
+
else
|
|
6190
|
+
{
|
|
6191
|
+
_addButton( b );
|
|
6192
|
+
}
|
|
6193
|
+
}
|
|
6194
|
+
|
|
6195
|
+
// Add floating info
|
|
6196
|
+
if( float )
|
|
6197
|
+
{
|
|
6198
|
+
var height = 0;
|
|
6199
|
+
overlayPanel.root.childNodes.forEach( c => { height += c.offsetHeight; } );
|
|
6200
|
+
|
|
6201
|
+
if( container.className.includes( "middle" ) )
|
|
6202
|
+
{
|
|
6203
|
+
container.style.top = "-moz-calc( 50% - " + (height * 0.5) + "px )";
|
|
6204
|
+
container.style.top = "-webkit-calc( 50% - " + (height * 0.5) + "px )";
|
|
6205
|
+
container.style.top = "calc( 50% - " + (height * 0.5) + "px )";
|
|
6206
|
+
}
|
|
6207
|
+
}
|
|
6208
|
+
};
|
|
6209
|
+
|
|
6210
|
+
_refreshPanel();
|
|
6211
|
+
}
|
|
6212
|
+
}
|
|
6213
|
+
|
|
6023
6214
|
class Area {
|
|
6024
6215
|
|
|
6025
6216
|
/**
|
|
@@ -6785,8 +6976,7 @@ class Area {
|
|
|
6785
6976
|
// Add to last split section if area has been split
|
|
6786
6977
|
if( this.sections.length )
|
|
6787
6978
|
{
|
|
6788
|
-
this.sections[ 1 ].addOverlayButtons( buttons, options );
|
|
6789
|
-
return;
|
|
6979
|
+
return this.sections[ 1 ].addOverlayButtons( buttons, options );
|
|
6790
6980
|
}
|
|
6791
6981
|
|
|
6792
6982
|
console.assert( buttons.constructor == Array && buttons.length );
|
|
@@ -6794,152 +6984,10 @@ class Area {
|
|
|
6794
6984
|
// Set area to relative to use local position
|
|
6795
6985
|
this.root.style.position = "relative";
|
|
6796
6986
|
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
let overlayPanel = this.addPanel( options );
|
|
6800
|
-
let overlayGroup = null;
|
|
6801
|
-
|
|
6802
|
-
const container = document.createElement("div");
|
|
6803
|
-
container.className = "lexoverlaybuttonscontainer";
|
|
6804
|
-
container.appendChild( overlayPanel.root );
|
|
6805
|
-
this.attach( container );
|
|
6806
|
-
|
|
6807
|
-
const float = options.float;
|
|
6808
|
-
let floatClass = "";
|
|
6809
|
-
|
|
6810
|
-
if( float )
|
|
6811
|
-
{
|
|
6812
|
-
for( let i = 0; i < float.length; i++ )
|
|
6813
|
-
{
|
|
6814
|
-
const t = float[ i ];
|
|
6815
|
-
switch( t )
|
|
6816
|
-
{
|
|
6817
|
-
case 'h': break;
|
|
6818
|
-
case 'v': floatClass += " vertical"; break;
|
|
6819
|
-
case 't': break;
|
|
6820
|
-
case 'm': floatClass += " middle"; break;
|
|
6821
|
-
case 'b': floatClass += " bottom"; break;
|
|
6822
|
-
case 'l': break;
|
|
6823
|
-
case 'c': floatClass += " center"; break;
|
|
6824
|
-
case 'r': floatClass += " right"; break;
|
|
6825
|
-
}
|
|
6826
|
-
}
|
|
6827
|
-
|
|
6828
|
-
container.className += ` ${ floatClass }`;
|
|
6829
|
-
}
|
|
6830
|
-
|
|
6831
|
-
const _addButton = function( b, group, last ) {
|
|
6832
|
-
|
|
6833
|
-
const _options = {
|
|
6834
|
-
width: "auto",
|
|
6835
|
-
selectable: b.selectable,
|
|
6836
|
-
selected: b.selected,
|
|
6837
|
-
icon: b.icon,
|
|
6838
|
-
img: b.img,
|
|
6839
|
-
className: b.class ?? "",
|
|
6840
|
-
title: b.name,
|
|
6841
|
-
overflowContainerX: overlayPanel.root,
|
|
6842
|
-
swap: b.swap
|
|
6843
|
-
};
|
|
6844
|
-
|
|
6845
|
-
if( group )
|
|
6846
|
-
{
|
|
6847
|
-
if( !overlayGroup )
|
|
6848
|
-
{
|
|
6849
|
-
overlayGroup = document.createElement('div');
|
|
6850
|
-
overlayGroup.className = "lexoverlaygroup";
|
|
6851
|
-
overlayPanel.queuedContainer = overlayGroup;
|
|
6852
|
-
}
|
|
6853
|
-
|
|
6854
|
-
_options.parent = overlayGroup;
|
|
6855
|
-
}
|
|
6856
|
-
|
|
6857
|
-
let callback = b.callback;
|
|
6858
|
-
|
|
6859
|
-
if( b.options )
|
|
6860
|
-
{
|
|
6861
|
-
overlayPanel.addSelect( null, b.options, b.name, callback, _options );
|
|
6862
|
-
}
|
|
6863
|
-
else
|
|
6864
|
-
{
|
|
6865
|
-
const button = overlayPanel.addButton( null, b.name, function( value, event ) {
|
|
6866
|
-
if( b.selectable )
|
|
6867
|
-
{
|
|
6868
|
-
if( b.group )
|
|
6869
|
-
{
|
|
6870
|
-
let _prev = b.selected;
|
|
6871
|
-
b.group.forEach( sub => sub.selected = false );
|
|
6872
|
-
b.selected = !_prev;
|
|
6873
|
-
}
|
|
6874
|
-
else
|
|
6875
|
-
{
|
|
6876
|
-
b.selected = !b.selected;
|
|
6877
|
-
}
|
|
6878
|
-
}
|
|
6879
|
-
|
|
6880
|
-
if( callback )
|
|
6881
|
-
{
|
|
6882
|
-
callback( value, event, button.root );
|
|
6883
|
-
}
|
|
6884
|
-
|
|
6885
|
-
}, _options );
|
|
6886
|
-
}
|
|
6887
|
-
|
|
6888
|
-
// ends the group
|
|
6889
|
-
if( overlayGroup && last )
|
|
6890
|
-
{
|
|
6891
|
-
overlayPanel.root.appendChild( overlayGroup );
|
|
6892
|
-
overlayGroup = null;
|
|
6893
|
-
overlayPanel.clearQueue();
|
|
6894
|
-
}
|
|
6895
|
-
};
|
|
6896
|
-
|
|
6897
|
-
const _refreshPanel = function() {
|
|
6898
|
-
|
|
6899
|
-
overlayPanel.clear();
|
|
6900
|
-
|
|
6901
|
-
for( let b of buttons )
|
|
6902
|
-
{
|
|
6903
|
-
if( b === null )
|
|
6904
|
-
{
|
|
6905
|
-
// Add a separator
|
|
6906
|
-
const separator = document.createElement("div");
|
|
6907
|
-
separator.className = "lexoverlayseparator" + floatClass;
|
|
6908
|
-
overlayPanel.root.appendChild( separator );
|
|
6909
|
-
continue;
|
|
6910
|
-
}
|
|
6911
|
-
|
|
6912
|
-
if( b.constructor === Array )
|
|
6913
|
-
{
|
|
6914
|
-
for( let i = 0; i < b.length; ++i )
|
|
6915
|
-
{
|
|
6916
|
-
let sub = b[ i ];
|
|
6917
|
-
sub.group = b;
|
|
6918
|
-
_addButton(sub, true, i == ( b.length - 1 ));
|
|
6919
|
-
}
|
|
6920
|
-
}
|
|
6921
|
-
else
|
|
6922
|
-
{
|
|
6923
|
-
_addButton( b );
|
|
6924
|
-
}
|
|
6925
|
-
}
|
|
6926
|
-
|
|
6927
|
-
// Add floating info
|
|
6928
|
-
if( float )
|
|
6929
|
-
{
|
|
6930
|
-
var height = 0;
|
|
6931
|
-
overlayPanel.root.childNodes.forEach( c => { height += c.offsetHeight; } );
|
|
6932
|
-
|
|
6933
|
-
if( container.className.includes( "middle" ) )
|
|
6934
|
-
{
|
|
6935
|
-
container.style.top = "-moz-calc( 50% - " + (height * 0.5) + "px )";
|
|
6936
|
-
container.style.top = "-webkit-calc( 50% - " + (height * 0.5) + "px )";
|
|
6937
|
-
container.style.top = "calc( 50% - " + (height * 0.5) + "px )";
|
|
6938
|
-
}
|
|
6939
|
-
}
|
|
6940
|
-
};
|
|
6987
|
+
// Reset if already exists
|
|
6988
|
+
this.overlayButtons = new AreaOverlayButtons( this, buttons, options );
|
|
6941
6989
|
|
|
6942
|
-
|
|
6990
|
+
return this.overlayButtons;
|
|
6943
6991
|
}
|
|
6944
6992
|
|
|
6945
6993
|
/**
|
|
@@ -8462,14 +8510,15 @@ class Button extends Widget {
|
|
|
8462
8510
|
super( Widget.BUTTON, name, null, options );
|
|
8463
8511
|
|
|
8464
8512
|
this.onGetValue = () => {
|
|
8465
|
-
|
|
8513
|
+
const swapInput = wValue.querySelector( "input" );
|
|
8514
|
+
return swapInput ? swapInput.checked : value
|
|
8466
8515
|
};
|
|
8467
8516
|
|
|
8468
8517
|
this.onSetValue = ( newValue, skipCallback, event ) => {
|
|
8469
8518
|
|
|
8470
8519
|
if( ( options.swap ?? false ) )
|
|
8471
8520
|
{
|
|
8472
|
-
this.
|
|
8521
|
+
this.setState( newValue, skipCallback );
|
|
8473
8522
|
return;
|
|
8474
8523
|
}
|
|
8475
8524
|
|
|
@@ -8499,6 +8548,30 @@ class Button extends Widget {
|
|
|
8499
8548
|
wValue.style.width = `calc( 100% - ${ realNameWidth })`;
|
|
8500
8549
|
};
|
|
8501
8550
|
|
|
8551
|
+
// In case of swap, set if a change has to be performed
|
|
8552
|
+
this.setState = function( v, skipCallback ) {
|
|
8553
|
+
const swapInput = wValue.querySelector( "input" );
|
|
8554
|
+
|
|
8555
|
+
if( swapInput )
|
|
8556
|
+
{
|
|
8557
|
+
swapInput.checked = v;
|
|
8558
|
+
}
|
|
8559
|
+
else if( options.selectable )
|
|
8560
|
+
{
|
|
8561
|
+
if( options.parent )
|
|
8562
|
+
{
|
|
8563
|
+
options.parent.querySelectorAll(".lexbutton.selected").forEach( b => { if( b == wValue ) return; b.classList.remove( "selected" ); } );
|
|
8564
|
+
}
|
|
8565
|
+
|
|
8566
|
+
wValue.classList.toggle( "selected", v );
|
|
8567
|
+
}
|
|
8568
|
+
|
|
8569
|
+
if( !skipCallback )
|
|
8570
|
+
{
|
|
8571
|
+
this._trigger( new LX.IEvent( name, swapInput ? swapInput.checked : ( options.selectable ? v : value ), null ), callback );
|
|
8572
|
+
}
|
|
8573
|
+
};
|
|
8574
|
+
|
|
8502
8575
|
var wValue = document.createElement( 'button' );
|
|
8503
8576
|
wValue.title = options.tooltip ? "" : ( options.title ?? "" );
|
|
8504
8577
|
wValue.className = "lexbutton p-1 " + ( options.buttonClass ?? "" );
|
|
@@ -8518,7 +8591,7 @@ class Button extends Widget {
|
|
|
8518
8591
|
}
|
|
8519
8592
|
else if( options.icon )
|
|
8520
8593
|
{
|
|
8521
|
-
const icon = LX.makeIcon( options.icon );
|
|
8594
|
+
const icon = LX.makeIcon( options.icon, { iconClass: options.iconClass, svgClass: options.svgClass } );
|
|
8522
8595
|
const iconPosition = options.iconPosition ?? "cover";
|
|
8523
8596
|
|
|
8524
8597
|
// Default
|
|
@@ -8589,7 +8662,7 @@ class Button extends Widget {
|
|
|
8589
8662
|
const swapIcon = LX.makeIcon( options.swap, { iconClass: "swap-on" } );
|
|
8590
8663
|
wValue.appendChild( swapIcon );
|
|
8591
8664
|
|
|
8592
|
-
this.
|
|
8665
|
+
this.swap = function( skipCallback ) {
|
|
8593
8666
|
const swapInput = wValue.querySelector( "input" );
|
|
8594
8667
|
swapInput.checked = !swapInput.checked;
|
|
8595
8668
|
if( !skipCallback )
|
|
@@ -8597,19 +8670,10 @@ class Button extends Widget {
|
|
|
8597
8670
|
trigger.click();
|
|
8598
8671
|
}
|
|
8599
8672
|
};
|
|
8600
|
-
|
|
8601
|
-
// Set if swap has to be performed
|
|
8602
|
-
this.root.setState = function( v, skipCallback ) {
|
|
8603
|
-
const swapInput = wValue.querySelector( "input" );
|
|
8604
|
-
swapInput.checked = v;
|
|
8605
|
-
if( !skipCallback )
|
|
8606
|
-
{
|
|
8607
|
-
trigger.click();
|
|
8608
|
-
}
|
|
8609
|
-
};
|
|
8610
8673
|
}
|
|
8611
8674
|
|
|
8612
8675
|
trigger.addEventListener( "click", e => {
|
|
8676
|
+
let isSelected;
|
|
8613
8677
|
if( options.selectable )
|
|
8614
8678
|
{
|
|
8615
8679
|
if( options.parent )
|
|
@@ -8617,7 +8681,7 @@ class Button extends Widget {
|
|
|
8617
8681
|
options.parent.querySelectorAll(".lexbutton.selected").forEach( b => { if( b == wValue ) return; b.classList.remove( "selected" ); } );
|
|
8618
8682
|
}
|
|
8619
8683
|
|
|
8620
|
-
wValue.classList.toggle('selected');
|
|
8684
|
+
isSelected = wValue.classList.toggle('selected');
|
|
8621
8685
|
}
|
|
8622
8686
|
|
|
8623
8687
|
if( options.fileInput )
|
|
@@ -8627,7 +8691,7 @@ class Button extends Widget {
|
|
|
8627
8691
|
else
|
|
8628
8692
|
{
|
|
8629
8693
|
const swapInput = wValue.querySelector( "input" );
|
|
8630
|
-
this._trigger( new LX.IEvent( name, swapInput?.checked ?? value, e ), callback );
|
|
8694
|
+
this._trigger( new LX.IEvent( name, swapInput?.checked ?? ( options.selectable ? isSelected : value ), e ), callback );
|
|
8631
8695
|
}
|
|
8632
8696
|
});
|
|
8633
8697
|
|
|
@@ -8919,16 +8983,17 @@ class Form extends Widget {
|
|
|
8919
8983
|
|
|
8920
8984
|
if( entryData.constructor != Object )
|
|
8921
8985
|
{
|
|
8922
|
-
|
|
8986
|
+
const oldValue = JSON.parse( JSON.stringify( entryData ) );
|
|
8987
|
+
entryData = { value: oldValue };
|
|
8923
8988
|
data[ entry ] = entryData;
|
|
8924
8989
|
}
|
|
8925
8990
|
|
|
8926
|
-
entryData.placeholder = entryData.placeholder ?? entry;
|
|
8991
|
+
entryData.placeholder = entryData.placeholder ?? ( entryData.label ?? `Enter ${ entry }` );
|
|
8927
8992
|
entryData.width = "100%";
|
|
8928
8993
|
|
|
8929
8994
|
if( !( options.skipLabels ?? false ) )
|
|
8930
8995
|
{
|
|
8931
|
-
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" } );
|
|
8932
8997
|
container.appendChild( label.root );
|
|
8933
8998
|
}
|
|
8934
8999
|
|
|
@@ -9033,6 +9098,7 @@ class Select extends Widget {
|
|
|
9033
9098
|
}
|
|
9034
9099
|
|
|
9035
9100
|
this.root.dataset["opened"] = ( !!suboptionsFunc );
|
|
9101
|
+
list.style.height = ""; // set auto height by default
|
|
9036
9102
|
|
|
9037
9103
|
if( !skipCallback )
|
|
9038
9104
|
{
|
|
@@ -9054,7 +9120,7 @@ class Select extends Widget {
|
|
|
9054
9120
|
wValue.name = name;
|
|
9055
9121
|
wValue.iValue = value;
|
|
9056
9122
|
|
|
9057
|
-
if( options.overflowContainer )
|
|
9123
|
+
if( options.overflowContainer !== undefined )
|
|
9058
9124
|
{
|
|
9059
9125
|
options.overflowContainerX = options.overflowContainerY = options.overflowContainer;
|
|
9060
9126
|
}
|
|
@@ -9067,7 +9133,7 @@ class Select extends Widget {
|
|
|
9067
9133
|
|
|
9068
9134
|
// Manage vertical aspect
|
|
9069
9135
|
{
|
|
9070
|
-
const overflowContainer = options.overflowContainerY
|
|
9136
|
+
const overflowContainer = options.overflowContainerY !== undefined ? options.overflowContainerY : parent.getParentArea();
|
|
9071
9137
|
const listHeight = parent.offsetHeight;
|
|
9072
9138
|
let topPosition = rect.y;
|
|
9073
9139
|
|
|
@@ -9087,18 +9153,25 @@ class Select extends Widget {
|
|
|
9087
9153
|
}
|
|
9088
9154
|
|
|
9089
9155
|
parent.style.top = ( topPosition + selectRoot.offsetHeight ) + 'px';
|
|
9156
|
+
list.style.height = ""; // set auto height by default
|
|
9090
9157
|
|
|
9091
|
-
const
|
|
9092
|
-
|
|
9158
|
+
const failBelow = ( topPosition + listHeight ) > maxY;
|
|
9159
|
+
const failAbove = ( topPosition - listHeight ) < 0;
|
|
9160
|
+
if( failBelow && !failAbove )
|
|
9093
9161
|
{
|
|
9094
9162
|
parent.style.top = ( topPosition - listHeight ) + 'px';
|
|
9095
9163
|
parent.classList.add( "place-above" );
|
|
9096
9164
|
}
|
|
9165
|
+
// If does not fit in any direction, put it below but limit height..
|
|
9166
|
+
else if( failBelow && failAbove )
|
|
9167
|
+
{
|
|
9168
|
+
list.style.height = `${ maxY - topPosition - 32 }px`; // 32px margin
|
|
9169
|
+
}
|
|
9097
9170
|
}
|
|
9098
9171
|
|
|
9099
9172
|
// Manage horizontal aspect
|
|
9100
9173
|
{
|
|
9101
|
-
const overflowContainer = options.overflowContainerX
|
|
9174
|
+
const overflowContainer = options.overflowContainerX !== undefined ? options.overflowContainerX : parent.getParentArea();
|
|
9102
9175
|
const listWidth = parent.offsetWidth;
|
|
9103
9176
|
let leftPosition = rect.x;
|
|
9104
9177
|
|
|
@@ -9526,10 +9599,12 @@ class Layers extends Widget {
|
|
|
9526
9599
|
container.style.width = `calc( 100% - ${ realNameWidth })`;
|
|
9527
9600
|
};
|
|
9528
9601
|
|
|
9529
|
-
|
|
9602
|
+
const container = document.createElement( "div" );
|
|
9530
9603
|
container.className = "lexlayers";
|
|
9531
9604
|
this.root.appendChild( container );
|
|
9532
9605
|
|
|
9606
|
+
const maxBits = options.maxBits ?? 16;
|
|
9607
|
+
|
|
9533
9608
|
this.setLayers = ( val ) => {
|
|
9534
9609
|
|
|
9535
9610
|
container.innerHTML = "";
|
|
@@ -9538,19 +9613,19 @@ class Layers extends Widget {
|
|
|
9538
9613
|
let nbits = binary.length;
|
|
9539
9614
|
|
|
9540
9615
|
// fill zeros
|
|
9541
|
-
for( let i = 0; i < (
|
|
9616
|
+
for( let i = 0; i < ( maxBits - nbits ); ++i )
|
|
9542
9617
|
{
|
|
9543
9618
|
binary = '0' + binary;
|
|
9544
9619
|
}
|
|
9545
9620
|
|
|
9546
|
-
for( let bit = 0; bit <
|
|
9621
|
+
for( let bit = 0; bit < maxBits; ++bit )
|
|
9547
9622
|
{
|
|
9548
9623
|
let layer = document.createElement( "div" );
|
|
9549
9624
|
layer.className = "lexlayer";
|
|
9550
9625
|
|
|
9551
9626
|
if( val != undefined )
|
|
9552
9627
|
{
|
|
9553
|
-
const valueBit = binary[
|
|
9628
|
+
const valueBit = binary[ maxBits - bit - 1 ];
|
|
9554
9629
|
if( valueBit != undefined && valueBit == '1' )
|
|
9555
9630
|
{
|
|
9556
9631
|
layer.classList.add( "selected" );
|
|
@@ -9558,7 +9633,7 @@ class Layers extends Widget {
|
|
|
9558
9633
|
}
|
|
9559
9634
|
|
|
9560
9635
|
layer.innerText = bit + 1;
|
|
9561
|
-
layer.title = "Bit " + bit + ", value " + (1 << bit);
|
|
9636
|
+
layer.title = "Bit " + bit + ", value " + ( 1 << bit );
|
|
9562
9637
|
container.appendChild( layer );
|
|
9563
9638
|
|
|
9564
9639
|
layer.addEventListener( "click", e => {
|
|
@@ -10205,9 +10280,7 @@ class ColorInput extends Widget {
|
|
|
10205
10280
|
colorModel: options.useRGB ? "RGB" : "Hex",
|
|
10206
10281
|
useAlpha,
|
|
10207
10282
|
onChange: ( color ) => {
|
|
10208
|
-
this._fromColorPicker = true;
|
|
10209
10283
|
this.set( color.hex );
|
|
10210
|
-
delete this._fromColorPicker;
|
|
10211
10284
|
}
|
|
10212
10285
|
} );
|
|
10213
10286
|
|
|
@@ -10245,6 +10318,7 @@ class ColorInput extends Widget {
|
|
|
10245
10318
|
this._skipTextUpdate = true;
|
|
10246
10319
|
this.set( v );
|
|
10247
10320
|
delete this._skipTextUpdate;
|
|
10321
|
+
this.picker.fromHexColor( v );
|
|
10248
10322
|
}, { width: "calc( 100% - 24px )", disabled: options.disabled });
|
|
10249
10323
|
|
|
10250
10324
|
textWidget.root.style.marginLeft = "6px";
|
|
@@ -10614,15 +10688,15 @@ class Vector extends Widget {
|
|
|
10614
10688
|
|
|
10615
10689
|
for( let i = 0; i < vectorInputs.length; ++i )
|
|
10616
10690
|
{
|
|
10617
|
-
let
|
|
10618
|
-
|
|
10619
|
-
|
|
10620
|
-
vectorInputs[ 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;
|
|
10621
10695
|
}
|
|
10622
10696
|
|
|
10623
10697
|
if( !skipCallback )
|
|
10624
10698
|
{
|
|
10625
|
-
this._trigger( new LX.IEvent( name,
|
|
10699
|
+
this._trigger( new LX.IEvent( name, value, event ), callback );
|
|
10626
10700
|
}
|
|
10627
10701
|
};
|
|
10628
10702
|
|
|
@@ -11212,12 +11286,18 @@ class Progress extends Widget {
|
|
|
11212
11286
|
};
|
|
11213
11287
|
|
|
11214
11288
|
this.onSetValue = ( newValue, skipCallback, event ) => {
|
|
11289
|
+
newValue = LX.clamp( newValue, progress.min, progress.max );
|
|
11215
11290
|
this.root.querySelector("meter").value = newValue;
|
|
11216
11291
|
_updateColor();
|
|
11217
11292
|
if( this.root.querySelector("span") )
|
|
11218
11293
|
{
|
|
11219
11294
|
this.root.querySelector("span").innerText = newValue;
|
|
11220
11295
|
}
|
|
11296
|
+
|
|
11297
|
+
if( !skipCallback )
|
|
11298
|
+
{
|
|
11299
|
+
this._trigger( new LX.IEvent( name, newValue, event ), options.callback );
|
|
11300
|
+
}
|
|
11221
11301
|
};
|
|
11222
11302
|
|
|
11223
11303
|
this.onResize = ( rect ) => {
|
|
@@ -11301,11 +11381,6 @@ class Progress extends Widget {
|
|
|
11301
11381
|
const rect = progress.getBoundingClientRect();
|
|
11302
11382
|
const newValue = LX.round( LX.remapRange( e.offsetX - rect.x, 0, rect.width, progress.min, progress.max ) );
|
|
11303
11383
|
this.set( newValue, false, e );
|
|
11304
|
-
|
|
11305
|
-
if( options.callback )
|
|
11306
|
-
{
|
|
11307
|
-
options.callback( newValue, e );
|
|
11308
|
-
}
|
|
11309
11384
|
}
|
|
11310
11385
|
|
|
11311
11386
|
e.stopPropagation();
|
|
@@ -11517,9 +11592,16 @@ class TabSections extends Widget {
|
|
|
11517
11592
|
throw( "Param @tabs must be an Array!" );
|
|
11518
11593
|
}
|
|
11519
11594
|
|
|
11595
|
+
if( !tabs.length )
|
|
11596
|
+
{
|
|
11597
|
+
throw( "Tab list cannot be empty!" );
|
|
11598
|
+
}
|
|
11599
|
+
|
|
11520
11600
|
const vertical = options.vertical ?? true;
|
|
11521
11601
|
const showNames = !vertical && ( options.showNames ?? false );
|
|
11522
11602
|
|
|
11603
|
+
this.tabDOMs = {};
|
|
11604
|
+
|
|
11523
11605
|
let container = document.createElement( 'div' );
|
|
11524
11606
|
container.className = "lextabscontainer";
|
|
11525
11607
|
if( !vertical )
|
|
@@ -11532,25 +11614,25 @@ class TabSections extends Widget {
|
|
|
11532
11614
|
container.appendChild( tabContainer );
|
|
11533
11615
|
this.root.appendChild( container );
|
|
11534
11616
|
|
|
11535
|
-
|
|
11617
|
+
// Check at least 1 is selected
|
|
11618
|
+
if( tabs.findIndex( e => e.selected === true ) < 0 )
|
|
11619
|
+
{
|
|
11620
|
+
tabs[ 0 ].selected = true;
|
|
11621
|
+
}
|
|
11622
|
+
|
|
11623
|
+
for( let tab of tabs )
|
|
11536
11624
|
{
|
|
11537
|
-
const tab = tabs[ i ];
|
|
11538
11625
|
console.assert( tab.name );
|
|
11539
|
-
const isSelected = ( i == 0 );
|
|
11540
11626
|
let tabEl = document.createElement( "div" );
|
|
11541
|
-
tabEl.className = "lextab " + (
|
|
11627
|
+
tabEl.className = "lextab " + ( ( tab.selected ?? false ) ? "selected" : "" );
|
|
11542
11628
|
tabEl.innerHTML = ( showNames ? tab.name : "" );
|
|
11543
11629
|
tabEl.appendChild( LX.makeIcon( tab.icon ?? "Hash", { title: tab.name, iconClass: tab.iconClass, svgClass: tab.svgClass } ) );
|
|
11630
|
+
this.tabDOMs[ tab.name ] = tabEl;
|
|
11544
11631
|
|
|
11545
11632
|
let infoContainer = document.createElement( "div" );
|
|
11546
11633
|
infoContainer.id = tab.name.replace( /\s/g, '' );
|
|
11547
11634
|
infoContainer.className = "widgets";
|
|
11548
|
-
|
|
11549
|
-
if( !isSelected )
|
|
11550
|
-
{
|
|
11551
|
-
infoContainer.toggleAttribute( "hidden", true );
|
|
11552
|
-
}
|
|
11553
|
-
|
|
11635
|
+
infoContainer.toggleAttribute( "hidden", !( tab.selected ?? false ) );
|
|
11554
11636
|
container.appendChild( infoContainer );
|
|
11555
11637
|
|
|
11556
11638
|
tabEl.addEventListener( "click", e => {
|
|
@@ -11580,6 +11662,20 @@ class TabSections extends Widget {
|
|
|
11580
11662
|
creationPanel.clearQueue();
|
|
11581
11663
|
}
|
|
11582
11664
|
}
|
|
11665
|
+
|
|
11666
|
+
this.tabs = tabs;
|
|
11667
|
+
}
|
|
11668
|
+
|
|
11669
|
+
select( name ) {
|
|
11670
|
+
|
|
11671
|
+
const tabEl = this.tabDOMs[ name ];
|
|
11672
|
+
|
|
11673
|
+
if( !tabEl )
|
|
11674
|
+
{
|
|
11675
|
+
return;
|
|
11676
|
+
}
|
|
11677
|
+
|
|
11678
|
+
tabEl.click();
|
|
11583
11679
|
}
|
|
11584
11680
|
}
|
|
11585
11681
|
|
|
@@ -14031,46 +14127,43 @@ class Menubar {
|
|
|
14031
14127
|
}
|
|
14032
14128
|
|
|
14033
14129
|
let button = this.buttons[ name ];
|
|
14130
|
+
// If the button already exists, delete it
|
|
14131
|
+
// since only one button of this type can exist
|
|
14034
14132
|
if( button )
|
|
14035
14133
|
{
|
|
14036
|
-
|
|
14037
|
-
|
|
14038
|
-
return;
|
|
14134
|
+
delete this.buttons[ name ];
|
|
14135
|
+
LX.deleteElement( button.root );
|
|
14039
14136
|
}
|
|
14040
14137
|
|
|
14041
14138
|
// Otherwise, create it
|
|
14042
|
-
button =
|
|
14043
|
-
|
|
14044
|
-
|
|
14045
|
-
|
|
14046
|
-
|
|
14139
|
+
button = new LX.Button( name, null, callback, {
|
|
14140
|
+
title: name,
|
|
14141
|
+
buttonClass: "lexmenubutton main bg-none",
|
|
14142
|
+
disabled: options.disabled,
|
|
14143
|
+
icon,
|
|
14144
|
+
svgClass: "xl",
|
|
14145
|
+
hideName: true,
|
|
14146
|
+
swap: options.swap
|
|
14147
|
+
} );
|
|
14047
14148
|
|
|
14048
14149
|
if( options.float == "right" )
|
|
14049
14150
|
{
|
|
14050
|
-
button.right = true;
|
|
14151
|
+
button.root.right = true;
|
|
14051
14152
|
}
|
|
14052
14153
|
|
|
14053
14154
|
if( this.root.lastChild && this.root.lastChild.right )
|
|
14054
14155
|
{
|
|
14055
|
-
this.root.lastChild.before( button );
|
|
14156
|
+
this.root.lastChild.before( button.root );
|
|
14056
14157
|
}
|
|
14057
14158
|
else if( options.float == "left" )
|
|
14058
14159
|
{
|
|
14059
|
-
this.root.prepend( button );
|
|
14160
|
+
this.root.prepend( button.root );
|
|
14060
14161
|
}
|
|
14061
14162
|
else
|
|
14062
14163
|
{
|
|
14063
|
-
this.root.appendChild( button );
|
|
14164
|
+
this.root.appendChild( button.root );
|
|
14064
14165
|
}
|
|
14065
14166
|
|
|
14066
|
-
const _b = button.querySelector('a');
|
|
14067
|
-
_b.addEventListener("click", (e) => {
|
|
14068
|
-
if( callback && !disabled )
|
|
14069
|
-
{
|
|
14070
|
-
callback.call( this, _b, e );
|
|
14071
|
-
}
|
|
14072
|
-
});
|
|
14073
|
-
|
|
14074
14167
|
this.buttons[ name ] = button;
|
|
14075
14168
|
}
|
|
14076
14169
|
|
|
@@ -14176,7 +14269,7 @@ class Menubar {
|
|
|
14176
14269
|
|
|
14177
14270
|
if( title )
|
|
14178
14271
|
{
|
|
14179
|
-
this.buttons[ title ] = button
|
|
14272
|
+
this.buttons[ title ] = button;
|
|
14180
14273
|
}
|
|
14181
14274
|
}
|
|
14182
14275
|
}
|
|
@@ -14937,10 +15030,14 @@ class AssetView {
|
|
|
14937
15030
|
|
|
14938
15031
|
if( options.rootPath )
|
|
14939
15032
|
{
|
|
14940
|
-
if(options.rootPath.constructor !== String)
|
|
14941
|
-
|
|
15033
|
+
if( options.rootPath.constructor !== String )
|
|
15034
|
+
{
|
|
15035
|
+
console.warn( `Asset Root Path must be a String (now is a ${ path.constructor.name })` );
|
|
15036
|
+
}
|
|
14942
15037
|
else
|
|
15038
|
+
{
|
|
14943
15039
|
this.rootPath = options.rootPath;
|
|
15040
|
+
}
|
|
14944
15041
|
}
|
|
14945
15042
|
|
|
14946
15043
|
let div = document.createElement('div');
|
|
@@ -15309,7 +15406,7 @@ class AssetView {
|
|
|
15309
15406
|
this.content.className = (isContentLayout ? "lexassetscontent" : "lexassetscontent list");
|
|
15310
15407
|
let that = this;
|
|
15311
15408
|
|
|
15312
|
-
const
|
|
15409
|
+
const _addItem = function(item) {
|
|
15313
15410
|
|
|
15314
15411
|
const type = item.type.charAt( 0 ).toUpperCase() + item.type.slice( 1 );
|
|
15315
15412
|
const extension = LX.getExtension( item.id );
|
|
@@ -15334,20 +15431,27 @@ class AssetView {
|
|
|
15334
15431
|
return;
|
|
15335
15432
|
}
|
|
15336
15433
|
|
|
15434
|
+
const dialog = itemEl.closest('dialog');
|
|
15337
15435
|
const rect = itemEl.getBoundingClientRect();
|
|
15338
15436
|
const targetRect = e.target.getBoundingClientRect();
|
|
15339
|
-
const parentRect = desc.parentElement.getBoundingClientRect();
|
|
15340
15437
|
|
|
15341
|
-
let localOffsetX =
|
|
15342
|
-
let localOffsetY =
|
|
15438
|
+
let localOffsetX = rect.x + e.offsetX;
|
|
15439
|
+
let localOffsetY = rect.y + e.offsetY;
|
|
15440
|
+
|
|
15441
|
+
if( dialog )
|
|
15442
|
+
{
|
|
15443
|
+
const dialogRect = dialog.getBoundingClientRect();
|
|
15444
|
+
localOffsetX -= dialogRect.x;
|
|
15445
|
+
localOffsetY -= dialogRect.y;
|
|
15446
|
+
}
|
|
15343
15447
|
|
|
15344
15448
|
if( e.target.classList.contains( "lexassettitle" ) )
|
|
15345
15449
|
{
|
|
15346
15450
|
localOffsetY += ( targetRect.y - rect.y );
|
|
15347
15451
|
}
|
|
15348
15452
|
|
|
15349
|
-
desc.style.left = (localOffsetX
|
|
15350
|
-
desc.style.top = (localOffsetY
|
|
15453
|
+
desc.style.left = ( localOffsetX ) + "px";
|
|
15454
|
+
desc.style.top = ( localOffsetY - 36 ) + "px";
|
|
15351
15455
|
});
|
|
15352
15456
|
|
|
15353
15457
|
itemEl.addEventListener("mouseenter", () => {
|
|
@@ -15545,7 +15649,7 @@ class AssetView {
|
|
|
15545
15649
|
} });
|
|
15546
15650
|
}else
|
|
15547
15651
|
{
|
|
15548
|
-
item.domEl =
|
|
15652
|
+
item.domEl = _addItem( item );
|
|
15549
15653
|
}
|
|
15550
15654
|
}
|
|
15551
15655
|
|
|
@@ -15747,4 +15851,281 @@ class AssetView {
|
|
|
15747
15851
|
|
|
15748
15852
|
LX.AssetView = AssetView;
|
|
15749
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
|
+
|
|
15750
16131
|
})( typeof(window) != 'undefined' ? window : (typeof(self) != 'undefined' ? self : global ) );
|