@rettangoli/ui 0.1.2-rc15 → 0.1.2-rc18
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/dist/rettangoli-iife-layout.min.js +14 -14
- package/dist/rettangoli-iife-ui.min.js +40 -40
- package/package.json +1 -1
- package/src/components/form/form.handlers.js +50 -1
- package/src/components/form/form.store.js +8 -1
- package/src/components/form/form.view.yaml +42 -0
- package/src/components/popoverInput/popoverInput.handlers.js +99 -0
- package/src/components/popoverInput/popoverInput.store.js +48 -0
- package/src/components/popoverInput/popoverInput.view.yaml +55 -0
- package/src/components/waveform/waveform.handlers.js +86 -0
- package/src/components/waveform/waveform.store.js +17 -0
- package/src/components/waveform/waveform.view.yaml +38 -0
- package/src/primitives/input.js +4 -0
package/package.json
CHANGED
|
@@ -3,6 +3,18 @@ export const handleBeforeMount = (deps) => {
|
|
|
3
3
|
store.setFormValues(props.defaultValues);
|
|
4
4
|
};
|
|
5
5
|
|
|
6
|
+
export const handleOnUpdate = (changes, deps) => {
|
|
7
|
+
const { oldAttrs, newAttrs } = changes
|
|
8
|
+
const { store, props, render } = deps;
|
|
9
|
+
|
|
10
|
+
if (oldAttrs?.key === newAttrs?.key) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
store.setFormValues(props.defaultValues);
|
|
15
|
+
render();
|
|
16
|
+
};
|
|
17
|
+
|
|
6
18
|
const dispatchFormChange = (name, fieldValue, formValues, dispatchEvent) => {
|
|
7
19
|
dispatchEvent(
|
|
8
20
|
new CustomEvent("form-change", {
|
|
@@ -41,6 +53,19 @@ export const handleInputChange = (e, deps) => {
|
|
|
41
53
|
}
|
|
42
54
|
};
|
|
43
55
|
|
|
56
|
+
export const handlePopoverInputChange = (e, deps) => {
|
|
57
|
+
const { store, dispatchEvent } = deps;
|
|
58
|
+
const name = e.currentTarget.id.replace("popover-input-", "");
|
|
59
|
+
// TODO fix double event
|
|
60
|
+
if (name && e.detail.value !== undefined) {
|
|
61
|
+
store.setFormFieldValue({
|
|
62
|
+
name: name,
|
|
63
|
+
value: e.detail.value,
|
|
64
|
+
});
|
|
65
|
+
dispatchFormChange(name, e.detail.value, store.selectFormValues(), dispatchEvent);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
44
69
|
export const handleSelectChange = (e, deps) => {
|
|
45
70
|
const { store, dispatchEvent } = deps;
|
|
46
71
|
const name = e.currentTarget.id.replace("select-", "");
|
|
@@ -90,12 +115,36 @@ export const handleSliderInputChange = (e, deps) => {
|
|
|
90
115
|
};
|
|
91
116
|
|
|
92
117
|
export const handleImageClick = (e, deps) => {
|
|
118
|
+
if (e.type === "contextmenu") {
|
|
119
|
+
e.preventDefault();
|
|
120
|
+
}
|
|
93
121
|
const { dispatchEvent } = deps;
|
|
94
122
|
const name = e.currentTarget.id.replace("image-", "");
|
|
95
123
|
dispatchEvent(
|
|
96
124
|
new CustomEvent("extra-event", {
|
|
97
125
|
detail: {
|
|
98
|
-
name: name
|
|
126
|
+
name: name,
|
|
127
|
+
x: e.clientX,
|
|
128
|
+
y: e.clientY,
|
|
129
|
+
trigger: e.type
|
|
130
|
+
},
|
|
131
|
+
}),
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const handleWaveformClick = (e, deps) => {
|
|
136
|
+
if (e.type === "contextmenu") {
|
|
137
|
+
e.preventDefault();
|
|
138
|
+
}
|
|
139
|
+
const { dispatchEvent } = deps;
|
|
140
|
+
const name = e.currentTarget.id.replace("waveform-", "");
|
|
141
|
+
dispatchEvent(
|
|
142
|
+
new CustomEvent("extra-event", {
|
|
143
|
+
detail: {
|
|
144
|
+
name: name,
|
|
145
|
+
x: e.clientX,
|
|
146
|
+
y: e.clientY,
|
|
147
|
+
trigger: e.type
|
|
99
148
|
},
|
|
100
149
|
}),
|
|
101
150
|
);
|
|
@@ -13,7 +13,7 @@ export const toViewData = ({ state, props, attrs }) => {
|
|
|
13
13
|
const fields = structuredClone(props.form.fields || []);
|
|
14
14
|
const defaultValues = props.defaultValues || {};
|
|
15
15
|
const fieldResources = props.fieldResources || {};
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
fields.forEach((field) => {
|
|
18
18
|
field.defaultValue = defaultValues[field.name];
|
|
19
19
|
if (field.inputType === 'image') {
|
|
@@ -23,6 +23,13 @@ export const toViewData = ({ state, props, attrs }) => {
|
|
|
23
23
|
// Set placeholder text
|
|
24
24
|
field.placeholderText = field.placeholder || 'No Image';
|
|
25
25
|
}
|
|
26
|
+
if (field.inputType === 'waveform') {
|
|
27
|
+
const waveformData = fieldResources[field.name]?.waveformData;
|
|
28
|
+
// Only set waveformData if it exists
|
|
29
|
+
field.waveformData = waveformData || null;
|
|
30
|
+
// Set placeholder text
|
|
31
|
+
field.placeholderText = field.placeholder || 'No Waveform';
|
|
32
|
+
}
|
|
26
33
|
})
|
|
27
34
|
|
|
28
35
|
return {
|
|
@@ -153,6 +153,27 @@ propsSchema:
|
|
|
153
153
|
- label
|
|
154
154
|
- inputType
|
|
155
155
|
additionalProperties: false
|
|
156
|
+
- type: object
|
|
157
|
+
properties:
|
|
158
|
+
name:
|
|
159
|
+
type: string
|
|
160
|
+
label:
|
|
161
|
+
type: string
|
|
162
|
+
description:
|
|
163
|
+
type: string
|
|
164
|
+
inputType:
|
|
165
|
+
const: waveform
|
|
166
|
+
width:
|
|
167
|
+
type: number
|
|
168
|
+
height:
|
|
169
|
+
type: number
|
|
170
|
+
placeholder:
|
|
171
|
+
type: string
|
|
172
|
+
required:
|
|
173
|
+
- name
|
|
174
|
+
- label
|
|
175
|
+
- inputType
|
|
176
|
+
additionalProperties: false
|
|
156
177
|
actions:
|
|
157
178
|
type: object
|
|
158
179
|
properties:
|
|
@@ -200,6 +221,18 @@ refs:
|
|
|
200
221
|
eventListeners:
|
|
201
222
|
click:
|
|
202
223
|
handler: handleImageClick
|
|
224
|
+
contextmenu:
|
|
225
|
+
handler: handleImageClick
|
|
226
|
+
waveform-*:
|
|
227
|
+
eventListeners:
|
|
228
|
+
click:
|
|
229
|
+
handler: handleWaveformClick
|
|
230
|
+
contextmenu:
|
|
231
|
+
handler: handleWaveformClick
|
|
232
|
+
popover-input-*:
|
|
233
|
+
eventListeners:
|
|
234
|
+
input-change:
|
|
235
|
+
handler: handlePopoverInputChange
|
|
203
236
|
|
|
204
237
|
events:
|
|
205
238
|
form-change: {}
|
|
@@ -216,8 +249,12 @@ template:
|
|
|
216
249
|
- rtgl-view g=sm:
|
|
217
250
|
- rtgl-text: ${field.label}
|
|
218
251
|
- rtgl-text s=sm c=mu-fg: ${field.description}
|
|
252
|
+
- $if field.inputType == "read-only-text":
|
|
253
|
+
- rtgl-text s=sm: ${field.defaultValue}
|
|
219
254
|
- $if field.inputType == "inputText":
|
|
220
255
|
- rtgl-input#input-${field.name} w=f placeholder=${field.placeholder} value=${field.defaultValue}:
|
|
256
|
+
- $if field.inputType == "popover-input":
|
|
257
|
+
- rtgl-popover-input#popover-input-${field.name} label="${field.label}" .defaultValue=fields[${i}].defaultValue:
|
|
221
258
|
- $if field.inputType == "select":
|
|
222
259
|
- rtgl-select#select-${field.name} w=f .options=fields[${i}].options .placeholder=fields[${i}].placeholder .selectedValue=fields[${i}].defaultValue:
|
|
223
260
|
- $if field.inputType == "colorPicker":
|
|
@@ -231,6 +268,11 @@ template:
|
|
|
231
268
|
- $if field.inputType == "image" && !field.imageSrc:
|
|
232
269
|
- rtgl-view#image-${field.name} w=${field.width} h=${field.height} bc=ac bw=sm ah=c av=c cur=p p=md:
|
|
233
270
|
- rtgl-text c=mu-fg ta=c: ${field.placeholderText}
|
|
271
|
+
- $if field.inputType == "waveform" && field.waveformData:
|
|
272
|
+
- rtgl-waveform#waveform-${field.name} .waveformData=fields[${i}].waveformData w=${field.width} h=${field.height} cur=p:
|
|
273
|
+
- $if field.inputType == "waveform" && !field.waveformData:
|
|
274
|
+
- rtgl-view#waveform-${field.name} w=${field.width} h=${field.height} bc=ac bw=sm ah=c av=c cur=p p=md:
|
|
275
|
+
- rtgl-text c=mu-fg ta=c: ${field.placeholderText}
|
|
234
276
|
- rtgl-view g=sm w=f:
|
|
235
277
|
- rtgl-view d=h ah=e g=sm w=f:
|
|
236
278
|
- $for button, i in actions.buttons:
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export const handleBeforeMount = (deps) => {
|
|
2
|
+
const { store, props } = deps;
|
|
3
|
+
|
|
4
|
+
if (props.value !== undefined || props.defaultValue !== undefined) {
|
|
5
|
+
store.setValue(props.value || props.defaultValue || '');
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const handleOnUpdate = (changes, deps) => {
|
|
10
|
+
const { oldProps, newProps} = changes
|
|
11
|
+
const { store, props, render } = deps;
|
|
12
|
+
|
|
13
|
+
if (oldProps.defaultValue !== newProps.defaultValue) {
|
|
14
|
+
store.setValue(props.defaultValue || '');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
render();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const handleTextClick = (e, deps) => {
|
|
21
|
+
const { store, render, getRefIds, attrs } = deps;
|
|
22
|
+
|
|
23
|
+
const value = store.selectValue();
|
|
24
|
+
store.setTempValue(value)
|
|
25
|
+
|
|
26
|
+
store.openPopover({
|
|
27
|
+
position: {
|
|
28
|
+
x: e.currentTarget.getBoundingClientRect().left,
|
|
29
|
+
y: e.currentTarget.getBoundingClientRect().bottom,
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const { input } = getRefIds();
|
|
34
|
+
input.elm.value = value;
|
|
35
|
+
render();
|
|
36
|
+
|
|
37
|
+
if (attrs['auto-focus']) {
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
input.elm.focus();
|
|
40
|
+
}, 50)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const handlePopoverClose = (e, deps) => {
|
|
45
|
+
const { store, render } = deps;
|
|
46
|
+
store.closePopover();
|
|
47
|
+
render();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const handleInputChange = (e, deps) => {
|
|
51
|
+
const { store, render, dispatchEvent } = deps;
|
|
52
|
+
const value = e.detail.value;
|
|
53
|
+
|
|
54
|
+
store.setTempValue(value);
|
|
55
|
+
|
|
56
|
+
dispatchEvent(new CustomEvent('temp-input-change', {
|
|
57
|
+
detail: { value },
|
|
58
|
+
bubbles: true
|
|
59
|
+
}));
|
|
60
|
+
|
|
61
|
+
render();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const handleSubmitClick = (e, deps) => {
|
|
65
|
+
const { store, render, dispatchEvent, getRefIds } = deps;
|
|
66
|
+
const { input } = getRefIds()
|
|
67
|
+
const value = input.elm.value;
|
|
68
|
+
|
|
69
|
+
store.setValue(value)
|
|
70
|
+
store.closePopover();
|
|
71
|
+
|
|
72
|
+
dispatchEvent(new CustomEvent('input-change', {
|
|
73
|
+
detail: { value },
|
|
74
|
+
bubbles: true
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
render();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const handleInputKeydown = (e, deps) => {
|
|
81
|
+
const { store, render, dispatchEvent, getRefIds } = deps;
|
|
82
|
+
|
|
83
|
+
if (e.key === 'Enter') {
|
|
84
|
+
const { input } = getRefIds()
|
|
85
|
+
const value = input.elm.value;
|
|
86
|
+
|
|
87
|
+
store.closePopover();
|
|
88
|
+
// Dispatch custom event
|
|
89
|
+
dispatchEvent(new CustomEvent('input-change', {
|
|
90
|
+
detail: { value },
|
|
91
|
+
bubbles: true
|
|
92
|
+
}));
|
|
93
|
+
|
|
94
|
+
render();
|
|
95
|
+
} else if (e.key === 'Escape') {
|
|
96
|
+
store.closePopover();
|
|
97
|
+
render();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export const INITIAL_STATE = Object.freeze({
|
|
2
|
+
isOpen: false,
|
|
3
|
+
position: {
|
|
4
|
+
x: 0,
|
|
5
|
+
y: 0,
|
|
6
|
+
},
|
|
7
|
+
value: '',
|
|
8
|
+
tempValue: '',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const toViewData = ({ attrs, state, props }) => {
|
|
12
|
+
// Use state's current value if it has been modified, otherwise use props
|
|
13
|
+
const value = state.value || '-';
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
isOpen: state.isOpen,
|
|
17
|
+
position: state.position,
|
|
18
|
+
value: value ?? '-',
|
|
19
|
+
tempValue: state.tempValue,
|
|
20
|
+
placeholder: props.placeholder ?? '',
|
|
21
|
+
label: attrs.label,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const setTempValue = (state, value) => {
|
|
26
|
+
state.tempValue = value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const openPopover = (state, payload) => {
|
|
30
|
+
const { position } = payload;
|
|
31
|
+
state.position = position;
|
|
32
|
+
state.isOpen = true;
|
|
33
|
+
// Reset the current value to match the display value when opening
|
|
34
|
+
state.hasUnsavedChanges = false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const closePopover = (state) => {
|
|
38
|
+
state.isOpen = false;
|
|
39
|
+
state.tempValue = '';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const setValue = (state, value) => {
|
|
43
|
+
state.value = value;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const selectValue = ({ state }) => {
|
|
47
|
+
return state.value;
|
|
48
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
elementName: rtgl-popover-input
|
|
2
|
+
|
|
3
|
+
viewDataSchema:
|
|
4
|
+
type: object
|
|
5
|
+
|
|
6
|
+
attrsSchema:
|
|
7
|
+
type: object
|
|
8
|
+
properties:
|
|
9
|
+
auto-focus:
|
|
10
|
+
type: boolean
|
|
11
|
+
|
|
12
|
+
propsSchema:
|
|
13
|
+
type: object
|
|
14
|
+
properties:
|
|
15
|
+
value:
|
|
16
|
+
type: string
|
|
17
|
+
defaultValue:
|
|
18
|
+
type: string
|
|
19
|
+
placeholder:
|
|
20
|
+
type: string
|
|
21
|
+
onChange:
|
|
22
|
+
type: function
|
|
23
|
+
|
|
24
|
+
refs:
|
|
25
|
+
text-display:
|
|
26
|
+
eventListeners:
|
|
27
|
+
click:
|
|
28
|
+
handler: handleTextClick
|
|
29
|
+
popover:
|
|
30
|
+
eventListeners:
|
|
31
|
+
close:
|
|
32
|
+
handler: handlePopoverClose
|
|
33
|
+
input:
|
|
34
|
+
eventListeners:
|
|
35
|
+
input-change:
|
|
36
|
+
handler: handleInputChange
|
|
37
|
+
keydown:
|
|
38
|
+
handler: handleInputKeydown
|
|
39
|
+
submit:
|
|
40
|
+
eventListeners:
|
|
41
|
+
click:
|
|
42
|
+
handler: handleSubmitClick
|
|
43
|
+
|
|
44
|
+
events:
|
|
45
|
+
input-change: {}
|
|
46
|
+
|
|
47
|
+
template:
|
|
48
|
+
- rtgl-view#text-display w=f cur=p:
|
|
49
|
+
- rtgl-text: ${value}
|
|
50
|
+
- rtgl-popover#popover ?open=${isOpen} x=${position.x} y=${position.y}:
|
|
51
|
+
- rtgl-view g=md w=240 slot=content bgc=background br=md:
|
|
52
|
+
- rtgl-text: ${label}
|
|
53
|
+
- rtgl-input#input w=f placeholder=${placeholder}:
|
|
54
|
+
- rtgl-view w=f ah=e:
|
|
55
|
+
- rtgl-button#submit: Submit
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export const handleAfterMount = async (deps) => {
|
|
2
|
+
const { props, store, render, getRefIds, } = deps;
|
|
3
|
+
const { waveformData } = props;
|
|
4
|
+
|
|
5
|
+
store.setWaveformData(waveformData);
|
|
6
|
+
render();
|
|
7
|
+
|
|
8
|
+
const canvas = getRefIds().canvas?.elm;
|
|
9
|
+
if (canvas) {
|
|
10
|
+
renderWaveform(waveformData, canvas);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const handleOnUpdate = async (changes, deps) => {
|
|
15
|
+
const { store, render, getRefIds, props } = deps;
|
|
16
|
+
const { waveformData } = props;
|
|
17
|
+
store.setWaveformData(waveformData);
|
|
18
|
+
render();
|
|
19
|
+
|
|
20
|
+
const canvas = getRefIds().canvas?.elm;
|
|
21
|
+
if (canvas) {
|
|
22
|
+
renderWaveform(waveformData, canvas);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
async function renderWaveform(waveformData, canvas) {
|
|
27
|
+
const ctx = canvas.getContext("2d");
|
|
28
|
+
|
|
29
|
+
// Get the actual display size of the canvas
|
|
30
|
+
const rect = canvas.getBoundingClientRect();
|
|
31
|
+
const displayWidth = rect.width;
|
|
32
|
+
const displayHeight = rect.height;
|
|
33
|
+
|
|
34
|
+
// Set canvas internal resolution to match display size
|
|
35
|
+
canvas.width = displayWidth;
|
|
36
|
+
canvas.height = displayHeight;
|
|
37
|
+
|
|
38
|
+
const width = canvas.width;
|
|
39
|
+
const height = canvas.height;
|
|
40
|
+
|
|
41
|
+
// Clear canvas
|
|
42
|
+
ctx.clearRect(0, 0, width, height);
|
|
43
|
+
|
|
44
|
+
// Dark theme background
|
|
45
|
+
ctx.fillStyle = "#1a1a1a";
|
|
46
|
+
ctx.fillRect(0, 0, width, height);
|
|
47
|
+
|
|
48
|
+
if (!waveformData || !waveformData.data) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const data = waveformData.data;
|
|
53
|
+
const centerY = height / 2;
|
|
54
|
+
|
|
55
|
+
// Create gradient for waveform
|
|
56
|
+
const gradient = ctx.createLinearGradient(0, 0, 0, height);
|
|
57
|
+
gradient.addColorStop(0, "#404040");
|
|
58
|
+
gradient.addColorStop(0.5, "#A1A1A1");
|
|
59
|
+
gradient.addColorStop(1, "#404040");
|
|
60
|
+
|
|
61
|
+
// Draw waveform bars
|
|
62
|
+
const barWidth = Math.max(1, width / data.length);
|
|
63
|
+
const barSpacing = 0.2; // 20% spacing between bars
|
|
64
|
+
|
|
65
|
+
for (let i = 0; i < data.length; i++) {
|
|
66
|
+
const amplitude = data[i];
|
|
67
|
+
const barHeight = amplitude * (height * 0.85);
|
|
68
|
+
const x = i * barWidth;
|
|
69
|
+
const y = centerY - barHeight / 2;
|
|
70
|
+
|
|
71
|
+
ctx.fillStyle = gradient;
|
|
72
|
+
ctx.fillRect(x, y, Math.max(1, barWidth * (1 - barSpacing)), barHeight);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Draw subtle center line
|
|
76
|
+
ctx.strokeStyle = "rgba(255, 255, 255, 0.1)";
|
|
77
|
+
ctx.lineWidth = 1;
|
|
78
|
+
ctx.beginPath();
|
|
79
|
+
ctx.moveTo(0, centerY);
|
|
80
|
+
ctx.lineTo(width, centerY);
|
|
81
|
+
ctx.stroke();
|
|
82
|
+
|
|
83
|
+
// Add subtle glow effect
|
|
84
|
+
ctx.shadowBlur = 10;
|
|
85
|
+
ctx.shadowColor = "#2196F3";
|
|
86
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const INITIAL_STATE = Object.freeze({
|
|
2
|
+
waveformData: null,
|
|
3
|
+
});
|
|
4
|
+
|
|
5
|
+
export const setWaveformData = (state, data) => {
|
|
6
|
+
state.waveformData = data;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const toViewData = ({ state, attrs, props }) => {
|
|
10
|
+
return {
|
|
11
|
+
isLoading: props.isLoading,
|
|
12
|
+
w: attrs.w || "250",
|
|
13
|
+
h: attrs.h || "150",
|
|
14
|
+
cur: attrs.cur,
|
|
15
|
+
waveformData: props.waveformData,
|
|
16
|
+
};
|
|
17
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
elementName: rtgl-waveform
|
|
2
|
+
|
|
3
|
+
attrsSchema:
|
|
4
|
+
type: object
|
|
5
|
+
properties:
|
|
6
|
+
w:
|
|
7
|
+
type: string
|
|
8
|
+
description: Width of the waveform visualizer
|
|
9
|
+
default: '250'
|
|
10
|
+
h:
|
|
11
|
+
type: string
|
|
12
|
+
description: Height of the waveform visualizer
|
|
13
|
+
default: '150'
|
|
14
|
+
cur:
|
|
15
|
+
type: string
|
|
16
|
+
description: cursor
|
|
17
|
+
|
|
18
|
+
propsSchema:
|
|
19
|
+
type: object
|
|
20
|
+
properties:
|
|
21
|
+
waveformData:
|
|
22
|
+
type: object
|
|
23
|
+
description: File ID of the waveform data in object storage
|
|
24
|
+
isLoading:
|
|
25
|
+
type: boolean
|
|
26
|
+
description: Whether the waveform data is currently being loaded
|
|
27
|
+
|
|
28
|
+
refs:
|
|
29
|
+
canvas:
|
|
30
|
+
selector: canvas
|
|
31
|
+
|
|
32
|
+
template:
|
|
33
|
+
- rtgl-view w=f h=f pos=rel w=${w} h=${h} cur=${cur}:
|
|
34
|
+
- $if isLoading:
|
|
35
|
+
- rtgl-view w=f h=f av=c ah=c:
|
|
36
|
+
- rtgl-text c=mu-fg: ...
|
|
37
|
+
$else:
|
|
38
|
+
- 'canvas#canvas style="width:100%; height:100%;"':
|
package/src/primitives/input.js
CHANGED
|
@@ -110,6 +110,10 @@ class RettangoliInputElement extends HTMLElement {
|
|
|
110
110
|
this._inputElement.value = newValue;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
focus() {
|
|
114
|
+
this._inputElement.focus();
|
|
115
|
+
}
|
|
116
|
+
|
|
113
117
|
_onChange = (event) => {
|
|
114
118
|
this.dispatchEvent(new CustomEvent('input-change', {
|
|
115
119
|
detail: {
|