lexgui 0.1.18 → 0.1.20

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.
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  var LX = {
11
- version: "0.1.18",
11
+ version: "0.1.20",
12
12
  ready: false,
13
13
  components: [], // specific pre-build components
14
14
  signals: {} // events and triggers
@@ -20,6 +20,13 @@ LX.MOUSE_TRIPLE_CLICK = 3;
20
20
  function clamp (num, min, max) { return Math.min(Math.max(num, min), max) }
21
21
  function round(num, n) { return +num.toFixed(n); }
22
22
 
23
+ function getSupportedDOMName( string )
24
+ {
25
+ return string.replace(/\s/g, '').replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll('.', '');
26
+ }
27
+
28
+ LX.getSupportedDOMName = getSupportedDOMName;
29
+
23
30
  function has( component_name )
24
31
  {
25
32
  return (LX.components.indexOf( component_name ) > -1);
@@ -254,7 +261,16 @@ function create_global_searchbar( root ) {
254
261
  e.stopPropagation();
255
262
  global_search.classList.toggle('hidden');
256
263
  global_search.querySelector('input').focus();
257
- add_elements(undefined);
264
+ add_elements( undefined );
265
+ }
266
+ else
267
+ {
268
+ for( let c of LX.components )
269
+ if( LX[c].prototype.onKeyPressed )
270
+ {
271
+ const instances = LX.CodeEditor.getInstances();
272
+ for( let i of instances ) i.onKeyPressed( e );
273
+ }
258
274
  }
259
275
  });
260
276
 
@@ -339,17 +355,23 @@ function create_global_searchbar( root ) {
339
355
  const instances = LX.CodeEditor.getInstances();
340
356
  if(!instances.length) return;
341
357
 
342
- const languages = Object.keys( instances[0].languages );
358
+ const languages = instances[ 0 ].languages;
359
+
360
+ for( let l of Object.keys( languages ) ) {
343
361
 
344
- for( let l of languages ) {
362
+ const key = "Language: " + l;
363
+ const icon = instances[ 0 ]._getFileIcon( null, languages[ l ].ext );
345
364
 
346
- const key = "Set language: " + l;
347
- if( key.toLowerCase().includes(filter) ) {
348
- add_element(key, () => {
365
+ let value = icon.includes( 'fa-' ) ? "<i class='" + icon + "'></i>" :
366
+ "<img src='" + ( "https://raw.githubusercontent.com/jxarco/lexgui.js/master/" + icon ) + "'>";
367
+
368
+ value += key + " <span class='lang-ext'>(" + languages[ l ].ext + ")</span>";
369
+ if( key.toLowerCase().includes( filter ) ) {
370
+ add_element( value, () => {
349
371
  for( let i of instances ) {
350
372
  i._changeLanguage( l );
351
373
  }
352
- }, "", {});
374
+ }, "", {} );
353
375
  }
354
376
  }
355
377
  }
@@ -1351,14 +1373,14 @@ class Area {
1351
1373
 
1352
1374
  _moveSplit( dt, force_animation = false, force_width = 0 ) {
1353
1375
 
1354
- if(!this.type)
1355
- throw("No split area");
1376
+ if( !this.type )
1377
+ throw( "No split area" );
1356
1378
 
1357
- if(dt === undefined) // splitbar didn't move!
1379
+ if( dt === undefined ) // Splitbar didn't move!
1358
1380
  return;
1359
1381
 
1360
- var a1 = this.sections[0];
1361
- var a2 = this.sections[1];
1382
+ var a1 = this.sections[ 0 ];
1383
+ var a2 = this.sections[ 1 ];
1362
1384
  var splitinfo = " - "+ LX.DEFAULT_SPLITBAR_SIZE + "px";
1363
1385
 
1364
1386
  let transition = null;
@@ -1367,29 +1389,30 @@ class Area {
1367
1389
  // Remove transitions for this change..
1368
1390
  transition = a1.root.style.transition;
1369
1391
  a1.root.style.transition = a2.root.style.transition = "none";
1370
- flushCss(a1.root);
1371
- flushCss(a2.root);
1392
+ flushCss( a1.root );
1393
+ flushCss( a2.root );
1372
1394
  }
1373
1395
 
1374
- if(this.type == "horizontal") {
1375
-
1376
- var size = Math.max(a2.root.offsetWidth + dt, parseInt(a2.minWidth));
1396
+ if( this.type == "horizontal" )
1397
+ {
1398
+ var size = Math.max( a2.root.offsetWidth + dt, parseInt( a2.minWidth ) );
1377
1399
  if( force_width ) size = force_width;
1378
1400
  a1.root.style.width = "-moz-calc( 100% - " + size + "px " + splitinfo + " )";
1379
1401
  a1.root.style.width = "-webkit-calc( 100% - " + size + "px " + splitinfo + " )";
1380
1402
  a1.root.style.width = "calc( 100% - " + size + "px " + splitinfo + " )";
1381
- a1.root.style.minWidth = a1.minWidth + "px";
1382
- a2.root.style.width = size + "px"; //other split
1403
+ a1.root.style.minWidth = parseInt( a1.minWidth ) + "px";
1404
+ a2.root.style.width = size + "px";
1405
+ if( a1.maxWidth != Infinity ) a2.root.style.minWidth = "calc( 100% - " + parseInt( a1.maxWidth ) + "px" + " )";
1383
1406
  }
1384
- else {
1385
-
1407
+ else
1408
+ {
1386
1409
  var size = Math.max((a2.root.offsetHeight + dt) + a2.offset, parseInt(a2.minHeight));
1387
1410
  if( force_width ) size = force_width;
1388
1411
  a1.root.style.height = "-moz-calc( 100% - " + size + "px " + splitinfo + " )";
1389
1412
  a1.root.style.height = "-webkit-calc( 100% - " + size + "px " + splitinfo + " )";
1390
1413
  a1.root.style.height = "calc( 100% - " + size + "px " + splitinfo + " )";
1391
1414
  a1.root.style.minHeight = a1.minHeight + "px";
1392
- a2.root.style.height = ( size - a2.offset ) + "px"; //other split
1415
+ a2.root.style.height = ( size - a2.offset ) + "px";
1393
1416
  }
1394
1417
 
1395
1418
  if( !force_animation )
@@ -1594,15 +1617,22 @@ class Tabs {
1594
1617
  this.area.root.classList.toggle('folded', !this.folded);
1595
1618
  }
1596
1619
 
1597
- if(options.onSelect) options.onSelect(e, tabEl.dataset.name);
1620
+ if(options.onSelect)
1621
+ options.onSelect(e, tabEl.dataset.name);
1622
+ });
1623
+
1624
+ tabEl.addEventListener("contextmenu", e => {
1625
+ e.preventDefault();
1626
+ e.stopPropagation();
1627
+
1628
+ if(options.onContextMenu)
1629
+ options.onContextMenu( e, tabEl.dataset.name );
1598
1630
  });
1599
1631
 
1600
1632
  tabEl.addEventListener("mouseup", e => {
1601
1633
  e.preventDefault();
1602
1634
  e.stopPropagation();
1603
- if(e.button == 1 ) {
1604
- if(this.onclose)
1605
- this.onclose( tabEl.dataset["name"] );
1635
+ if( e.button == 1 ) {
1606
1636
  this.delete( tabEl.dataset["name"] );
1607
1637
  }
1608
1638
  });
@@ -1613,7 +1643,7 @@ class Tabs {
1613
1643
  e.preventDefault();
1614
1644
  return;
1615
1645
  }
1616
- e.dataTransfer.setData("source", e.target.id);
1646
+ e.dataTransfer.setData( "source", e.target.id );
1617
1647
  });
1618
1648
 
1619
1649
  // Attach content
@@ -1642,6 +1672,9 @@ class Tabs {
1642
1672
  if(!tabEl || tabEl.fixed)
1643
1673
  return;
1644
1674
 
1675
+ if( this.onclose )
1676
+ this.onclose( name );
1677
+
1645
1678
  // Delete tab element
1646
1679
  this.tabDOMs[ name ].remove();
1647
1680
  delete this.tabDOMs[ name ];
@@ -2140,8 +2173,8 @@ class Widget {
2140
2173
 
2141
2174
  set( value ) {
2142
2175
 
2143
- if(this.onSetValue)
2144
- this.onSetValue(value);
2176
+ if( this.onSetValue )
2177
+ this.onSetValue( value );
2145
2178
  }
2146
2179
 
2147
2180
  oncontextmenu(e) {
@@ -2384,22 +2417,33 @@ class NodeTree {
2384
2417
 
2385
2418
  let item = document.createElement('li');
2386
2419
  item.className = "lextreeitem " + "datalevel" + level + (is_parent ? " parent" : "") + (is_selected ? " selected" : "");
2387
- item.id = node.id;
2420
+ item.id = LX.getSupportedDOMName( node.id );
2388
2421
  item.tabIndex = "0";
2389
2422
 
2390
2423
  // Select hierarchy icon
2391
- let icon = "fa-solid fa-square"; // Default: no childs
2424
+ let icon = (this.options.skip_default_icon ?? true) ? "" : "fa-solid fa-square"; // Default: no childs
2392
2425
  if( is_parent ) icon = node.closed ? "fa-solid fa-caret-right" : "fa-solid fa-caret-down";
2393
2426
  item.innerHTML = "<a class='" + icon + " hierarchy'></a>";
2394
2427
 
2395
2428
  // Add display icon
2396
2429
  icon = node.icon;
2397
- if( icon ) item.innerHTML += "<a class='" + icon + "'></a>";
2430
+
2431
+ // Process icon
2432
+ if( node.icon )
2433
+ {
2434
+ if( node.icon.includes( 'fa-' ) ) // It's fontawesome icon...
2435
+ item.innerHTML += "<a class='" + node.icon + " tree-item-icon'></a>";
2436
+ else // an image..
2437
+ {
2438
+ const rootPath = "https://raw.githubusercontent.com/jxarco/lexgui.js/master/";
2439
+ item.innerHTML += "<img src='" + ( rootPath + node.icon ) + "'>";
2440
+ }
2441
+ }
2398
2442
 
2399
2443
  item.innerHTML += (node.rename ? "" : node.id);
2400
2444
 
2401
2445
  item.setAttribute('draggable', true);
2402
- item.style.paddingLeft = ((is_parent ? 0 : 3 ) + (3 + (level+1) * 25)) + "px";
2446
+ item.style.paddingLeft = ((is_parent ? 0 : 3 ) + (3 + (level+1) * 15)) + "px";
2403
2447
  list.appendChild(item);
2404
2448
 
2405
2449
  // Callbacks
@@ -2441,16 +2485,19 @@ class NodeTree {
2441
2485
  }
2442
2486
  });
2443
2487
 
2444
- if( this.options.rename ?? true )
2445
- item.addEventListener("dblclick", function() {
2488
+ item.addEventListener("dblclick", function() {
2489
+ if( that.options.rename ?? true )
2490
+ {
2446
2491
  // Trigger rename
2447
2492
  node.rename = true;
2448
2493
  that.refresh();
2449
- if(that.onevent) {
2450
- const event = new TreeEvent(TreeEvent.NODE_DBLCLICKED, node);
2451
- that.onevent( event );
2452
- }
2453
- });
2494
+ }
2495
+ if( that.onevent )
2496
+ {
2497
+ const event = new TreeEvent(TreeEvent.NODE_DBLCLICKED, node);
2498
+ that.onevent( event );
2499
+ }
2500
+ });
2454
2501
 
2455
2502
  item.addEventListener("contextmenu", e => {
2456
2503
  e.preventDefault();
@@ -2488,7 +2535,7 @@ class NodeTree {
2488
2535
  else if( e.key == "ArrowUp" || e.key == "ArrowDown" ) // Unique or zero selected
2489
2536
  {
2490
2537
  var selected = this.selected.length > 1 ? (e.key == "ArrowUp" ? this.selected.shift() : this.selected.pop()) : this.selected[0];
2491
- var el = this.domEl.querySelector("#" + selected.id);
2538
+ var el = this.domEl.querySelector("#" + LX.getSupportedDOMName( selected.id ) );
2492
2539
  var sibling = e.key == "ArrowUp" ? el.previousSibling : el.nextSibling;
2493
2540
  if( sibling ) sibling.click();
2494
2541
  }
@@ -2516,10 +2563,10 @@ class NodeTree {
2516
2563
  that.onevent( event );
2517
2564
  }
2518
2565
 
2519
- node.id = this.value;
2566
+ node.id = LX.getSupportedDOMName( this.value );
2520
2567
  delete node.rename;
2521
2568
  that.frefresh( node.id );
2522
- list.querySelector("#" + this.value).classList.add('selected');
2569
+ list.querySelector("#" + node.id).classList.add('selected');
2523
2570
  }
2524
2571
  if(e.key == 'Escape') {
2525
2572
  delete node.rename;
@@ -2667,21 +2714,21 @@ class NodeTree {
2667
2714
  }
2668
2715
  }
2669
2716
 
2670
- refresh(newData, selectedId) {
2717
+ refresh( newData, selectedId ) {
2671
2718
  this.data = newData ?? this.data;
2672
- this.domEl.querySelector("ul").innerHTML = "";
2719
+ this.domEl.querySelector( "ul" ).innerHTML = "";
2673
2720
  this._create_item( null, this.data, 0, selectedId );
2674
2721
  }
2675
2722
 
2676
2723
  /* Refreshes the tree and focuses current element */
2677
2724
  frefresh( id ) {
2678
2725
  this.refresh();
2679
- var el = this.domEl.querySelector("#" + id);
2680
- if(el) el.focus();
2726
+ var el = this.domEl.querySelector( "#" + id );
2727
+ if( el ) el.focus();
2681
2728
  }
2682
2729
 
2683
- select(id) {
2684
- this.refresh(null, id);
2730
+ select( id ) {
2731
+ this.refresh( null, id );
2685
2732
  }
2686
2733
  }
2687
2734
 
@@ -3513,6 +3560,15 @@ class Panel {
3513
3560
  addButton( name, value, callback, options = {} ) {
3514
3561
 
3515
3562
  let widget = this.create_widget(name, Widget.BUTTON, options);
3563
+ widget.onGetValue = () => {
3564
+ return wValue.innerText;
3565
+ };
3566
+ widget.onSetValue = (new_value) => {
3567
+ wValue.innerHTML = "<span>" +
3568
+ (options.icon ? "<a class='" + options.icon + "'></a>" :
3569
+ ( options.img ? "<img src='" + options.img + "'>" : (new_value || ""))) + "</span>";
3570
+ };
3571
+
3516
3572
  let element = widget.domEl;
3517
3573
 
3518
3574
  var wValue = document.createElement('button');
@@ -5848,7 +5904,7 @@ class ContextMenu {
5848
5904
  const hasSubmenu = o[ k ].length;
5849
5905
  let entry = document.createElement('div');
5850
5906
  entry.className = "lexcontextmenuentry" + (o[ 'className' ] ? " " + o[ 'className' ] : "" );
5851
- entry.id = o.id ?? ("eId" + this._getSupportedDOMName( k ));
5907
+ entry.id = o.id ?? ("eId" + getSupportedDOMName( k ));
5852
5908
  entry.innerHTML = "";
5853
5909
  const icon = o[ 'icon' ];
5854
5910
  if(icon) {
@@ -5995,7 +6051,7 @@ class ContextMenu {
5995
6051
  for( let item of this.items )
5996
6052
  {
5997
6053
  let key = Object.keys(item)[0];
5998
- let pKey = "eId" + this._getSupportedDOMName( key );
6054
+ let pKey = "eId" + getSupportedDOMName( key );
5999
6055
 
6000
6056
  // Item already created
6001
6057
  const id = "#" + (item.id ?? pKey);
@@ -6011,11 +6067,6 @@ class ContextMenu {
6011
6067
 
6012
6068
  this.colors[ token ] = color;
6013
6069
  }
6014
-
6015
- _getSupportedDOMName( key ) {
6016
- return key.replace(/\s/g, '').replaceAll('@', '_').replaceAll('+', '_plus_');
6017
- }
6018
-
6019
6070
  };
6020
6071
 
6021
6072
  LX.ContextMenu = ContextMenu;
package/changelog.md ADDED
@@ -0,0 +1,15 @@
1
+ # lexgui.js changelog
2
+
3
+ ## 0.1.20
4
+
5
+ Active line is now hightlighted.
6
+ Using CommitMono font (https://commitmono.com/) as the font for the Code Editor.
7
+ Added "Rust" syntax highlighting.
8
+ Improved all code selections (and some bugs fixed).
9
+ Block comments are now working again (with bugs probably).
10
+ Minor fixes.
11
+
12
+ ## 0.1.19
13
+
14
+ Add file explorer to Code Editor component.
15
+ Minor fixes.
@@ -23,48 +23,63 @@
23
23
  // init library and get main area
24
24
  let area = LX.init();
25
25
 
26
- // split main area
27
- var [leftArea, rightArea] = area.split({ sizes:["55%","45%"] });
26
+ const file_explorer = false;
28
27
 
29
- // add canvas to leftArea
30
- var canvas = document.createElement('canvas');
31
- canvas.id = "mycanvas";
32
- canvas.width = leftArea.root.clientWidth;
33
- canvas.height = leftArea.root.clientHeight;
34
- canvas.style.width = "100%";
35
- canvas.style.height = "100%";
36
- leftArea.attach( canvas );
28
+ if( !file_explorer )
29
+ {
30
+ var [leftArea, rightArea] = area.split({ sizes:["55%","45%"] });
31
+
32
+ var canvas = document.createElement('canvas');
33
+ canvas.id = "mycanvas";
34
+ canvas.width = leftArea.root.clientWidth;
35
+ canvas.height = leftArea.root.clientHeight;
36
+ canvas.style.width = "100%";
37
+ canvas.style.height = "100%";
38
+ leftArea.attach( canvas );
37
39
 
38
- // add on resize event to control canvas size
39
- leftArea.onresize = function( bounding ) {
40
- canvas.width = bounding.width;
41
- canvas.height = bounding.height;
42
- };
40
+ leftArea.onresize = function( bounding ) {
41
+ canvas.width = bounding.width;
42
+ canvas.height = bounding.height;
43
+ };
43
44
 
44
- let editor = new LX.CodeEditor(rightArea, {
45
+ area = rightArea;
46
+ }
47
+
48
+ let editor = new LX.CodeEditor(area, {
45
49
  // allow_add_scripts: false,
46
50
  // autocomplete: false,
47
- // disable_edition: true
51
+ // disable_edition: true,
52
+ file_explorer: file_explorer
48
53
  });
49
54
 
50
- editor.loadFile( "../demo.js" );
55
+ editor.loadFile( "../data/js_sample.js" );
56
+ // editor.loadFile( "../data/json_sample.json" );
57
+ // editor.loadFile( "../data/css_sample.css" );
58
+ // editor.loadFile( "../data/cpp_sample.cpp" );
59
+ // editor.loadFile( "../data/xml_sample.xml" );
60
+ // editor.loadFile( "../data/python_sample.py" );
61
+ // editor.loadFile( "../data/rust_sample.rs" );
62
+ // editor.loadFile( "../localhost.bat" );
51
63
 
52
- var ctx = canvas.getContext("2d");
53
- ctx.fillStyle = "#b7a9b1";
54
- ctx.font = "48px Monospace";
55
- ctx.strokeStyle = "#ff1999";
56
-
57
- function loop(dt) {
58
-
64
+ if( !file_explorer )
65
+ {
59
66
  var ctx = canvas.getContext("2d");
67
+ ctx.fillStyle = "#b7a9b1";
68
+ ctx.font = "48px Monospace";
69
+ ctx.strokeStyle = "#ff1999";
70
+
71
+ function loop(dt) {
72
+
73
+ var ctx = canvas.getContext("2d");
60
74
 
61
- ctx.fillRect(0, 0, canvas.width, canvas.height);
62
- ctx.strokeText("Lexgui.js @jxarco", 200, 300);
75
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
76
+ ctx.strokeText("Lexgui.js @jxarco", 200, 300);
77
+
78
+ requestAnimationFrame(loop);
79
+ }
63
80
 
64
81
  requestAnimationFrame(loop);
65
82
  }
66
83
 
67
- requestAnimationFrame(loop);
68
-
69
84
  </script>
70
85
  </html>
@@ -49,8 +49,7 @@
49
49
  'Code Editor',
50
50
  'Dialogs',
51
51
  'Immediate UI',
52
- 'Node Graph',
53
- 'Overlay Area'
52
+ 'Node Graph'
54
53
  ];
55
54
 
56
55
  let panel = leftArea.addPanel({ className: "lexexamplespanel" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lexgui",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "JS library to create web graphical user interfaces",
5
5
  "type": "module",
6
6
  "main": "./build/lexgui.js",
@@ -15,6 +15,7 @@
15
15
  "examples",
16
16
  "LICENSE",
17
17
  "package.json",
18
+ "changelog.md",
18
19
  "README.md",
19
20
  "demo.js"
20
21
  ],
@@ -1,61 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3
- <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
5
- <title>LexGUI Overlay Timeline Demo</title>
6
- <link rel="stylesheet" href="../build/lexgui.css">
7
- <link rel="icon" href="../images/icon.png">
8
- <script type="importmap">
9
- {
10
- "imports": {
11
- "lexgui": "../build/lexgui.module.js",
12
- "lexgui/components/": "../build/components/"
13
- }
14
- }
15
- </script>
16
- </head>
17
- <body></body>
18
- <script type="module">
19
-
20
- import { LX } from 'lexgui';
21
- import 'lexgui/components/timeline.js';
22
-
23
- // init library and get main area
24
- let area = LX.init();
25
-
26
- // add canvas
27
- var canvas = document.createElement('canvas');
28
- canvas.id = "mycanvas";
29
- canvas.width = window.innerWidth;
30
- canvas.height = window.innerHeight
31
- canvas.style.width = "100%";
32
- canvas.style.height = "100%";
33
- area.attach( canvas );
34
-
35
- let timeline = new LX.KeyFramesTimeline("kf-timeline", {opacity: 0.8});
36
- // timeline.setSelectedItems(["Item 1", "Item 2", "Item 3"]);
37
- // timeline.setAnimationClip({tracks: [{name: "Item 1.position", values: [0,1,0, 1], times: [0, 0.1, 0.2, 0.3]}, {name: "Item 1.scale", values: [0,1,0, 0.5], times: [0, 0.1, 0.2, 0.3]}, {name: "Item 2", values: [0,1,0,1], times: [0.1, 0.2, 0.3, 0.8]}, {name: "Item 3.position", values: [0,1,0], times: [0, 0.1, 0.2, 0.3]}, {name: "Item 3.scale", values: [0,1,0], times: [0, 0.1, 0.2, 0.3]}], duration: 1});
38
- let timelinearea = new LX.Area({ height: 400, overlay:"bottom", resize: true});
39
- timelinearea.attach(timeline.root);
40
-
41
- timelinearea.onresize = (bounding) => {timeline.resize( [ bounding.width, bounding.height ] );}
42
- area.attach(timelinearea)
43
-
44
- timeline.draw(0);
45
-
46
- function loop(dt) {
47
-
48
- var ctx = canvas.getContext("2d");
49
- ctx.fillStyle = "cyan";
50
- ctx.fillRect(0,0,1000,800);
51
- ctx.fillStyle = "black";
52
- ctx.font = "bold 48px serif"
53
- ctx.fillText("Overlay timeline area", 400, 400);
54
- timeline.draw();
55
-
56
- requestAnimationFrame(loop);
57
- }
58
-
59
- requestAnimationFrame(loop);
60
- </script>
61
- </html>
Binary file