lexgui 0.1.45 → 0.1.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/lexgui.js CHANGED
@@ -12,7 +12,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
12
12
  */
13
13
 
14
14
  var LX = global.LX = {
15
- version: "0.1.45",
15
+ version: "0.1.46",
16
16
  ready: false,
17
17
  components: [], // specific pre-build components
18
18
  signals: {} // events and triggers
@@ -36,34 +36,103 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
36
36
  LX.round = round;
37
37
  LX.remapRange = remapRange;
38
38
 
39
- function getSupportedDOMName( string )
39
+ // Timer that works everywhere (from litegraph.js)
40
+ if ( typeof performance != "undefined" )
41
+ {
42
+ LX.getTime = performance.now.bind( performance );
43
+ }
44
+ else if( typeof Date != "undefined" && Date.now )
45
+ {
46
+ LX.getTime = Date.now.bind( Date );
47
+ }
48
+ else if ( typeof process != "undefined" )
49
+ {
50
+ LX.getTime = function() {
51
+ var t = process.hrtime();
52
+ return t[ 0 ] * 0.001 + t[ 1 ] * 1e-6;
53
+ };
54
+ }
55
+ else
56
+ {
57
+ LX.getTime = function() {
58
+ return new Date().getTime();
59
+ };
60
+ }
61
+
62
+ let ASYNC_ENABLED = true;
63
+
64
+ /**
65
+ * @method doAsync
66
+ * @description Call a function asynchronously
67
+ * @param {Function} fn Function to call
68
+ * @param {Number} ms Time to wait until calling the function (in milliseconds)
69
+ */
70
+ function doAsync( fn, ms ) {
71
+ if( ASYNC_ENABLED )
72
+ {
73
+ setTimeout( fn, ms ?? 0 );
74
+ }
75
+ else
76
+ {
77
+ fn();
78
+ }
79
+ }
80
+
81
+ LX.doAsync = doAsync;
82
+
83
+ /**
84
+ * @method getSupportedDOMName
85
+ * @description Convert a text string to a valid DOM name
86
+ * @param {String} text Original text
87
+ */
88
+ function getSupportedDOMName( text )
40
89
  {
41
- return string.replace(/\s/g, '').replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll('.', '');
90
+ return text.replace(/\s/g, '').replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll('.', '');
42
91
  }
43
92
 
44
93
  LX.getSupportedDOMName = getSupportedDOMName;
45
94
 
46
- function has( component_name )
95
+ /**
96
+ * @method has
97
+ * @description Ask if LexGUI is using a specific component
98
+ * @param {String} componentName Name of the LexGUI component
99
+ */
100
+ function has( componentName )
47
101
  {
48
- return (LX.components.indexOf( component_name ) > -1);
102
+ return ( LX.components.indexOf( componentName ) > -1 );
49
103
  }
50
104
 
51
105
  LX.has = has;
52
106
 
53
- function getExtension( s )
107
+ /**
108
+ * @method getExtension
109
+ * @description Get a extension from a path/url/filename
110
+ * @param {String} name
111
+ */
112
+ function getExtension( name )
54
113
  {
55
- return s.includes('.') ? s.split('.').pop() : null;
114
+ return name.includes('.') ? name.split('.').pop() : null;
56
115
  }
57
116
 
58
117
  LX.getExtension = getExtension;
59
118
 
60
- function deepCopy( o )
119
+ /**
120
+ * @method deepCopy
121
+ * @description Create a deep copy with no references from an object
122
+ * @param {Object} obj
123
+ */
124
+ function deepCopy( obj )
61
125
  {
62
- return JSON.parse(JSON.stringify(o))
126
+ return JSON.parse( JSON.stringify( obj ) )
63
127
  }
64
128
 
65
129
  LX.deepCopy = deepCopy;
66
130
 
131
+ /**
132
+ * @method setTheme
133
+ * @description Set dark or light theme
134
+ * @param {String} colorScheme Name of the scheme
135
+ */
67
136
  function setTheme( colorScheme )
68
137
  {
69
138
  colorScheme = ( colorScheme == "light" ) ? "light" : "dark";
@@ -73,6 +142,12 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
73
142
 
74
143
  LX.setTheme = setTheme;
75
144
 
145
+ /**
146
+ * @method setThemeColor
147
+ * @description Sets a new value for one of the main theme variables
148
+ * @param {String} colorName Name of the theme variable
149
+ * @param {String} color Color in rgba/hex
150
+ */
76
151
  function setThemeColor( colorName, color )
77
152
  {
78
153
  var r = document.querySelector( ':root' );
@@ -81,6 +156,11 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
81
156
 
82
157
  LX.setThemeColor = setThemeColor;
83
158
 
159
+ /**
160
+ * @method getThemeColor
161
+ * @description Get the value for one of the main theme variables
162
+ * @param {String} colorName Name of the theme variable
163
+ */
84
164
  function getThemeColor( colorName )
85
165
  {
86
166
  const r = getComputedStyle( document.querySelector( ':root' ) );
@@ -105,7 +185,13 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
105
185
 
106
186
  LX.getThemeColor = getThemeColor;
107
187
 
108
- function getBase64Image( img ) {
188
+ /**
189
+ * @method getBase64Image
190
+ * @description Convert an image to a base64 string
191
+ * @param {Image} img
192
+ */
193
+ function getBase64Image( img )
194
+ {
109
195
  var canvas = document.createElement( 'canvas' );
110
196
  canvas.width = img.width;
111
197
  canvas.height = img.height;
@@ -116,7 +202,13 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
116
202
 
117
203
  LX.getBase64Image = getBase64Image;
118
204
 
119
- function hexToRgb( hexStr ) {
205
+ /**
206
+ * @method hexToRgb
207
+ * @description Convert a hexadecimal string to a valid RGB color array
208
+ * @param {String} hexStr Hexadecimal color
209
+ */
210
+ function hexToRgb( hexStr )
211
+ {
120
212
  const red = parseInt( hexStr.substring( 1, 3 ), 16 ) / 255;
121
213
  const green = parseInt( hexStr.substring( 3, 5 ), 16 ) / 255;
122
214
  const blue = parseInt( hexStr.substring( 5, 7 ), 16 ) / 255;
@@ -125,7 +217,13 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
125
217
 
126
218
  LX.hexToRgb = hexToRgb;
127
219
 
128
- function rgbToHex( rgb ) {
220
+ /**
221
+ * @method rgbToHex
222
+ * @description Convert a RGB color array to a hexadecimal string
223
+ * @param {Array} rgb Array containing R, G, B, A*
224
+ */
225
+ function rgbToHex( rgb )
226
+ {
129
227
  let hex = "#";
130
228
  for( let c of rgb ) {
131
229
  c = Math.floor( c * 255 );
@@ -136,7 +234,14 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
136
234
 
137
235
  LX.rgbToHex = rgbToHex;
138
236
 
139
- function measureRealWidth( value, paddingPlusMargin = 8 ) {
237
+ /**
238
+ * @method measureRealWidth
239
+ * @description Measure the pixel width of a text
240
+ * @param {Object} value Text to measure
241
+ * @param {Number} paddingPlusMargin Padding offset
242
+ */
243
+ function measureRealWidth( value, paddingPlusMargin = 8 )
244
+ {
140
245
  var i = document.createElement( "span" );
141
246
  i.className = "lexinputmeasure";
142
247
  i.innerHTML = value;
@@ -148,16 +253,35 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
148
253
 
149
254
  LX.measureRealWidth = measureRealWidth;
150
255
 
151
- function simple_guidGenerator() {
256
+ /**
257
+ * @method simple_guidGenerator
258
+ * @description Get a random unique id
259
+ */
260
+ function simple_guidGenerator()
261
+ {
152
262
  var S4 = function() {
153
- return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
263
+ return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
154
264
  };
155
265
  return (S4()+"-"+S4()+"-"+S4());
156
266
  }
157
267
 
158
268
  LX.guidGenerator = simple_guidGenerator;
159
269
 
160
- function buildTextPattern( options = {} ) {
270
+ /**
271
+ * @method buildTextPattern
272
+ * @description Create a validation pattern using specific options
273
+ * @param {Object} options
274
+ * lowercase (Boolean): Text must contain a lowercase char
275
+ * uppercase (Boolean): Text must contain an uppercase char
276
+ * digit (Boolean): Text must contain a digit
277
+ * specialChar (Boolean): Text must contain a special char
278
+ * noSpaces (Boolean): Do not allow spaces in text
279
+ * minLength (Number): Text minimum length
280
+ * maxLength (Number): Text maximum length
281
+ * asRegExp (Boolean): Return pattern as Regular Expression instance
282
+ */
283
+ function buildTextPattern( options = {} )
284
+ {
161
285
  let patterns = [];
162
286
  if ( options.lowercase ) patterns.push("(?=.*[a-z])");
163
287
  if ( options.uppercase ) patterns.push("(?=.*[A-Z])");
@@ -174,67 +298,9 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
174
298
 
175
299
  LX.buildTextPattern = buildTextPattern;
176
300
 
177
- // Timer that works everywhere (from litegraph.js)
178
- if (typeof performance != "undefined") {
179
- LX.getTime = performance.now.bind(performance);
180
- } else if (typeof Date != "undefined" && Date.now) {
181
- LX.getTime = Date.now.bind(Date);
182
- } else if (typeof process != "undefined") {
183
- LX.getTime = function() {
184
- var t = process.hrtime();
185
- return t[0] * 0.001 + t[1] * 1e-6;
186
- };
187
- } else {
188
- LX.getTime = function getTime() {
189
- return new Date().getTime();
190
- };
191
- }
192
-
193
- let ASYNC_ENABLED = true;
194
-
195
- function doAsync( fn, ms ) {
196
- if( ASYNC_ENABLED )
197
- {
198
- setTimeout( fn, ms ?? 0 );
199
- }
200
- else
201
- {
202
- fn();
203
- }
204
- }
205
-
206
- // Math classes
207
-
208
- class vec2 {
209
-
210
- constructor( x, y ) {
211
- this.x = x ?? 0;
212
- this.y = y ?? ( x ?? 0 );
213
- }
214
-
215
- get xy() { return [ this.x, this.y ]; }
216
- get yx() { return [ this.y, this.x ]; }
217
-
218
- set ( x, y ) { this.x = x; this.y = y; }
219
- add ( v, v0 = new vec2() ) { v0.set( this.x + v.x, this.y + v.y ); return v0; }
220
- sub ( v, v0 = new vec2() ) { v0.set( this.x - v.x, this.y - v.y ); return v0; }
221
- mul ( v, v0 = new vec2() ) { if( v.constructor == Number ) { v = new vec2( v ) } v0.set( this.x * v.x, this.y * v.y ); return v0; }
222
- div ( v, v0 = new vec2() ) { if( v.constructor == Number ) { v = new vec2( v ) } v0.set( this.x / v.x, this.y / v.y ); return v0; }
223
- abs ( v0 = new vec2() ) { v0.set( Math.abs( this.x ), Math.abs( this.y ) ); return v0; }
224
- dot ( v ) { return this.x * v.x + this.y * v.y; }
225
- len2 () { return this.dot( this ) }
226
- len () { return Math.sqrt( this.len2() ); }
227
- nrm ( v0 = new vec2() ) { v0.set( this.x, this.y ); return v0.mul( 1.0 / this.len(), v0 ); }
228
- dst ( v ) { return v.sub( this ).len(); }
229
- clp ( min, max, v0 = new vec2() ) { v0.set( clamp( this.x, min, max ), clamp( this.y, min, max ) ); return v0; }
230
- };
231
-
232
- LX.vec2 = vec2;
233
-
234
- // Other utils
235
-
236
301
  /**
237
302
  * @method makeDraggable
303
+ * @description Allow an element to be dragged
238
304
  * @param {Element} domEl
239
305
  * @param {Object} options
240
306
  * autoAdjust (Bool): Sets in a correct position at the beggining
@@ -242,8 +308,8 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
242
308
  * onMove (Function): Called each move event
243
309
  * onDragStart (Function): Called when drag event starts
244
310
  */
245
- function makeDraggable( domEl, options = { } ) {
246
-
311
+ function makeDraggable( domEl, options = { } )
312
+ {
247
313
  let offsetX = 0;
248
314
  let offsetY = 0;
249
315
  let currentTarget = null;
@@ -264,7 +330,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
264
330
  // Initial adjustment
265
331
  if( options.autoAdjust )
266
332
  {
267
- _computePosition( null, parseInt( domEl.style.left ), parseInt( domEl.style.top ) )
333
+ _computePosition( null, parseInt( domEl.style.left ), parseInt( domEl.style.top ) )
268
334
  }
269
335
 
270
336
  let id = LX.UTILS.uidGenerator();
@@ -333,7 +399,131 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
333
399
 
334
400
  LX.makeDraggable = makeDraggable;
335
401
 
336
- function create_global_searchbar( root ) {
402
+ /**
403
+ * @method makeCodeSnippet
404
+ * @description Create a code snippet in a specific language
405
+ * @param {String} code
406
+ * @param {Array} size
407
+ * @param {Object} options
408
+ * language (String):
409
+ * windowMode (Boolean):
410
+ * lineNumbers (Boolean):
411
+ * tabName (String):
412
+ */
413
+ function makeCodeSnippet( code, size, options = { } )
414
+ {
415
+ if( !LX.has('CodeEditor') )
416
+ {
417
+ console.error( "Import the CodeEditor component to create snippets!" );
418
+ return;
419
+ }
420
+
421
+ const snippet = document.createElement( "div" );
422
+ snippet.className = "lexcodesnippet";
423
+ snippet.style.width = size[ 0 ];
424
+ snippet.style.height = size[ 1 ];
425
+ const area = new Area( { noAppend: true } );
426
+ let editor = new LX.CodeEditor( area, {
427
+ skipInfo: true,
428
+ disableEdition: true,
429
+ allowAddScripts: false,
430
+ name: options.tabName,
431
+ // showTab: options.showTab ?? true,
432
+ // lineNumbers: options.lineNumbers ?? true
433
+ } );
434
+ editor.setText( code, options.language ?? "Plain Text" );
435
+
436
+ if( options.linesAdded )
437
+ {
438
+ const code = editor.root.querySelector( ".code" );
439
+ for( let l of options.linesAdded )
440
+ {
441
+ if( l.constructor == Number )
442
+ {
443
+ code.childNodes[ l - 1 ].classList.add( "added" );
444
+ }
445
+ else if( l.constructor == Array ) // It's a range
446
+ {
447
+ for( let i = ( l[0] - 1 ); i <= ( l[1] - 1 ); i++ )
448
+ {
449
+ code.childNodes[ i ].classList.add( "added" );
450
+ }
451
+ }
452
+ }
453
+ }
454
+
455
+ if( options.linesRemoved )
456
+ {
457
+ const code = editor.root.querySelector( ".code" );
458
+ for( let l of options.linesRemoved )
459
+ {
460
+ if( l.constructor == Number )
461
+ {
462
+ code.childNodes[ l - 1 ].classList.add( "removed" );
463
+ }
464
+ else if( l.constructor == Array ) // It's a range
465
+ {
466
+ for( let i = ( l[0] - 1 ); i <= ( l[1] - 1 ); i++ )
467
+ {
468
+ code.childNodes[ i ].classList.add( "removed" );
469
+ }
470
+ }
471
+ }
472
+ }
473
+
474
+ if( options.windowMode )
475
+ {
476
+ const windowActionButtons = document.createElement( "div" );
477
+ windowActionButtons.className = "lexwindowbuttons";
478
+ const aButton = document.createElement( "span" );
479
+ aButton.style.background = "#ee4f50";
480
+ const bButton = document.createElement( "span" );
481
+ bButton.style.background = "#f5b720";
482
+ const cButton = document.createElement( "span" );
483
+ cButton.style.background = "#53ca29";
484
+ windowActionButtons.appendChild( aButton );
485
+ windowActionButtons.appendChild( bButton );
486
+ windowActionButtons.appendChild( cButton );
487
+ const tabs = editor.root.querySelector( ".lexareatabs" );
488
+ tabs.prepend( windowActionButtons );
489
+ }
490
+
491
+ snippet.appendChild( area.root );
492
+ return snippet;
493
+ }
494
+
495
+ LX.makeCodeSnippet = makeCodeSnippet;
496
+
497
+ // Math classes
498
+
499
+ class vec2 {
500
+
501
+ constructor( x, y ) {
502
+ this.x = x ?? 0;
503
+ this.y = y ?? ( x ?? 0 );
504
+ }
505
+
506
+ get xy() { return [ this.x, this.y ]; }
507
+ get yx() { return [ this.y, this.x ]; }
508
+
509
+ set ( x, y ) { this.x = x; this.y = y; }
510
+ add ( v, v0 = new vec2() ) { v0.set( this.x + v.x, this.y + v.y ); return v0; }
511
+ sub ( v, v0 = new vec2() ) { v0.set( this.x - v.x, this.y - v.y ); return v0; }
512
+ mul ( v, v0 = new vec2() ) { if( v.constructor == Number ) { v = new vec2( v ) } v0.set( this.x * v.x, this.y * v.y ); return v0; }
513
+ div ( v, v0 = new vec2() ) { if( v.constructor == Number ) { v = new vec2( v ) } v0.set( this.x / v.x, this.y / v.y ); return v0; }
514
+ abs ( v0 = new vec2() ) { v0.set( Math.abs( this.x ), Math.abs( this.y ) ); return v0; }
515
+ dot ( v ) { return this.x * v.x + this.y * v.y; }
516
+ len2 () { return this.dot( this ) }
517
+ len () { return Math.sqrt( this.len2() ); }
518
+ nrm ( v0 = new vec2() ) { v0.set( this.x, this.y ); return v0.mul( 1.0 / this.len(), v0 ); }
519
+ dst ( v ) { return v.sub( this ).len(); }
520
+ clp ( min, max, v0 = new vec2() ) { v0.set( clamp( this.x, min, max ), clamp( this.y, min, max ) ); return v0; }
521
+ };
522
+
523
+ LX.vec2 = vec2;
524
+
525
+ function create_global_searchbar( root )
526
+ {
337
527
 
338
528
  let globalSearch = document.createElement("div");
339
529
  globalSearch.id = "global-search";
@@ -2583,6 +2773,17 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
2583
2773
  const swapIcon = document.createElement( "a" );
2584
2774
  swapIcon.className = data.swap + " swap-on lexicon";
2585
2775
  button.appendChild( swapIcon );
2776
+
2777
+ button.swap = function() {
2778
+ const swapInput = this.querySelector( "input" );
2779
+ swapInput.checked = !swapInput.checked;
2780
+ };
2781
+
2782
+ // Set if swap has to be performed
2783
+ button.setState = function( v ) {
2784
+ const swapInput = this.querySelector( "input" );
2785
+ swapInput.checked = v;
2786
+ };
2586
2787
  }
2587
2788
 
2588
2789
  trigger.addEventListener("click", e => {
@@ -4802,10 +5003,11 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
4802
5003
  const topPosition = rect.y;
4803
5004
 
4804
5005
  let maxY = window.innerHeight;
5006
+ let overflowContainer = list.getParentArea();
4805
5007
 
4806
- if( this.mainContainer )
5008
+ if( overflowContainer )
4807
5009
  {
4808
- const parentRect = this.mainContainer.getBoundingClientRect();
5010
+ const parentRect = overflowContainer.getBoundingClientRect();
4809
5011
  maxY = parentRect.y + parentRect.height;
4810
5012
  }
4811
5013
 
@@ -9849,6 +10051,14 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
9849
10051
  }
9850
10052
  }
9851
10053
 
10054
+ Element.prototype.getParentArea = function() {
10055
+ let parent = this.parentElement;
10056
+ while( parent ) {
10057
+ if( parent.classList.contains( "lexarea" ) ) { return parent; }
10058
+ parent = parent.parentElement;
10059
+ }
10060
+ }
10061
+
9852
10062
  LX.UTILS = {
9853
10063
  getTime() { return new Date().getTime() },
9854
10064
  compareThreshold( v, p, n, t ) { return Math.abs(v - p) >= t || Math.abs(v - n) >= t },