@liquidcars/atlas 0.1.16 → 0.1.18

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 CHANGED
@@ -65,6 +65,7 @@ atlas.setTheme({
65
65
  ui: { breadcrumbs: true, panel: true, toolbar: true, hint: false }
66
66
  });
67
67
  atlas.setPalette({ channels: '#58b6ec', offers: '#48c8b0', connection: '#f4edba' });
68
+ atlas.setSelectionMode('event'); // el clic emite lc-select sin navegar internamente
68
69
 
69
70
  // El componente se puede modificar sin volver a crearlo.
70
71
  atlas.addEntity({ id: 'service', name: 'Service', geometry: 'cone', p: [4, 0, 0], s: [2, 2, 2] });
@@ -95,6 +96,12 @@ null`. Los eventos de selección y cambios de modelo son `bubbles` y
95
96
  `composed`, por lo que funcionan también al integrar el componente en otras
96
97
  capas de Web Components.
97
98
 
99
+ El comportamiento del clic se puede elegir con `selection-mode="internal"`
100
+ (por defecto) o `selection-mode="event"`. En el segundo caso el componente
101
+ emite `lc-select` con `source: "pointer"`, pero deja la decisión a la página
102
+ anfitriona. La API equivalente es `setSelectionMode()` (también disponible
103
+ como `setClickBehavior()`).
104
+
98
105
  ## Contrato de datos
99
106
 
100
107
  - `palette`: mapa de nombres de color a valores CSS/hex.
@@ -105,8 +112,8 @@ capas de Web Components.
105
112
  - `relations` acepta objetos `{from, to, label}` o la forma corta `[from, to, label]`.
106
113
  El campo visual opcional `mode` admite `directed` (por defecto),
107
114
  `bidirectional` y `broken`. En modo bidireccional los indicadores animados
108
- circulan en ambos sentidos por el mismo tubo; en modo broken el tubo aparece
109
- interrumpido en su punto medio.
115
+ circulan en ambos sentidos por el mismo tubo; en modo broken los dos tramos
116
+ aparecen en rojo, con una X y un anillo detenido en el punto de interrupción.
110
117
 
111
118
  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.
112
119
 
@@ -134,9 +141,9 @@ Una vez publicado, los consumidores podrán instalarlo con `npm install @liquidc
134
141
  Para probar el paquete sin publicarlo, basta con instalar el tarball generado:
135
142
 
136
143
  ```bash
137
- npm install ./liquidcars-atlas-0.1.15.tgz
144
+ npm install ./liquidcars-atlas-0.1.18.tgz
138
145
  ```
139
146
 
140
147
  ## Estado
141
148
 
142
- `0.1.16` mantiene la corrección del desplazamiento interno del texto y ancla las etiquetas a las dimensiones reales de las geometrías redondeadas. Además fija un margen superior absoluto para las etiquetas secundarias de contenedores abiertos, situado dentro del frontal del contenedor y sin depender de sus dimensiones. También corrige los sólidos truncados, normaliza sus dimensiones finales, refuerza la visibilidad de la toolbar con el atributo `toolbar="on"`/`"off"` y `setToolbarVisible()`, desacopla la paleta por defecto de nombres de dominio, añade actualización programática de la paleta con `setPalette`, expone las acciones de navegación para controles externos y mantiene siempre visibles las ayudas de interacción dentro del viewport. Esta versión añade edición en caliente de entidades y relaciones, eventos compuestos de selección y los modos de relación `directed`, `bidirectional` y `broken`.
149
+ `0.1.18` mantiene la corrección del desplazamiento interno del texto y ancla las etiquetas a las dimensiones reales de las geometrías redondeadas. Además fija un margen superior absoluto para las etiquetas secundarias de contenedores abiertos, situado dentro del frontal del contenedor y sin depender de sus dimensiones. También corrige los sólidos truncados, normaliza sus dimensiones finales, refuerza la visibilidad de la toolbar con el atributo `toolbar="on"`/`"off"` y `setToolbarVisible()`, desacopla la paleta por defecto de nombres de dominio, añade actualización programática de la paleta con `setPalette`, expone las acciones de navegación para controles externos y mantiene siempre visibles las ayudas de interacción dentro del viewport. Esta versión añade edición en caliente de entidades y relaciones, eventos compuestos de selección y los modos de relación `directed`, `bidirectional` y `broken`.
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.15"></script>
17
+ <script type="module" src="../dist/liquidcars-atlas.js?v=0.1.18"></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>&lt;liquidcars-atlas&gt;</code> · v0.1.15</p>
22
+ <p>Prueba de distribución del componente <code>&lt;liquidcars-atlas&gt;</code> · v0.1.18</p>
23
23
  </header>
24
24
  <main>
25
25
  <liquidcars-atlas id="atlas" height="720" relation-mode="selected" shell-labels="on"></liquidcars-atlas>
@@ -1,4 +1,4 @@
1
- /*! LiquidCars Atlas 0.1.16 | MIT */
1
+ /*! LiquidCars Atlas 0.1.18 | MIT */
2
2
 
3
3
  // src/three.core.js
4
4
  /**
@@ -29578,7 +29578,7 @@ function makeLabel(text, color, dimensions, type = "") {
29578
29578
  }
29579
29579
  var LiquidCarsAtlas = class extends HTMLElement {
29580
29580
  static get observedAttributes() {
29581
- return ["height", "relation-mode", "shell-labels", "toolbar"];
29581
+ return ["height", "relation-mode", "shell-labels", "toolbar", "selection-mode"];
29582
29582
  }
29583
29583
  constructor() {
29584
29584
  super();
@@ -29598,6 +29598,7 @@ var LiquidCarsAtlas = class extends HTMLElement {
29598
29598
  this.modelData = null;
29599
29599
  this.theme = normalizeTheme();
29600
29600
  this.relationMode = this.getAttribute("relation-mode") || "selected";
29601
+ this.selectionMode = this.getAttribute("selection-mode") || "internal";
29601
29602
  this.showShellLabels = this.getAttribute("shell-labels") !== "false";
29602
29603
  this.yaw = 0.37;
29603
29604
  this.pitch = 0.22;
@@ -29639,6 +29640,7 @@ var LiquidCarsAtlas = class extends HTMLElement {
29639
29640
  this._toolbarVisible = value !== "off";
29640
29641
  if (this.ready) this._applyTheme();
29641
29642
  }
29643
+ if (name === "selection-mode") this.selectionMode = ["internal", "event"].includes(value) ? value : "internal";
29642
29644
  }
29643
29645
  get model() {
29644
29646
  return this.modelData;
@@ -29649,6 +29651,17 @@ var LiquidCarsAtlas = class extends HTMLElement {
29649
29651
  get selectedId() {
29650
29652
  return this.selected?.id || null;
29651
29653
  }
29654
+ get clickBehavior() {
29655
+ return this.selectionMode;
29656
+ }
29657
+ setClickBehavior(value) {
29658
+ return this.setSelectionMode(value);
29659
+ }
29660
+ setSelectionMode(mode = "internal") {
29661
+ this.selectionMode = mode === "event" || mode === "external" ? "event" : "internal";
29662
+ this.setAttribute("selection-mode", this.selectionMode);
29663
+ return this;
29664
+ }
29652
29665
  _emit(type, detail = {}) {
29653
29666
  this.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true }));
29654
29667
  }
@@ -30101,17 +30114,32 @@ var LiquidCarsAtlas = class extends HTMLElement {
30101
30114
  const delta = end.clone().sub(start);
30102
30115
  if (delta.lengthSq() < 0.01) continue;
30103
30116
  const visualMode = relationVisualMode(relation);
30104
- const makeTube = (from2, to2, opacity = 0.82) => {
30105
- const tube = new Mesh(new TubeGeometry(new LineCurve3(from2, to2), 10, 0.045, 6, false), new MeshBasicMaterial({ color, transparent: true, opacity }));
30117
+ const makeTube = (from2, to2, opacity = 0.82, tubeColor = color, tubeRadius = 0.045) => {
30118
+ const tube = new Mesh(new TubeGeometry(new LineCurve3(from2, to2), 10, tubeRadius, 6, false), new MeshBasicMaterial({ color: tubeColor, transparent: true, opacity }));
30106
30119
  tube.userData.relationIndex = index;
30107
30120
  this.relationGroup.add(tube);
30108
30121
  };
30109
30122
  if (visualMode === "broken") {
30123
+ const brokenColor = new Color(0xe45b63);
30110
30124
  const direction = delta.clone().normalize();
30111
30125
  const midpoint = start.clone().lerp(end, 0.5);
30112
30126
  const gap = Math.min(delta.length() * 0.16, 0.72);
30113
- makeTube(start, midpoint.clone().sub(direction.clone().multiplyScalar(gap / 2)), 0.55);
30114
- makeTube(midpoint.clone().add(direction.clone().multiplyScalar(gap / 2)), end, 0.55);
30127
+ makeTube(start, midpoint.clone().sub(direction.clone().multiplyScalar(gap / 2)), 0.86, brokenColor, 0.055);
30128
+ makeTube(midpoint.clone().add(direction.clone().multiplyScalar(gap / 2)), end, 0.86, brokenColor, 0.055);
30129
+ // Mark the interruption with a red X in a plane perpendicular to
30130
+ // the communication line. The two arms are fixed at the midpoint,
30131
+ // making the broken state visible from every camera angle.
30132
+ const reference = Math.abs(direction.y) < 0.9 ? new Vector3(0, 1, 0) : new Vector3(1, 0, 0);
30133
+ const axisA = new Vector3().crossVectors(direction, reference).normalize();
30134
+ const axisB = new Vector3().crossVectors(direction, axisA).normalize();
30135
+ const arm = Math.min(0.52, Math.max(0.28, delta.length() * 0.07));
30136
+ makeTube(midpoint.clone().addScaledVector(axisA, -arm), midpoint.clone().addScaledVector(axisA, arm), 1, brokenColor, 0.065);
30137
+ makeTube(midpoint.clone().addScaledVector(axisB, -arm), midpoint.clone().addScaledVector(axisB, arm), 1, brokenColor, 0.065);
30138
+ const stoppedRing = new Mesh(new TorusGeometry(0.09, 0.025, 8, 20), new MeshBasicMaterial({ color: brokenColor, transparent: true, opacity: 1 }));
30139
+ stoppedRing.userData.start = midpoint.clone();
30140
+ stoppedRing.userData.end = midpoint.clone();
30141
+ stoppedRing.quaternion.setFromUnitVectors(new Vector3(0, 0, 1), direction);
30142
+ this.relationGroup.add(stoppedRing);
30115
30143
  continue;
30116
30144
  }
30117
30145
  makeTube(start, end);
@@ -30377,7 +30405,10 @@ var LiquidCarsAtlas = class extends HTMLElement {
30377
30405
  this.canvas.style.cursor = "grab";
30378
30406
  if (drag && !drag.moved) {
30379
30407
  const node = this._pick(event);
30380
- if (node) this.select(node.id, { source: "pointer" });
30408
+ if (node) {
30409
+ if (this.selectionMode === "event") this._emit("lc-select", { id: node.id, entity: this._publicEntity(node.id), source: "pointer" });
30410
+ else this.select(node.id, { source: "pointer" });
30411
+ }
30381
30412
  }
30382
30413
  this.invalidate();
30383
30414
  });
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.15"></script>
17
+ <script type="module" src="./dist/liquidcars-atlas.js?v=0.1.18"></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>&lt;liquidcars-atlas&gt;</code> · v0.1.15</p>
22
+ <p>Prueba de distribución del componente <code>&lt;liquidcars-atlas&gt;</code> · v0.1.18</p>
23
23
  </header>
24
24
  <main>
25
25
  <liquidcars-atlas id="atlas" height="720" relation-mode="selected" shell-labels="on"></liquidcars-atlas>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liquidcars/atlas",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Reusable 3D conceptual atlas Web Component for LiquidCars-style models",
5
5
  "type": "module",
6
6
  "main": "./dist/liquidcars-atlas.js",