lexgui 0.1.36 → 0.1.39
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/README.md +70 -19
- package/build/components/audio.js +174 -0
- package/build/components/timeline.js +2958 -3260
- package/build/components/videoeditor.js +10 -2
- package/build/lexgui.css +117 -2
- package/build/lexgui.js +825 -257
- package/build/lexgui.module.js +794 -297
- package/changelog.md +32 -2
- package/demo.js +9 -2
- package/examples/timeline.html +33 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,18 +2,81 @@
|
|
|
2
2
|
|
|
3
3
|
**lexgui.js** is a lightweight JavaScript library that allows you to create web interfaces using only JavaScript, HTML, and CSS. It provides an easy-to-use API for building dynamic and interactive common and complex editor interfaces without the need for tedious frameworks or big libraries. With lexgui.js, you can create custom UI components, handle user interactions, and update the interface dynamically.
|
|
4
4
|
|
|
5
|
-
<
|
|
6
|
-
<
|
|
5
|
+
<table>
|
|
6
|
+
<tr>
|
|
7
|
+
<td valign="top"><img src="data/Screenshot.png"/></td>
|
|
8
|
+
<td valign="top"><img src="data/Screenshot_Godot.png"/></td>
|
|
9
|
+
</tr>
|
|
10
|
+
</table>
|
|
11
|
+
|
|
12
|
+
<table>
|
|
13
|
+
<tr>
|
|
14
|
+
<td valign="top"><h3>Code Editor</h3><img src="data/Screenshot_Code.png"/></td>
|
|
15
|
+
<td valign="top"><h3>Node Graph Editor (WIP)</h3><img src="data/Screenshot_Graph.png"/></td>
|
|
16
|
+
</tr>
|
|
17
|
+
</table>
|
|
7
18
|
|
|
8
|
-
|
|
9
|
-
|
|
19
|
+
## Component Features
|
|
20
|
+
|
|
21
|
+
- [x] Asset Browser
|
|
22
|
+
- [x] Timeline
|
|
23
|
+
- [x] Code Editor
|
|
24
|
+
- [ ] Node Graphs (WIP)
|
|
10
25
|
|
|
11
|
-
|
|
12
|
-
|
|
26
|
+
## Quick start
|
|
27
|
+
|
|
28
|
+
`index.html`:
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<!DOCTYPE html>
|
|
32
|
+
<html lang="en">
|
|
33
|
+
<head>
|
|
34
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
|
35
|
+
<title>My first lexgui.js app</title>
|
|
36
|
+
<link rel="stylesheet" href="https://cdn.skypack.dev/lexgui@^<version>/build/lexgui.css">
|
|
37
|
+
<script type="importmap">
|
|
38
|
+
{
|
|
39
|
+
"imports": {
|
|
40
|
+
"lexgui": "https://cdn.skypack.dev/lexgui@^<version>/build/lexgui.module.js",
|
|
41
|
+
"lexgui/components/": "https://cdn.skypack.dev/lexgui@^<version>/build/components/"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
</head>
|
|
46
|
+
<body>
|
|
47
|
+
<script type="module" src="my_app.js"></script>
|
|
48
|
+
<body>
|
|
49
|
+
</html>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`my_app.js`:
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
import { LX } from 'lexgui';
|
|
56
|
+
|
|
57
|
+
// Using components
|
|
58
|
+
import { CodeEditor } from 'lexgui/components/codeeditor.js';
|
|
59
|
+
|
|
60
|
+
// Create main area
|
|
61
|
+
let area = LX.init();
|
|
62
|
+
|
|
63
|
+
// Create area panels
|
|
64
|
+
let panel = area.addPanel();
|
|
65
|
+
|
|
66
|
+
// Start branch/section
|
|
67
|
+
panel.branch("Section Title");
|
|
68
|
+
|
|
69
|
+
// Add some widgets
|
|
70
|
+
panel.addButton(null, "Click me, Im Full Width...");
|
|
71
|
+
panel.addText("Text", "Warning text", null, { warning: true });
|
|
72
|
+
|
|
73
|
+
// Close section
|
|
74
|
+
panel.merge();
|
|
75
|
+
```
|
|
13
76
|
|
|
14
77
|
## Docs
|
|
15
78
|
|
|
16
|
-
The library documentation is
|
|
79
|
+
The library documentation is available at [lexgui.js/docs/](https://jxarco.github.io/lexgui.js/docs/).
|
|
17
80
|
|
|
18
81
|
## Examples
|
|
19
82
|
|
|
@@ -28,18 +91,6 @@ Look at this [examples](https://jxarco.github.io/lexgui.js/examples/) to see how
|
|
|
28
91
|
</tr>
|
|
29
92
|
</table>
|
|
30
93
|
|
|
31
|
-
## Contributors
|
|
32
|
-
|
|
33
|
-
* Alex Rodríguez @jxarco
|
|
34
|
-
* Eva Valls @evallsg
|
|
35
|
-
|
|
36
94
|
## Feedback/Issues
|
|
37
95
|
|
|
38
96
|
You can use the [repository issues section](https://github.com/jxarco/lexgui.js/issues) or simply write any feedback to alexroco.30@gmail.com.
|
|
39
|
-
|
|
40
|
-
## Component Features
|
|
41
|
-
|
|
42
|
-
- [x] Asset Browser
|
|
43
|
-
- [x] Timeline
|
|
44
|
-
- [x] Code Editor
|
|
45
|
-
- [ ] Node Graphs (WIP)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { LX } from 'lexgui';
|
|
2
|
+
|
|
3
|
+
if(!LX) {
|
|
4
|
+
throw("lexgui.js missing!");
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
LX.components.push( 'Audio' );
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @method addKnob
|
|
11
|
+
* @param {String} name Widget name
|
|
12
|
+
* @param {Number} value Knob value
|
|
13
|
+
* @param {Number} min Min Knob value
|
|
14
|
+
* @param {Number} max Max Knob value
|
|
15
|
+
* @param {Function} callback Callback function on change
|
|
16
|
+
* @param {*} options:
|
|
17
|
+
* minLabel (String): Label to show as min value
|
|
18
|
+
* maxLabel (String): Label to show as max value
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
let Panel = LX.Panel;
|
|
22
|
+
let Widget = LX.Widget;
|
|
23
|
+
|
|
24
|
+
Panel.prototype.addKnob = function( name, value, min, max, callback, options = {} ) {
|
|
25
|
+
|
|
26
|
+
let widget = this.create_widget( name, Widget.KNOB, options );
|
|
27
|
+
|
|
28
|
+
widget.onGetValue = () => {
|
|
29
|
+
return innerKnobCircle.value;
|
|
30
|
+
};
|
|
31
|
+
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
32
|
+
innerSetValue( newValue );
|
|
33
|
+
Panel._dispatch_event( innerKnobCircle, "change", skipCallback );
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
let element = widget.domEl;
|
|
37
|
+
|
|
38
|
+
// Add reset functionality
|
|
39
|
+
if( widget.name ) {
|
|
40
|
+
Panel._add_reset_property( element.domName, function() {
|
|
41
|
+
this.style.display = "none";
|
|
42
|
+
innerSetValue( innerKnobCircle.iValue );
|
|
43
|
+
Panel._dispatch_event( innerKnobCircle, "change" );
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
var container = document.createElement( 'div' );
|
|
48
|
+
container.className = "lexknob " + ( options.size ?? '' );
|
|
49
|
+
container.style.width = options.inputWidth || "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
50
|
+
|
|
51
|
+
let knobCircle = document.createElement( 'div' );
|
|
52
|
+
knobCircle.className = "knobcircle";
|
|
53
|
+
|
|
54
|
+
let innerKnobCircle = document.createElement( 'div' );
|
|
55
|
+
innerKnobCircle.className = "innerknobcircle";
|
|
56
|
+
innerKnobCircle.min = min;
|
|
57
|
+
innerKnobCircle.max = max;
|
|
58
|
+
knobCircle.appendChild( innerKnobCircle );
|
|
59
|
+
|
|
60
|
+
let knobMarker = document.createElement( 'div' );
|
|
61
|
+
knobMarker.className = "knobmarker";
|
|
62
|
+
innerKnobCircle.appendChild( knobMarker );
|
|
63
|
+
|
|
64
|
+
if( value.constructor == Number )
|
|
65
|
+
{
|
|
66
|
+
value = LX.clamp( value, min, max );
|
|
67
|
+
value = options.precision ? LX.round( value, options.precision ) : value;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
innerKnobCircle.value = innerKnobCircle.iValue = value;
|
|
71
|
+
|
|
72
|
+
let innerSetValue = function( v ) {
|
|
73
|
+
// Convert val between (-135 and 135)
|
|
74
|
+
const angle = LX.remapRange( v, innerKnobCircle.min, innerKnobCircle.max, -135.0, 135.0 );
|
|
75
|
+
innerKnobCircle.style.rotate = angle + 'deg';
|
|
76
|
+
innerKnobCircle.value = v;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const angle = LX.remapRange( value, min, max, -135.0, 135.0 );
|
|
80
|
+
innerKnobCircle.style.rotate = angle + 'deg';
|
|
81
|
+
|
|
82
|
+
if( options.disabled )
|
|
83
|
+
{
|
|
84
|
+
// vecinput.disabled = true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Add wheel input
|
|
88
|
+
|
|
89
|
+
innerKnobCircle.addEventListener( "wheel", function( e ) {
|
|
90
|
+
e.preventDefault();
|
|
91
|
+
if( this !== document.activeElement )
|
|
92
|
+
return;
|
|
93
|
+
let mult = options.step ?? 1;
|
|
94
|
+
if( e.shiftKey ) mult *= 10;
|
|
95
|
+
else if( e.altKey ) mult *= 0.1;
|
|
96
|
+
let new_value = ( this.value - mult * ( e.deltaY > 0 ? 1 : -1 ) );
|
|
97
|
+
this.value = new_value;// .toFixed( 4 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' );
|
|
98
|
+
Panel._dispatch_event( innerKnobCircle, "change" );
|
|
99
|
+
}, { passive: false });
|
|
100
|
+
|
|
101
|
+
innerKnobCircle.addEventListener( "change", e => {
|
|
102
|
+
|
|
103
|
+
const knob = e.target;
|
|
104
|
+
|
|
105
|
+
const skipCallback = e.detail;
|
|
106
|
+
|
|
107
|
+
let val = knob.value = LX.clamp( knob.value, knob.min, knob.max );
|
|
108
|
+
val = options.precision ? LX.round( val, options.precision ) : val;
|
|
109
|
+
|
|
110
|
+
innerSetValue( val );
|
|
111
|
+
|
|
112
|
+
// Reset button (default value)
|
|
113
|
+
if( !skipCallback )
|
|
114
|
+
{
|
|
115
|
+
let btn = element.querySelector( ".lexwidgetname .lexicon" );
|
|
116
|
+
if( btn ) btn.style.display = val != innerKnobCircle.iValue ? "block": "none";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if( !skipCallback ) this._trigger( new LX.IEvent( name, val, e ), callback );
|
|
120
|
+
}, { passive: false });
|
|
121
|
+
|
|
122
|
+
// Add drag input
|
|
123
|
+
|
|
124
|
+
innerKnobCircle.addEventListener( "mousedown", inner_mousedown );
|
|
125
|
+
|
|
126
|
+
var that = this;
|
|
127
|
+
var lastY = 0;
|
|
128
|
+
function inner_mousedown( e ) {
|
|
129
|
+
if( document.activeElement == innerKnobCircle ) return;
|
|
130
|
+
var doc = that.root.ownerDocument;
|
|
131
|
+
doc.addEventListener("mousemove",inner_mousemove);
|
|
132
|
+
doc.addEventListener("mouseup",inner_mouseup);
|
|
133
|
+
lastY = e.pageY;
|
|
134
|
+
document.body.classList.add('nocursor');
|
|
135
|
+
document.body.classList.add('noevents');
|
|
136
|
+
e.stopImmediatePropagation();
|
|
137
|
+
e.stopPropagation();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function inner_mousemove( e ) {
|
|
141
|
+
if (lastY != e.pageY) {
|
|
142
|
+
let dt = lastY - e.pageY;
|
|
143
|
+
let mult = options.step ?? 1;
|
|
144
|
+
if(e.shiftKey) mult *= 10;
|
|
145
|
+
else if(e.altKey) mult *= 0.1;
|
|
146
|
+
let new_value = (innerKnobCircle.value - mult * dt);
|
|
147
|
+
innerKnobCircle.value = new_value;//.toFixed( 4 ).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1');
|
|
148
|
+
Panel._dispatch_event( innerKnobCircle, 'change' );
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
lastY = e.pageY;
|
|
152
|
+
e.stopPropagation();
|
|
153
|
+
e.preventDefault();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function inner_mouseup( e ) {
|
|
157
|
+
var doc = that.root.ownerDocument;
|
|
158
|
+
doc.removeEventListener( 'mousemove', inner_mousemove );
|
|
159
|
+
doc.removeEventListener( 'mouseup', inner_mouseup );
|
|
160
|
+
document.body.classList.remove( 'nocursor' );
|
|
161
|
+
document.body.classList.remove( 'noevents' );
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
container.appendChild( knobCircle );
|
|
165
|
+
element.appendChild( container );
|
|
166
|
+
|
|
167
|
+
// Remove branch padding and margins
|
|
168
|
+
if( !widget.name ) {
|
|
169
|
+
element.className += " noname";
|
|
170
|
+
container.style.width = "100%";
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return widget;
|
|
174
|
+
}
|