@zumer/orbit 0.5.0 → 1.0.0

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/orbit.js CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  /*
3
3
  * orbit
4
- * v.0.5.0
4
+ * v.1.0.0
5
5
  * Author Juan Martin Muda - Zumerlab
6
6
  * License MIT
7
7
  **/
@@ -27,14 +27,14 @@
27
27
  }
28
28
  .progress-bar {
29
29
  fill: transparent;
30
- stroke: var(--o-progress-color);
30
+ stroke: var(--o-color);
31
31
  transition: stroke 0.3s;
32
32
  }
33
33
  .progress-bg {
34
- stroke: var(--o-bg-color, transparent);
34
+ stroke: var(--o-background-color, transparent);
35
35
  }
36
36
  :host(:hover) .progress-bar {
37
- stroke: var(--o-hover-progress-color, var(--o-progress-color));
37
+ stroke: var(--o-hover-color, var(--o-color));
38
38
 
39
39
  }
40
40
  </style>
@@ -57,16 +57,16 @@
57
57
  update() {
58
58
  const { shape } = this.getAttributes();
59
59
  const svg = this.shadowRoot.querySelector("svg");
60
- const defs = this.createDefs();
61
- if (shape !== "none") {
60
+ if (shape !== "none" && shape !== "circle") {
61
+ const defs = this.createDefs();
62
62
  defs.appendChild(this.createMarker("head", "end"));
63
63
  defs.appendChild(this.createMarker("tail", "start"));
64
+ svg.querySelector("defs").replaceWith(defs);
64
65
  }
65
66
  const progressBg = this.shadowRoot.querySelector(".progress-bg");
66
67
  const progressBar = this.shadowRoot.querySelector(".progress-bar");
67
68
  this.updateArc(progressBg, true);
68
69
  this.updateArc(progressBar, false);
69
- svg.querySelector("defs").replaceWith(defs);
70
70
  }
71
71
  createSVGElement() {
72
72
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
@@ -91,7 +91,9 @@
91
91
  arc.setAttribute("d", d);
92
92
  arc.setAttribute("stroke", full ? progressBgColor : progressBarColor);
93
93
  arc.setAttribute("fill", "transparent");
94
- if (shape !== "none") {
94
+ if (shape === "circle")
95
+ arc.setAttribute("stroke-linecap", "round");
96
+ if (shape !== "none" && shape !== "circle" && CSS.supports("fill", "context-stroke")) {
95
97
  arc.setAttribute("marker-end", "url(#head)");
96
98
  arc.setAttribute("marker-start", "url(#tail)");
97
99
  }
@@ -235,23 +237,30 @@
235
237
  overflow: visible;
236
238
  pointer-events: none;
237
239
  }
238
- svg * {
239
- pointer-events: stroke;
240
- }
241
- .arc {
242
- stroke: var(--o-arc-color, var(--o-cyan-light));
243
- stroke-width: calc(var(--o-radius) / var(--o-orbit-number) * var(--o-size-ratio, 1));
244
- transition: stroke 0.3s;
245
- }
246
-
247
- :host(:hover) .arc {
248
- stroke: var(--o-hover-arc-color, var(--o-arc-color));
249
-
250
- }
240
+ svg * {
241
+ pointer-events: stroke;
242
+ }
243
+ .arc {
244
+ stroke: var(--o-color, transparent);
245
+ stroke-width: calc(var(--o-radius) / var(--o-orbit-number) * var(--o-size-ratio, 1));
246
+ transition: stroke 0.3s;
247
+ }
248
+ text {
249
+ color: var(--o-text-color, currentcolor);
250
+ }
251
+ :host(:hover) text {
252
+ color: var(--o-hover-text-color, var(--o-text-color));
253
+ }
254
+ :host(:hover) .arc {
255
+ stroke: var(--o-hover-color, var(--o-color));
256
+ }
251
257
  </style>
252
258
  <svg viewBox="0 0 100 100">
253
259
  <defs></defs>
254
- <path class="arc" vector-effect="non-scaling-stroke" fill="transparent"></path>
260
+ <path id="orbitPath" class="arc" vector-effect="non-scaling-stroke" fill="transparent"></path>
261
+ <text>
262
+ <textPath href="#orbitPath" alignment-baseline="middle"></textPath>
263
+ </text>
255
264
  </svg>
256
265
  `;
257
266
  var OrbitArc = class extends HTMLElement {
@@ -262,38 +271,99 @@
262
271
  }
263
272
  connectedCallback() {
264
273
  this.update();
265
- const observer = new MutationObserver((mutations) => {
274
+ this.observer = new MutationObserver((mutations) => {
275
+ this.observer.disconnect();
266
276
  mutations.forEach((mutation) => {
267
277
  this.update();
268
278
  });
279
+ this.observer.observe(this, { attributes: true, childList: true });
269
280
  });
270
- observer.observe(this, { attributes: true, childList: true });
281
+ this.observer.observe(this, { attributes: true, childList: true });
271
282
  }
272
283
  update() {
273
- const { shape } = this.getAttributes();
274
- const svg = this.shadowRoot.querySelector("svg");
275
- const path = this.shadowRoot.querySelector("path");
284
+ const { shape, realRadius, gap, flip } = this.getAttributes();
285
+ const path = this.shadowRoot.getElementById("orbitPath");
276
286
  const defs = this.shadowRoot.querySelector("defs");
277
- if (shape !== "none") {
287
+ const text = this.shadowRoot.querySelector("text");
288
+ const textPath = this.shadowRoot.querySelector("textPath");
289
+ if (shape === "circle")
290
+ path.setAttribute("stroke-linecap", "round");
291
+ if (shape !== "none" && shape !== "circle" && CSS.supports("fill", "context-stroke")) {
278
292
  defs.innerHTML = "";
279
293
  defs.appendChild(this.createMarker("head", "end"));
280
294
  defs.appendChild(this.createMarker("tail", "start"));
281
295
  path.setAttribute("marker-end", "url(#head)");
282
296
  path.setAttribute("marker-start", "url(#tail)");
283
297
  }
284
- const { realRadius, arcColor, gap } = this.getAttributes();
298
+ const { length, fontSize, textAnchor, fitRange } = this.getTextAttributes();
285
299
  const angle = this.calculateAngle();
286
- const { d } = this.calculateArcParameters(angle, realRadius, gap);
300
+ const { d } = this.calculateArcParameters(angle, realRadius, gap, flip);
287
301
  path.setAttribute("d", d);
288
- path.setAttribute("stroke", arcColor);
302
+ if (textAnchor === "start") {
303
+ textPath.setAttribute("startOffset", "0%");
304
+ textPath.setAttribute("text-anchor", "start");
305
+ } else if (textAnchor === "middle") {
306
+ textPath.setAttribute("startOffset", "50%");
307
+ textPath.setAttribute("text-anchor", "middle");
308
+ } else if (textAnchor === "end") {
309
+ textPath.setAttribute("startOffset", "100%");
310
+ textPath.setAttribute("text-anchor", "end");
311
+ }
312
+ if (fitRange) {
313
+ textPath.parentElement.setAttribute("textLength", path.getTotalLength());
314
+ }
315
+ text.style.fontSize = `calc(${fontSize} * (100 / (${length}) * (12 / var(--o-orbit-number) ))`;
316
+ textPath.textContent = this.textContent;
317
+ }
318
+ getTextAttributes() {
319
+ const { length, fontSize, textAnchor, fitRange } = this.getAttributes();
320
+ return { length, fontSize, textAnchor, fitRange };
289
321
  }
290
322
  getAttributes() {
291
- const orbitRadius = parseFloat(getComputedStyle(this).getPropertyValue("r") || 0);
292
- const gap = parseFloat(getComputedStyle(this).getPropertyValue("--o-gap") || 1e-3);
323
+ const orbitRadius = parseFloat(
324
+ getComputedStyle(this).getPropertyValue("r") || 0
325
+ );
326
+ const gap = parseFloat(getComputedStyle(this).getPropertyValue("--o-gap")) || 1e-3;
293
327
  const shape = this.getAttribute("shape") || "none";
294
- const arcColor = this.getAttribute("arc-color");
295
- const rawAngle = getComputedStyle(this).getPropertyValue("--o-angle");
296
- const strokeWidth = parseFloat(getComputedStyle(this).getPropertyValue("stroke-width") || 1);
328
+ const flip = this.hasAttribute("flip") || this.classList.contains("flip");
329
+ const fitRange = this.hasAttribute("fit-range") || this.classList.contains("fit-range") || false;
330
+ const length = parseFloat(
331
+ getComputedStyle(this).getPropertyValue("--o-force")
332
+ );
333
+ const textAnchor = this.getAttribute("text-anchor") || "middle";
334
+ const fontSize = getComputedStyle(this).getPropertyValue("font-size") || getComputedStyle(this).getPropertyValue("--font-size");
335
+ const value = parseFloat(this.getAttribute("value"));
336
+ const range = parseFloat(
337
+ getComputedStyle(this).getPropertyValue("--o-range") || 360
338
+ );
339
+ let rawAngle;
340
+ let arcAngle;
341
+ if (value) {
342
+ arcAngle = this.getProgressAngle(range, value);
343
+ const prevElement = this.previousElementSibling;
344
+ const stackOffset = prevElement ? parseFloat(
345
+ getComputedStyle(prevElement).getPropertyValue("--o_stack")
346
+ ) : 0;
347
+ this.style.setProperty("--o_stack", stackOffset + arcAngle);
348
+ if (stackOffset >= 0 && flip) {
349
+ this.style.setProperty(
350
+ "--o-angle-composite",
351
+ parseFloat(stackOffset + arcAngle) + "deg"
352
+ );
353
+ }
354
+ if (stackOffset > 0 && !flip) {
355
+ this.style.setProperty(
356
+ "--o-angle-composite",
357
+ parseFloat(stackOffset) + "deg"
358
+ );
359
+ }
360
+ } else {
361
+ rawAngle = getComputedStyle(this).getPropertyValue("--o-angle");
362
+ arcAngle = calcularExpresionCSS(rawAngle);
363
+ }
364
+ const strokeWidth = parseFloat(
365
+ getComputedStyle(this).getPropertyValue("stroke-width") || 1
366
+ );
297
367
  const strokeWithPercentage = strokeWidth / 2 * 100 / orbitRadius / 2;
298
368
  let innerOuter = strokeWithPercentage;
299
369
  if (this.classList.contains("outer-orbit")) {
@@ -309,35 +379,58 @@
309
379
  innerOuter = strokeWithPercentage * 0.75;
310
380
  }
311
381
  const realRadius = 50 + innerOuter - strokeWithPercentage;
312
- const arcAngle = calcularExpresionCSS(rawAngle);
313
382
  return {
314
383
  orbitRadius,
315
384
  strokeWidth,
316
385
  realRadius,
317
- arcColor,
318
386
  gap,
319
387
  arcAngle,
320
- shape
388
+ shape,
389
+ length,
390
+ fontSize,
391
+ flip,
392
+ fitRange,
393
+ textAnchor
321
394
  };
322
395
  }
323
396
  calculateAngle() {
324
- const { arcAngle, gap } = this.getAttributes();
325
- return arcAngle - gap;
397
+ const { arcAngle, gap, flip } = this.getAttributes();
398
+ let calculation = flip ? arcAngle : arcAngle;
399
+ return calculation;
326
400
  }
327
- calculateArcParameters(angle, realRadius) {
401
+ getProgressAngle(maxAngle, value) {
402
+ const progress = value;
403
+ const maxValue = parseFloat(this.getAttribute("max")) || 100;
404
+ return progress / maxValue * maxAngle;
405
+ }
406
+ calculateArcParameters(angle, realRadius, gap, flip) {
328
407
  const radiusX = realRadius / 1;
329
408
  const radiusY = realRadius / 1;
330
- const startX = 50 + radiusX * Math.cos(-Math.PI / 2);
331
- const startY = 50 + radiusY * Math.sin(-Math.PI / 2);
332
- const endX = 50 + radiusX * Math.cos((angle - 90) * Math.PI / 180);
333
- const endY = 50 + radiusY * Math.sin((angle - 90) * Math.PI / 180);
334
- const largeArcFlag = angle <= 180 ? 0 : 1;
335
- const d = `M ${startX},${startY} A ${radiusX},${radiusY} 0 ${largeArcFlag} 1 ${endX},${endY}`;
336
- return { startX, startY, endX, endY, largeArcFlag, d };
409
+ let startX, startY, endX, endY, largeArcFlag, d;
410
+ let adjustedGap = gap * 0.5;
411
+ if (flip) {
412
+ startX = 50 + radiusX * Math.cos((-90 - adjustedGap) * (Math.PI / 180));
413
+ startY = 50 + radiusY * Math.sin((-90 - adjustedGap) * (Math.PI / 180));
414
+ endX = 50 + radiusX * Math.cos((270 - angle + adjustedGap) * Math.PI / 180);
415
+ endY = 50 + radiusY * Math.sin((270 - angle + adjustedGap) * Math.PI / 180);
416
+ largeArcFlag = angle <= 180 ? 0 : 1;
417
+ d = `M ${startX},${startY} A ${radiusX},${radiusY} 0 ${largeArcFlag} 0 ${endX},${endY}`;
418
+ } else {
419
+ startX = 50 + radiusX * Math.cos((-90 + adjustedGap) * (Math.PI / 180));
420
+ startY = 50 + radiusY * Math.sin((-90 + adjustedGap) * (Math.PI / 180));
421
+ endX = 50 + radiusX * Math.cos((angle - 90 - adjustedGap) * Math.PI / 180);
422
+ endY = 50 + radiusY * Math.sin((angle - 90 - adjustedGap) * Math.PI / 180);
423
+ largeArcFlag = angle <= 180 ? 0 : 1;
424
+ d = `M ${startX},${startY} A ${radiusX},${radiusY} 0 ${largeArcFlag} 1 ${endX},${endY}`;
425
+ }
426
+ return { d };
337
427
  }
338
428
  createMarker(id, position = "end") {
339
429
  const { shape } = this.getAttributes();
340
- const marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");
430
+ const marker = document.createElementNS(
431
+ "http://www.w3.org/2000/svg",
432
+ "marker"
433
+ );
341
434
  marker.setAttribute("id", id);
342
435
  marker.setAttribute("viewBox", "0 0 10 10");
343
436
  position === "start" && shape !== "circle" ? marker.setAttribute("refX", "2") : position === "start" && shape === "circle" ? marker.setAttribute("refX", "5") : marker.setAttribute("refX", "0.1");
@@ -376,174 +469,9 @@
376
469
  }
377
470
  };
378
471
  function calcularExpresionCSS(cssExpression) {
379
- const match = cssExpression.match(/calc\(\s*([\d.]+)deg\s*\/\s*\(\s*(\d+)\s*-\s*(\d+)\s*\)\s*\)/);
380
- if (match) {
381
- const value = parseFloat(match[1]);
382
- const divisor = parseInt(match[2]) - parseInt(match[3]);
383
- if (!isNaN(value) && !isNaN(divisor) && divisor !== 0) {
384
- return value / divisor;
385
- }
386
- }
387
- }
388
-
389
- // src/js/orbit-text.js
390
- var OrbitText = class extends HTMLElement {
391
- constructor() {
392
- super();
393
- this.attachShadow({ mode: "open" });
394
- const template2 = document.createElement("template");
395
- template2.innerHTML = `
396
- <svg viewBox="0 0 100 100" >
397
- <path id="orbitPath" fill="none" vector-effect="non-scaling-stroke"></path>
398
- <text>
399
- <textPath href="#orbitPath" alignment-baseline="middle"></textPath>
400
- </text>
401
- </svg>
402
- <style>
403
- :host {
404
- display: inline-block;
405
-
406
- }
407
- svg {
408
- width: 100%;
409
- height: 100%;
410
- overflow: visible;
411
- pointer-events: none;
412
-
413
- }
414
- svg * {
415
- pointer-events: stroke;
416
- }
417
-
418
- path {
419
- fill: transparent;
420
- stroke: var(--o-text-color);
421
- transition: stroke 0.3s;
422
- }
423
-
424
- :host(:hover) path {
425
- stroke: var(--o-hover-text-color, var(--o-text-color));
426
-
427
- }
428
-
429
-
430
- </style>
431
- `;
432
- this.shadowRoot.appendChild(template2.content.cloneNode(true));
433
- }
434
- connectedCallback() {
435
- this.update();
436
- const observer = new MutationObserver((mutations) => {
437
- mutations.forEach((mutation) => {
438
- this.update();
439
- });
440
- });
441
- observer.observe(this, { attributes: true, childList: true });
442
- }
443
- update() {
444
- const path = this.shadowRoot.getElementById("orbitPath");
445
- const text = this.shadowRoot.querySelector("text");
446
- const textPath = this.shadowRoot.querySelector("textPath");
447
- const { d, strokeWidth, lineCap } = this.getPathAttributes();
448
- path.setAttribute("d", d);
449
- path.setAttribute("stroke-width", strokeWidth);
450
- path.setAttribute("stroke-linecap", lineCap);
451
- const { length, fontSize, textAnchor, fitRange } = this.getTextAttributes();
452
- if (textAnchor === "start") {
453
- textPath.setAttribute("startOffset", "0%");
454
- textPath.setAttribute("text-anchor", "start");
455
- } else if (textAnchor === "middle") {
456
- textPath.setAttribute("startOffset", "50%");
457
- textPath.setAttribute("text-anchor", "middle");
458
- } else if (textAnchor === "end") {
459
- textPath.setAttribute("startOffset", "100%");
460
- textPath.setAttribute("text-anchor", "end");
461
- }
462
- if (fitRange) {
463
- textPath.parentElement.setAttribute("textLength", path.getTotalLength());
464
- }
465
- text.style.fontSize = `calc(${fontSize} * (100 / (${length}) * (12 / var(--o-orbit-number) ))`;
466
- textPath.textContent = this.textContent.trim();
467
- }
468
- getPathAttributes() {
469
- const { realRadius, gap, textBgColor, flip, lineCap, strokeWidth } = this.getAttributes();
470
- const angle = this.calculateAngle();
471
- const { d } = this.calculateArcParameters(angle, realRadius, gap, flip);
472
- return { d, strokeWidth, textBgColor, lineCap };
473
- }
474
- getTextAttributes() {
475
- const { length, fontSize, textAnchor, fitRange } = this.getAttributes();
476
- return { length, fontSize, textAnchor, fitRange };
477
- }
478
- getAttributes() {
479
- const orbitRadius = parseFloat(getComputedStyle(this).getPropertyValue("r") || 0);
480
- const flip = this.hasAttribute("flip");
481
- const fitRange = this.hasAttribute("fit-range");
482
- const lineCap = getComputedStyle(this).getPropertyValue("--o-linecap") || "butt";
483
- const gap = parseFloat(getComputedStyle(this).getPropertyValue("--o-gap") || 1e-3);
484
- const length = parseFloat(getComputedStyle(this).getPropertyValue("--o-force"));
485
- const textAnchor = this.getAttribute("text-anchor") || "middle";
486
- const fontSize = getComputedStyle(this).getPropertyValue("font-size") || getComputedStyle(this).getPropertyValue("--font-size");
487
- const rawAngle = getComputedStyle(this).getPropertyValue("--o-angle");
488
- const strokeWidth = parseFloat(getComputedStyle(this).getPropertyValue("stroke-width") || 1);
489
- let strokeWithPercentage = strokeWidth / 2 * 100 / orbitRadius / 2;
490
- let innerOuter = strokeWithPercentage;
491
- if (this.classList.contains("outer-orbit")) {
492
- innerOuter = strokeWithPercentage * 2;
493
- }
494
- if (this.classList.contains("quarter-outer-orbit")) {
495
- innerOuter = strokeWithPercentage * 1.75;
496
- }
497
- if (this.classList.contains("inner-orbit")) {
498
- innerOuter = 0;
499
- }
500
- if (this.classList.contains("quarter-inner-orbit")) {
501
- innerOuter = strokeWithPercentage * 0.75;
502
- }
503
- const realRadius = 50 + innerOuter - strokeWithPercentage;
504
- const textAngle = calcularExpresionCSS2(rawAngle);
505
- return {
506
- orbitRadius,
507
- strokeWidth,
508
- realRadius,
509
- length,
510
- fontSize,
511
- gap,
512
- textAngle,
513
- flip,
514
- textAnchor,
515
- lineCap,
516
- fitRange
517
- };
518
- }
519
- calculateAngle() {
520
- const { textAngle, gap } = this.getAttributes();
521
- return textAngle - gap;
522
- }
523
- calculateArcParameters(angle, realRadius, gap, flip) {
524
- const radiusX = realRadius / 1;
525
- const radiusY = realRadius / 1;
526
- let startX, startY, endX, endY, largeArcFlag, d;
527
- if (flip) {
528
- startX = 50 - gap + radiusX * Math.cos(-Math.PI / 2);
529
- startY = 50 + radiusY * Math.sin(-Math.PI / 2);
530
- endX = 50 + radiusX * Math.cos((270 - angle) * Math.PI / 180);
531
- endY = 50 + radiusY * Math.sin((270 - angle) * Math.PI / 180);
532
- largeArcFlag = angle <= 180 ? 0 : 1;
533
- d = `M ${startX},${startY} A ${radiusX},${radiusY} 0 ${largeArcFlag} 0 ${endX},${endY}`;
534
- } else {
535
- startX = 50 + gap + radiusX * Math.cos(-Math.PI / 2);
536
- startY = 50 + radiusY * Math.sin(-Math.PI / 2);
537
- endX = 50 + radiusX * Math.cos((angle - 90) * Math.PI / 180);
538
- endY = 50 + radiusY * Math.sin((angle - 90) * Math.PI / 180);
539
- largeArcFlag = angle <= 180 ? 0 : 1;
540
- d = `M ${startX},${startY} A ${radiusX},${radiusY} 0 ${largeArcFlag} 1 ${endX},${endY}`;
541
- }
542
- return { startX, startY, endX, endY, largeArcFlag, d };
543
- }
544
- };
545
- function calcularExpresionCSS2(cssExpression) {
546
- const match = cssExpression.match(/calc\(\s*([\d.]+)deg\s*\/\s*\(\s*(\d+)\s*-\s*(\d+)\s*\)\s*\)/);
472
+ const match = cssExpression.match(
473
+ /calc\(\s*([\d.]+)deg\s*\/\s*\(\s*(\d+)\s*-\s*(\d+)\s*\)\s*\)/
474
+ );
547
475
  if (match) {
548
476
  const value = parseFloat(match[1]);
549
477
  const divisor = parseInt(match[2]) - parseInt(match[3]);
@@ -559,17 +487,21 @@
559
487
  resize: (parentElementSelector) => {
560
488
  const parentElement = document.querySelector(parentElementSelector);
561
489
  if (!parentElement) {
562
- console.error(`No se encontr\xF3 ning\xFAn elemento con el selector ${parentElementSelector}`);
490
+ console.error(`Not found: ${parentElementSelector}`);
563
491
  return;
564
492
  }
565
493
  const resizeObserver = new ResizeObserver((entries) => {
566
494
  for (let entry of entries) {
567
495
  const { width } = entry.contentRect;
568
- const childElement = parentElement.querySelector(".gravity-spot");
569
- if (childElement) {
570
- childElement.style.setProperty("--o-force", `${width}px`);
496
+ const childElements = parentElement.querySelectorAll(".gravity-spot");
497
+ if (childElements) {
498
+ childElements.forEach((childElement) => {
499
+ let gravityForce = getComputedStyle(childElement).getPropertyValue("--o-force");
500
+ let forceRatio = width / 500;
501
+ childElement.style.setProperty("--o-force-ratio", `${forceRatio}`);
502
+ });
571
503
  } else {
572
- console.error("No se encontr\xF3 ning\xFAn elemento hijo con la clase .child-element");
504
+ console.error("No gravity-spot found");
573
505
  }
574
506
  }
575
507
  });
@@ -580,6 +512,5 @@
580
512
  // src/orbit.js
581
513
  customElements.define("o-progress", OrbitProgress);
582
514
  customElements.define("o-arc", OrbitArc);
583
- customElements.define("o-text", OrbitText);
584
515
  window.Orbit = Orbit;
585
516
  })();