iobroker.mywebui 1.42.13 → 1.42.14
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/io-package.json
CHANGED
package/package.json
CHANGED
|
@@ -1498,19 +1498,22 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
|
|
|
1498
1498
|
}
|
|
1499
1499
|
}
|
|
1500
1500
|
show3DObjectProperties(obj, onChange) {
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
let panel;
|
|
1505
|
-
if (!existing) {
|
|
1501
|
+
// Reuse cached panel reference (avoid querySelector with invalid CSS id)
|
|
1502
|
+
let panel = this._tdPropsPanel;
|
|
1503
|
+
if (!panel || !panel.isConnected) {
|
|
1506
1504
|
panel = document.createElement('div');
|
|
1507
|
-
panel.id =
|
|
1505
|
+
panel.id = 'tdPropsPanel';
|
|
1508
1506
|
panel.title = '3D Properties';
|
|
1509
1507
|
panel.style.cssText = 'width:100%;height:100%;overflow:auto;background:#1e1e1e;color:#ccc;font-size:12px;font-family:"Segoe UI",sans-serif;';
|
|
1510
|
-
|
|
1508
|
+
// Dock to right side (attributeDock area)
|
|
1509
|
+
panel.setAttribute('dock-spawn-dock-to', 'attributeDock');
|
|
1510
|
+
panel.setAttribute('dock-spawn-dock-type', 'fill');
|
|
1511
|
+
panel.setAttribute('dock-spawn-panel-type', 'document');
|
|
1512
|
+
this._dock.appendChild(panel);
|
|
1513
|
+
this._tdPropsPanel = panel;
|
|
1511
1514
|
} else {
|
|
1512
|
-
|
|
1513
|
-
|
|
1515
|
+
// Activate existing tab
|
|
1516
|
+
this.isDockOpenAndActivate('tdPropsPanel');
|
|
1514
1517
|
}
|
|
1515
1518
|
if (!panel) return;
|
|
1516
1519
|
|
|
@@ -1520,63 +1523,68 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
|
|
|
1520
1523
|
const rot = obj.rotation ?? { x: 0, y: 0, z: 0 };
|
|
1521
1524
|
const scl = obj.scale ?? { x: 1, y: 1, z: 1 };
|
|
1522
1525
|
|
|
1526
|
+
const bindingsHtml = obj.bindings && Object.keys(obj.bindings).length > 0
|
|
1527
|
+
? Object.entries(obj.bindings).map(([k, bv]) =>
|
|
1528
|
+
`<div style="padding:2px 0;border-bottom:1px solid #3c3c3c;display:flex;gap:4px;">
|
|
1529
|
+
<span style="color:#4ec9b0;flex:1;">${k}</span>
|
|
1530
|
+
<span style="color:#888;flex:2;overflow:hidden;text-overflow:ellipsis;">${bv.signal||''}</span>
|
|
1531
|
+
</div>`).join('')
|
|
1532
|
+
: '<span style="font-style:italic;color:#555;">No bindings</span>';
|
|
1533
|
+
|
|
1523
1534
|
panel.innerHTML = `
|
|
1535
|
+
<style>
|
|
1536
|
+
.pg-group{margin-bottom:10px;}
|
|
1537
|
+
.pg-header{color:#888;font-size:10px;font-weight:bold;text-transform:uppercase;letter-spacing:0.5px;padding:4px 0;border-bottom:1px solid #3c3c3c;margin-bottom:4px;}
|
|
1538
|
+
.pg-row{display:flex;align-items:center;margin-bottom:3px;}
|
|
1539
|
+
.pg-row label{width:16px;color:#888;font-size:10px;margin-right:6px;}
|
|
1540
|
+
.pg-input{flex:1;background:#3c3c3c;border:1px solid #555;color:#ccc;padding:3px 5px;border-radius:2px;font-size:11px;}
|
|
1541
|
+
.pg-input:focus{outline:none;border-color:#9cdcfe;}
|
|
1542
|
+
</style>
|
|
1524
1543
|
<div style="padding:8px;border-bottom:1px solid #3c3c3c;background:#252526;">
|
|
1525
|
-
<div style="color:#9cdcfe;font-weight:bold;font-size:11px;letter-spacing:0.5px;"
|
|
1544
|
+
<div style="color:#9cdcfe;font-weight:bold;font-size:11px;letter-spacing:0.5px;">📦 ${obj.name || 'Object'}</div>
|
|
1526
1545
|
<div style="color:#666;font-size:10px;">${obj.type || 'model'}</div>
|
|
1527
1546
|
</div>
|
|
1528
1547
|
<div style="padding:8px;">
|
|
1529
1548
|
<div class="pg-group">
|
|
1530
1549
|
<div class="pg-header">Position</div>
|
|
1531
|
-
<div class="pg-row"><label>X</label><input class="pg-input"
|
|
1532
|
-
<div class="pg-row"><label>Y</label><input class="pg-input"
|
|
1533
|
-
<div class="pg-row"><label>Z</label><input class="pg-input"
|
|
1550
|
+
<div class="pg-row"><label>X</label><input class="pg-input" data-fid="px" type="number" step="0.1" value="${(pos.x||0).toFixed(3)}"></div>
|
|
1551
|
+
<div class="pg-row"><label>Y</label><input class="pg-input" data-fid="py" type="number" step="0.1" value="${(pos.y||0).toFixed(3)}"></div>
|
|
1552
|
+
<div class="pg-row"><label>Z</label><input class="pg-input" data-fid="pz" type="number" step="0.1" value="${(pos.z||0).toFixed(3)}"></div>
|
|
1534
1553
|
</div>
|
|
1535
1554
|
<div class="pg-group">
|
|
1536
1555
|
<div class="pg-header">Rotation (rad)</div>
|
|
1537
|
-
<div class="pg-row"><label>X</label><input class="pg-input"
|
|
1538
|
-
<div class="pg-row"><label>Y</label><input class="pg-input"
|
|
1539
|
-
<div class="pg-row"><label>Z</label><input class="pg-input"
|
|
1556
|
+
<div class="pg-row"><label>X</label><input class="pg-input" data-fid="rx" type="number" step="0.01" value="${(rot.x||0).toFixed(4)}"></div>
|
|
1557
|
+
<div class="pg-row"><label>Y</label><input class="pg-input" data-fid="ry" type="number" step="0.01" value="${(rot.y||0).toFixed(4)}"></div>
|
|
1558
|
+
<div class="pg-row"><label>Z</label><input class="pg-input" data-fid="rz" type="number" step="0.01" value="${(rot.z||0).toFixed(4)}"></div>
|
|
1540
1559
|
</div>
|
|
1541
1560
|
<div class="pg-group">
|
|
1542
1561
|
<div class="pg-header">Scale</div>
|
|
1543
|
-
<div class="pg-row"><label>X</label><input class="pg-input"
|
|
1544
|
-
<div class="pg-row"><label>Y</label><input class="pg-input"
|
|
1545
|
-
<div class="pg-row"><label>Z</label><input class="pg-input"
|
|
1562
|
+
<div class="pg-row"><label>X</label><input class="pg-input" data-fid="sx" type="number" step="0.1" value="${(scl.x||1).toFixed(3)}"></div>
|
|
1563
|
+
<div class="pg-row"><label>Y</label><input class="pg-input" data-fid="sy" type="number" step="0.1" value="${(scl.y||1).toFixed(3)}"></div>
|
|
1564
|
+
<div class="pg-row"><label>Z</label><input class="pg-input" data-fid="sz" type="number" step="0.1" value="${(scl.z||1).toFixed(3)}"></div>
|
|
1546
1565
|
</div>
|
|
1547
1566
|
<div class="pg-group">
|
|
1548
1567
|
<div class="pg-header">ioBroker Bindings</div>
|
|
1549
|
-
<div
|
|
1550
|
-
|
|
1551
|
-
? Object.entries(obj.bindings).map(([k,v]) =>
|
|
1552
|
-
`<div style="padding:2px 0;border-bottom:1px solid #3c3c3c;display:flex;gap:4px;">
|
|
1553
|
-
<span style="color:#4ec9b0;flex:1;">${k}</span>
|
|
1554
|
-
<span style="color:#888;flex:2;overflow:hidden;text-overflow:ellipsis;">${v.signal||''}</span>
|
|
1555
|
-
</div>`).join('')
|
|
1556
|
-
: '<span style="font-style:italic;">No bindings</span>'
|
|
1557
|
-
}</div>
|
|
1558
|
-
<button id="addBindBtn" style="width:100%;padding:4px;background:#1a3a1a;color:#4ec9b0;border:1px solid #2a5a2a;border-radius:3px;cursor:pointer;font-size:10px;margin-top:4px;">+ Add Binding</button>
|
|
1568
|
+
<div style="font-size:10px;padding:4px 0;">${bindingsHtml}</div>
|
|
1569
|
+
<button class="bind-add-btn" style="width:100%;padding:4px;background:#1a3a1a;color:#4ec9b0;border:1px solid #2a5a2a;border-radius:3px;cursor:pointer;font-size:10px;margin-top:4px;">+ Add Binding</button>
|
|
1559
1570
|
</div>
|
|
1560
1571
|
</div>
|
|
1561
|
-
<style>
|
|
1562
|
-
.pg-group { margin-bottom:10px; }
|
|
1563
|
-
.pg-header { color:#888;font-size:10px;font-weight:bold;text-transform:uppercase;letter-spacing:0.5px;padding:4px 0;border-bottom:1px solid #3c3c3c;margin-bottom:4px; }
|
|
1564
|
-
.pg-row { display:flex;align-items:center;margin-bottom:3px; }
|
|
1565
|
-
.pg-row label { width:16px;color:#888;font-size:10px;margin-right:6px; }
|
|
1566
|
-
.pg-input { flex:1;background:#3c3c3c;border:1px solid #555;color:#ccc;padding:3px 5px;border-radius:2px;font-size:11px; }
|
|
1567
|
-
.pg-input:focus { outline:none;border-color:#9cdcfe; }
|
|
1568
|
-
</style>
|
|
1569
1572
|
`;
|
|
1570
1573
|
|
|
1571
|
-
const
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1574
|
+
const p = panel;
|
|
1575
|
+
const v = (id) => parseFloat(p.querySelector('[data-fid="'+id+'"]')?.value) || 0;
|
|
1576
|
+
const v1 = (id) => parseFloat(p.querySelector('[data-fid="'+id+'"]')?.value) || 1;
|
|
1577
|
+
|
|
1578
|
+
// Replace #id inputs with data-fid to avoid querySelector ID issues
|
|
1579
|
+
p.querySelectorAll('[data-fid]').forEach(inp => {
|
|
1580
|
+
inp.addEventListener('change', () => {
|
|
1581
|
+
obj.position = { x: v('px'), y: v('py'), z: v('pz') };
|
|
1582
|
+
obj.rotation = { x: v('rx'), y: v('ry'), z: v('rz') };
|
|
1583
|
+
obj.scale = { x: v1('sx'), y: v1('sy'), z: v1('sz') };
|
|
1584
|
+
if (onChange) onChange(obj);
|
|
1585
|
+
});
|
|
1586
|
+
});
|
|
1587
|
+
p.querySelector('.bind-add-btn')?.addEventListener('click', () => {
|
|
1580
1588
|
const prop = prompt('Property (e.g. position.x, rotation.y, scale.z):', 'position.x');
|
|
1581
1589
|
if (!prop) return;
|
|
1582
1590
|
const signal = prompt('ioBroker signal path:', '');
|