lexgui 0.7.5 → 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.
- package/build/extensions/codeeditor.js +69 -14
- package/build/lexgui.css +4 -0
- package/build/lexgui.js +59 -17
- package/build/lexgui.min.css +1 -1
- package/build/lexgui.min.js +1 -1
- package/build/lexgui.module.js +59 -17
- package/build/lexgui.module.min.js +1 -1
- package/changelog.md +16 -1
- package/package.json +1 -1
|
@@ -319,6 +319,25 @@ class CodeEditor {
|
|
|
319
319
|
|
|
320
320
|
constructor( area, options = {} ) {
|
|
321
321
|
|
|
322
|
+
if( options.filesAsync )
|
|
323
|
+
{
|
|
324
|
+
options.files = [ ...options.filesAsync ];
|
|
325
|
+
|
|
326
|
+
return (async () => {
|
|
327
|
+
await this._init( area, options );
|
|
328
|
+
// Constructors return `this` implicitly, but this is an IIFE, so
|
|
329
|
+
// return `this` explicitly (else we'd return an empty object).
|
|
330
|
+
return this;
|
|
331
|
+
})();
|
|
332
|
+
}
|
|
333
|
+
else
|
|
334
|
+
{
|
|
335
|
+
this._init( area, options );
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async _init( area, options ) {
|
|
340
|
+
|
|
322
341
|
window.editor = this;
|
|
323
342
|
|
|
324
343
|
CodeEditor.__instances.push( this );
|
|
@@ -1259,7 +1278,6 @@ class CodeEditor {
|
|
|
1259
1278
|
if( options.allowAddScripts ?? true )
|
|
1260
1279
|
{
|
|
1261
1280
|
this.onCreateFile = options.onCreateFile;
|
|
1262
|
-
|
|
1263
1281
|
this.addTab( "+", false, "Create file" );
|
|
1264
1282
|
}
|
|
1265
1283
|
|
|
@@ -1267,11 +1285,14 @@ class CodeEditor {
|
|
|
1267
1285
|
{
|
|
1268
1286
|
console.assert( options.files.constructor === Array, "_files_ must be an Array!" );
|
|
1269
1287
|
const numFiles = options.files.length;
|
|
1288
|
+
const loadAsync = ( options.filesAsync !== undefined );
|
|
1270
1289
|
let filesLoaded = 0;
|
|
1271
|
-
|
|
1272
1290
|
for( let url of options.files )
|
|
1273
1291
|
{
|
|
1274
|
-
|
|
1292
|
+
const finalUrl = url.constructor === Array ? url[ 0 ] : url;
|
|
1293
|
+
const finalFileName = url.constructor === Array ? url[ 1 ] : url;
|
|
1294
|
+
|
|
1295
|
+
await this.loadFile( finalUrl, { filename: finalFileName, async: loadAsync, callback: ( name, text ) => {
|
|
1275
1296
|
filesLoaded++;
|
|
1276
1297
|
if( filesLoaded == numFiles )
|
|
1277
1298
|
{
|
|
@@ -1279,7 +1300,7 @@ class CodeEditor {
|
|
|
1279
1300
|
|
|
1280
1301
|
if( options.onFilesLoaded )
|
|
1281
1302
|
{
|
|
1282
|
-
options.onFilesLoaded( this, numFiles );
|
|
1303
|
+
options.onFilesLoaded( this.loadedTabs, numFiles );
|
|
1283
1304
|
}
|
|
1284
1305
|
}
|
|
1285
1306
|
}});
|
|
@@ -1421,15 +1442,12 @@ class CodeEditor {
|
|
|
1421
1442
|
const _innerAddTab = ( text, name, title ) => {
|
|
1422
1443
|
|
|
1423
1444
|
// Remove Carriage Return in some cases and sub tabs using spaces
|
|
1424
|
-
text = text.replaceAll( '\r', '' );
|
|
1425
|
-
text = text.replaceAll( /\t|\\t/g, ' '.repeat( this.tabSpaces ) );
|
|
1445
|
+
text = text.replaceAll( '\r', '' ).replaceAll( /\t|\\t/g, ' '.repeat( this.tabSpaces ) );
|
|
1426
1446
|
|
|
1427
1447
|
// Set current text and language
|
|
1428
|
-
|
|
1429
1448
|
const lines = text.split( '\n' );
|
|
1430
1449
|
|
|
1431
1450
|
// Add item in the explorer if used
|
|
1432
|
-
|
|
1433
1451
|
if( this.useFileExplorer || this.skipTabs )
|
|
1434
1452
|
{
|
|
1435
1453
|
this._tabStorage[ name ] = {
|
|
@@ -1465,13 +1483,20 @@ class CodeEditor {
|
|
|
1465
1483
|
|
|
1466
1484
|
if( file.constructor == String )
|
|
1467
1485
|
{
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
LX.request({ url: filename, success: text => {
|
|
1471
|
-
const name = filename.substring(filename.lastIndexOf( '/' ) + 1);
|
|
1472
|
-
_innerAddTab( text, name, filename );
|
|
1473
|
-
} });
|
|
1486
|
+
const filename = file;
|
|
1487
|
+
const name = options.filename ?? filename.substring(filename.lastIndexOf( '/' ) + 1);
|
|
1474
1488
|
|
|
1489
|
+
if( options.async ?? false )
|
|
1490
|
+
{
|
|
1491
|
+
const text = await this._requestFileAsync( filename, "text" );
|
|
1492
|
+
_innerAddTab( text, name, options.filename ?? filename );
|
|
1493
|
+
}
|
|
1494
|
+
else
|
|
1495
|
+
{
|
|
1496
|
+
LX.request({ url: filename, success: text => {
|
|
1497
|
+
_innerAddTab( text, name, options.filename ?? filename );
|
|
1498
|
+
} });
|
|
1499
|
+
}
|
|
1475
1500
|
}
|
|
1476
1501
|
else // File Blob
|
|
1477
1502
|
{
|
|
@@ -5602,6 +5627,36 @@ s
|
|
|
5602
5627
|
delete this._lastResult;
|
|
5603
5628
|
delete this._scopeStack;
|
|
5604
5629
|
}
|
|
5630
|
+
|
|
5631
|
+
async _requestFileAsync( url, dataType, nocache ) {
|
|
5632
|
+
return new Promise( (resolve, reject) => {
|
|
5633
|
+
dataType = dataType ?? "arraybuffer";
|
|
5634
|
+
const mimeType = dataType === "arraybuffer" ? "application/octet-stream" : undefined;
|
|
5635
|
+
var xhr = new XMLHttpRequest();
|
|
5636
|
+
xhr.open( 'GET', url, true );
|
|
5637
|
+
xhr.responseType = dataType;
|
|
5638
|
+
if( mimeType )
|
|
5639
|
+
xhr.overrideMimeType( mimeType );
|
|
5640
|
+
if( nocache )
|
|
5641
|
+
xhr.setRequestHeader('Cache-Control', 'no-cache');
|
|
5642
|
+
xhr.onload = function(load)
|
|
5643
|
+
{
|
|
5644
|
+
var response = this.response;
|
|
5645
|
+
if( this.status != 200)
|
|
5646
|
+
{
|
|
5647
|
+
var err = "Error " + this.status;
|
|
5648
|
+
reject(err);
|
|
5649
|
+
return;
|
|
5650
|
+
}
|
|
5651
|
+
resolve( response );
|
|
5652
|
+
};
|
|
5653
|
+
xhr.onerror = function(err) {
|
|
5654
|
+
reject(err);
|
|
5655
|
+
};
|
|
5656
|
+
xhr.send();
|
|
5657
|
+
return xhr;
|
|
5658
|
+
});
|
|
5659
|
+
}
|
|
5605
5660
|
}
|
|
5606
5661
|
|
|
5607
5662
|
CodeEditor.languages = {
|
package/build/lexgui.css
CHANGED
|
@@ -6337,7 +6337,11 @@ ul.lexassetscontent {
|
|
|
6337
6337
|
|
|
6338
6338
|
.uppercase { text-transform: uppercase }
|
|
6339
6339
|
.capitalize { text-transform: capitalize }
|
|
6340
|
+
|
|
6340
6341
|
.decoration-none { text-decoration: none }
|
|
6342
|
+
.text-underline { text-decoration: underline }
|
|
6343
|
+
|
|
6344
|
+
.hover\:text-underline:hover { text-decoration: underline }
|
|
6341
6345
|
|
|
6342
6346
|
/* Width / Height */
|
|
6343
6347
|
|
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.7.
|
|
17
|
+
version: "0.7.6",
|
|
18
18
|
ready: false,
|
|
19
19
|
extensions: [], // Store extensions used
|
|
20
20
|
signals: {}, // Events and triggers
|
|
@@ -543,16 +543,30 @@ async function init( options = { } )
|
|
|
543
543
|
this.main_area = new LX.Area( { id: options.id ?? 'mainarea' } );
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
-
|
|
546
|
+
// Initial or automatic changes don't force color scheme
|
|
547
|
+
// to be stored in localStorage
|
|
548
|
+
|
|
549
|
+
this._onChangeSystemTheme = function( event ) {
|
|
550
|
+
const storedcolorScheme = localStorage.getItem( "lxColorScheme" );
|
|
551
|
+
if( storedcolorScheme ) return;
|
|
552
|
+
LX.setTheme( event.matches ? "dark" : "light", false );
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
this._mqlPrefersDarkScheme = window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null;
|
|
556
|
+
|
|
557
|
+
const storedcolorScheme = localStorage.getItem( "lxColorScheme" );
|
|
558
|
+
if( storedcolorScheme )
|
|
559
|
+
{
|
|
560
|
+
LX.setTheme( storedcolorScheme );
|
|
561
|
+
}
|
|
562
|
+
else if( this._mqlPrefersDarkScheme && ( options.autoTheme ?? true ) )
|
|
547
563
|
{
|
|
548
|
-
if( window.matchMedia
|
|
564
|
+
if( window.matchMedia( "(prefers-color-scheme: light)" ).matches )
|
|
549
565
|
{
|
|
550
|
-
LX.setTheme( "light" );
|
|
566
|
+
LX.setTheme( "light", false );
|
|
551
567
|
}
|
|
552
568
|
|
|
553
|
-
|
|
554
|
-
LX.setTheme( event.matches ? "dark" : "light" );
|
|
555
|
-
});
|
|
569
|
+
this._mqlPrefersDarkScheme.addEventListener( "change", this._onChangeSystemTheme );
|
|
556
570
|
}
|
|
557
571
|
|
|
558
572
|
return this.main_area;
|
|
@@ -2552,8 +2566,9 @@ class Tabs {
|
|
|
2552
2566
|
});
|
|
2553
2567
|
|
|
2554
2568
|
// Attach content
|
|
2555
|
-
|
|
2556
|
-
this.root.
|
|
2569
|
+
const indexOffset = options.indexOffset ?? -1;
|
|
2570
|
+
tabEl.childIndex = ( this.root.childElementCount + indexOffset );
|
|
2571
|
+
this.root.insertChildAtIndex( tabEl, tabEl.childIndex + 1 );
|
|
2557
2572
|
this.area.attach( contentEl );
|
|
2558
2573
|
this.tabDOMs[ name ] = tabEl;
|
|
2559
2574
|
this.tabs[ name ] = content;
|
|
@@ -4978,11 +4993,13 @@ LX.deepCopy = deepCopy;
|
|
|
4978
4993
|
* @method setTheme
|
|
4979
4994
|
* @description Set dark or light theme
|
|
4980
4995
|
* @param {String} colorScheme Name of the scheme
|
|
4996
|
+
* @param {Boolean} storeLocal Store in localStorage
|
|
4981
4997
|
*/
|
|
4982
|
-
function setTheme( colorScheme )
|
|
4998
|
+
function setTheme( colorScheme, storeLocal = true )
|
|
4983
4999
|
{
|
|
4984
5000
|
colorScheme = ( colorScheme == "light" ) ? "light" : "dark";
|
|
4985
5001
|
document.documentElement.setAttribute( "data-theme", colorScheme );
|
|
5002
|
+
if( storeLocal ) localStorage.setItem( "lxColorScheme", colorScheme );
|
|
4986
5003
|
LX.emit( "@on_new_color_scheme", colorScheme );
|
|
4987
5004
|
}
|
|
4988
5005
|
|
|
@@ -5011,6 +5028,26 @@ function switchTheme()
|
|
|
5011
5028
|
|
|
5012
5029
|
LX.switchTheme = switchTheme;
|
|
5013
5030
|
|
|
5031
|
+
/**
|
|
5032
|
+
* @method setSystemTheme
|
|
5033
|
+
* @description Sets back the system theme
|
|
5034
|
+
*/
|
|
5035
|
+
function setSystemTheme()
|
|
5036
|
+
{
|
|
5037
|
+
const currentTheme = ( window.matchMedia && window.matchMedia( "(prefers-color-scheme: light)" ).matches ) ? "light" : "dark";
|
|
5038
|
+
setTheme( currentTheme );
|
|
5039
|
+
localStorage.removeItem( "lxColorScheme" );
|
|
5040
|
+
|
|
5041
|
+
// Reapply listener
|
|
5042
|
+
if( this._mqlPrefersDarkScheme )
|
|
5043
|
+
{
|
|
5044
|
+
this._mqlPrefersDarkScheme.removeEventListener( "change", this._onChangeSystemTheme );
|
|
5045
|
+
this._mqlPrefersDarkScheme.addEventListener( "change", this._onChangeSystemTheme );
|
|
5046
|
+
}
|
|
5047
|
+
}
|
|
5048
|
+
|
|
5049
|
+
LX.setSystemTheme = setSystemTheme;
|
|
5050
|
+
|
|
5014
5051
|
/**
|
|
5015
5052
|
* @method setThemeColor
|
|
5016
5053
|
* @description Sets a new value for one of the main theme variables
|
|
@@ -8993,7 +9030,7 @@ class TextInput extends BaseComponent {
|
|
|
8993
9030
|
|
|
8994
9031
|
this.valid = ( v ) => {
|
|
8995
9032
|
v = v ?? this.value();
|
|
8996
|
-
if(
|
|
9033
|
+
if( ( wValue.pattern ?? "" ) == "" ) return true;
|
|
8997
9034
|
const regexp = new RegExp( wValue.pattern );
|
|
8998
9035
|
return regexp.test( v );
|
|
8999
9036
|
};
|
|
@@ -9732,19 +9769,21 @@ class Form extends BaseComponent {
|
|
|
9732
9769
|
|
|
9733
9770
|
const primaryButton = new LX.Button( null, options.primaryActionName ?? "Submit", ( value, event ) => {
|
|
9734
9771
|
|
|
9772
|
+
const errors = [];
|
|
9773
|
+
|
|
9735
9774
|
for( let entry in data )
|
|
9736
9775
|
{
|
|
9737
9776
|
let entryData = data[ entry ];
|
|
9738
9777
|
|
|
9739
9778
|
if( !entryData.textComponent.valid() )
|
|
9740
9779
|
{
|
|
9741
|
-
|
|
9780
|
+
errors.push( { type: "input_not_valid", entry } );
|
|
9742
9781
|
}
|
|
9743
9782
|
}
|
|
9744
9783
|
|
|
9745
9784
|
if( callback )
|
|
9746
9785
|
{
|
|
9747
|
-
callback( container.formData, event );
|
|
9786
|
+
callback( container.formData, errors, event );
|
|
9748
9787
|
}
|
|
9749
9788
|
}, { width: "100%", minWidth: "0", buttonClass: options.primaryButtonClass ?? "contrast" } );
|
|
9750
9789
|
|
|
@@ -15949,8 +15988,7 @@ class Sidebar {
|
|
|
15949
15988
|
return;
|
|
15950
15989
|
}
|
|
15951
15990
|
|
|
15952
|
-
|
|
15953
|
-
if( f ) f.call( this, key, item.value, e );
|
|
15991
|
+
let value = undefined;
|
|
15954
15992
|
|
|
15955
15993
|
if( isCollapsable )
|
|
15956
15994
|
{
|
|
@@ -15960,14 +15998,18 @@ class Sidebar {
|
|
|
15960
15998
|
{
|
|
15961
15999
|
item.value = !item.value;
|
|
15962
16000
|
item.checkbox.set( item.value, true );
|
|
16001
|
+
value = item.value;
|
|
15963
16002
|
}
|
|
15964
|
-
|
|
15965
|
-
if( options.swap && !( e.target instanceof HTMLInputElement ) )
|
|
16003
|
+
else if( options.swap && !( e.target instanceof HTMLInputElement ) )
|
|
15966
16004
|
{
|
|
15967
16005
|
const swapInput = itemDom.querySelector( "input" );
|
|
15968
16006
|
swapInput.checked = !swapInput.checked;
|
|
16007
|
+
value = swapInput.checked;
|
|
15969
16008
|
}
|
|
15970
16009
|
|
|
16010
|
+
const f = options.callback;
|
|
16011
|
+
if( f ) f.call( this, key, value ?? entry, e );
|
|
16012
|
+
|
|
15971
16013
|
// Manage selected
|
|
15972
16014
|
if( this.displaySelected && !options.skipSelection )
|
|
15973
16015
|
{
|