lexgui 0.1.46 → 0.2.0

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,905 +5,121 @@ import 'lexgui/components/audio.js';
5
5
 
6
6
  window.LX = LX;
7
7
 
8
- // Init library and get main area
9
- let area = LX.init();
8
+ let area = LX.init( { strictViewport: false } );
10
9
 
11
- // Change global properties after init
12
- // LX.DEFAULT_NAME_WIDTH = "10%";
13
- // LX.DEFAULT_SPLITBAR_SIZE = 16;
14
- // LX.OPEN_CONTEXTMENU_ENTRY = 'mouseover';
15
-
16
- // LX.message("Im in another position", null, { position: [10, 10] });
17
- // LX.message("Welcome to Lexgui", "Welcome!");
18
-
19
- // Change some theme colors...
20
- // LX.setThemeColor('global-color-primary', "#211");
21
- // LX.setThemeColor('global-selected', "#a74");
22
- // LX.setThemeColor('global-text', "#f21");
23
-
24
- const snippet = LX.makeCodeSnippet(`
25
- import { LX } from 'lexgui';
26
-
27
- class Test {
28
-
29
- constructor() {
30
-
31
- this.foo = 1;
32
-
33
- var div = document.createElement('div');
34
- div.style.width = "100px"
35
- div.style.height = "100px"
36
-
37
- // single line comment
38
-
39
- document.body.appendChild( div );
40
-
41
- let a = 1; /* single line block comment */ let b = 2;
42
-
43
- /*
44
- multiple line block comment
45
- */
46
- }
47
- }
48
- `, ["780px", "580px"], { tabName: "script.js", language: "JavaScript", linesAdded: [2, [10, 12]], linesRemoved: [14, 16], windowMode: true });
49
- snippet.style.left = "200px";
50
- snippet.style.top = "200px";
51
- snippet.style.position = "absolute";
52
- document.body.appendChild( snippet );
53
-
54
- // menu bar
55
- area.addMenubar( m => {
56
-
57
- // {options}: callback, icon, short
58
-
59
- m.add( "Scene/New Scene", () => { console.log("New scene created!") });
60
- m.add( "Scene/Open Scene", { icon: "fa-solid fa-folder-open", short: "S", callback: () => { console.log("Opening SCENE Dialog") } } );
61
- m.add( "Scene/Open Recent/hello.scene", name => { console.log("Opening " + name) });
62
- m.add( "Scene/Open Recent/goodbye.scene", name => { console.log("Opening " + name) });
63
- m.add( "Project/Project Settings" );
64
- m.add( "Project/Export", { icon: "fa-solid fa-download" });
65
- m.add( "Project/Export/DAE", { icon: "fa-solid fa-cube", short: "D", callback: () => { console.log("Exporting DAE...") }} );
66
- m.add( "Project/Export/GLTF", { short: "G" } );
67
- m.add( "Editor/Autosave", { type: 'checkbox', icon: "fa fa-floppy-disk", callback: (v, name) => { console.log(name + ": " + v ) } });
68
- m.add( "Editor/Test", () => LX.prompt("Write in the text area below the bml instructions to move the avatar from the web application. A sample of BML instructions can be tested through the helper tabs in the right panel.", "Test?"));
69
- m.add( "Editor/Settings", { icon: "fa-solid fa-gears", callback: () => {
70
- const dialog = new LX.Dialog( "Settings", p => {
71
- p.addText("A Text", "Testing first widget");
72
- p.sameLine(3);
73
- p.addLabel("Buttons:");
74
- p.addButton(null, "Click me", () => {
75
- console.log( p.getValue("A Text") );
76
- });
77
- p.addButton(null, "Click me v2!", () => {
78
- console.log( p.getValue("A Text") );
79
- });
80
- });
81
- }} );
82
- m.add( "Editor/Write BML", { icon: "fa-solid fa-gears", callback: () => {
83
-
84
- new LX.PocketDialog( "BML Instruction", p => {
85
-
86
- let htmlStr = "Write in the text area below the bml instructions to move the avatar from the web application. A sample of BML instructions can be tested through the helper tabs in the right panel.";
87
- p.addTextArea(null, htmlStr, null, {disabled: true, fitHeight: true});
88
-
89
- p.addButton(null, "Click here to see BML instructions and attributes", () => {
90
- window.open("https://github.com/upf-gti/SignON-realizer/blob/SiGMLExperiments/docs/InstructionsBML.md");
91
- });
92
-
93
- htmlStr = "Note: In 'speech', all text between '%' is treated as actual words. An automatic translation from words (dutch) to phonemes (arpabet) is performed.";
94
- htmlStr += "\n\nNote: Each instruction is inside '{}'. Each instruction is separated by a coma ',' except que last one.";
95
- p.addTextArea(null, htmlStr, null, {disabled: true, fitHeight: true});
96
-
97
- htmlStr = 'An example: { "type":"speech", "start": 0, "text": "%hallo%.", "sentT": 1, "sentInt": 0.5 }, { "type": "gesture", "start": 0, "attackPeak": 0.5, "relax": 1, "end": 2, "locationBodyArm": "shoulder", "lrSym": true, "hand": "both", "distance": 0.1 }';
98
- p.addTextArea(null, htmlStr, null, {disabled: true, fitHeight: true});
99
-
100
- const area = new LX.Area({ height: "250px" });
101
- p.attach( area.root );
102
-
103
- window.editor = new LX.CodeEditor(area, {
104
- highlight: 'JSON',
105
- skip_info: true
106
- });
107
-
108
- p.addButton(null, "Send", () => {
109
- console.log(":)")
110
- });
111
-
112
- }, { size: ["30%", null], float: "right", draggable: false});
113
- }} );
114
- m.add( "Editor/Open AssetView", { icon: "fa-solid fa-rect", callback: () => { createAssetDialog(); }} );
115
- m.add( "Account/Login", { icon: "fa-solid fa-user", callback: () => { createLoginForm(); }} );
116
- m.add( "Timeline/Shortcuts", { disabled: true });
117
- m.add( "Timeline/Shortcuts/Play-Pause", { short: "SPACE" });
118
- m.add( "Timeline/Shortcuts/Zoom", { short: "Wheel" });
119
- m.add( "Timeline/Shortcuts/Change time", { short: "Left Click+Drag" });
120
- m.add( "Timeline/Shortcuts/Move keys", { short: "Hold CTRL" });
121
- m.add( "Timeline/Shortcuts/Add keys", { short: "Right Click" });
122
- m.add( "Timeline/Shortcuts/Delete keys");
123
- m.add( "Timeline/Shortcuts/Delete keys/Single", { short: "DEL" });
124
- m.add( "Timeline/Shortcuts/Delete keys/Multiple", { short: "Hold LSHIFT" });
125
- m.add( "Timeline/Shortcuts/Key Selection");
126
- m.add( "Timeline/Shortcuts/Key Selection/Single", { short: "Left Click" });
127
- m.add( "Timeline/Shortcuts/Key Selection/Multiple", { short: "Hold LSHIFT" });
128
- m.add( "Timeline/Shortcuts/Key Selection/Box", { short: "Hold LSHIFT+Drag" });
129
- m.add( "Help/Search Help", { icon: "fa-solid fa-magnifying-glass", short: "F1", callback: () => { window.open("./docs/") }});
130
- m.add( "Help/Support LexGUI/Please", { icon: "fa-solid fa-heart" } );
131
- m.add( "Help/Support LexGUI/Do it" );
132
- m.addButtons( [
133
- {
134
- title: "Play",
135
- icon: "fa-solid fa-play",
136
- swap: "fa-solid fa-stop",
137
- callback: (event, swapValue) => {
138
- if( swapValue ) console.log("play!");
139
- else console.log("stop!");
140
- }
141
- },
142
- {
143
- title: "Pause",
144
- icon: "fa-solid fa-pause",
145
- disabled: true,
146
- callback: (event) => { console.log("pause!"); }
147
- },
148
- {
149
- icon: "fa-solid fa-magnifying-glass",
150
- callback: (event) => {
151
- const playButton = m.getButton( "Play" );
152
- playButton.swap();
153
- console.log("glass!");
154
- }
155
- },
156
- {
157
- title: "Change Theme",
158
- icon: "fa-solid fa-moon",
159
- swap: "fa-solid fa-sun",
160
- callback: (event, swapValue) => { LX.setTheme( swapValue ? "light" : "dark" ) }
161
- }
162
- ]);
163
-
164
- m.getButton("Play");
165
- m.setButtonIcon("Github", "fa-brands fa-github", () => {window.open("https://github.com/jxarco/lexgui.js/")})
166
- m.setButtonImage("lexgui.js", "images/icon.png", () => {window.open("https://jxarco.github.io/lexgui.js/")}, {float: "left"})
167
- });
168
-
169
- // split main area
170
- var [left, right] = area.split({ sizes:["80%","20%"], minimizable: true });
171
-
172
- // left.addSidebar( m => {
173
- // m.add( "Scene", { icon: "fa fa-cube", callback: () => { } } );
174
- // m.add( "Code", { icon: "fa fa-code", callback: () => { } } );
175
- // m.add( "Search", { icon: "fa fa-search", bottom: true, callback: () => { } } );
176
- // });
177
-
178
- // split left area
179
- var [up, bottom] = left.split({ type: 'vertical', sizes:["50%", null], minimizable: true });
180
-
181
- var kfTimeline = null;
182
- var clipsTimeline = null;
183
- var curvesTimeline = null;
184
-
185
- bottom.onresize = bounding => {
186
- if(kfTimeline) kfTimeline.resize( [ bounding.width, bounding.height ] );
187
- if(clipsTimeline) clipsTimeline.resize( [ bounding.width, bounding.height ] );
188
- if(curvesTimeline) curvesTimeline.resize( [ bounding.width, bounding.height ] );
189
- }
190
-
191
- // another menu bar
192
- bottom.addMenubar( m => {
193
- m.add( "Information", e => {
194
- console.log(e);
195
- var el = document.getElementById('kf-timeline');
196
- if(el)
197
- el.style.display = 'none';
198
- el = document.getElementById('clips-timeline');
199
- if(el)
200
- el.style.display = 'none';
201
- el = document.getElementById('curves-timeline');
202
- if(el)
203
- el.style.display = 'none';
204
- var bottomPanel = document.getElementById('bottom-panel');
205
- bottomPanel.style.display = 'block';
206
- });
207
-
208
- m.add( "Keyframes Timeline", e => {
209
- console.log(e);
210
- let el = document.getElementById('bottom-panel');
211
- if(el)
212
- el.style.display = 'none';
213
- el = document.getElementById('clips-timeline');
214
- if(el)
215
- el.style.display = 'none';
216
- el = document.getElementById('curves-timeline');
217
- if(el)
218
- el.style.display = 'none';
219
- var timeline = document.getElementById('kf-timeline');
220
- if(timeline) {
221
- timeline.style.display = 'block';
222
- kfTimeline.resize();
223
- }
224
- else {
225
- kfTimeline = new LX.KeyFramesTimeline("kf-timeline", {
226
- onBeforeCreateTopBar: panel => {
227
- panel.addButton('', '<i class="fa fa-wand-magic-sparkles"></i>', ( value, event ) => { });
228
- }
229
- });
230
-
231
- bottom.attach(kfTimeline.root);
232
- kfTimeline.setSelectedItems(["Item 1", "Item 2", "Item 3"]);
233
- kfTimeline.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});
234
- kfTimeline.draw( 0 );
235
- }
236
- });
237
-
238
- m.add( "Clips Timeline", e => {
239
- console.log(e);
240
- let el = document.getElementById('bottom-panel');
241
- if(el)
242
- el.style.display = 'none';
243
-
244
- el = document.getElementById('kf-timeline');
245
- if(el)
246
- el.style.display = 'none';
247
- el = document.getElementById('curves-timeline');
248
- if(el)
249
- el.style.display = 'none';
250
- var ctimeline = document.getElementById('clips-timeline');
251
- if(ctimeline) {
252
- ctimeline.style.display = 'block';
253
- clipsTimeline.resize();
254
- }
255
- else {
256
- clipsTimeline = new LX.ClipsTimeline("clips-timeline", {width: m.root.clientWidth, height: m.parent.root.parentElement.clientHeight - m.root.clientHeight});
257
- bottom.attach(clipsTimeline.root);
258
- var clip = {id:"Clip1", start:0, duration:1, type:""};
259
- clipsTimeline.addClip(clip);
260
- var clip = {id:"Clip2", start:0, fadein: 0.5, fadeout: 0.8, duration:1, type:""};
261
- clipsTimeline.addClip(clip);
262
- var clip = {id:"Clip3", start:0, fadein: 0.5, fadeout: 0.8, duration:1, type:""};
263
- clipsTimeline.addClip(clip);
264
- var clip = {id:"Clip4", start:0, fadein: 0.5, fadeout: 0.8, duration:1, type:""};
265
- clipsTimeline.addClip(clip);
266
- var clip = {id:"Clip5", start:0, fadein: 0.5, fadeout: 0.8, duration:1, type:""};
267
- clipsTimeline.addClip(clip);
268
-
269
- // clipsTimeline.setAnimationClip({tracks: [{clips: [clip]}], duration: 2});
270
- clipsTimeline.selectedItems = ["Clip1"];
271
-
272
- clipsTimeline.draw(0);
273
- }
274
- });
275
-
276
- m.add( "Curves Timeline", e => {
277
- console.log(e);
278
- let el = document.getElementById('bottom-panel');
279
- if(el)
280
- el.style.display = 'none';
281
- el = document.getElementById('kf-timeline');
282
- if(el)
283
- el.style.display = 'none';
284
- el = document.getElementById('clips-timeline');
285
- if(el)
286
- el.style.display = 'none';
287
-
288
- var timeline = document.getElementById('curves-timeline');
289
- if(timeline) {
290
- timeline.style.display = 'block';
291
- curvesTimeline.resize();
292
- }
293
- else {
294
- curvesTimeline = new LX.CurvesTimeline("curves-timeline", {width: m.root.clientWidth, height: m.parent.root.parentElement.clientHeight - m.root.clientHeight, range: [-1,1]});
295
- curvesTimeline.setSelectedItems(["Item 1", "Item 2", "Item 3"]);
296
- curvesTimeline.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,0,0,1], 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});
297
- bottom.attach(curvesTimeline.root);
298
- curvesTimeline.draw(0);
299
- }
300
- });
301
-
302
- bottom.onresize = bounding => {
303
- if(clipsTimeline)
304
- clipsTimeline.resize( );
10
+ // Menubar
11
+ {
12
+ area.addMenubar( m => {
305
13
 
306
- if(kfTimeline)
307
- kfTimeline.resize();
308
-
309
- if(curvesTimeline)
310
- curvesTimeline.resize();
311
- }
312
- } );
313
-
314
- var bottomPanel = bottom.addPanel({id: "bottom-panel"});
315
- fillBottomPanel( bottomPanel );
316
-
317
- // split right area
318
- var [rup, rbottom] = right.split({type: 'vertical', sizes:["70%","30%"]});
319
-
320
- // Get new content area to fill it
321
- const topTabs = up.addTabs();
322
-
323
- // add canvas to left upper part
324
- var canvas = document.createElement('canvas');
325
- canvas.style.width = "100%";
326
- canvas.style.height = "100%";
327
-
328
- const resizeCanvas = ( bounding ) => {
329
- canvas.width = bounding.width;
330
- canvas.height = bounding.height;
331
- };
332
-
333
- topTabs.add( "Canvas", canvas, { selected: true, onCreate: resizeCanvas } );
334
- topTabs.add( "Debug", document.createElement('div'));
335
-
336
- // add on resize event to control canvas size
337
- topTabs.area.onresize = resizeCanvas;
338
-
339
- topTabs.area.addOverlayButtons( [
340
- [
341
- {
342
- name: "Select",
343
- icon: "fa fa-arrow-pointer",
344
- callback: (value, event) => console.log(value),
345
- selectable: true
346
- },
347
- {
348
- name: "Move",
349
- icon: "fa-solid fa-arrows-up-down-left-right",
350
- callback: (value, event) => console.log(value),
351
- selectable: true
352
- },
353
- {
354
- name: "Rotate",
355
- icon: "fa-solid fa-rotate-right",
356
- callback: (value, event) => console.log(value),
357
- selectable: true
358
- }
359
- ],
360
- {
361
- name: "Lit",
362
- options: ["Lit", "Unlit", "Wireframe"],
363
- callback: (value, event) => console.log(value)
364
- },
365
- [
366
- {
367
- name: "Enable Snap",
368
- icon: "fa fa-table-cells",
369
- callback: (value, event) => console.log(value),
370
- selectable: true
371
- },
372
- {
373
- name: 10,
374
- options: [10, 100, 1000],
375
- callback: value => console.log(value)
376
- }
377
- ], {
378
- name: "Button 4",
379
- // img: "https://webglstudio.org/latest/imgs/mini-icon-gizmo.png",
380
- icon: "fa fa-cube",
381
- callback: (value, event) => console.log(value)
382
- }
383
- ], { float: "htc" } );
384
-
385
- // add panels
386
- var sidePanel = rup.addPanel();
387
- fillPanel( sidePanel );
388
-
389
- const bottomTabs = rbottom.addTabs({ fit: true });
390
- var sideBottomPanel = new LX.Panel();
391
- var sideBottomPanelH = new LX.Panel();
392
- fillRightBottomPanel( sideBottomPanel, 'Vertical' );
393
- fillRightBottomPanel( sideBottomPanelH, 'Horizontal' );
394
-
395
- bottomTabs.add( "Panel V", sideBottomPanel );
396
- bottomTabs.add( "Panel H", sideBottomPanelH );
397
-
398
- const footer = new LX.Footer( {
399
- parent: bottomPanel.root,
400
- columns: [
401
- {
402
- title: "LexGUI",
403
- items: [
404
- { title: "Download", link: "" },
405
- { title: "Documentation", link: "" },
406
- { title: "Web demo", link: "" },
407
- { title: "Source code", link: "" }
408
- ]
409
- },
410
- {
411
- title: "Projects",
412
- items: [
413
- { title: "Animics", link: "" },
414
- { title: "Performs", link: "" }
415
- ]
416
- },
417
- {
418
- title: "Other stuff",
419
- items: [
420
- { title: "Some section", link: "" },
421
- { title: "Just filling", link: "" },
422
- { title: "No more ideas", link: "" },
423
- ]
424
- }
425
- ],
426
- credits: `2019-${ new Date().getUTCFullYear() } Alex Rodríguez and contributors. Website source code on GitHub.`,
427
- socials: [
428
- { title: "Github", link: "", icon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6.0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6.0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3.0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1.0-6.2-.3-40.4-.3-61.4.0.0-70 15-84.7-29.8.0.0-11.4-29.1-27.8-36.6.0.0-22.9-15.7 1.6-15.4.0.0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5.0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9.0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4.0 33.7-.3 75.4-.3 83.6.0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6.0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9.0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg>` },
429
- { title: "BlueSky", link: "", icon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M407.8 294.7c-3.3-.4-6.7-.8-10-1.3 3.4.4 6.7.9 10 1.3zM288 227.1C261.9 176.4 190.9 81.9 124.9 35.3 61.6-9.4 37.5-1.7 21.6 5.5 3.3 13.8.0 41.9.0 58.4S9.1 194 15 213.9c19.5 65.7 89.1 87.9 153.2 80.7 3.3-.5 6.6-.9 10-1.4-3.3.5-6.6 1-10 1.4-93.9 14-177.3 48.2-67.9 169.9C220.6 589.1 265.1 437.8 288 361.1c22.9 76.7 49.2 222.5 185.6 103.4 102.4-103.4 28.1-156-65.8-169.9-3.3-.4-6.7-.8-10-1.3 3.4.4 6.7.9 10 1.3 64.1 7.1 133.6-15.1 153.2-80.7C566.9 194 576 75 576 58.4s-3.3-44.7-21.6-52.9c-15.8-7.1-40-14.9-103.2 29.8C385.1 81.9 314.1 176.4 288 227.1z"></path></svg>` },
430
- { title: "Mastodon", link: "", icon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433 179.1c0-97.2-63.7-125.7-63.7-125.7-62.5-28.7-228.6-28.4-290.5.0.0.0-63.7 28.5-63.7 125.7.0 115.7-6.6 259.4 105.6 289.1 40.5 10.7 75.3 13 103.3 11.4 50.8-2.8 79.3-18.1 79.3-18.1l-1.7-36.9s-36.3 11.4-77.1 10.1c-40.4-1.4-83-4.4-89.6-54a102.5 102.5.0 01-.9-13.9c85.6 20.9 158.7 9.1 178.8 6.7 56.1-6.7 105-41.3 111.2-72.9 9.8-49.8 9-121.5 9-121.5zm-75.1 125.2h-46.6V190.1c0-49.7-64-51.6-64 6.9v62.5H201V197c0-58.5-64-56.6-64-6.9v114.2H90.2c0-122.1-5.2-147.9 18.4-175 25.9-28.9 79.8-30.8 103.8 6.1l11.6 19.5 11.6-19.5c24.1-37.1 78.1-34.8 103.8-6.1 23.7 27.3 18.4 53 18.4 175z"></path></svg>` },
431
- { title: "Discord", link: "", icon: `<a class="fa-brands fa-discord"></a>` },
432
- { title: "Reddit", link: "", icon: `<a class="fa-brands fa-reddit"></a>` }
433
- ]
434
- } );
435
-
436
- function loop(dt) {
14
+ m.setButtonImage("lexgui.js", "images/icon.png", () => {window.open("https://jxarco.github.io/lexgui.js/")}, {float: "left"})
437
15
 
438
- var ctx = canvas.getContext("2d");
439
-
440
- // Get values from panel widgets (e.g. color value)
441
- ctx.fillStyle = sidePanel.getValue('Background');
442
-
443
- ctx.fillRect(0, 0, canvas.width, canvas.height);
444
- ctx.font = sidePanel.getValue('Font Size') + "px Monospace";
445
-
446
- ctx.fillStyle = sidePanel.getValue('Font Color');
447
-
448
- const text = sidePanel.getValue('Text');
449
- const pos2D = sidePanel.getValue('2D Position');
450
- ctx.fillText(text, pos2D[0], pos2D[1]);
451
-
452
- if(kfTimeline)
453
- kfTimeline.draw();
454
-
455
- if(clipsTimeline)
456
- clipsTimeline.draw();
457
-
458
- if(curvesTimeline)
459
- curvesTimeline.draw();
460
-
461
- requestAnimationFrame(loop);
462
- }
463
-
464
- // createAssetDialog();
465
-
466
- requestAnimationFrame(loop);
467
-
468
- // **** **** **** **** **** **** **** **** **** **** **** ****
469
-
470
- function fillPanel( panel ) {
16
+ m.add( "Docs", { icon: "fa-solid fa-magnifying-glass", short: "F1", callback: () => { window.open("./docs/") }});
471
17
 
472
- // Add data tree
473
-
474
- let sceneData = {
475
- 'id': 'root',
476
- 'children': [
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
+
22
+ m.addButtons( [
477
23
  {
478
- 'id': 'node_1',
479
- 'children': [
480
- {
481
- 'id': 'node_1_1',
482
- 'icon': 'fa-solid fa-cube',
483
- 'children': [],
484
- 'actions': [
485
- {
486
- 'name': 'Open script',
487
- 'icon': 'fa-solid fa-scroll',
488
- 'callback': function(node) {
489
- console.log(node.id + ": Script opened!")
490
- }
491
- }
492
- ]
493
- }
494
- ]
24
+ title: "Github",
25
+ icon: "fa-brands fa-github",
26
+ callback: (event) => {
27
+ window.open( "https://github.com/jxarco/lexgui.js/", "_blank" );
28
+ }
495
29
  },
496
30
  {
497
- 'id': 'node_2',
498
- 'icon': 'fa-solid fa-circle-play',
499
- 'children': []
500
- }
501
- ]
502
- };
503
-
504
- // This is optional!
505
- const treeIcons = [
506
- {
507
- 'name':'Add node',
508
- 'icon': 'fa-solid fa-plus',
509
- 'callback': () => { console.log("Node added!") }
510
- },
511
- {
512
- 'name':'Instantiate scene',
513
- 'icon': 'fa-solid fa-link',
514
- 'callback': () => { console.log("Scene instantiated!") }
515
- }
516
- ];
517
-
518
- window.tree = panel.addTree("Scene Tree", sceneData, {
519
- icons: treeIcons,
520
- // filter: false,
521
- addDefault: true,
522
- onevent: (event) => {
523
- console.log(event.string());
524
-
525
- switch(event.type) {
526
- case LX.TreeEvent.NODE_SELECTED:
527
- if(event.multiple)
528
- console.log("Selected: ", event.node);
529
- else
530
- console.log(event.node.id + " selected");
531
- break;
532
- case LX.TreeEvent.NODE_DELETED:
533
- if(event.multiple)
534
- console.log("Deleted: ", event.node);
535
- else
536
- console.log(event.node.id + " deleted");
537
- break;
538
- case LX.TreeEvent.NODE_DBLCLICKED:
539
- console.log(event.node.id + " dbl clicked");
540
- break;
541
- case LX.TreeEvent.NODE_CONTEXTMENU:
542
- const m = event.panel;
543
- m.add( "Components/Transform");
544
- m.add( "Components/MeshRenderer");
545
- break;
546
- case LX.TreeEvent.NODE_DRAGGED:
547
- console.log(event.node.id + " is now child of " + event.value.id);
548
- break;
549
- case LX.TreeEvent.NODE_RENAMED:
550
- console.log(event.node.id + " is now called " + event.value);
551
- break;
552
- case LX.TreeEvent.NODE_VISIBILITY:
553
- console.log(event.node.id + " visibility: " + event.value);
554
- break;
31
+ title: "Change Theme",
32
+ icon: "fa-solid fa-sun",
33
+ swap: "fa-solid fa-moon",
34
+ callback: (event, swapValue) => { LX.setTheme( swapValue ? "light" : "dark" ) }
555
35
  }
556
- }
557
- });
558
-
559
- // add widgets to panel branch
560
- panel.branch("Preferences", {icon: "fa-solid fa-gear"});
561
- panel.addButton(null, "Show Notifications" + LX.badge("+99", "accent sm"));
562
- panel.addCounter("Calories Counter ", 350, (v) => { console.log( v + " calories!" ) }, { label: "CALORIES/DAY", max: 500 });
563
- panel.addButton("Colored Tiny Button", "Click here!", () => {}, { buttonClass: "primary xs" });
564
- panel.addButton("Colored Small Button", "Click here!", () => {}, { buttonClass: "accent sm" });
565
- panel.addButton("A Classic Button", "Click here!", () => {}, { buttonClass: "md" });
566
- panel.addCheckbox("Check me, Please", false, (value, event) => {
567
- console.log(value);
568
- }, { className: "secondary" });
569
- panel.sameLine(2);
570
- panel.addToggle("Colored Toggle", false, (value, event) => {
571
- console.log(value);
572
- }, { className: "accent", nameWidth: "50%" });
573
- panel.addToggle("Outlined Checkbox ", false, (value, event) => {
574
- console.log(value);
575
- }, { className: "secondary outline", nameWidth: "50%" });
576
- panel.addFile("I'm a File Input", data => { console.log(data) }, { disabled: true } );
577
- panel.addDropdown("Best Engine", ["Godot", "Unity", "Unreal Engine"], "Unity", (value, event) => {
578
- console.log(value);
579
- });
580
- panel.addDropdown("Best Logo", [{value:"Godot", src: "https://godotengine.org/assets/press/logo_vertical_color_light.png"}, {value: "Unity", src: "https://logos-world.net/wp-content/uploads/2023/01/Unity-Logo.png"}, {value:"Unreal Engine", src: "https://cdn2.unrealengine.com/ue-logo-stacked-unreal-engine-w-677x545-fac11de0943f.png"}], "Godot", (value, event) => {
581
- console.log(value);
582
- }, {filter: true});
583
- panel.addDropdown("Best Gif", [{value:"Godot", src: "https://i.redd.it/4vepr95bye861.gif"}, {value: "Unity", src: "https://i.gifer.com/origin/db/db3cb258e9bbb78c5851a000742e5468_w200.gif"}, {value:"Unreal Engine", src: "https://d3kjluh73b9h9o.cloudfront.net/original/4X/e/0/d/e0deb23c10cc7852c6ab91c28083e27f9c8228f8.gif"}], "Godot", (value, event) => {
584
- console.log(value);
585
- }, {filter: true});
586
-
587
- panel.addVector3("Im a Vec3", [0.1, 0.4, 0.5], (value, event) => {
588
- console.log(value);
589
- });
590
- panel.addLayers("Layers", 10, (value, event) => {
591
- console.log(value);
592
- });
593
- panel.addArray("Array", ['GPTeam', 'Blat Panthers', 'Blat Bunny'], (value, event) => {
594
- console.log(value);
36
+ ], { float: "right" });
595
37
  });
596
- panel.addTags("Game Tags", "2d, karate, ai, engine, ps5, console", (value, event) => {
597
- console.log(value);
598
- });
599
- panel.addComboButtons("Alignment", [
600
- {
601
- value: 'left',
602
- icon: 'fa fa-align-left',
603
- callback: (value, event) => {
604
- console.log(value);
605
- }
606
- }, {
607
- value: 'center',
608
- icon: 'fa fa-align-center',
609
- callback: (value, event) => {
610
- console.log(value);
611
- }
612
- }, {
613
- value: 'right',
614
- icon: 'fa fa-align-right',
615
- callback: (value, event) => {
616
- console.log(value);
617
- }
618
- }
619
- ], {selected: "center"});
620
- panel.addList(null, ['GPTeam', 'Blat Bunny', ['Blat Panthers', 'fa-solid fa-paw']], 'Blat Panthers', (value, event) => {
621
- console.log(value);
622
- });
623
- const opacityValues = [
624
- [0.2, 0.3146875],
625
- [0.417313915857606, 0.8946875000000003],
626
- [0.5495145631067961, 0.6746875],
627
- [1, 1]
628
- ];
629
- panel.addCurve("Opacity", opacityValues, (value, event) => {
630
- console.log(value);
631
- });
632
- panel.addPad("2D Pad", [0.5, 0.5], (value, event) => {
633
- console.log(value);
634
- }, { padSize: "100px", min: -1, max: 2 });
635
- panel.addSize("Screen Res", [1280, 720], (value, event) => {
636
- console.log(value);
637
- }, { units: "p", precision: 0 });
638
-
639
- // another branch
640
- panel.branch("Canvas", {icon: "fa-solid fa-palette", filter: true});
641
- panel.addColor("Background", "#b7a9b1");
642
- panel.addText("Text", "Lexgui.js @jxarco", null, {placeholder: "e.g. ColorPicker", icon: "fa fa-font"});
643
- panel.addColor("Font Color", [1, 0.1, 0.6], (value, event) => {
644
- console.log("Font Color: ", value);
645
- });
646
- panel.addNumber("Font Size", 36, (value, event) => {
647
- console.log(value);
648
- }, { min: 1, max: 48, step: 1, units: "px"});
649
- panel.addVector2("2D Position", [250, 350], (value, event) => {
650
- console.log(value);
651
- }, { min: 0, max: 1024 });
652
- panel.addSeparator();
653
- panel.addTitle("Configuration (Im a title)");
654
- panel.addCheckbox("Toggle me", true, (value, event) => {
655
- console.log(value);
656
- }, { suboptions: (p) => {
657
- p.addText(null, "Suboption 1");
658
- p.addNumber("Suboption 2", 12);
659
- } });
660
- panel.addFile("Image", data => { console.log(data) }, {} );
661
- panel.merge();
662
-
663
- // This is outside a branch
664
- panel.addText("Im out :(", "", null, { placeholder: "Alone..." });
665
- panel.addVector4("Im a Vec4", [0.3, 0.3, 0.5, 1], (value, event) => {
666
- console.log(value);
667
- });
668
- panel.addButton(null, "Click me, Im Full Width...");
669
- panel.addButton("Test Button", "Reduced width...");
670
- panel.addBlank(12);
671
38
  }
672
39
 
673
- function fillRightBottomPanel( panel, tab ) {
40
+ // Header
41
+ {
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
+ } );
674
47
 
675
- panel.clear();
676
-
677
- panel.branch("Bottom", {icon: "fa-solid fa-table-list"});
678
-
679
- if(tab == 'Horizontal')
680
- {
681
- panel.addTabs([
682
- {
683
- name: "First tab",
684
- icon: "fa-brands fa-discord",
685
- onCreate: p => {
686
- p.addTitle("Discord tab");
687
- p.addButton(null, "Connect");
688
- },
689
- onSelect: p => {
690
- console.log( p );
691
- }
692
- },
693
- {
694
- name: "Second tab",
695
- icon: "fa-brands fa-twitter",
696
- onCreate: p => {
697
- p.addTitle("Twitter tab");
698
- p.addText("Tweet", "", null, {placeholder: "Tyler Rake 2"});
699
- }
700
- },
701
- {
702
- name: "Third tab",
703
- icon: "fa-brands fa-github",
704
- onCreate: p => {
705
- p.addTitle("Github tab");
706
- p.addButton(null, "Go", () => {window.open("https://github.com/jxarco/lexgui.js/")});
707
- }
708
- }
709
- ], { vertical: false /*, showNames: true */});
710
-
711
- panel.addText(null, "Widgets below are out the tabs", null, { disabled: true })
712
-
713
- // update panel values uising widget name
714
- panel.addNumber("HeadRoll Value", 0, (value, event) => {
715
- panel.setValue('HeadRoll', value);
716
- }, { min: -1, max: 1, step: 0.1 });
717
- panel.addProgress("HeadRoll", 0, { min: -1, max: 1, low: -0.25, high: 0.25, optimum: 0.75, showValue: true, editable: true, callback: (value, event) => {
718
- panel.setValue('HeadRoll Value', value);
719
- } });
720
- }
721
- else if(tab == 'Vertical')
722
- {
723
- panel.addTabs([
724
- {
725
- name: "First tab",
726
- icon: "fa-brands fa-discord",
727
- onCreate: (p, content) => {
728
- p.addTitle("Discord tab");
729
- p.addButton("Apply", "Add button to branch", (value, event) => {
730
- p.queue( content );
731
- p.addButton(null, "Hello");
732
- p.clearQueue();
733
- });
734
- }
735
- },
736
- {
737
- name: "Second tab",
738
- icon: "fa-brands fa-twitter",
739
- onCreate: p => {
740
- p.addTitle("Twitter tab");
741
- p.addText("Tweet", "", null, {placeholder: "Tyler Rake 2"});
742
- }
743
- },
744
- {
745
- name: "Third tab",
746
- icon: "fa-brands fa-github",
747
- onCreate: p => {
748
- p.addTitle("Github tab");
749
- p.addButton(null, "Go", (value, event) => {window.open("https://github.com/jxarco/lexgui.js/")});
750
- }
751
- }
752
- ]);
753
-
754
- /************** */
755
- // Custom Widget
756
-
757
- LX.ADD_CUSTOM_WIDGET( "Shader", {
758
- icon: "fa-cube",
759
- default: {
760
- position: [0, 0],
761
- velocity: [0, 0, 0],
762
- color: [0, 0, 0, 0],
763
- hexColor: "#000",
764
- highRes: false
765
- }
766
- });
767
-
768
- const shaderInstance = {
769
- 'hexColor': "#f5f505",
770
- 'highRes': true
771
- };
772
-
773
- panel.addShader( "A Shader", shaderInstance, (instance) => { console.log(instance) } );
774
- panel.addShader( "Empty Instance", null );
775
-
776
- /************** */
777
- }
778
-
779
- panel.merge();
780
- }
781
-
782
- function fillBottomPanel( panel ) {
48
+ header.innerHTML = `
49
+ <a>Get started with LexGUI.js</a>
50
+ <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
+ `;
783
54
 
784
- // add widgets to panel branch
785
- panel.branch("Information", {icon: "fa fa-circle-info"});
786
- panel.addText("Camera", "Canon EOS 80D", null, {disabled: true});
787
- panel.addText("Text", "Warning text", null, { warning: true });
788
- const patternOptions = { uppercase: true }
789
- panel.addText("Text With Validator Pattern", "", (value, event) => {
790
- console.log(value);
791
- }, { pattern: LX.buildTextPattern( patternOptions ) });
792
- panel.addTextArea("Notes", "", (value, event) => {
793
- console.log(value);
794
- }, { placeholder: 'Some notes...' });
795
- panel.addKnob("A Small but disabled Knob", 4, 0, 200, value => { console.log( value ) }, { size: 'sm', disabled: true });
796
- panel.addKnob("A Knob", 4, 0, 200, value => { console.log( value ) } );
797
- panel.addKnob("A Big Knob with Snap", 4, 0, 200, value => { console.log( value ) }, { size: 'bg', snap: 4 });
798
- panel.addButton("Apply", "Add button to branch", (value, event) => {
799
- const branch = panel.getBranch("Information");
800
- panel.queue( branch.content );
801
- panel.addButton(null, "Hello");
802
- panel.clearQueue();
803
- });
804
-
805
- panel.branch("A collapsed branch", { closed: true });
806
- panel.addText(null, "Nothing here", null, { disabled: true });
807
- panel.merge();
55
+ area.attach( header );
808
56
  }
809
57
 
810
- function createLoginForm() {
58
+ // Content
59
+ {
60
+ area.attach( document.createElement('br') );
811
61
 
812
- let dialog = new LX.Dialog('Login', panel => {
62
+ const tabs = area.addTabs( { sizes: [ "auto", "auto" ] } );
813
63
 
814
- const formData = {
815
- Username: {
816
- value: "",
817
- placeholder: "Enter username",
818
- icon: "fa fa-user",
819
- pattern: LX.buildTextPattern( { minLength: 3 } )
820
- },
821
- Password: {
822
- value: "",
823
- type: "password",
824
- placeholder: "Enter password",
825
- icon: "fa fa-key",
826
- pattern: LX.buildTextPattern( { lowercase: true, uppercase: true, digit: true, minLength: 6 } )
827
- }
828
- };
64
+ const examplesContainer = LX.makeContainer( [ "auto", "850px" ], "", {
65
+ backgroundColor: "red"
66
+ } );
829
67
 
830
- panel.addForm("Test form", formData, (value, event) => {
831
- console.log(value);
832
- }, { actionName: "Login" });
68
+ const tasksContainer = LX.makeContainer( [ "auto", "850px" ], "", {
69
+ backgroundColor: "red"
70
+ } );
833
71
 
834
- panel.addLabel( "Or", { float: 'center' } );
72
+ const codeContainer = LX.makeContainer( [ "auto", "850px" ], "", {
73
+ backgroundColor: "red"
74
+ } );
835
75
 
836
- panel.addButton( null, "Sign up", ( value, event ) => { });
76
+ const audioContainer = LX.makeContainer( [ "auto", "850px" ], "", {
77
+ backgroundColor: "red"
78
+ } );
837
79
 
838
- }, { close: true, minimize: false, size: ["25%"], scroll: true, resizable: true, draggable: true });
80
+ tabs.add( "Examples", examplesContainer, { selected: true } );
81
+ tabs.add( "Tasks", tasksContainer );
82
+ tabs.add( "Code", codeContainer );
83
+ tabs.add( "Audio", audioContainer );
839
84
  }
840
85
 
841
- function createAssetDialog() {
842
-
843
- let dialog = new LX.Dialog('Non Manual Features lexemes', (p) => {
844
-
845
- const previewActions = [
86
+ // Footer
87
+ {
88
+ const footer = new LX.Footer( {
89
+ parent: area.root,
90
+ columns: [
846
91
  {
847
- name: 'Print Clip',
848
- type: 'clip',
849
- callback: ( item ) => {
850
- console.log(item);
851
- }
92
+ title: "LexGUI",
93
+ items: [
94
+ { title: "Download", link: "" },
95
+ { title: "Documentation", link: "" },
96
+ { title: "Web demo", link: "" },
97
+ { title: "Source code", link: "" }
98
+ ]
852
99
  },
853
100
  {
854
- name: 'Print Image',
855
- type: 'image',
856
- callback: ( item ) => {
857
- console.log(item);
858
- }
101
+ title: "Projects",
102
+ items: [
103
+ { title: "Animics", link: "" },
104
+ { title: "Performs", link: "" }
105
+ ]
859
106
  },
860
107
  {
861
- name: 'Common',
862
- callback: ( item ) => {
863
- console.log(item);
864
- }
865
- }
866
- ];
867
-
868
- var assetView = new LX.AssetView({
869
- skip_browser: true,
870
- skip_navigation: true,
871
- preview_actions: previewActions
872
- });
873
-
874
- p.attach( assetView );
875
- let assetData = [];
876
- const values = ['brow_lowerer.png', 'godot_pixelart.png', 'godot_canvas.png' ];
877
-
878
- for(let i = 0; i < values.length; i++){
879
- let data = {
880
- id: values[i],
881
- type: i == 0 ? "clip" : "image",
882
- src: "data/" + values[i].toLowerCase(),
883
- }
884
- assetData.push(data);
885
- }
886
-
887
- assetView.load( assetData, (e,v) => {
888
- switch(e.type) {
889
- case LX.AssetViewEvent.ASSET_SELECTED:
890
- if(e.multiple)
891
- console.log("Selected: ", e.item);
892
- else
893
- console.log(e.item.id + " selected");
894
- break;
895
- case LX.AssetViewEvent.ASSET_DELETED:
896
- console.log(e.item.id + " deleted");
897
- break;
898
- case LX.AssetViewEvent.ASSET_CLONED:
899
- console.log(e.item.id + " cloned");
900
- break;
901
- case LX.AssetViewEvent.ASSET_RENAMED:
902
- console.log(e.item.id + " is now called " + e.value);
903
- break;
108
+ title: "Other stuff",
109
+ items: [
110
+ { title: "Some section", link: "" },
111
+ { title: "Just filling", link: "" },
112
+ { title: "No more ideas", link: "" },
113
+ ]
904
114
  }
905
- })
906
- },{ title:'Lexemes', close: true, minimize: false, size: ["80%"], scroll: true, resizable: true, draggable: true });
907
- }
908
-
909
- LX.popup("Hello! I'm a popup :)", null, {position: ["50px", "100px"]});
115
+ ],
116
+ credits: `2019-${ new Date().getUTCFullYear() } Alex Rodríguez and contributors. Website source code on GitHub.`,
117
+ socials: [
118
+ { title: "Github", link: "", icon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6.0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6.0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3.0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1.0-6.2-.3-40.4-.3-61.4.0.0-70 15-84.7-29.8.0.0-11.4-29.1-27.8-36.6.0.0-22.9-15.7 1.6-15.4.0.0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5.0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9.0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4.0 33.7-.3 75.4-.3 83.6.0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6.0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9.0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg>` },
119
+ { title: "BlueSky", link: "", icon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M407.8 294.7c-3.3-.4-6.7-.8-10-1.3 3.4.4 6.7.9 10 1.3zM288 227.1C261.9 176.4 190.9 81.9 124.9 35.3 61.6-9.4 37.5-1.7 21.6 5.5 3.3 13.8.0 41.9.0 58.4S9.1 194 15 213.9c19.5 65.7 89.1 87.9 153.2 80.7 3.3-.5 6.6-.9 10-1.4-3.3.5-6.6 1-10 1.4-93.9 14-177.3 48.2-67.9 169.9C220.6 589.1 265.1 437.8 288 361.1c22.9 76.7 49.2 222.5 185.6 103.4 102.4-103.4 28.1-156-65.8-169.9-3.3-.4-6.7-.8-10-1.3 3.4.4 6.7.9 10 1.3 64.1 7.1 133.6-15.1 153.2-80.7C566.9 194 576 75 576 58.4s-3.3-44.7-21.6-52.9c-15.8-7.1-40-14.9-103.2 29.8C385.1 81.9 314.1 176.4 288 227.1z"></path></svg>` },
120
+ { title: "Mastodon", link: "", icon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433 179.1c0-97.2-63.7-125.7-63.7-125.7-62.5-28.7-228.6-28.4-290.5.0.0.0-63.7 28.5-63.7 125.7.0 115.7-6.6 259.4 105.6 289.1 40.5 10.7 75.3 13 103.3 11.4 50.8-2.8 79.3-18.1 79.3-18.1l-1.7-36.9s-36.3 11.4-77.1 10.1c-40.4-1.4-83-4.4-89.6-54a102.5 102.5.0 01-.9-13.9c85.6 20.9 158.7 9.1 178.8 6.7 56.1-6.7 105-41.3 111.2-72.9 9.8-49.8 9-121.5 9-121.5zm-75.1 125.2h-46.6V190.1c0-49.7-64-51.6-64 6.9v62.5H201V197c0-58.5-64-56.6-64-6.9v114.2H90.2c0-122.1-5.2-147.9 18.4-175 25.9-28.9 79.8-30.8 103.8 6.1l11.6 19.5 11.6-19.5c24.1-37.1 78.1-34.8 103.8-6.1 23.7 27.3 18.4 53 18.4 175z"></path></svg>` },
121
+ { title: "Discord", link: "", icon: `<a class="fa-brands fa-discord"></a>` },
122
+ { title: "Reddit", link: "", icon: `<a class="fa-brands fa-reddit"></a>` }
123
+ ]
124
+ } );
125
+ }