lexgui 0.6.6 → 0.6.7

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.
@@ -221,8 +221,9 @@ class CodeEditor {
221
221
 
222
222
  static __instances = [];
223
223
 
224
- static CURSOR_LEFT = 1;
225
- static CURSOR_TOP = 2;
224
+ static CURSOR_LEFT = 1;
225
+ static CURSOR_TOP = 2;
226
+ static CURSOR_LEFT_TOP = CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP;
226
227
 
227
228
  static SELECTION_X = 1;
228
229
  static SELECTION_Y = 2
@@ -265,8 +266,6 @@ class CodeEditor {
265
266
 
266
267
  panel.addTitle( "EXPLORER" );
267
268
 
268
- this._tabStorage = {};
269
-
270
269
  let sceneData = {
271
270
  'id': 'WORKSPACE',
272
271
  'skipVisibility': true,
@@ -320,6 +319,7 @@ class CodeEditor {
320
319
  this.skipInfo = options.skipInfo ?? false;
321
320
  this.disableEdition = options.disableEdition ?? false;
322
321
 
322
+ this._tabStorage = {};
323
323
  this.tabs = this.area.addTabs( { onclose: (name) => {
324
324
  delete this.openedTabs[ name ];
325
325
  if( Object.keys( this.openedTabs ).length < 2 )
@@ -976,7 +976,7 @@ class CodeEditor {
976
976
  }
977
977
  else {
978
978
  cursor.selection.invertIfNecessary();
979
- this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP, cursor );
979
+ this.resetCursorPos( CodeEditor.CURSOR_LEFT_TOP, cursor );
980
980
  this.cursorToLine( cursor, cursor.selection.fromY, true );
981
981
  this.cursorToPosition( cursor, cursor.selection.fromX );
982
982
  this.endSelection();
@@ -1057,7 +1057,7 @@ class CodeEditor {
1057
1057
  else
1058
1058
  {
1059
1059
  cursor.selection.invertIfNecessary();
1060
- this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP, cursor );
1060
+ this.resetCursorPos( CodeEditor.CURSOR_LEFT_TOP, cursor );
1061
1061
  this.cursorToLine( cursor, cursor.selection.toY );
1062
1062
  this.cursorToPosition( cursor, cursor.selection.toX );
1063
1063
  this.endSelection();
@@ -1090,7 +1090,7 @@ class CodeEditor {
1090
1090
  this.addTab("+", false, "New File");
1091
1091
  }
1092
1092
 
1093
- this.addTab( options.name || "untitled", true, options.title, { language: "Plain Text" } );
1093
+ this.addTab( options.name || "untitled", true, options.title, { language: options.highlight ?? "Plain Text" } );
1094
1094
 
1095
1095
  // Create inspector panel
1096
1096
  let panel = this._createPanelInfo();
@@ -1771,7 +1771,7 @@ class CodeEditor {
1771
1771
  if( selected )
1772
1772
  {
1773
1773
  this.code = code;
1774
- this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP );
1774
+ this.resetCursorPos( CodeEditor.CURSOR_LEFT_TOP );
1775
1775
  this.processLines();
1776
1776
  }
1777
1777
 
@@ -1845,10 +1845,26 @@ class CodeEditor {
1845
1845
 
1846
1846
  // Select as current...
1847
1847
  this.code = code;
1848
- this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP );
1848
+ this.resetCursorPos( CodeEditor.CURSOR_LEFT_TOP );
1849
1849
  this.processLines();
1850
1850
  this._changeLanguageFromExtension( LX.getExtension( name ) );
1851
- this._updateDataInfoPanel( "@tab-name", code.tabname );
1851
+ this._updateDataInfoPanel( "@tab-name", code.tabName );
1852
+ }
1853
+
1854
+ closeTab( name, eraseAll ) {
1855
+
1856
+ this.tabs.delete( name );
1857
+
1858
+ if( eraseAll )
1859
+ {
1860
+ delete this.openedTabs[ name ];
1861
+ delete this.loadedTabs[ name ];
1862
+ delete this._tabStorage[ name ];
1863
+ }
1864
+ }
1865
+
1866
+ getSelectedTabName() {
1867
+ return this.tabs.selected;
1852
1868
  }
1853
1869
 
1854
1870
  loadTabFromFile() {
@@ -3491,7 +3507,7 @@ class CodeEditor {
3491
3507
  this._removeSecondaryCursors();
3492
3508
 
3493
3509
  var cursor = this._getCurrentCursor();
3494
- this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP, cursor );
3510
+ this.resetCursorPos( CodeEditor.CURSOR_LEFT_TOP, cursor );
3495
3511
 
3496
3512
  this.startSelection( cursor );
3497
3513
 
@@ -190,12 +190,14 @@ function MAKE_CODE( text, language = "js" )
190
190
 
191
191
  window.MAKE_CODE = MAKE_CODE;
192
192
 
193
- function MAKE_BULLET_LIST( list )
193
+ function MAKE_LIST( list, type )
194
194
  {
195
- console.assert(list && list.length > 0);
196
- let ul = document.createElement('ul');
195
+ const validTypes = [ 'bullet', 'numbered' ];
196
+ console.assert( list && list.length > 0 && validTypes.includes(type), "Invalid list type or empty list" + type );
197
+ const typeString = type == 'bullet' ? 'ul' : 'ol';
198
+ let ul = document.createElement( typeString );
197
199
  for( var el of list ) {
198
- let li = document.createElement('li');
200
+ let li = document.createElement( 'li' );
199
201
  li.className = "leading-loose";
200
202
  li.innerHTML = el;
201
203
  ul.appendChild( li );
@@ -203,8 +205,20 @@ function MAKE_BULLET_LIST( list )
203
205
  mainContainer.appendChild( ul );
204
206
  }
205
207
 
208
+ function MAKE_BULLET_LIST( list )
209
+ {
210
+ MAKE_LIST( list, 'bullet' );
211
+ }
212
+
206
213
  window.MAKE_BULLET_LIST = MAKE_BULLET_LIST;
207
214
 
215
+ function MAKE_NUMBERED_LIST( list )
216
+ {
217
+ MAKE_LIST( list, 'numbered' );
218
+ }
219
+
220
+ window.MAKE_NUMBERED_LIST = MAKE_NUMBERED_LIST;
221
+
208
222
  function ADD_CODE_LIST_ITEM( item, target )
209
223
  {
210
224
  target = target ?? window.listQueued;
@@ -388,25 +402,19 @@ function INSERT_VIDEO( src, caption = "", controls = true, autoplay = false )
388
402
 
389
403
  window.INSERT_VIDEO = INSERT_VIDEO;
390
404
 
391
- function MAKE_NOTE( string, title = "Note" )
405
+ function MAKE_NOTE( string, warning, title, icon )
392
406
  {
393
407
  console.assert( string );
394
408
 
395
- let note = document.createElement( 'div' );
396
- note.className = "note";
409
+ const note = LX.makeContainer( [], "border rounded-lg overflow-hidden text-md fg-secondary my-6", "", mainContainer );
397
410
 
398
411
  let header = document.createElement( 'div' );
399
- header.className = "note-header";
400
- header.appendChild( LX.makeIcon( "NotepadText" ) );
401
- header.innerHTML += "<b>" + title + "</b>";
402
-
403
- let body = document.createElement( 'div' );
404
- body.className = "note-body";
405
- body.innerHTML = string;
406
-
412
+ header.className = "flex bg-tertiary font-semibold px-3 py-2 gap-2 fg-secondary";
413
+ header.appendChild( LX.makeIcon( icon ?? ( warning ? "MessageSquareWarning" : "NotepadText" ) ) );
414
+ header.innerHTML += ( title ?? ( warning ? "Important" : "Note" ) );
407
415
  note.appendChild( header );
408
- note.appendChild( body );
409
- mainContainer.appendChild( note );
416
+
417
+ const body = LX.makeContainer( [], "leading-6 p-3", string, note );
410
418
  }
411
419
 
412
420
  window.MAKE_NOTE = MAKE_NOTE;
@@ -151,7 +151,7 @@ code.inline.desc {
151
151
  }
152
152
 
153
153
  #content strong {
154
- font-weight:900;
154
+ font-weight:700;
155
155
  }
156
156
 
157
157
  #content a.permalink {
@@ -225,29 +225,6 @@ code.inline.desc {
225
225
 
226
226
  }
227
227
 
228
- #goUpButton {
229
- position: fixed;
230
- z-index: 10;
231
- bottom: 32px;
232
- right: 32px;
233
- border: 1px solid #666;
234
- border-radius: 6px;
235
- outline: none;
236
- background: none;
237
- font-size: 18px;
238
- padding: 6px;
239
- color: #bbb;
240
- transition: all 0.25s;
241
- width: 32px;
242
- height: 32px;
243
- }
244
-
245
- #goUpButton:hover {
246
- color: #ccc;
247
- border-color: #ccc;
248
- cursor: pointer;
249
- }
250
-
251
228
  pre .str, code .str { color: #c79369; } /* string */
252
229
  pre .kwd, code .kwd { color: #2194ce; } /* keyword */
253
230
  pre .com, code .com { color: #999999; } /* comment */
@@ -295,50 +272,17 @@ code:has(.constructor) {
295
272
  }
296
273
 
297
274
  #content span.solid {
298
- /* background-color: var(--global-selected); */
299
275
  border-radius: 8px;
300
276
  padding: 2px;
301
277
  padding-inline: 8px;
302
278
  }
303
279
 
304
280
  #content span.outline {
305
- /* border: 1px solid var(--global-accent); */
306
- /* color: var(--global-selected); */
307
281
  border-radius: 8px;
308
282
  padding: 2px;
309
283
  padding-inline: 8px;
310
284
  }
311
285
 
312
- .note {
313
- border-radius: 8px;
314
- overflow: hidden;
315
- margin: 16px 0;
316
- font-size: 0.95rem;
317
- color: var(--global-text-secondary);
318
- box-shadow: 0 1px 3px var(--global-color-tertiary);
319
- }
320
-
321
- .note-header {
322
- background-color: var(--global-color-tertiary);
323
- color: var(--global-text-secondary);
324
- padding: 8px 12px;
325
- display: flex;
326
- align-items: center;
327
- gap: 0.5em;
328
- font-weight: bold;
329
- }
330
-
331
- .note-header svg {
332
- width: 1em;
333
- height: 1em;
334
- flex-shrink: 0;
335
- }
336
-
337
- .note-body {
338
- padding: 12px;
339
- line-height: 1.5;
340
- }
341
-
342
286
  :root[data-theme="light"] #content {
343
287
  color: #202124;
344
288
  }
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.6",
17
+ version: "0.6.7",
18
18
  ready: false,
19
19
  components: [], // Specific pre-build components
20
20
  signals: {}, // Events and triggers
@@ -877,7 +877,7 @@ class Sheet {
877
877
  this.root.dataset["side"] = this.side;
878
878
  this.root.tabIndex = "1";
879
879
  this.root.role = "dialog";
880
- this.root.className = "lexsheet fixed z-100 bg-primary";
880
+ this.root.className = "lexsheet fixed z-1000 bg-primary";
881
881
  LX.root.appendChild( this.root );
882
882
 
883
883
  this.root.addEventListener( "keydown", (e) => {
@@ -2212,6 +2212,11 @@ class Tabs {
2212
2212
 
2213
2213
  delete( name ) {
2214
2214
 
2215
+ if( this.selected == name )
2216
+ {
2217
+ this.selected = null;
2218
+ }
2219
+
2215
2220
  const tabEl = this.tabDOMs[ name ];
2216
2221
 
2217
2222
  if( !tabEl || tabEl.fixed )
@@ -7409,11 +7414,6 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7409
7414
 
7410
7415
  const refresh_widget = () => {
7411
7416
 
7412
- if( instance )
7413
- {
7414
- widget.instance = instance = Object.assign( LX.deepCopy(defaultInstance), instance );
7415
- }
7416
-
7417
7417
  if( container ) container.remove();
7418
7418
  if( customWidgetsDom ) customWidgetsDom.remove();
7419
7419
 
@@ -7478,13 +7478,36 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7478
7478
  this.queue( customWidgetsDom );
7479
7479
 
7480
7480
  const on_instance_changed = ( key, value, event ) => {
7481
- instance[ key ] = value;
7481
+ const setter = options[ `_set_${ key }` ];
7482
+ if( setter )
7483
+ {
7484
+ setter.call( instance, value );
7485
+ }
7486
+ else
7487
+ {
7488
+ instance[ key ] = value;
7489
+ }
7482
7490
  widget._trigger( new LX.IEvent( name, instance, event ), callback );
7483
7491
  };
7484
7492
 
7485
7493
  for( let key in defaultInstance )
7486
7494
  {
7487
- const value = instance[ key ] ?? defaultInstance[ key ];
7495
+ let value = null;
7496
+
7497
+ const getter = options[ `_get_${ key }` ];
7498
+ if( getter )
7499
+ {
7500
+ value = instance[ key ] ? getter.call( instance ) : getter.call( defaultInstance );
7501
+ }
7502
+ else
7503
+ {
7504
+ value = instance[ key ] ?? defaultInstance[ key ];
7505
+ }
7506
+
7507
+ if( !value )
7508
+ {
7509
+ continue;
7510
+ }
7488
7511
 
7489
7512
  switch( value.constructor )
7490
7513
  {
@@ -7514,6 +7537,9 @@ function ADD_CUSTOM_WIDGET( customWidgetName, options = {} )
7514
7537
  this._addVector( value.length, key, value, on_instance_changed.bind( this, key ) );
7515
7538
  }
7516
7539
  break;
7540
+ default:
7541
+ console.warn( `Unsupported property type: ${ value.constructor.name }` );
7542
+ break;
7517
7543
  }
7518
7544
  }
7519
7545
 
@@ -8451,6 +8477,27 @@ class Button extends Widget {
8451
8477
  wValue.innerHTML = `<span>${ ( value || "" ) }</span>`;
8452
8478
  }
8453
8479
 
8480
+ if( options.fileInput )
8481
+ {
8482
+ const fileInput = document.createElement( "input" );
8483
+ fileInput.type = "file";
8484
+ fileInput.className = "file-input";
8485
+ fileInput.style.display = "none";
8486
+ wValue.appendChild( fileInput );
8487
+
8488
+ fileInput.addEventListener( 'change', function( e ) {
8489
+ const files = e.target.files;
8490
+ if( !files.length ) return;
8491
+
8492
+ const reader = new FileReader();
8493
+ if( options.fileInputType === 'text' ) reader.readAsText( files[ 0 ] );
8494
+ else if( options.fileInputType === 'buffer' ) reader.readAsArrayBuffer( files[ 0 ] );
8495
+ else if( options.fileInputType === 'bin' ) reader.readAsBinaryString( files[ 0 ] );
8496
+ else if( options.fileInputType === 'url' ) reader.readAsDataURL( files[ 0 ] );
8497
+ reader.onload = e => { callback.call( this, e.target.result, files[ 0 ] ); } ;
8498
+ });
8499
+ }
8500
+
8454
8501
  if( options.disabled )
8455
8502
  {
8456
8503
  this.disabled = true;
@@ -8503,8 +8550,15 @@ class Button extends Widget {
8503
8550
  wValue.classList.toggle('selected');
8504
8551
  }
8505
8552
 
8506
- const swapInput = wValue.querySelector( "input" );
8507
- this._trigger( new LX.IEvent( name, swapInput?.checked ?? value, e ), callback );
8553
+ if( options.fileInput )
8554
+ {
8555
+ wValue.querySelector( ".file-input" ).click();
8556
+ }
8557
+ else
8558
+ {
8559
+ const swapInput = wValue.querySelector( "input" );
8560
+ this._trigger( new LX.IEvent( name, swapInput?.checked ?? value, e ), callback );
8561
+ }
8508
8562
  });
8509
8563
 
8510
8564
  if( options.tooltip )
@@ -12840,6 +12894,8 @@ class Panel {
12840
12894
  * hideName: Don't use name as label [false]
12841
12895
  * disabled: Make the widget disabled [false]
12842
12896
  * icon: Icon class to show as button value
12897
+ * fileInput: Button click requests a file
12898
+ * fileInputType: Type of the requested file
12843
12899
  * img: Path to image to show as button value
12844
12900
  * title: Text to show in native Element title
12845
12901
  * buttonClass: Class to add to the native button element
@@ -14180,6 +14236,13 @@ class Sidebar {
14180
14236
  info.appendChild( infoSubtext );
14181
14237
  }
14182
14238
 
14239
+ // Add icon if onHeaderPressed is defined and not collapsable (it uses the toggler icon)
14240
+ if( options.onHeaderPressed && !this.collapsable )
14241
+ {
14242
+ const icon = LX.makeIcon( "MenuArrows" );
14243
+ header.appendChild( icon );
14244
+ }
14245
+
14183
14246
  return header;
14184
14247
  }
14185
14248
 
@@ -14225,8 +14288,13 @@ class Sidebar {
14225
14288
  info.appendChild( infoSubtext );
14226
14289
  }
14227
14290
 
14228
- const icon = LX.makeIcon( "MenuArrows" );
14229
- footer.appendChild( icon );
14291
+ // Add icon if onFooterPressed is defined
14292
+ // Useful to indicate that the footer is clickable
14293
+ if( options.onFooterPressed )
14294
+ {
14295
+ const icon = LX.makeIcon( "MenuArrows" );
14296
+ footer.appendChild( icon );
14297
+ }
14230
14298
 
14231
14299
  return footer;
14232
14300
  }