@liquidcars/atlas 0.1.14 → 0.1.15

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
@@ -103,9 +103,9 @@ Una vez publicado, los consumidores podrán instalarlo con `npm install @liquidc
103
103
  Para probar el paquete sin publicarlo, basta con instalar el tarball generado:
104
104
 
105
105
  ```bash
106
- npm install ./liquidcars-atlas-0.1.14.tgz
106
+ npm install ./liquidcars-atlas-0.1.15.tgz
107
107
  ```
108
108
 
109
109
  ## Estado
110
110
 
111
- `0.1.14` 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` y expone las acciones de navegación para controles externos.
111
+ `0.1.15` 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.
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.14"></script>
17
+ <script type="module" src="../dist/liquidcars-atlas.js?v=0.1.15"></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.14</p>
22
+ <p>Prueba de distribución del componente <code>&lt;liquidcars-atlas&gt;</code> · v0.1.15</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.14 | MIT */
1
+ /*! LiquidCars Atlas 0.1.15 | MIT */
2
2
 
3
3
  // src/three.core.js
4
4
  var REVISION = "180";
@@ -221,6 +221,7 @@ var EventDispatcher = class {
221
221
  }
222
222
  };
223
223
  var _lut = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"];
224
+ var _seed = 1234567;
224
225
  var DEG2RAD = Math.PI / 180;
225
226
  var RAD2DEG = 180 / Math.PI;
226
227
  function generateUUID() {
@@ -237,9 +238,102 @@ function clamp(value, min, max) {
237
238
  function euclideanModulo(n, m) {
238
239
  return (n % m + m) % m;
239
240
  }
241
+ function mapLinear(x, a1, a2, b1, b2) {
242
+ return b1 + (x - a1) * (b2 - b1) / (a2 - a1);
243
+ }
244
+ function inverseLerp(x, y, value) {
245
+ if (x !== y) {
246
+ return (value - x) / (y - x);
247
+ } else {
248
+ return 0;
249
+ }
250
+ }
240
251
  function lerp(x, y, t) {
241
252
  return (1 - t) * x + t * y;
242
253
  }
254
+ function damp(x, y, lambda, dt) {
255
+ return lerp(x, y, 1 - Math.exp(-lambda * dt));
256
+ }
257
+ function pingpong(x, length = 1) {
258
+ return length - Math.abs(euclideanModulo(x, length * 2) - length);
259
+ }
260
+ function smoothstep(x, min, max) {
261
+ if (x <= min) return 0;
262
+ if (x >= max) return 1;
263
+ x = (x - min) / (max - min);
264
+ return x * x * (3 - 2 * x);
265
+ }
266
+ function smootherstep(x, min, max) {
267
+ if (x <= min) return 0;
268
+ if (x >= max) return 1;
269
+ x = (x - min) / (max - min);
270
+ return x * x * x * (x * (x * 6 - 15) + 10);
271
+ }
272
+ function randInt(low, high) {
273
+ return low + Math.floor(Math.random() * (high - low + 1));
274
+ }
275
+ function randFloat(low, high) {
276
+ return low + Math.random() * (high - low);
277
+ }
278
+ function randFloatSpread(range) {
279
+ return range * (0.5 - Math.random());
280
+ }
281
+ function seededRandom(s) {
282
+ if (s !== void 0) _seed = s;
283
+ let t = _seed += 1831565813;
284
+ t = Math.imul(t ^ t >>> 15, t | 1);
285
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
286
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
287
+ }
288
+ function degToRad(degrees) {
289
+ return degrees * DEG2RAD;
290
+ }
291
+ function radToDeg(radians) {
292
+ return radians * RAD2DEG;
293
+ }
294
+ function isPowerOfTwo(value) {
295
+ return (value & value - 1) === 0 && value !== 0;
296
+ }
297
+ function ceilPowerOfTwo(value) {
298
+ return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2));
299
+ }
300
+ function floorPowerOfTwo(value) {
301
+ return Math.pow(2, Math.floor(Math.log(value) / Math.LN2));
302
+ }
303
+ function setQuaternionFromProperEuler(q, a, b, c, order) {
304
+ const cos = Math.cos;
305
+ const sin = Math.sin;
306
+ const c2 = cos(b / 2);
307
+ const s2 = sin(b / 2);
308
+ const c13 = cos((a + c) / 2);
309
+ const s13 = sin((a + c) / 2);
310
+ const c1_3 = cos((a - c) / 2);
311
+ const s1_3 = sin((a - c) / 2);
312
+ const c3_1 = cos((c - a) / 2);
313
+ const s3_1 = sin((c - a) / 2);
314
+ switch (order) {
315
+ case "XYX":
316
+ q.set(c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13);
317
+ break;
318
+ case "YZY":
319
+ q.set(s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13);
320
+ break;
321
+ case "ZXZ":
322
+ q.set(s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13);
323
+ break;
324
+ case "XZX":
325
+ q.set(c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13);
326
+ break;
327
+ case "YXY":
328
+ q.set(s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13);
329
+ break;
330
+ case "ZYZ":
331
+ q.set(s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13);
332
+ break;
333
+ default:
334
+ console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: " + order);
335
+ }
336
+ }
243
337
  function denormalize(value, array) {
244
338
  switch (array.constructor) {
245
339
  case Float32Array:
@@ -280,6 +374,250 @@ function normalize(value, array) {
280
374
  throw new Error("Invalid component type.");
281
375
  }
282
376
  }
377
+ var MathUtils = {
378
+ DEG2RAD,
379
+ RAD2DEG,
380
+ /**
381
+ * Generate a [UUID]{@link https://en.wikipedia.org/wiki/Universally_unique_identifier}
382
+ * (universally unique identifier).
383
+ *
384
+ * @static
385
+ * @method
386
+ * @return {string} The UUID.
387
+ */
388
+ generateUUID,
389
+ /**
390
+ * Clamps the given value between min and max.
391
+ *
392
+ * @static
393
+ * @method
394
+ * @param {number} value - The value to clamp.
395
+ * @param {number} min - The min value.
396
+ * @param {number} max - The max value.
397
+ * @return {number} The clamped value.
398
+ */
399
+ clamp,
400
+ /**
401
+ * Computes the Euclidean modulo of the given parameters that
402
+ * is `( ( n % m ) + m ) % m`.
403
+ *
404
+ * @static
405
+ * @method
406
+ * @param {number} n - The first parameter.
407
+ * @param {number} m - The second parameter.
408
+ * @return {number} The Euclidean modulo.
409
+ */
410
+ euclideanModulo,
411
+ /**
412
+ * Performs a linear mapping from range `<a1, a2>` to range `<b1, b2>`
413
+ * for the given value.
414
+ *
415
+ * @static
416
+ * @method
417
+ * @param {number} x - The value to be mapped.
418
+ * @param {number} a1 - Minimum value for range A.
419
+ * @param {number} a2 - Maximum value for range A.
420
+ * @param {number} b1 - Minimum value for range B.
421
+ * @param {number} b2 - Maximum value for range B.
422
+ * @return {number} The mapped value.
423
+ */
424
+ mapLinear,
425
+ /**
426
+ * Returns the percentage in the closed interval `[0, 1]` of the given value
427
+ * between the start and end point.
428
+ *
429
+ * @static
430
+ * @method
431
+ * @param {number} x - The start point
432
+ * @param {number} y - The end point.
433
+ * @param {number} value - A value between start and end.
434
+ * @return {number} The interpolation factor.
435
+ */
436
+ inverseLerp,
437
+ /**
438
+ * Returns a value linearly interpolated from two known points based on the given interval -
439
+ * `t = 0` will return `x` and `t = 1` will return `y`.
440
+ *
441
+ * @static
442
+ * @method
443
+ * @param {number} x - The start point
444
+ * @param {number} y - The end point.
445
+ * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
446
+ * @return {number} The interpolated value.
447
+ */
448
+ lerp,
449
+ /**
450
+ * Smoothly interpolate a number from `x` to `y` in a spring-like manner using a delta
451
+ * time to maintain frame rate independent movement. For details, see
452
+ * [Frame rate independent damping using lerp]{@link http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/}.
453
+ *
454
+ * @static
455
+ * @method
456
+ * @param {number} x - The current point.
457
+ * @param {number} y - The target point.
458
+ * @param {number} lambda - A higher lambda value will make the movement more sudden,
459
+ * and a lower value will make the movement more gradual.
460
+ * @param {number} dt - Delta time in seconds.
461
+ * @return {number} The interpolated value.
462
+ */
463
+ damp,
464
+ /**
465
+ * Returns a value that alternates between `0` and the given `length` parameter.
466
+ *
467
+ * @static
468
+ * @method
469
+ * @param {number} x - The value to pingpong.
470
+ * @param {number} [length=1] - The positive value the function will pingpong to.
471
+ * @return {number} The alternated value.
472
+ */
473
+ pingpong,
474
+ /**
475
+ * Returns a value in the range `[0,1]` that represents the percentage that `x` has
476
+ * moved between `min` and `max`, but smoothed or slowed down the closer `x` is to
477
+ * the `min` and `max`.
478
+ *
479
+ * See [Smoothstep]{@link http://en.wikipedia.org/wiki/Smoothstep} for more details.
480
+ *
481
+ * @static
482
+ * @method
483
+ * @param {number} x - The value to evaluate based on its position between min and max.
484
+ * @param {number} min - The min value. Any x value below min will be `0`.
485
+ * @param {number} max - The max value. Any x value above max will be `1`.
486
+ * @return {number} The alternated value.
487
+ */
488
+ smoothstep,
489
+ /**
490
+ * A [variation on smoothstep]{@link https://en.wikipedia.org/wiki/Smoothstep#Variations}
491
+ * that has zero 1st and 2nd order derivatives at x=0 and x=1.
492
+ *
493
+ * @static
494
+ * @method
495
+ * @param {number} x - The value to evaluate based on its position between min and max.
496
+ * @param {number} min - The min value. Any x value below min will be `0`.
497
+ * @param {number} max - The max value. Any x value above max will be `1`.
498
+ * @return {number} The alternated value.
499
+ */
500
+ smootherstep,
501
+ /**
502
+ * Returns a random integer from `<low, high>` interval.
503
+ *
504
+ * @static
505
+ * @method
506
+ * @param {number} low - The lower value boundary.
507
+ * @param {number} high - The upper value boundary
508
+ * @return {number} A random integer.
509
+ */
510
+ randInt,
511
+ /**
512
+ * Returns a random float from `<low, high>` interval.
513
+ *
514
+ * @static
515
+ * @method
516
+ * @param {number} low - The lower value boundary.
517
+ * @param {number} high - The upper value boundary
518
+ * @return {number} A random float.
519
+ */
520
+ randFloat,
521
+ /**
522
+ * Returns a random integer from `<-range/2, range/2>` interval.
523
+ *
524
+ * @static
525
+ * @method
526
+ * @param {number} range - Defines the value range.
527
+ * @return {number} A random float.
528
+ */
529
+ randFloatSpread,
530
+ /**
531
+ * Returns a deterministic pseudo-random float in the interval `[0, 1]`.
532
+ *
533
+ * @static
534
+ * @method
535
+ * @param {number} [s] - The integer seed.
536
+ * @return {number} A random float.
537
+ */
538
+ seededRandom,
539
+ /**
540
+ * Converts degrees to radians.
541
+ *
542
+ * @static
543
+ * @method
544
+ * @param {number} degrees - A value in degrees.
545
+ * @return {number} The converted value in radians.
546
+ */
547
+ degToRad,
548
+ /**
549
+ * Converts radians to degrees.
550
+ *
551
+ * @static
552
+ * @method
553
+ * @param {number} radians - A value in radians.
554
+ * @return {number} The converted value in degrees.
555
+ */
556
+ radToDeg,
557
+ /**
558
+ * Returns `true` if the given number is a power of two.
559
+ *
560
+ * @static
561
+ * @method
562
+ * @param {number} value - The value to check.
563
+ * @return {boolean} Whether the given number is a power of two or not.
564
+ */
565
+ isPowerOfTwo,
566
+ /**
567
+ * Returns the smallest power of two that is greater than or equal to the given number.
568
+ *
569
+ * @static
570
+ * @method
571
+ * @param {number} value - The value to find a POT for.
572
+ * @return {number} The smallest power of two that is greater than or equal to the given number.
573
+ */
574
+ ceilPowerOfTwo,
575
+ /**
576
+ * Returns the largest power of two that is less than or equal to the given number.
577
+ *
578
+ * @static
579
+ * @method
580
+ * @param {number} value - The value to find a POT for.
581
+ * @return {number} The largest power of two that is less than or equal to the given number.
582
+ */
583
+ floorPowerOfTwo,
584
+ /**
585
+ * Sets the given quaternion from the [Intrinsic Proper Euler Angles]{@link https://en.wikipedia.org/wiki/Euler_angles}
586
+ * defined by the given angles and order.
587
+ *
588
+ * Rotations are applied to the axes in the order specified by order:
589
+ * rotation by angle `a` is applied first, then by angle `b`, then by angle `c`.
590
+ *
591
+ * @static
592
+ * @method
593
+ * @param {Quaternion} q - The quaternion to set.
594
+ * @param {number} a - The rotation applied to the first axis, in radians.
595
+ * @param {number} b - The rotation applied to the second axis, in radians.
596
+ * @param {number} c - The rotation applied to the third axis, in radians.
597
+ * @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - A string specifying the axes order.
598
+ */
599
+ setQuaternionFromProperEuler,
600
+ /**
601
+ * Normalizes the given value according to the given typed array.
602
+ *
603
+ * @static
604
+ * @method
605
+ * @param {number} value - The float value in the range `[0,1]` to normalize.
606
+ * @param {TypedArray} array - The typed array that defines the data type of the value.
607
+ * @return {number} The normalize value.
608
+ */
609
+ normalize,
610
+ /**
611
+ * Denormalizes the given value according to the given typed array.
612
+ *
613
+ * @static
614
+ * @method
615
+ * @param {number} value - The value to denormalize.
616
+ * @param {TypedArray} array - The typed array that defines the data type of the value.
617
+ * @return {number} The denormalize (float) value in the range `[0,1]`.
618
+ */
619
+ denormalize
620
+ };
283
621
  var Vector2 = class _Vector2 {
284
622
  /**
285
623
  * Constructs a new 2D vector.
@@ -29021,7 +29359,7 @@ function normalizeTheme(value) {
29021
29359
  }
29022
29360
  var CSS = [
29023
29361
  ":host{display:block;position:relative;height:var(--lc-height,680px);min-height:420px;color:var(--lc-panel-title,#e9f0f5);font:14px Inter,system-ui,-apple-system,sans-serif;background:var(--lc-bg,#0a111a);border:1px solid #294252;border-radius:12px;overflow:hidden;contain:content}",
29024
- "*{box-sizing:border-box}.atlas{display:grid;grid-template-columns:minmax(0,1fr) 300px;height:100%}.atlas[data-panel=hidden]{grid-template-columns:1fr}.viewport{position:relative;min-width:0;background:radial-gradient(ellipse at 50% 45%,var(--lc-bg-glow,#1c2b39),var(--lc-bg-fade,#0a111a) 82%)}canvas{display:block;width:100%;height:100%;cursor:grab;touch-action:none}.toolbar{position:absolute;z-index:10;bottom:16px;left:50%;transform:translateX(-50%);display:flex;gap:3px;padding:6px;background:var(--lc-toolbar-bg,#15232fe8);border:1px solid var(--lc-toolbar-border,#3a5062);border-radius:8px;white-space:nowrap}.toolbar[data-hidden=true],.toolbar[hidden],.panel[data-hidden=true],.panel[hidden],.crumbs[data-hidden=true],.crumbs[hidden],.hint[data-hidden=true],.hint[hidden]{display:none!important}.toolbar button{height:30px;padding:0 9px;border:0;border-radius:5px;background:none;color:var(--lc-toolbar-text,#dbe7ec);cursor:pointer}.toolbar button:hover,.toolbar button.active{background:var(--lc-toolbar-active,#1f3d4b);color:var(--lc-toolbar-active-text,#c5f2e9)}.toolbar i{display:block;width:1px;margin:2px 3px;background:#38515f}.hint{position:absolute;bottom:5px;left:0;right:0;text-align:center;font-size:11px;color:var(--lc-hint,#8da6b8);pointer-events:none}.panel{overflow:auto;padding:24px 20px;background:var(--lc-panel-bg,linear-gradient(140deg,#182633,#0e1925 65%));border-left:1px solid var(--lc-panel-border,#2a3a48)}.panel h2{font-size:26px;line-height:1.12;font-weight:470;margin:12px 0;color:var(--lc-panel-title,#e9f0f5)}.panel h3{font-size:11px;letter-spacing:1.4px;color:#91aabd;margin:24px 0 10px}.panel p{font-size:14px;line-height:1.55;color:var(--lc-panel-text,#b5c6d2)}.panel .eyebrow{font-size:11px;letter-spacing:1.7px;color:#6ad7c0}.panel .sub{font-size:13px;color:#8fa8bd;margin-bottom:16px}.panel button{display:block;width:100%;padding:10px 0;text-align:left;background:none;border:0;border-bottom:1px solid var(--lc-panel-border,#2a3a48);color:#d9e7eb;cursor:pointer}.panel button:hover{color:#6ad7c0}.panel .relation{padding:10px 0;border-bottom:1px solid var(--lc-panel-border,#2a3a48)}.panel .relation strong{display:block;font-weight:550}.panel .relation small{display:block;color:#86a6b9;font-size:12px;margin-top:4px}.panel .back{color:#9db7c8;font-size:13px}.panel .crumbs{display:flex;flex-wrap:wrap;gap:5px;align-items:center;margin:0 0 12px}.panel .crumbs button{display:inline;width:auto;padding:3px 7px;border:0;border-radius:4px;background:var(--lc-crumb-bg,#142733);color:var(--lc-crumb-text,#91b6c7);font-size:12px}.panel .crumbs button.current{background:var(--lc-crumb-active,#1c4a4d);color:var(--lc-crumb-active-text,#c5f2e9)}.panel .note{border-top:1px solid var(--lc-panel-border,#2a3a48);padding-top:16px;margin-top:22px;font-size:12px;color:#7692a6}.error{position:absolute;inset:20%;padding:18px;background:#172b3b;border:1px solid #7896a9;line-height:1.5;z-index:4}@media(max-width:900px){.toolbar{gap:0}.toolbar button{padding:0 6px;font-size:12px}}@media(max-width:760px){:host{height:680px}.atlas{grid-template-columns:1fr;grid-template-rows:minmax(420px,1fr) auto}.panel{max-height:250px;border-left:0;border-top:1px solid var(--lc-panel-border,#2a3a48);padding:18px}.toolbar{bottom:10px}.hint{display:none}}"
29362
+ "*{box-sizing:border-box}.atlas{display:grid;grid-template-columns:minmax(0,1fr) 300px;height:100%}.atlas[data-panel=hidden]{grid-template-columns:1fr}.viewport{position:relative;min-width:0;overflow:hidden;background:radial-gradient(ellipse at 50% 45%,var(--lc-bg-glow,#1c2b39),var(--lc-bg-fade,#0a111a) 82%)}canvas{display:block;width:100%;height:100%;cursor:grab;touch-action:none}.toolbar{position:absolute;z-index:10;bottom:28px;left:50%;transform:translateX(-50%);display:flex;gap:3px;padding:6px;background:var(--lc-toolbar-bg,#15232fe8);border:1px solid var(--lc-toolbar-border,#3a5062);border-radius:8px;white-space:nowrap}.toolbar[data-hidden=true],.toolbar[hidden],.panel[data-hidden=true],.panel[hidden],.crumbs[data-hidden=true],.crumbs[hidden],.hint[data-hidden=true],.hint[hidden]{display:none!important}.toolbar button{height:30px;padding:0 9px;border:0;border-radius:5px;background:none;color:var(--lc-toolbar-text,#dbe7ec);cursor:pointer}.toolbar button:hover,.toolbar button.active{background:var(--lc-toolbar-active,#1f3d4b);color:var(--lc-toolbar-active-text,#c5f2e9)}.toolbar i{display:block;width:1px;margin:2px 3px;background:#38515f}.hint{position:absolute;z-index:9;top:8px;bottom:auto;left:0;right:0;text-align:center;padding:2px 8px;font-size:11px;line-height:16px;color:var(--lc-hint,#8da6b8);pointer-events:none}.panel{overflow:auto;padding:24px 20px;background:var(--lc-panel-bg,linear-gradient(140deg,#182633,#0e1925 65%));border-left:1px solid var(--lc-panel-border,#2a3a48)}.panel h2{font-size:26px;line-height:1.12;font-weight:470;margin:12px 0;color:var(--lc-panel-title,#e9f0f5)}.panel h3{font-size:11px;letter-spacing:1.4px;color:#91aabd;margin:24px 0 10px}.panel p{font-size:14px;line-height:1.55;color:var(--lc-panel-text,#b5c6d2)}.panel .eyebrow{font-size:11px;letter-spacing:1.7px;color:#6ad7c0}.panel .sub{font-size:13px;color:#8fa8bd;margin-bottom:16px}.panel button{display:block;width:100%;padding:10px 0;text-align:left;background:none;border:0;border-bottom:1px solid var(--lc-panel-border,#2a3a48);color:#d9e7eb;cursor:pointer}.panel button:hover{color:#6ad7c0}.panel .relation{padding:10px 0;border-bottom:1px solid var(--lc-panel-border,#2a3a48)}.panel .relation strong{display:block;font-weight:550}.panel .relation small{display:block;color:#86a6b9;font-size:12px;margin-top:4px}.panel .back{color:#9db7c8;font-size:13px}.panel .crumbs{display:flex;flex-wrap:wrap;gap:5px;align-items:center;margin:0 0 12px}.panel .crumbs button{display:inline;width:auto;padding:3px 7px;border:0;border-radius:4px;background:var(--lc-crumb-bg,#142733);color:var(--lc-crumb-text,#91b6c7);font-size:12px}.panel .crumbs button.current{background:var(--lc-crumb-active,#1c4a4d);color:var(--lc-crumb-active-text,#c5f2e9)}.panel .note{border-top:1px solid var(--lc-panel-border,#2a3a48);padding-top:16px;margin-top:22px;font-size:12px;color:#7692a6}.error{position:absolute;inset:20%;padding:18px;background:#172b3b;border:1px solid #7896a9;line-height:1.5;z-index:4}@media(max-width:900px){.toolbar{gap:0}.toolbar button{padding:0 6px;font-size:12px}}@media(max-width:760px){:host{height:680px}.atlas{grid-template-columns:1fr;grid-template-rows:minmax(420px,1fr) auto}.panel{max-height:250px;border-left:0;border-top:1px solid var(--lc-panel-border,#2a3a48);padding:18px}.toolbar{bottom:24px}.hint{top:8px;bottom:auto;display:block}}"
29025
29363
  ].join("");
29026
29364
  var TEMPLATE = '<div class="atlas"><section class="viewport"><canvas tabindex="0" aria-label="Modelo 3D interactivo"></canvas><div class="toolbar"><button data-action="minus" aria-label="Alejar">\u2212</button><button data-action="plus" aria-label="Acercar">+</button><i></i><button data-action="fit">\u2316 Encuadrar</button><button data-action="front">\u25B1 Frontal</button><button data-action="labels" class="active" aria-pressed="true">\u25A7 Etiquetas</button><i></i><button data-action="relations-all" aria-pressed="false">Todas</button><button data-action="relations-selected" class="active" aria-pressed="true">Selecci\xF3n</button><button data-action="relations-none" aria-pressed="false">Ocultar</button></div><div class="hint">Arrastra para girar \xB7 rueda para zoom \xB7 clic para seleccionar</div></section><aside class="panel" aria-live="polite"></aside></div>';
29027
29365
  function escapeHtml(value) {
@@ -29329,8 +29667,21 @@ var LiquidCarsAtlas = class extends HTMLElement {
29329
29667
  return this;
29330
29668
  }
29331
29669
  fit() {
29332
- this.targetZoom = 1;
29333
- this.targetFocus.set(0, 0, 0);
29670
+ const bounds = new Box3();
29671
+ for (const node of this.nodes.values()) {
29672
+ const center2 = this._worldPosition(node);
29673
+ const half = new Vector3(node.s[0] / 2, node.s[1] / 2, node.s[2] / 2);
29674
+ bounds.expandByPoint(center2.clone().sub(half));
29675
+ bounds.expandByPoint(center2.clone().add(half));
29676
+ }
29677
+ const center = bounds.isEmpty() ? new Vector3() : bounds.getCenter(new Vector3());
29678
+ const size = bounds.isEmpty() ? new Vector3(1, 1, 1) : bounds.getSize(new Vector3());
29679
+ const radius = Math.max(1, size.length() / 2);
29680
+ const fov2 = MathUtils.degToRad(this.camera.fov);
29681
+ const requiredDistance = radius / Math.sin(fov2 / 2) * 1.12;
29682
+ const baseDistance = Math.max(29, 39.5 / Math.max(this.camera.aspect, 0.5));
29683
+ this.targetZoom = Math.max(0.55, Math.min(2.8, baseDistance / requiredDistance));
29684
+ this.targetFocus.copy(center);
29334
29685
  this.invalidate();
29335
29686
  return this;
29336
29687
  }
@@ -29712,6 +30063,7 @@ var LiquidCarsAtlas = class extends HTMLElement {
29712
30063
  this.targetZoom = 1;
29713
30064
  this.focus.set(0, 0, 0);
29714
30065
  this.targetFocus.set(0, 0, 0);
30066
+ this.fit();
29715
30067
  this._renderPanel();
29716
30068
  this._rebuildRelations();
29717
30069
  this.invalidate();
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.14"></script>
17
+ <script type="module" src="./dist/liquidcars-atlas.js?v=0.1.15"></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.14</p>
22
+ <p>Prueba de distribución del componente <code>&lt;liquidcars-atlas&gt;</code> · v0.1.15</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.14",
3
+ "version": "0.1.15",
4
4
  "description": "Reusable 3D conceptual atlas Web Component for LiquidCars-style models",
5
5
  "type": "module",
6
6
  "main": "./dist/liquidcars-atlas.js",