lexgui 0.5.2 → 0.5.4

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/demo.js CHANGED
@@ -5,20 +5,21 @@ import 'lexgui/components/audio.js';
5
5
 
6
6
  window.LX = LX;
7
7
 
8
- let area = LX.init( { strictViewport: false } );
8
+ const area = LX.init( { strictViewport: false, rootClass: "wrapper" } );
9
9
 
10
10
  // Menubar
11
11
  {
12
12
  area.addMenubar( m => {
13
-
13
+
14
14
  m.setButtonImage("lexgui.js", "images/icon.png", () => {window.open("https://jxarco.github.io/lexgui.js/")}, {float: "left"})
15
-
15
+
16
16
  m.add( "Docs", { icon: "fa-solid fa-magnifying-glass", short: "F1", callback: () => { window.open("./docs/") }});
17
-
18
- const panel = new LX.Panel();
19
- panel.addButton(null, "Search command...", () => { LX.setCommandbarState( true ) }, { width: "256px", className: "right", buttonClass: "outline left" });
20
- m.root.appendChild( panel.root.childNodes[ 0 ] );
21
-
17
+
18
+ const commandButton = new LX.Button(null, "Search command...", () => { LX.setCommandbarState( true ) }, {
19
+ width: "256px", className: "right", buttonClass: "outline left fg-tertiary bg-secondary" }
20
+ );
21
+ m.root.appendChild( commandButton.root );
22
+
22
23
  m.addButtons( [
23
24
  {
24
25
  title: "Github",
@@ -39,77 +40,461 @@ let area = LX.init( { strictViewport: false } );
39
40
 
40
41
  // Header
41
42
  {
42
- const header = LX.makeContainer( [ null, "auto" ], "col", {
43
- border: "1px solid rgba(255, 255, 255, 0.08)",
44
- padding: "36px 24px 36px 24px",
45
- gap: "8px"
46
- } );
47
-
48
- header.innerHTML = `
43
+ const header = LX.makeContainer( [ null, "auto" ], "flex flex-col border-top border-bottom gap-2 px-6 py-12", `
49
44
  <a>Get started with LexGUI.js</a>
50
45
  <h1>Build your application interface</h1>
51
- <p style="max-width:42rem">A set of beautifully-designed, accessible components and a code distribution platform.
52
- Works with your favorite frameworks. Open Source. Open Code.</p>
53
- `;
54
-
55
- area.attach( header );
46
+ <p class="font-light" style="max-width:32rem">A set of beautifully-designed, accessible widgets and components.
47
+ No complex frameworks. Pure JavaScript and CSS. Open Source.</p>
48
+ `, area );
56
49
  }
57
50
 
58
51
  // Content
59
52
  {
60
- area.attach( document.createElement('br') );
53
+ const tabs = area.addTabs( { parentClass: "p-4", sizes: [ "auto", "auto" ], contentClass: "p-6 pt-0" } );
61
54
 
62
- const tabs = area.addTabs( { sizes: [ "auto", "auto" ] } );
55
+ // Editor
56
+ {
57
+ const editorContainer = LX.makeContainer( [ null, "800px" ], "flex flex-col bg-primary border rounded-lg overflow-hidden" );
58
+ tabs.add( "Editor", editorContainer, { selected: true } );
63
59
 
64
- const examplesContainer = LX.makeContainer( [ "auto", "850px" ], "", {
65
- backgroundColor: "red"
66
- } );
60
+ const editorArea = new LX.Area({ className: "rounded-lg" });
61
+ editorContainer.appendChild( editorArea.root );
67
62
 
68
- const tasksContainer = LX.makeContainer( [ "auto", "850px" ], "", {
69
- backgroundColor: "red"
70
- } );
63
+ editorArea.addMenubar( m => {
64
+ m.add( "Scene/New Scene", () => { console.log("New scene created!") });
65
+ m.add( "Scene/Open Scene", { icon: "fa-solid fa-folder-open", short: "S" } );
66
+ m.add( "Scene/Open Recent/hello.scene" );
67
+ m.add( "Scene/Open Recent/goodbye.scene" );
68
+ m.add( "Project/Project Settings", { disabled: true } );
69
+ m.add( "Project/" );
70
+ m.add( "Project/Export", { icon: "fa-solid fa-download" });
71
+ m.add( "Project/Export/DAE", { icon: "fa-solid fa-cube", short: "D" } );
72
+ m.add( "Project/Export/GLTF", { short: "G" } );
73
+ m.add( "Account/Login", { icon: "fa-solid fa-user" } );
74
+ m.add( "Help/Search Help", { icon: "fa-solid fa-magnifying-glass", short: "F1" } );
75
+ m.add( "Help/Support LexGUI/Please", { icon: "fa-solid fa-heart" } );
76
+ m.add( "Help/Support LexGUI/Do it" );
77
+ m.addButtons( [
78
+ {
79
+ title: "Play",
80
+ icon: "fa-solid fa-play",
81
+ swap: "fa-solid fa-stop"
82
+ },
83
+ {
84
+ title: "Pause",
85
+ icon: "fa-solid fa-pause",
86
+ disabled: true
87
+ }
88
+ ]);
89
+ }, { sticky: false });
71
90
 
72
- const codeContainer = LX.makeContainer( [ "auto", "850px" ], "", {
73
- backgroundColor: "red"
74
- } );
91
+ // split main area
92
+ const [ left, right ] = editorArea.split({ sizes:["70%","30%"], minimizable: true });
75
93
 
76
- const audioContainer = LX.makeContainer( [ "auto", "850px" ], "", {
77
- backgroundColor: "red"
78
- } );
94
+ // add canvas to left upper part
95
+ const canvas = document.createElement('canvas');
96
+ canvas.style.width = "100%";
97
+ canvas.style.height = "100%";
98
+ canvas.width = left.root.offsetWidth;
99
+ canvas.height = left.root.offsetHeight
100
+
101
+ const resizeCanvas = ( bounding ) => {
102
+ canvas.width = bounding.width;
103
+ canvas.height = bounding.height;
104
+ };
105
+
106
+ left.attach( canvas );
107
+ left.onresize = resizeCanvas;
108
+ left.addOverlayButtons( [
109
+ [
110
+ { name: "Select", icon: "fa fa-arrow-pointer", selectable: true },
111
+ { name: "Move", icon: "fa-solid fa-arrows-up-down-left-right", selectable: true },
112
+ { name: "Rotate", icon: "fa-solid fa-rotate-right", selectable: true }
113
+ ],
114
+ { name: "Lit", options: ["Lit", "Unlit", "Wireframe"] },
115
+ [
116
+ { name: "Enable Snap", icon: "fa fa-table-cells", selectable: true },
117
+ { name: 10, options: [10, 100, 1000] }
118
+ ]
119
+ ], { float: "htc" } );
120
+
121
+ // add panels
122
+ var sidePanel = right.addPanel();
123
+ fillPanel( sidePanel );
124
+
125
+ function loop(dt) {
126
+
127
+ var ctx = canvas.getContext("2d");
128
+ ctx.fillStyle = sidePanel.getValue('Background');
129
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
130
+ ctx.font = `${ sidePanel.getValue('Font Size') }px ${ sidePanel.getValue('Font Family') }`;
131
+ ctx.fillStyle = sidePanel.getValue('Font Color');
132
+ const pos2D = sidePanel.getValue('2D Position');
133
+ ctx.fillText( sidePanel.getValue('Text'), pos2D[0], pos2D[1]);
134
+ requestAnimationFrame(loop);
135
+ }
136
+
137
+ requestAnimationFrame(loop);
138
+
139
+ // **** **** **** **** **** **** **** **** **** **** **** ****
140
+
141
+ function fillPanel( panel ) {
142
+
143
+ // Add data tree
144
+
145
+ let sceneData = {
146
+ 'id': 'root',
147
+ 'children': [
148
+ {
149
+ 'id': 'node_1',
150
+ 'children': [
151
+ {
152
+ 'id': 'node_1_1',
153
+ 'icon': 'fa-solid fa-cube',
154
+ 'children': [],
155
+ 'actions': [
156
+ {
157
+ 'name': 'Open script',
158
+ 'icon': 'fa-solid fa-scroll'
159
+ }
160
+ ]
161
+ }
162
+ ]
163
+ },
164
+ {
165
+ 'id': 'node_2',
166
+ 'icon': 'fa-solid fa-circle-play',
167
+ 'children': []
168
+ }
169
+ ]
170
+ };
171
+
172
+ // This is optional!
173
+ const treeIcons = [
174
+ {
175
+ 'name':'Add node',
176
+ 'icon': 'fa-solid fa-plus'
177
+ },
178
+ {
179
+ 'name':'Instantiate scene',
180
+ 'icon': 'fa-solid fa-link'
181
+ }
182
+ ];
183
+
184
+ window.tree = panel.addTree("Scene Tree", sceneData, {
185
+ icons: treeIcons,
186
+ addDefault: true,
187
+ onevent: (event) => {
188
+ switch(event.type) {
189
+ case LX.TreeEvent.NODE_CONTEXTMENU:
190
+ const m = event.panel;
191
+ m.add( "Components/Transform");
192
+ m.add( "Components/MeshRenderer");
193
+ break;
194
+ }
195
+ }
196
+ });
197
+
198
+ // add widgets to panel branch
199
+ panel.branch("Canvas", {icon: "fa-solid fa-palette", filter: true});
200
+ panel.addColor("Background", "#b7a9b1", null);
201
+ panel.addText("Text", "LexGUI.js @jxarco", null, {placeholder: "e.g. ColorPicker", icon: "fa fa-font"});
202
+ panel.addColor("Font Color", "#303b8d", null);
203
+ panel.addNumber("Font Size", 36, null, { min: 1, max: 48, step: 1, units: "px"});
204
+ panel.addSelect("Font Family", ["Arial", "GeistSans", "Monospace"], "GeistSans");
205
+ panel.addVector2("2D Position", [300, 350], null, { min: 0, max: 1024 });
206
+ const opacityValues = [
207
+ [0.2, 0.3146875],
208
+ [0.417313915857606, 0.8946875000000003],
209
+ [0.5495145631067961, 0.6746875],
210
+ [1, 1]
211
+ ];
212
+ panel.addCurve("Opacity", opacityValues);
213
+ panel.addSize("Resolution", [1280, 720], null, { units: "p", precision: 0 });
214
+ panel.merge();
215
+
216
+ panel.branch("Node", { icon: "fa-solid fa-cube" });
217
+ panel.addText("Name", "node_1");
218
+ panel.addCheckbox("Visibility", true, null, { className: "accent" });
219
+ panel.addLayers("Layers", 10, null);
220
+
221
+ panel.addTitle( "Transform" );
222
+ panel.addVector3( "Position", [0.0, 0.0, 0.0] );
223
+ panel.addVector4( "Rotation", [0.0, 0.0, 0.0, 1.0] );
224
+ panel.addVector3( "Scale", [1.0, 1.0, 1.0] );
225
+ panel.addButton(null, "Export", null, { buttonClass: "contrast" });
226
+ panel.merge();
227
+ }
228
+ }
229
+
230
+ // Mail
231
+ {
232
+ const mailContainer = LX.makeContainer( [ null, "800px" ], "flex flex-col bg-primary border rounded-lg overflow-hidden" );
233
+ tabs.add( "Mail", mailContainer, { xselected: true } );
234
+
235
+ const mailArea = new LX.Area();
236
+ mailContainer.appendChild( mailArea.root );
237
+ const badgeClass = "ml-auto no-bg font-medium";
238
+
239
+ const sidebar = mailArea.addSidebar( m => {
240
+ m.add( "Inbox", { selected: true, icon: "inbox", content: LX.badge("128", badgeClass, { asElement: true }) } );
241
+ m.add( "Drafts", { icon: "file", content: LX.badge("9", badgeClass, { asElement: true }) } );
242
+ m.add( "Sent", { icon: "paper-plane" } );
243
+ m.add( "Junk", { icon: "box-archive-x", content: LX.badge("23", badgeClass, { asElement: true }) } );
244
+ m.add( "Trash", { icon: "trash-can" } );
245
+ m.add( "Archive", { icon: "box-archive" } );
246
+ m.separator();
247
+ m.add( "Social", { icon: "user", content: LX.badge("972", badgeClass, { asElement: true }) } );
248
+ m.add( "Updates", { icon: "circle-info", content: LX.badge("342", badgeClass, { asElement: true }) } );
249
+ m.add( "Forums", { icon: "comments", content: LX.badge("96", badgeClass, { asElement: true }) } );
250
+ m.add( "Shopping ", { icon: "shopping-cart" } );
251
+ m.add( "Promotions", { icon: "flag", content: LX.badge("21", badgeClass, { asElement: true }) } );
252
+ }, {
253
+ // collapseToIcons: false,
254
+ className: "border-right",
255
+ headerTitle: "jxarco",
256
+ headerSubtitle: "alexroco.30@gmail.com",
257
+ headerImage: "https://raw.githubusercontent.com/jxarco/lexgui.js/refs/heads/master/images/icon.png",
258
+ skipFooter: true,
259
+ displaySelected: true,
260
+ onHeaderPressed: (e, element) => { }
261
+ });
262
+
263
+ const inboxArea = sidebar.siblingArea;
264
+
265
+ var [ left, right ] = inboxArea.split({ sizes:["40%","60%"] });
266
+ left.setLimitBox( 350, null, 650, null );
267
+
268
+ // Manage Inbox
269
+ {
270
+ const inboxTabs = left.addTabs({ parentClass: "flex p-3 items-end border-bottom", sizes: [ "auto", "auto" ], float: "end" });
271
+ const tabsRowContainer = inboxTabs.root.parentElement;
272
+
273
+ const mailSectionTitle = LX.makeContainer( [ "auto", "auto" ], "mr-auto ml-2 self-center text-xxl font-semibold", "Inbox" );
274
+ tabsRowContainer.prepend( mailSectionTitle );
275
+
276
+ window.__showMailList = ( container, unreadOnly = false ) => {
277
+
278
+ // Filter
279
+ {
280
+ const allMailFilter = LX.makeContainer( [ "100%", "50px" ], "flex p-2", "", container );
281
+ const filterInput = new LX.TextInput(null, "", null,
282
+ { inputClass: "outline", width: "100%", icon: "fa fa-magnifying-glass", placeholder: "Search..." }
283
+ );
284
+ allMailFilter.appendChild( filterInput.root );
285
+ }
286
+
287
+ // Content
288
+ {
289
+ const allMailContent = LX.makeContainer( [ "100%", "calc(100% - 50px)" ], "flex flex-col p-4 pt-0 gap-2 overflow-scroll", "", container );
290
+
291
+ window.__addMail = ( mail, mailContainer ) => {
292
+
293
+ const msgContent = LX.makeContainer( [ "100%", "auto" ],
294
+ "flex flex-col border p-3 rounded-lg gap-2 select-none hover:bg-secondary cursor-pointer", "", mailContainer );
295
+
296
+ // Name, subject, date
297
+ {
298
+ const msgInfo = LX.makeContainer( [ "100%", "auto" ], "flex flex-col gap-0.5", "", msgContent );
299
+ const msgNameDate = LX.makeContainer( [ "100%", "auto" ], "flex flex-row", "", msgInfo );
300
+
301
+ // Name + Date
302
+ {
303
+ const msgName = LX.makeContainer( [ "auto", "auto" ], "flex font-semibold text-md gap-2", "", msgNameDate );
304
+ msgName.innerHTML = mail.name;
305
+ msgName.innerHTML += ( mail.read ? "" : `<span class="rounded-full self-center bg-accent" style="width: 8px; height: 8px"></span>` );
306
+ const msgDate = LX.makeContainer( [ "auto", "auto" ], "fg-tertiary text-sm ml-auto self-center", mail.date, msgNameDate );
307
+ }
308
+
309
+ const msgSubject = LX.makeContainer( [ "100%", "auto" ], "font-semibold text-sm", mail.subject, msgInfo );
310
+ }
311
+
312
+ const msgText = LX.makeContainer( [ "100%", "auto" ], "text-sm line-clamp-2 fg-tertiary", mail.content, msgContent );
313
+ const msgTags = LX.makeContainer( [ "100%", "auto" ], "flex flex-row gap-0.5 font-semibold", "", msgContent );
314
+ for( const tag of mail.tags )
315
+ {
316
+ msgTags.appendChild( LX.badge( tag, "sm", { asElement: true } ) );
317
+ }
318
+
319
+ msgContent.listen( "click", () => {
320
+ window.__openMail( mail );
321
+ } );
322
+ };
323
+
324
+ LX.requestJSON( "data/example_mail_data.json", data => {
325
+ data.forEach( e => { if( !unreadOnly || ( unreadOnly && !e.read ) ) window.__addMail( e, allMailContent ) } );
326
+ window.__openMail( data[ 0 ] );
327
+ } )
328
+ }
329
+ }
330
+
331
+ const allMailContainer = LX.makeContainer( [ "100%", "100%" ], "flex flex-col" );
332
+ inboxTabs.add( "All mail", allMailContainer, { selected: true } );
333
+ window.__showMailList( allMailContainer );
334
+
335
+ const unreadMailContainer = LX.makeContainer( [ "100%", "100%" ], "flex flex-col" );
336
+ inboxTabs.add( "Unread", unreadMailContainer );
337
+ window.__showMailList( unreadMailContainer, true );
338
+ }
339
+
340
+ // Manage Message Preview
341
+ {
342
+ // Buttons
343
+ {
344
+ const mailPreviewHeader = LX.makeContainer( [ "100%", "59.59px" ], "flex flex-row border-bottom p-1", "", right );
345
+
346
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Archive", tooltip: true, buttonClass: "bg-none", icon: "box-archive" } ).root );
347
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Move to junk", tooltip: true, buttonClass: "bg-none", icon: "box-archive-x" } ).root );
348
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Move to trash", tooltip: true, buttonClass: "bg-none", icon: "trash-can" } ).root );
349
+ mailPreviewHeader.appendChild( LX.makeContainer( [ "1px", "35%" ], "border-right self-center ml-2 mr-2" ) );
350
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Snooze", tooltip: true, buttonClass: "bg-none", icon: "clock" } ).root );
351
+
352
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Reply", tooltip: true, buttonClass: "bg-none", className: "ml-auto", icon: "reply" } ).root );
353
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Reply all", tooltip: true, buttonClass: "bg-none", icon: "reply-all" } ).root );
354
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Forward", tooltip: true, buttonClass: "bg-none", icon: "forward" } ).root );
355
+ mailPreviewHeader.appendChild( LX.makeContainer( [ "1px", "35%" ], "border-right self-center ml-2 mr-2" ) );
356
+ mailPreviewHeader.appendChild( new LX.Button( null, "", (value, event) => {
357
+ new LX.DropdownMenu( event.target, [
358
+ { name: "Mark as unread" },
359
+ { name: "Star thread" },
360
+ { name: "Add label" },
361
+ { name: "Mute thread" }
362
+ ], { side: "bottom", align: "end" });
363
+ }, { buttonClass: "bg-none", icon: "more" } ).root );
364
+ }
365
+
366
+ // Prewiew Info
367
+ {
368
+ const previewDataContent = LX.makeContainer( [ "100%", "100%" ], "", "", right );
369
+
370
+ window.__openMail = ( mail ) => {
371
+
372
+ previewDataContent.innerHTML = "";
373
+
374
+ const mailPreviewInfo = LX.makeContainer( [ "100%", "auto" ], "flex flex-row border-bottom p-6", "", previewDataContent );
375
+
376
+ const senderData = LX.makeContainer( [ "100%", "auto" ], "flex flex-col gap-0.5", `
377
+ <div class="text-md font-semibold">${ mail.name }</div>
378
+ <div class="text-sm">${ mail.subject }</div>
379
+ <div class="text-sm">Reply-To: ${ mail.email }</div>
380
+ `, mailPreviewInfo );
381
+
382
+ const exactDate = LX.makeContainer( [ "100%", "auto" ], "flex flex-row text-sm fg-tertiary justify-end", mail.exactDate, mailPreviewInfo );
383
+ const mailPreviewContent = LX.makeContainer( [ "100%", "505px" ], "flex flex-row border-bottom text-md whitespace-pre-wrap p-4", mail.content, previewDataContent );
384
+ const previewFooter = LX.makeContainer( [ "100%", "auto" ], "flex flex-col p-2", "", previewDataContent );
385
+
386
+ const msgReplyTextArea = new LX.TextArea(null, "", null,
387
+ { className: "mt-1", inputClass: "outline", width: "100%", resize: false, placeholder: `Reply ${ mail.name }` }
388
+ );
389
+ previewFooter.appendChild( msgReplyTextArea.root );
390
+
391
+ const previewButtons = LX.makeContainer( [ "100%", "auto" ], "flex flex-row p-1", "", previewFooter );
392
+
393
+ const muteToggle = new LX.Toggle( null, false, null, { label: "Mute this thread", className: "contrast" } );
394
+ previewButtons.appendChild( muteToggle.root );
395
+
396
+ const sendButton = new LX.Button( null, "Send", () => {
397
+ LX.toast( "Message sent!", "To:" + mail.email, { timeout: 5000, action: { name: "Undo", callback: ( toast, actionName, event ) => {
398
+ toast.close();
399
+ } } } );
400
+ }, { className: "ml-auto", buttonClass: "contrast" } );
401
+ previewButtons.appendChild( sendButton.root );
402
+ };
403
+ }
404
+ }
405
+ }
406
+
407
+ // Tasks
408
+ {
409
+ const tasksContainer = LX.makeContainer( [ null, "auto" ], "col bg-primary border rounded-lg p-6 overflow-hidden" );
410
+ tabs.add( "Tasks", tasksContainer, { xselected: true } );
411
+
412
+ const header = LX.makeContainer( [ null, "auto" ], "col p-4", `
413
+ <h2>Welcome back!</h2>
414
+ <p class="fg-tertiary">Here's a list of your tasks for this month!</p>
415
+ `, tasksContainer );
416
+
417
+ const tableWidget = new LX.Table(null, {
418
+ head: ["Name", "Status", "Priority"],
419
+ body: [
420
+ ["Alice", "In Progress", "High"],
421
+ ["Bob", "Backlog", "Medium"],
422
+ ["Prince", "Canceled", "Low"],
423
+ ["Sean", "Done", "High"],
424
+ ["Carter", "In Progress", "Medium"],
425
+ ["James", "Backlog", "Low"],
426
+ ["Mickey", "Todo", "Low"],
427
+ ["Charlie", "Canceled", "Low"],
428
+ ["Potato", "Todo", "High"]
429
+ ]
430
+ }, {
431
+ selectable: true,
432
+ sortable: true,
433
+ toggleColumns: true,
434
+ filter: "Name",
435
+ customFilters: [
436
+ { name: "Status", options: ["Backlog", "Todo", "In Progress", "Done", "Cancelled"] },
437
+ { name: "Priority", options: ["Low", "Medium", "High"] },
438
+ ],
439
+ rowActions: [
440
+ { icon: "edit", title: "Edit Row" },
441
+ "delete",
442
+ "menu"
443
+ ],
444
+ onMenuAction: (index, tableData) => {
445
+ return [
446
+ { name: "Export" },
447
+ { name: "Make a copy" },
448
+ { name: "Favourite" }
449
+ ]
450
+ }
451
+ });
452
+ tasksContainer.appendChild( tableWidget.root );
453
+ }
454
+
455
+ // Code
456
+ // {
457
+ // const codeContainer = LX.makeContainer( [ "auto", "850px" ], "", {
458
+ // backgroundColor: "red"
459
+ // } );
460
+
461
+ // tabs.add( "Code", codeContainer );
462
+ // }
463
+
464
+ // Audio
465
+ // {
466
+ // const audioContainer = LX.makeContainer( [ "auto", "850px" ], "", {
467
+ // backgroundColor: "red"
468
+ // } );
79
469
 
80
- tabs.add( "Examples", examplesContainer, { selected: true } );
81
- tabs.add( "Tasks", tasksContainer );
82
- tabs.add( "Code", codeContainer );
83
- tabs.add( "Audio", audioContainer );
470
+ // tabs.add( "Audio", audioContainer );
471
+ // }
84
472
  }
85
473
 
86
474
  // Footer
87
475
  {
88
476
  const footer = new LX.Footer( {
89
- parent: area.root,
477
+ parent: LX.root,
90
478
  columns: [
91
479
  {
92
480
  title: "LexGUI",
93
481
  items: [
94
- { title: "Download", link: "" },
95
- { title: "Documentation", link: "" },
96
- { title: "Web demo", link: "" },
97
- { title: "Source code", link: "" }
482
+ { title: "Documentation", link: "https://jxarco.github.io/lexgui.js/docs/" },
483
+ { title: "Source code", link: "https://github.com/jxarco/lexgui.js/" }
98
484
  ]
99
485
  },
100
486
  {
101
487
  title: "Projects",
102
488
  items: [
103
- { title: "Animics", link: "" },
104
- { title: "Performs", link: "" }
489
+ { title: "Animics", link: "https://animics.gti.upf.edu/" },
490
+ { title: "Performs", link: "https://performs.gti.upf.edu/" }
105
491
  ]
106
492
  },
107
493
  {
108
- title: "Other stuff",
494
+ title: "References",
109
495
  items: [
110
- { title: "Some section", link: "" },
111
- { title: "Just filling", link: "" },
112
- { title: "No more ideas", link: "" },
496
+ { title: "shadcn/ui", link: "https://ui.shadcn.com/" },
497
+ { title: "Radix UI", link: "https://www.radix-ui.com/" },
113
498
  ]
114
499
  }
115
500
  ],