@liquidcars/atlas 0.1.20 → 0.1.22
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 +22 -7
- package/demo/index.html +2 -2
- package/dist/liquidcars-atlas.js +102 -14
- package/index.html +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,6 +50,7 @@ También se puede cargar el modelo desde JavaScript:
|
|
|
50
50
|
const atlas = document.querySelector('liquidcars-atlas');
|
|
51
51
|
atlas.model = model;
|
|
52
52
|
atlas.select('distribution-agreement');
|
|
53
|
+
atlas.selectRelation(0); // también acepta el id de una relación
|
|
53
54
|
atlas.setRelationMode('all'); // 'all' | 'selected' | 'none'
|
|
54
55
|
atlas.setToolbarVisible(true); // también se puede usar toolbar="on" | "off"
|
|
55
56
|
atlas.zoomIn();
|
|
@@ -76,7 +77,11 @@ atlas.removeRelation(0);
|
|
|
76
77
|
atlas.removeEntity('service');
|
|
77
78
|
|
|
78
79
|
atlas.addEventListener('lc-select', event => {
|
|
79
|
-
|
|
80
|
+
if (event.detail.kind === 'entity') {
|
|
81
|
+
console.log('Entidad seleccionada:', event.detail.id, event.detail.entity);
|
|
82
|
+
} else if (event.detail.kind === 'relation') {
|
|
83
|
+
console.log('Relación seleccionada:', event.detail.index, event.detail.relation);
|
|
84
|
+
}
|
|
80
85
|
});
|
|
81
86
|
atlas.addEventListener('lc-model-change', event => {
|
|
82
87
|
console.log('Modelo actualizado:', event.detail.kind);
|
|
@@ -90,9 +95,11 @@ por lo que una aplicación puede adaptar la apariencia sin modificar el bundle.
|
|
|
90
95
|
Las propiedades `atlas.theme` y `atlas.styles` son alias prácticos de esta configuración.
|
|
91
96
|
|
|
92
97
|
Eventos disponibles: `lc-ready`, `lc-error`, `lc-select`, `lc-model-change`,
|
|
93
|
-
`lc-relation-mode` y `lc-disconnect`. `lc-select`
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
`lc-relation-mode` y `lc-disconnect`. `lc-select` usa un detalle discriminado:
|
|
99
|
+
las entidades incluyen `{ kind: 'entity', id, entity, source }` y las relaciones
|
|
100
|
+
`{ kind: 'relation', id, index, relation, source }`. Los campos históricos `id`
|
|
101
|
+
y `entity` se conservan para las selecciones de entidad. Al volver a la vista
|
|
102
|
+
general, `kind`, `id`, `entity` y `relation` son `null`. Los eventos de selección y cambios de modelo son `bubbles` y
|
|
96
103
|
`composed`, por lo que funcionan también al integrar el componente en otras
|
|
97
104
|
capas de Web Components.
|
|
98
105
|
|
|
@@ -113,7 +120,8 @@ como `setClickBehavior()`).
|
|
|
113
120
|
El campo visual opcional `mode` admite `directed` (por defecto),
|
|
114
121
|
`bidirectional` y `broken`. En modo bidireccional los indicadores animados
|
|
115
122
|
circulan en ambos sentidos por el mismo tubo; en modo broken los dos tramos
|
|
116
|
-
|
|
123
|
+
se sustituyen por un único tubo rojo con tres anillos que vibran localmente,
|
|
124
|
+
distribuidos a lo largo del recorrido.
|
|
117
125
|
|
|
118
126
|
Geometrías incluidas en esta primera versión: `box`, `cylinder`, `sphere`, `cone`, `frustum-cone`, `frustum-pyramid`, `frustum-triangle`, `prism`, `pyramid-square`, `pyramid-triangle`, `octahedron`, `dodecahedron` e `icosahedron`. Las variantes `frustum-*` son sólidos truncados con dos caras finitas paralelas; las dimensiones `s` se aplican sobre su caja final normalizada.
|
|
119
127
|
|
|
@@ -141,9 +149,16 @@ Una vez publicado, los consumidores podrán instalarlo con `npm install @liquidc
|
|
|
141
149
|
Para probar el paquete sin publicarlo, basta con instalar el tarball generado:
|
|
142
150
|
|
|
143
151
|
```bash
|
|
144
|
-
npm install ./liquidcars-atlas-0.1.
|
|
152
|
+
npm install ./liquidcars-atlas-0.1.22.tgz
|
|
145
153
|
```
|
|
146
154
|
|
|
147
155
|
## Estado
|
|
148
156
|
|
|
149
|
-
`0.1.
|
|
157
|
+
`0.1.22` amplía la selección contextual a las relaciones. El usuario puede
|
|
158
|
+
seleccionar un tubo directamente, el componente lo realza, muestra sus extremos
|
|
159
|
+
y modo en el panel y emite el mismo evento `lc-select` con `kind: 'relation'`.
|
|
160
|
+
La API pública añade `selectRelation()`, `selectedRelation` y `selection`, y la
|
|
161
|
+
selección se conserva durante las mutaciones del modelo siempre que el elemento
|
|
162
|
+
siga existiendo. Se mantienen las correcciones de geometría, toolbar, etiquetas,
|
|
163
|
+
paleta externa, edición en caliente y los modos `directed`, `bidirectional` y
|
|
164
|
+
`broken` introducidos en las versiones anteriores.
|
package/demo/index.html
CHANGED
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
liquidcars-atlas { display: block; width: 100%; max-width: 1480px; margin: 0 auto; }
|
|
15
15
|
code { color: #85e5d3; }
|
|
16
16
|
</style>
|
|
17
|
-
<script type="module" src="../dist/liquidcars-atlas.js?v=0.1.
|
|
17
|
+
<script type="module" src="../dist/liquidcars-atlas.js?v=0.1.21"></script>
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
20
|
<header>
|
|
21
21
|
<h1>LiquidCars Atlas</h1>
|
|
22
|
-
<p>Prueba de distribución del componente <code><liquidcars-atlas></code> · v0.1.
|
|
22
|
+
<p>Prueba de distribución del componente <code><liquidcars-atlas></code> · v0.1.21</p>
|
|
23
23
|
</header>
|
|
24
24
|
<main>
|
|
25
25
|
<liquidcars-atlas id="atlas" height="720" relation-mode="selected" shell-labels="on"></liquidcars-atlas>
|
package/dist/liquidcars-atlas.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! LiquidCars Atlas 0.1.
|
|
1
|
+
/*! LiquidCars Atlas 0.1.22 | MIT */
|
|
2
2
|
|
|
3
3
|
// src/three.core.js
|
|
4
4
|
/**
|
|
@@ -29595,6 +29595,7 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
29595
29595
|
this.nodes = /* @__PURE__ */ new Map();
|
|
29596
29596
|
this.open = /* @__PURE__ */ new Set();
|
|
29597
29597
|
this.selected = null;
|
|
29598
|
+
this.selectedRelationIndex = null;
|
|
29598
29599
|
this.modelData = null;
|
|
29599
29600
|
this.theme = normalizeTheme();
|
|
29600
29601
|
this.relationMode = this.getAttribute("relation-mode") || "selected";
|
|
@@ -29651,6 +29652,14 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
29651
29652
|
get selectedId() {
|
|
29652
29653
|
return this.selected?.id || null;
|
|
29653
29654
|
}
|
|
29655
|
+
get selectedRelation() {
|
|
29656
|
+
return this._publicRelation(this.selectedRelationIndex);
|
|
29657
|
+
}
|
|
29658
|
+
get selection() {
|
|
29659
|
+
if (this.selected) return { kind: "entity", id: this.selected.id, entity: this._publicEntity(this.selected.id) };
|
|
29660
|
+
const relation = this.selectedRelation;
|
|
29661
|
+
return relation ? { kind: "relation", id: relation.id || null, index: relation.index, relation } : null;
|
|
29662
|
+
}
|
|
29654
29663
|
get clickBehavior() {
|
|
29655
29664
|
return this.selectionMode;
|
|
29656
29665
|
}
|
|
@@ -29673,10 +29682,17 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
29673
29682
|
s: Array.isArray(entity.s) ? [...entity.s] : [1, 1, 1]
|
|
29674
29683
|
} : null;
|
|
29675
29684
|
}
|
|
29685
|
+
_publicRelation(reference) {
|
|
29686
|
+
const index = this._relationIndex(reference);
|
|
29687
|
+
const relation = this.modelData?.relations?.[index];
|
|
29688
|
+
return relation ? { ...relation, index } : null;
|
|
29689
|
+
}
|
|
29676
29690
|
_commitModelChange(kind, detail = {}, options = {}) {
|
|
29677
29691
|
const selectedId = options.preserveSelection === false ? null : this.selected?.id;
|
|
29692
|
+
const selectedRelation = options.preserveSelection === false ? null : this._publicRelation(this.selectedRelationIndex);
|
|
29693
|
+
const selectedRelationReference = selectedRelation?.id ?? selectedRelation?.index ?? null;
|
|
29678
29694
|
this.modelData = normalizeModel(this.modelData);
|
|
29679
|
-
this._build({ preserveSelection: selectedId });
|
|
29695
|
+
this._build({ preserveSelection: selectedId, preserveRelation: selectedRelationReference });
|
|
29680
29696
|
this._emit("lc-model-change", {
|
|
29681
29697
|
kind,
|
|
29682
29698
|
model: this.modelData,
|
|
@@ -29735,8 +29751,11 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
29735
29751
|
}
|
|
29736
29752
|
}
|
|
29737
29753
|
if (!this.modelData.entities.some((item) => item.id === id)) throw new Error(`No existe una entidad con id "${id}".`);
|
|
29754
|
+
const selectedRelation = this.modelData.relations[this.selectedRelationIndex];
|
|
29738
29755
|
this.modelData.entities = this.modelData.entities.filter((item) => !removed.has(item.id));
|
|
29739
29756
|
this.modelData.relations = this.modelData.relations.filter((relation) => !removed.has(relation.from) && !removed.has(relation.to));
|
|
29757
|
+
const nextSelectedRelationIndex = selectedRelation ? this.modelData.relations.indexOf(selectedRelation) : -1;
|
|
29758
|
+
this.selectedRelationIndex = nextSelectedRelationIndex >= 0 ? nextSelectedRelationIndex : null;
|
|
29740
29759
|
for (const removedId of removed) this.open.delete(removedId);
|
|
29741
29760
|
if (this.selected && removed.has(this.selected.id)) this.selected = null;
|
|
29742
29761
|
return this._commitModelChange("entity-remove", { id, removed: [...removed] });
|
|
@@ -29770,6 +29789,8 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
29770
29789
|
const index = this._relationIndex(reference);
|
|
29771
29790
|
if (index < 0 || index >= this.modelData.relations.length) throw new Error("No existe la relaci\xF3n indicada.");
|
|
29772
29791
|
const [relation] = this.modelData.relations.splice(index, 1);
|
|
29792
|
+
if (this.selectedRelationIndex === index) this.selectedRelationIndex = null;
|
|
29793
|
+
else if (this.selectedRelationIndex > index) this.selectedRelationIndex -= 1;
|
|
29773
29794
|
return this._commitModelChange("relation-remove", { index, relation: { ...relation } }, options);
|
|
29774
29795
|
}
|
|
29775
29796
|
get palette() {
|
|
@@ -29858,6 +29879,7 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
29858
29879
|
closeAllContainers() {
|
|
29859
29880
|
this.open.clear();
|
|
29860
29881
|
this.selected = null;
|
|
29882
|
+
this.selectedRelationIndex = null;
|
|
29861
29883
|
this._renderPanel();
|
|
29862
29884
|
this._rebuildRelations();
|
|
29863
29885
|
this.invalidate();
|
|
@@ -30027,6 +30049,7 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30027
30049
|
_build(options = {}) {
|
|
30028
30050
|
if (!this._ensureRenderer()) return;
|
|
30029
30051
|
const selectedId = options.preserveSelection || null;
|
|
30052
|
+
const selectedRelationReference = options.preserveRelation ?? null;
|
|
30030
30053
|
this._clearObjects();
|
|
30031
30054
|
for (const entity of this.modelData.entities) this.nodes.set(entity.id, { ...entity });
|
|
30032
30055
|
this.open = new Set([...this.open].filter((id) => this.nodes.has(id)));
|
|
@@ -30061,8 +30084,10 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30061
30084
|
node.group.add(node.label);
|
|
30062
30085
|
this.scene.add(node.group);
|
|
30063
30086
|
}
|
|
30064
|
-
this.selected = selectedId && this.nodes.has(selectedId) ? this.nodes.get(selectedId) : null;
|
|
30065
30087
|
this.relations = this.modelData.relations;
|
|
30088
|
+
this.selected = selectedId && this.nodes.has(selectedId) ? this.nodes.get(selectedId) : null;
|
|
30089
|
+
const selectedRelationIndex = this._relationIndex(selectedRelationReference);
|
|
30090
|
+
this.selectedRelationIndex = !this.selected && selectedRelationIndex >= 0 && selectedRelationIndex < this.relations.length ? selectedRelationIndex : null;
|
|
30066
30091
|
this._renderPanel();
|
|
30067
30092
|
this._rebuildRelations();
|
|
30068
30093
|
this.ready = true;
|
|
@@ -30097,7 +30122,9 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30097
30122
|
}
|
|
30098
30123
|
_activeRelationIndexes() {
|
|
30099
30124
|
if (this.relationMode === "all") return this.relations.map((_, index) => index);
|
|
30100
|
-
if (this.relationMode !== "selected"
|
|
30125
|
+
if (this.relationMode !== "selected") return [];
|
|
30126
|
+
if (this.selectedRelationIndex !== null) return [this.selectedRelationIndex];
|
|
30127
|
+
if (!this.selected) return [];
|
|
30101
30128
|
return this.relations.map((relation, index) => relation.from === this.selected.id || relation.to === this.selected.id ? index : -1).filter((index) => index >= 0);
|
|
30102
30129
|
}
|
|
30103
30130
|
_rebuildRelations() {
|
|
@@ -30114,8 +30141,14 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30114
30141
|
const delta = end.clone().sub(start);
|
|
30115
30142
|
if (delta.lengthSq() < 0.01) continue;
|
|
30116
30143
|
const visualMode = relationVisualMode(relation);
|
|
30144
|
+
const isSelected = index === this.selectedRelationIndex;
|
|
30145
|
+
const pickTube = new Mesh(new TubeGeometry(new LineCurve3(start, end), 10, 0.16, 6, false), new MeshBasicMaterial({ transparent: true, opacity: 0, depthWrite: false }));
|
|
30146
|
+
pickTube.userData.relationIndex = index;
|
|
30147
|
+
pickTube.userData.relationPick = true;
|
|
30148
|
+
this.relationGroup.add(pickTube);
|
|
30117
30149
|
const makeTube = (from2, to2, opacity = 0.82, tubeColor = color, tubeRadius = 0.045) => {
|
|
30118
|
-
const
|
|
30150
|
+
const displayColor = isSelected ? tubeColor.clone().lerp(new Color(16777215), 0.28) : tubeColor;
|
|
30151
|
+
const tube = new Mesh(new TubeGeometry(new LineCurve3(from2, to2), 10, isSelected ? tubeRadius * 1.45 : tubeRadius, 6, false), new MeshBasicMaterial({ color: displayColor, transparent: true, opacity: isSelected ? 1 : opacity }));
|
|
30119
30152
|
tube.userData.relationIndex = index;
|
|
30120
30153
|
this.relationGroup.add(tube);
|
|
30121
30154
|
};
|
|
@@ -30125,11 +30158,15 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30125
30158
|
// A broken communication remains a continuous red tube. Its rings
|
|
30126
30159
|
// oscillate locally around their positions instead of travelling
|
|
30127
30160
|
// along the connection, conveying a failed/retrying signal.
|
|
30128
|
-
|
|
30161
|
+
const displayBrokenColor = isSelected ? brokenColor.clone().lerp(new Color(16777215), 0.22) : brokenColor;
|
|
30162
|
+
const brokenTube = new Mesh(new TubeGeometry(new LineCurve3(start, end), 10, isSelected ? 0.08 : 0.055, 6, false), new MeshBasicMaterial({ color: displayBrokenColor, transparent: true, opacity: isSelected ? 1 : 0.88 }));
|
|
30163
|
+
brokenTube.userData.relationIndex = index;
|
|
30164
|
+
this.relationGroup.add(brokenTube);
|
|
30129
30165
|
const amplitude = Math.min(0.18, Math.max(0.07, delta.length() * 0.018));
|
|
30130
30166
|
for (let ringIndex = 0; ringIndex < 3; ringIndex++) {
|
|
30131
30167
|
const position = start.clone().lerp(end, (ringIndex + 1) / 4);
|
|
30132
|
-
const ring = new Mesh(new TorusGeometry(0.085, 0.024, 8, 20), new MeshBasicMaterial({ color:
|
|
30168
|
+
const ring = new Mesh(new TorusGeometry(isSelected ? 0.105 : 0.085, isSelected ? 0.03 : 0.024, 8, 20), new MeshBasicMaterial({ color: displayBrokenColor, transparent: true, opacity: 1 }));
|
|
30169
|
+
ring.userData.relationIndex = index;
|
|
30133
30170
|
ring.userData.phase = ringIndex / 3;
|
|
30134
30171
|
ring.userData.oscillate = true;
|
|
30135
30172
|
ring.userData.start = position.clone().addScaledVector(direction, -amplitude);
|
|
@@ -30141,7 +30178,9 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30141
30178
|
}
|
|
30142
30179
|
makeTube(start, end);
|
|
30143
30180
|
for (let ringIndex = 0; ringIndex < 4; ringIndex++) {
|
|
30144
|
-
const
|
|
30181
|
+
const displayColor = isSelected ? color.clone().lerp(new Color(16777215), 0.28) : color;
|
|
30182
|
+
const ring = new Mesh(new TorusGeometry(isSelected ? 0.088 : 0.068, isSelected ? 0.024 : 0.018, 8, 20), new MeshBasicMaterial({ color: displayColor, transparent: true, opacity: isSelected ? 1 : 0.9 }));
|
|
30183
|
+
ring.userData.relationIndex = index;
|
|
30145
30184
|
ring.userData.phase = ringIndex / 4;
|
|
30146
30185
|
ring.userData.direction = visualMode === "bidirectional" && ringIndex % 2 ? -1 : 1;
|
|
30147
30186
|
ring.userData.start = start.clone();
|
|
@@ -30154,6 +30193,16 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30154
30193
|
_renderPanel() {
|
|
30155
30194
|
if (!this.modelData) return;
|
|
30156
30195
|
const node = this.selected;
|
|
30196
|
+
const selectedRelation = this._publicRelation(this.selectedRelationIndex);
|
|
30197
|
+
if (selectedRelation) {
|
|
30198
|
+
const mode = relationVisualMode(selectedRelation);
|
|
30199
|
+
const title = selectedRelation.label || `${selectedRelation.from} \u2192 ${selectedRelation.to}`;
|
|
30200
|
+
this.panel.innerHTML = '<button class="back" data-action="overview">\u2190 Vista de conjunto</button><div class="eyebrow">RELACI\xD3N</div><h2>' + escapeHtml(title) + '</h2><div class="sub">' + escapeHtml(mode) + '</div><h3>ORIGEN</h3><button data-action="relation-endpoint" data-id="' + escapeHtml(selectedRelation.from) + '">' + escapeHtml(selectedRelation.from) + '</button><h3>DESTINO</h3><button data-action="relation-endpoint" data-id="' + escapeHtml(selectedRelation.to) + '">' + escapeHtml(selectedRelation.to) + '</button>';
|
|
30201
|
+
this.panel.querySelector('[data-action="overview"]')?.addEventListener("click", () => this.reset());
|
|
30202
|
+
this.panel.querySelectorAll('[data-action="relation-endpoint"]').forEach((button) => button.addEventListener("click", () => this.select(button.dataset.id)));
|
|
30203
|
+
this._applyTheme();
|
|
30204
|
+
return;
|
|
30205
|
+
}
|
|
30157
30206
|
if (!node) {
|
|
30158
30207
|
this.panel.innerHTML = '<div class="eyebrow">LIQUIDCARS ATLAS</div><h2>Explora el modelo.</h2><p>Selecciona un volumen para consultar su funci\xF3n y sus relaciones.</p><p class="note">El componente acepta un objeto JSON con palette, entities y relations.</p>';
|
|
30159
30208
|
this._applyTheme();
|
|
@@ -30203,13 +30252,38 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30203
30252
|
parent = parent.parent ? this.nodes.get(parent.parent) : null;
|
|
30204
30253
|
}
|
|
30205
30254
|
this.selected = node;
|
|
30255
|
+
this.selectedRelationIndex = null;
|
|
30206
30256
|
if (node.type === "shell") this.open.add(node.id);
|
|
30207
30257
|
this.targetFocus.copy(this._worldPosition(node));
|
|
30208
30258
|
this.targetZoom = node.parent ? 1.35 : 1.1;
|
|
30209
30259
|
this._renderPanel();
|
|
30210
30260
|
this._rebuildRelations();
|
|
30211
30261
|
this.invalidate();
|
|
30212
|
-
this._emit("lc-select", { id, entity: this._publicEntity(id), source: options.source || "api" });
|
|
30262
|
+
if (options.emit !== false) this._emit("lc-select", { kind: "entity", id, index: null, entity: this._publicEntity(id), relation: null, source: options.source || "api" });
|
|
30263
|
+
return this;
|
|
30264
|
+
}
|
|
30265
|
+
selectRelation(reference, options = {}) {
|
|
30266
|
+
const index = this._relationIndex(reference);
|
|
30267
|
+
const relation = this._publicRelation(index);
|
|
30268
|
+
if (!relation) return;
|
|
30269
|
+
for (const endpoint of [relation.from, relation.to]) {
|
|
30270
|
+
let node = this.nodes.get(endpoint);
|
|
30271
|
+
while (node?.parent) {
|
|
30272
|
+
this.open.add(node.parent);
|
|
30273
|
+
node = this.nodes.get(node.parent);
|
|
30274
|
+
}
|
|
30275
|
+
}
|
|
30276
|
+
this.selected = null;
|
|
30277
|
+
this.selectedRelationIndex = index;
|
|
30278
|
+
const from = this.nodes.get(relation.from);
|
|
30279
|
+
const to = this.nodes.get(relation.to);
|
|
30280
|
+
if (from && to) this.targetFocus.copy(this._worldPosition(from).add(this._worldPosition(to)).multiplyScalar(0.5));
|
|
30281
|
+
this.targetZoom = 1.22;
|
|
30282
|
+
this._renderPanel();
|
|
30283
|
+
this._rebuildRelations();
|
|
30284
|
+
this.invalidate();
|
|
30285
|
+
if (options.emit !== false) this._emit("lc-select", { kind: "relation", id: relation.id || null, index, entity: null, relation, source: options.source || "api" });
|
|
30286
|
+
return this;
|
|
30213
30287
|
}
|
|
30214
30288
|
setRelationMode(mode) {
|
|
30215
30289
|
this.relationMode = ["all", "selected", "none"].includes(mode) ? mode : "selected";
|
|
@@ -30228,7 +30302,9 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30228
30302
|
}
|
|
30229
30303
|
reset() {
|
|
30230
30304
|
const previousId = this.selected?.id || null;
|
|
30305
|
+
const previousRelation = this._publicRelation(this.selectedRelationIndex);
|
|
30231
30306
|
this.selected = null;
|
|
30307
|
+
this.selectedRelationIndex = null;
|
|
30232
30308
|
this.open.clear();
|
|
30233
30309
|
this.relationMode = "selected";
|
|
30234
30310
|
this.setAttribute("relation-mode", "selected");
|
|
@@ -30250,7 +30326,8 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30250
30326
|
this._renderPanel();
|
|
30251
30327
|
this._rebuildRelations();
|
|
30252
30328
|
this.invalidate();
|
|
30253
|
-
if (previousId) this._emit("lc-select", { id: null, entity: null, previousId, source: "reset" });
|
|
30329
|
+
if (previousId || previousRelation) this._emit("lc-select", { kind: null, id: null, index: null, entity: null, relation: null, previousId, previousRelation, source: "reset" });
|
|
30330
|
+
return this;
|
|
30254
30331
|
}
|
|
30255
30332
|
resize() {
|
|
30256
30333
|
if (!this.renderer) return;
|
|
@@ -30366,7 +30443,12 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30366
30443
|
if (!(node.type === "shell" && this.open.has(node.id))) meshes.push(node.mesh);
|
|
30367
30444
|
if (node.label?.visible) meshes.push(...node.label.children.filter((face) => face.visible));
|
|
30368
30445
|
}
|
|
30369
|
-
|
|
30446
|
+
const nodeHit = this.raycaster.intersectObjects(meshes, false)[0] || null;
|
|
30447
|
+
const relationTargets = this.relationGroup.children.filter((object) => object.userData.relationPick);
|
|
30448
|
+
const relationHit = this.raycaster.intersectObjects(relationTargets, false)[0] || null;
|
|
30449
|
+
if (nodeHit && (!relationHit || nodeHit.distance <= relationHit.distance + 0.12)) return { kind: "entity", node: nodeHit.object.userData.node };
|
|
30450
|
+
if (relationHit) return { kind: "relation", index: relationHit.object.userData.relationIndex };
|
|
30451
|
+
return nodeHit ? { kind: "entity", node: nodeHit.object.userData.node } : null;
|
|
30370
30452
|
}
|
|
30371
30453
|
_bindControls() {
|
|
30372
30454
|
this.shadowRoot.addEventListener("click", (event) => {
|
|
@@ -30403,11 +30485,17 @@ var LiquidCarsAtlas = class extends HTMLElement {
|
|
|
30403
30485
|
this.drag = null;
|
|
30404
30486
|
this.canvas.style.cursor = "grab";
|
|
30405
30487
|
if (drag && !drag.moved) {
|
|
30406
|
-
const
|
|
30407
|
-
if (
|
|
30408
|
-
|
|
30488
|
+
const picked = this._pick(event);
|
|
30489
|
+
if (picked?.kind === "entity") {
|
|
30490
|
+
const node = picked.node;
|
|
30491
|
+
if (this.selectionMode === "event") this._emit("lc-select", { kind: "entity", id: node.id, index: null, entity: this._publicEntity(node.id), relation: null, source: "pointer" });
|
|
30409
30492
|
else this.select(node.id, { source: "pointer" });
|
|
30410
30493
|
}
|
|
30494
|
+
if (picked?.kind === "relation") {
|
|
30495
|
+
const relation = this._publicRelation(picked.index);
|
|
30496
|
+
if (this.selectionMode === "event") this._emit("lc-select", { kind: "relation", id: relation?.id || null, index: picked.index, entity: null, relation, source: "pointer" });
|
|
30497
|
+
else this.selectRelation(picked.index, { source: "pointer" });
|
|
30498
|
+
}
|
|
30411
30499
|
}
|
|
30412
30500
|
this.invalidate();
|
|
30413
30501
|
});
|
package/index.html
CHANGED
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
liquidcars-atlas { display: block; width: 100%; max-width: 1480px; margin: 0 auto; }
|
|
15
15
|
code { color: #85e5d3; }
|
|
16
16
|
</style>
|
|
17
|
-
<script type="module" src="./dist/liquidcars-atlas.js?v=0.1.
|
|
17
|
+
<script type="module" src="./dist/liquidcars-atlas.js?v=0.1.21"></script>
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
20
|
<header>
|
|
21
21
|
<h1>LiquidCars Atlas</h1>
|
|
22
|
-
<p>Prueba de distribución del componente <code><liquidcars-atlas></code> · v0.1.
|
|
22
|
+
<p>Prueba de distribución del componente <code><liquidcars-atlas></code> · v0.1.21</p>
|
|
23
23
|
</header>
|
|
24
24
|
<main>
|
|
25
25
|
<liquidcars-atlas id="atlas" height="720" relation-mode="selected" shell-labels="on"></liquidcars-atlas>
|