diff --git a/README.md b/README.md index 6ccb2431..5208f89f 100644 --- a/README.md +++ b/README.md @@ -227,13 +227,13 @@ The curly brackets are made with SVG paths, and it is required to have the follo ```html diff --git a/speccer.css b/speccer.css index e38320b4..4d26d778 100644 --- a/speccer.css +++ b/speccer.css @@ -1,4 +1,4 @@ -.ph.speccer { +.ph-speccer.speccer { --ph-speccer-color-padding: rgba(219,111,255,0.4); --ph-speccer-color-padding-hover: #db6fff; --ph-speccer-color-margin: rgba(255,247,111,0.4); @@ -25,17 +25,17 @@ --ph-speccer-line-width-negative: -1px; --ph-speccer-measure-size: 8px; } -svg.ph, -.ph.speccer, -.ph.speccer::after, -.ph.speccer::before { +svg.ph-speccer, +.ph-speccer.speccer, +.ph-speccer.speccer::after, +.ph-speccer.speccer::before { pointer-events: none; user-select: none; box-sizing: border-box; } -.ph.speccer:not(path), -.ph.speccer::after, -.ph.speccer::before { +.ph-speccer.speccer:not(path), +.ph-speccer.speccer::after, +.ph-speccer.speccer::before { font-family: var(--ph-speccer-font-family) !important; justify-content: center; align-items: center; @@ -54,10 +54,10 @@ svg.ph, pointer-events: none; z-index: 3; } -svg.ph .ph.path { +svg.ph-speccer .ph-speccer.path { color: var(--ph-speccer-color-contrast, #ff3aa8); } -.ph.speccer.dissection { +.ph-speccer.speccer.dissection { font-family: sans-serif; height: var(--ph-speccer-pin-size); width: var(--ph-speccer-pin-size); @@ -73,7 +73,7 @@ svg.ph .ph.path { font-size: 16px; z-index: 100000; } -.ph.speccer.dissection::after { +.ph-speccer.speccer.dissection::after { content: ""; position: absolute; height: var(--ph-speccer-pin-space); @@ -82,38 +82,38 @@ svg.ph .ph.path { background-color: var(--ph-speccer-pin-color); z-index: 99999; } -.ph.speccer.dissection.svg::after, -.ph.speccer.dissection.curly::after { +.ph-speccer.speccer.dissection.svg::after, +.ph-speccer.speccer.dissection.curly::after { content: none !important; } -.ph.speccer.dissection.outline::after, -.ph.speccer.dissection.outline.top::after { +.ph-speccer.speccer.dissection.outline::after, +.ph-speccer.speccer.dissection.outline.top::after { height: var(--ph-speccer-pin-space); width: var(--ph-speccer-line-width); top: 100%; right: 50%; } -.ph.speccer.dissection.outline.left::after { +.ph-speccer.speccer.dissection.outline.left::after { height: var(--ph-speccer-line-width); width: var(--ph-speccer-pin-space); top: 50%; left: 100%; right: auto; } -.ph.speccer.dissection.outline.right::after { +.ph-speccer.speccer.dissection.outline.right::after { height: var(--ph-speccer-line-width); width: var(--ph-speccer-pin-space); top: 50%; left: auto; right: 100%; } -.ph.speccer.dissection.outline.bottom::after { +.ph-speccer.speccer.dissection.outline.bottom::after { height: var(--ph-speccer-pin-space); width: var(--ph-speccer-line-width); top: calc(-100% - (var(--ph-speccer-pin-space) / 2)); right: 50%; } -.ph.speccer.dissection::after { +.ph-speccer.speccer.dissection::after { content: ""; position: absolute; height: var(--ph-speccer-pin-space); @@ -122,127 +122,127 @@ svg.ph .ph.path { background-color: var(--ph-speccer-pin-color); z-index: 99999; } -.ph.speccer.dissection.outline.left::after { +.ph-speccer.speccer.dissection.outline.left::after { height: var(--ph-speccer-line-width); width: var(--ph-speccer-pin-space); top: 50%; left: 100%; } -.ph.speccer.dissection.outline.right::after { +.ph-speccer.speccer.dissection.outline.right::after { height: var(--ph-speccer-line-width); width: var(--ph-speccer-pin-space); top: 50%; right: 100%; } -.ph.speccer.dissection.outline.enclose { +.ph-speccer.speccer.dissection.outline.enclose { border-radius: 0; background-color: transparent; color: var(--ph-speccer-measure-color); border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); } -.ph.speccer.dissection.outline.enclose::after { +.ph-speccer.speccer.dissection.outline.enclose::after { top: calc(var(--ph-speccer-line-width-negative) - var(--ph-speccer-pin-size) - var(--ph-speccer-pin-space)); bottom: auto; } -.ph.speccer.dissection.outline.enclose::before { +.ph-speccer.speccer.dissection.outline.enclose::before { bottom: 100%; top: auto; } -.ph.speccer.dissection.outline.enclose.right::after { +.ph-speccer.speccer.dissection.outline.enclose.right::after { left: calc(100% + calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width))); right: auto; } -.ph.speccer.dissection.outline.enclose.right::before { +.ph-speccer.speccer.dissection.outline.enclose.right::before { left: 100%; right: auto; } -.ph.speccer.dissection.outline.enclose.left::after { +.ph-speccer.speccer.dissection.outline.enclose.left::after { left: calc(var(--ph-speccer-line-width-negative) - var(--ph-speccer-pin-size) - var(--ph-speccer-pin-space)); right: auto; } -.ph.speccer.dissection.outline.enclose.left::before { +.ph-speccer.speccer.dissection.outline.enclose.left::before { right: 100%; left: auto; } -.ph.speccer.dissection.outline.enclose.top::after { +.ph-speccer.speccer.dissection.outline.enclose.top::after { top: calc(var(--ph-speccer-line-width-negative) - var(--ph-speccer-pin-size) - var(--ph-speccer-pin-space)); bottom: auto; } -.ph.speccer.dissection.outline.enclose.top::before { +.ph-speccer.speccer.dissection.outline.enclose.top::before { bottom: 100%; top: auto; } -.ph.speccer.dissection.outline.enclose.bottom::after { +.ph-speccer.speccer.dissection.outline.enclose.bottom::after { top: calc(100% + calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width))); bottom: auto; } -.ph.speccer.dissection.outline.enclose.bottom::before { +.ph-speccer.speccer.dissection.outline.enclose.bottom::before { top: 100%; bottom: auto; } -.ph.speccer.dissection.outline.full:not(.curly) { +.ph-speccer.speccer.dissection.outline.full:not(.curly) { border-radius: 0; background-color: transparent; color: var(--ph-speccer-measure-color); border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); border-bottom: none; } -.ph.speccer.dissection.outline.full:not(.curly)::after { +.ph-speccer.speccer.dissection.outline.full:not(.curly)::after { top: calc(-8px - var(--ph-speccer-pin-space)); } -.ph.speccer.dissection.outline.full:not(.curly)::before { +.ph-speccer.speccer.dissection.outline.full:not(.curly)::before { bottom: 100%; } -.ph.speccer.dissection.outline.full:not(.curly).right { +.ph-speccer.speccer.dissection.outline.full:not(.curly).right { border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); border-left: none; } -.ph.speccer.dissection.outline.full:not(.curly).right::after { +.ph-speccer.speccer.dissection.outline.full:not(.curly).right::after { left: calc(8px + var(--ph-speccer-pin-space)); } -.ph.speccer.dissection.outline.full:not(.curly).right::before { +.ph-speccer.speccer.dissection.outline.full:not(.curly).right::before { left: 100%; right: auto; } -.ph.speccer.dissection.outline.full:not(.curly).left { +.ph-speccer.speccer.dissection.outline.full:not(.curly).left { border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); border-right: none; } -.ph.speccer.dissection.outline.full:not(.curly).left::after { +.ph-speccer.speccer.dissection.outline.full:not(.curly).left::after { left: calc(-8px - var(--ph-speccer-pin-space)); } -.ph.speccer.dissection.outline.full:not(.curly).left::before { +.ph-speccer.speccer.dissection.outline.full:not(.curly).left::before { right: 100%; left: auto; } -.ph.speccer.dissection.outline.full:not(.curly).top { +.ph-speccer.speccer.dissection.outline.full:not(.curly).top { border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); border-bottom: none; } -.ph.speccer.dissection.outline.full:not(.curly).top::after { +.ph-speccer.speccer.dissection.outline.full:not(.curly).top::after { top: calc(-8px - var(--ph-speccer-pin-space)); } -.ph.speccer.dissection.outline.full:not(.curly).top::before { +.ph-speccer.speccer.dissection.outline.full:not(.curly).top::before { bottom: 100%; } -.ph.speccer.dissection.outline.full:not(.curly).bottom { +.ph-speccer.speccer.dissection.outline.full:not(.curly).bottom { border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); border-top: none; } -.ph.speccer.dissection.outline.full:not(.curly).bottom::after { +.ph-speccer.speccer.dissection.outline.full:not(.curly).bottom::after { top: calc(8px + var(--ph-speccer-pin-space)); } -.ph.speccer.dissection.outline.full:not(.curly).bottom::before { +.ph-speccer.speccer.dissection.outline.full:not(.curly).bottom::before { top: 100%; } -.ph.speccer.dissection.outline.bottom::after { +.ph-speccer.speccer.dissection.outline.bottom::after { height: var(--ph-speccer-pin-space); width: var(--ph-speccer-line-width); top: calc(-100% - (var(--ph-speccer-pin-space) / 2)); right: 50%; } -.ph.speccer.dissection.outline.top::after, -.ph.speccer.dissection.outline::after { +.ph-speccer.speccer.dissection.outline.top::after, +.ph-speccer.speccer.dissection.outline::after { height: var(--ph-speccer-pin-space); width: var(--ph-speccer-line-width); top: 100%; @@ -251,20 +251,20 @@ svg.ph .ph.path { [data-anatomy-section] { counter-reset: type; } -.ph.speccer.dissection.outline.full.right:not(.curly), -.ph.speccer.dissection.outline.full.left:not(.curly) { +.ph-speccer.speccer.dissection.outline.full.right:not(.curly), +.ph-speccer.speccer.dissection.outline.full.left:not(.curly) { width: 8px; } -.ph.speccer.dissection.outline.full:not(.curly), -.ph.speccer.dissection.outline.full.top:not(.curly), -.ph.speccer.dissection.outline.full.bottom:not(.curly) { +.ph-speccer.speccer.dissection.outline.full:not(.curly), +.ph-speccer.speccer.dissection.outline.full.top:not(.curly), +.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly) { height: 8px; } -.ph.speccer.dissection.outline.full:not(.curly)::after, -.ph.speccer.dissection.outline.full.right:not(.curly)::after, -.ph.speccer.dissection.outline.full.left:not(.curly)::after, -.ph.speccer.dissection.outline.full.top:not(.curly)::after, -.ph.speccer.dissection.outline.full.bottom:not(.curly)::after { +.ph-speccer.speccer.dissection.outline.full:not(.curly)::after, +.ph-speccer.speccer.dissection.outline.full.right:not(.curly)::after, +.ph-speccer.speccer.dissection.outline.full.left:not(.curly)::after, +.ph-speccer.speccer.dissection.outline.full.top:not(.curly)::after, +.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly)::after { content: attr(data-dissection-counter); height: var(--ph-speccer-pin-size); width: var(--ph-speccer-pin-size); @@ -279,57 +279,57 @@ svg.ph .ph.path { font-size: 16px; z-index: 100000; } -.ph.speccer.dissection.outline.full.right:not(.curly)::after, -.ph.speccer.dissection.outline.full.left:not(.curly)::after { +.ph-speccer.speccer.dissection.outline.full.right:not(.curly)::after, +.ph-speccer.speccer.dissection.outline.full.left:not(.curly)::after { top: 50%; transform: translateY(-50%); } -.ph.speccer.dissection.outline.full:not(.curly)::after, -.ph.speccer.dissection.outline.full.top:not(.curly)::after, -.ph.speccer.dissection.outline.full.bottom:not(.curly)::after { +.ph-speccer.speccer.dissection.outline.full:not(.curly)::after, +.ph-speccer.speccer.dissection.outline.full.top:not(.curly)::after, +.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly)::after { left: 50%; transform: translateX(-50%); } -.ph.speccer.dissection.outline.full:not(.curly)::before, -.ph.speccer.dissection.outline.full.right:not(.curly)::before, -.ph.speccer.dissection.outline.full.left:not(.curly)::before, -.ph.speccer.dissection.outline.full.top:not(.curly)::before, -.ph.speccer.dissection.outline.full.bottom:not(.curly)::before { +.ph-speccer.speccer.dissection.outline.full:not(.curly)::before, +.ph-speccer.speccer.dissection.outline.full.right:not(.curly)::before, +.ph-speccer.speccer.dissection.outline.full.left:not(.curly)::before, +.ph-speccer.speccer.dissection.outline.full.top:not(.curly)::before, +.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly)::before { content: ""; position: absolute; background-color: var(--ph-speccer-pin-color); z-index: 100000; display: block; } -.ph.speccer.dissection.outline.full.right:not(.curly)::before, -.ph.speccer.dissection.outline.full.left:not(.curly)::before { +.ph-speccer.speccer.dissection.outline.full.right:not(.curly)::before, +.ph-speccer.speccer.dissection.outline.full.left:not(.curly)::before { top: 50%; transform: translateY(-50%); height: var(--ph-speccer-line-width); width: calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width)); } -.ph.speccer.dissection.outline.full:not(.curly)::before, -.ph.speccer.dissection.outline.full.top:not(.curly)::before, -.ph.speccer.dissection.outline.full.bottom:not(.curly)::before { +.ph-speccer.speccer.dissection.outline.full:not(.curly)::before, +.ph-speccer.speccer.dissection.outline.full.top:not(.curly)::before, +.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly)::before { left: 50%; transform: translateX(-50%); width: var(--ph-speccer-line-width); height: calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width)); } -.ph.speccer.dissection.outline.enclose.right, -.ph.speccer.dissection.outline.enclose.left { +.ph-speccer.speccer.dissection.outline.enclose.right, +.ph-speccer.speccer.dissection.outline.enclose.left { width: 8px; } -.ph.speccer.dissection.outline.enclose, -.ph.speccer.dissection.outline.enclose.top, -.ph.speccer.dissection.outline.enclose.bottom { +.ph-speccer.speccer.dissection.outline.enclose, +.ph-speccer.speccer.dissection.outline.enclose.top, +.ph-speccer.speccer.dissection.outline.enclose.bottom { height: 8px; } -.ph.speccer.dissection.outline.enclose::after, -.ph.speccer.dissection.outline.enclose.right::after, -.ph.speccer.dissection.outline.enclose.left::after, -.ph.speccer.dissection.outline.enclose.top::after, -.ph.speccer.dissection.outline.enclose.bottom::after { +.ph-speccer.speccer.dissection.outline.enclose::after, +.ph-speccer.speccer.dissection.outline.enclose.right::after, +.ph-speccer.speccer.dissection.outline.enclose.left::after, +.ph-speccer.speccer.dissection.outline.enclose.top::after, +.ph-speccer.speccer.dissection.outline.enclose.bottom::after { content: attr(data-dissection-counter); height: var(--ph-speccer-pin-size); width: var(--ph-speccer-pin-size); @@ -344,140 +344,140 @@ svg.ph .ph.path { font-size: 16px; z-index: 100000; } -.ph.speccer.dissection.outline.enclose.right::after, -.ph.speccer.dissection.outline.enclose.left::after { +.ph-speccer.speccer.dissection.outline.enclose.right::after, +.ph-speccer.speccer.dissection.outline.enclose.left::after { top: 50%; transform: translateY(-50%); } -.ph.speccer.dissection.outline.enclose::after, -.ph.speccer.dissection.outline.enclose.top::after, -.ph.speccer.dissection.outline.enclose.bottom::after { +.ph-speccer.speccer.dissection.outline.enclose::after, +.ph-speccer.speccer.dissection.outline.enclose.top::after, +.ph-speccer.speccer.dissection.outline.enclose.bottom::after { left: 50%; transform: translateX(-50%); } -.ph.speccer.dissection.outline.enclose::before, -.ph.speccer.dissection.outline.enclose.right::before, -.ph.speccer.dissection.outline.enclose.left::before, -.ph.speccer.dissection.outline.enclose.top::before, -.ph.speccer.dissection.outline.enclose.bottom::before { +.ph-speccer.speccer.dissection.outline.enclose::before, +.ph-speccer.speccer.dissection.outline.enclose.right::before, +.ph-speccer.speccer.dissection.outline.enclose.left::before, +.ph-speccer.speccer.dissection.outline.enclose.top::before, +.ph-speccer.speccer.dissection.outline.enclose.bottom::before { content: ""; position: absolute; background-color: var(--ph-speccer-pin-color); z-index: 100000; display: block; } -.ph.speccer.dissection.outline.enclose.right::before, -.ph.speccer.dissection.outline.enclose.left::before { +.ph-speccer.speccer.dissection.outline.enclose.right::before, +.ph-speccer.speccer.dissection.outline.enclose.left::before { top: 50%; transform: translateY(-50%); height: var(--ph-speccer-line-width); width: calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width)); } -.ph.speccer.dissection.outline.enclose::before, -.ph.speccer.dissection.outline.enclose.top::before, -.ph.speccer.dissection.outline.enclose.bottom::before { +.ph-speccer.speccer.dissection.outline.enclose::before, +.ph-speccer.speccer.dissection.outline.enclose.top::before, +.ph-speccer.speccer.dissection.outline.enclose.bottom::before { left: 50%; transform: translateX(-50%); width: var(--ph-speccer-line-width); height: calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width)); } -.ph.speccer.dissection.outline.subtle { +.ph-speccer.speccer.dissection.outline.subtle { border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); background-color: var(--ph-speccer-color-text-light); color: var(--ph-speccer-pin-color); } -.ph.speccer.dissection.outline.subtle.top::after, -.ph.speccer.dissection.outline.subtle.bottom::after { +.ph-speccer.speccer.dissection.outline.subtle.top::after, +.ph-speccer.speccer.dissection.outline.subtle.bottom::after { width: 0; background-color: transparent; border-right: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); } -.ph.speccer.dissection.outline.subtle.right::after, -.ph.speccer.dissection.outline.subtle.left::after { +.ph-speccer.speccer.dissection.outline.subtle.right::after, +.ph-speccer.speccer.dissection.outline.subtle.left::after { height: 0; background-color: transparent; border-top: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); } -.ph.speccer.dissection.outline.full.subtle:not(.curly) { +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly) { border: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); background-color: transparent; border-bottom: none; } -.ph.speccer.dissection.outline.full.subtle:not(.curly).top { +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).top { border: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); border-bottom: none; } -.ph.speccer.dissection.outline.full.subtle:not(.curly).bottom { +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).bottom { border: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); border-top: none; } -.ph.speccer.dissection.outline.full.subtle:not(.curly).right { +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).right { border: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); border-left: none; } -.ph.speccer.dissection.outline.full.subtle:not(.curly).left { +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).left { border: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); border-right: none; } -.ph.speccer.dissection.outline.full.subtle:not(.curly)::after { +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly)::after { height: var(--ph-speccer-pin-size); width: var(--ph-speccer-pin-size); border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); background-color: var(--ph-speccer-color-text-light); color: var(--ph-speccer-pin-color); } -.ph.speccer.dissection.outline.full.subtle:not(.curly).top::before, -.ph.speccer.dissection.outline.full.subtle:not(.curly).bottom::before { +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).top::before, +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).bottom::before { width: 0; background-color: transparent; border-right: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); } -.ph.speccer.dissection.outline.full.subtle:not(.curly).right::before, -.ph.speccer.dissection.outline.full.subtle:not(.curly).left::before { +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).right::before, +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).left::before { height: 0; background-color: transparent; border-top: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); } -.ph.speccer.dissection.outline.enclose.subtle { +.ph-speccer.speccer.dissection.outline.enclose.subtle { border-style: dashed; } -.ph.speccer.dissection.outline.enclose.subtle::after { +.ph-speccer.speccer.dissection.outline.enclose.subtle::after { height: var(--ph-speccer-pin-size); width: var(--ph-speccer-pin-size); border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); background-color: var(--ph-speccer-color-text-light); color: var(--ph-speccer-pin-color); } -.ph.speccer.dissection.outline.enclose.subtle.top::before, -.ph.speccer.dissection.outline.enclose.subtle.bottom::before { +.ph-speccer.speccer.dissection.outline.enclose.subtle.top::before, +.ph-speccer.speccer.dissection.outline.enclose.subtle.bottom::before { width: 0; background-color: transparent; border-right: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); } -.ph.speccer.dissection.outline.enclose.subtle.right::before, -.ph.speccer.dissection.outline.enclose.subtle.left::before { +.ph-speccer.speccer.dissection.outline.enclose.subtle.right::before, +.ph-speccer.speccer.dissection.outline.enclose.subtle.left::before { height: 0; background-color: transparent; border-top: var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color); } -.ph.speccer.spacing { +.ph-speccer.speccer.spacing { pointer-events: auto; transition: none; border: var(--ph-speccer-line-width) solid transparent; } -.ph.speccer.spacing:hover { +.ph-speccer.speccer.spacing:hover { border: var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark); } -.ph.speccer.spacing.margin { +.ph-speccer.speccer.spacing.margin { background-color: var(--ph-speccer-color-margin); color: var(--ph-speccer-color-text-dark); } -.ph.speccer.spacing.padding { +.ph-speccer.speccer.spacing.padding { background-color: var(--ph-speccer-color-padding); color: var(--ph-speccer-spacing-color); } -.ph.speccer.spacing.margin.bottom::after, -.ph.speccer.spacing.margin.top::after { +.ph-speccer.speccer.spacing.margin.bottom::after, +.ph-speccer.speccer.spacing.margin.top::after { transition: none; content: ""; position: absolute; @@ -487,8 +487,8 @@ svg.ph .ph.path { width: 9px; left: 40%; } -.ph.speccer.spacing.margin.bottom::before, -.ph.speccer.spacing.margin.top::before { +.ph-speccer.speccer.spacing.margin.bottom::before, +.ph-speccer.speccer.spacing.margin.top::before { transition: none; content: ""; position: absolute; @@ -498,8 +498,8 @@ svg.ph .ph.path { width: 0; left: 40%; } -.ph.speccer.spacing.margin.left::after, -.ph.speccer.spacing.margin.right::after { +.ph-speccer.speccer.spacing.margin.left::after, +.ph-speccer.speccer.spacing.margin.right::after { transition: none; content: ""; position: absolute; @@ -509,8 +509,8 @@ svg.ph .ph.path { width: 100%; top: 10%; } -.ph.speccer.spacing.margin.left::before, -.ph.speccer.spacing.margin.right::before { +.ph-speccer.speccer.spacing.margin.left::before, +.ph-speccer.speccer.spacing.margin.right::before { transition: none; content: ""; position: absolute; @@ -520,8 +520,8 @@ svg.ph .ph.path { width: 100%; top: 10%; } -.ph.speccer.spacing.padding.bottom::after, -.ph.speccer.spacing.padding.top::after { +.ph-speccer.speccer.spacing.padding.bottom::after, +.ph-speccer.speccer.spacing.padding.top::after { transition: none; content: ""; position: absolute; @@ -531,8 +531,8 @@ svg.ph .ph.path { width: 9px; left: 40%; } -.ph.speccer.spacing.padding.bottom::before, -.ph.speccer.spacing.padding.top::before { +.ph-speccer.speccer.spacing.padding.bottom::before, +.ph-speccer.speccer.spacing.padding.top::before { transition: none; content: ""; position: absolute; @@ -542,8 +542,8 @@ svg.ph .ph.path { width: 0; left: 40%; } -.ph.speccer.spacing.padding.left::after, -.ph.speccer.spacing.padding.right::after { +.ph-speccer.speccer.spacing.padding.left::after, +.ph-speccer.speccer.spacing.padding.right::after { transition: none; content: ""; position: absolute; @@ -553,8 +553,8 @@ svg.ph .ph.path { width: 100%; top: 10%; } -.ph.speccer.spacing.padding.left::before, -.ph.speccer.spacing.padding.right::before { +.ph-speccer.speccer.spacing.padding.left::before, +.ph-speccer.speccer.spacing.padding.right::before { transition: none; content: ""; position: absolute; @@ -564,7 +564,7 @@ svg.ph .ph.path { width: 100%; top: 10%; } -.ph.speccer.typography { +.ph-speccer.speccer.typography { background-color: var(--ph-speccer-typography-background-color); color: var(--ph-speccer-typography-color-text); font-size: 10px; @@ -576,10 +576,10 @@ svg.ph .ph.path { line-height: 140%; border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); } -.ph.speccer.typography:hover { +.ph-speccer.speccer.typography:hover { border: var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color); } -.ph.speccer.typography:after { +.ph-speccer.speccer.typography:after { content: ""; position: absolute; display: block; @@ -590,14 +590,14 @@ svg.ph .ph.path { height: var(--ph-speccer-line-width); width: var(--ph-speccer-pin-space); } -.ph.speccer.typography.left:after { +.ph-speccer.speccer.typography.left:after { left: 100%; top: 50%; transform: translateY(-50%); height: var(--ph-speccer-line-width); width: var(--ph-speccer-pin-space); } -.ph.speccer.typography.right:after { +.ph-speccer.speccer.typography.right:after { left: auto; right: 100%; top: 50%; @@ -605,7 +605,7 @@ svg.ph .ph.path { height: var(--ph-speccer-line-width); width: var(--ph-speccer-pin-space); } -.ph.speccer.typography.top:after { +.ph-speccer.speccer.typography.top:after { left: 50%; right: auto; top: 100%; @@ -613,7 +613,7 @@ svg.ph .ph.path { height: var(--ph-speccer-pin-space); width: var(--ph-speccer-line-width); } -.ph.speccer.typography.bottom:after { +.ph-speccer.speccer.typography.bottom:after { left: 50%; right: auto; top: auto; @@ -622,7 +622,7 @@ svg.ph .ph.path { height: var(--ph-speccer-pin-space); width: var(--ph-speccer-line-width); } -.ph.speccer.typography .speccer-styles { +.ph-speccer.speccer.typography .speccer-styles { list-style: none; width: 100%; padding: 0; @@ -631,7 +631,7 @@ svg.ph .ph.path { padding-left: 8px; font-size: 10px; } -.ph.speccer.typography .speccer-styles .property { +.ph-speccer.speccer.typography .speccer-styles .property { font-weight: normal; color: var(--ph-speccer-typography-color-property); text-align: left; @@ -639,7 +639,7 @@ svg.ph .ph.path { font-size: 10px; margin: 0; } -.ph.speccer.typography .speccer-styles > li { +.ph-speccer.speccer.typography .speccer-styles > li { font-weight: normal; color: var(--ph-speccer-typography-color-value); text-align: left; @@ -649,85 +649,85 @@ svg.ph .ph.path { list-style: none; border: none; } -.ph.speccer.measure { +.ph-speccer.speccer.measure { display: flex; } -.ph.speccer.measure.width { +.ph-speccer.speccer.measure.width { color: var(--ph-speccer-measure-color); border: var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color); border-bottom: none; height: var(--ph-speccer-measure-size); } -.ph.speccer.measure.width::after { +.ph-speccer.speccer.measure.width::after { content: attr(data-measure); position: absolute; top: calc(-100% - 10px); } -.ph.speccer.measure.width.bottom { +.ph-speccer.speccer.measure.width.bottom { color: var(--ph-speccer-measure-color); border: var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color); border-top: none; } -.ph.speccer.measure.width.bottom::after { +.ph-speccer.speccer.measure.width.bottom::after { content: attr(data-measure); position: absolute; top: calc(100% + 5px); } -.ph.speccer.measure.width.top { +.ph-speccer.speccer.measure.width.top { color: var(--ph-speccer-measure-color); border: var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color); border-bottom: none; } -.ph.speccer.measure.width.top::after { +.ph-speccer.speccer.measure.width.top::after { content: attr(data-measure); position: absolute; bottom: calc(100% + 5px); } -.ph.speccer.measure.height.left { +.ph-speccer.speccer.measure.height.left { color: var(--ph-speccer-measure-color); border: var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color); border-right: none; width: var(--ph-speccer-measure-size); } -.ph.speccer.measure.height.left::after { +.ph-speccer.speccer.measure.height.left::after { content: attr(data-measure); position: absolute; top: 50%; left: calc(-100% - 20px - var(--ph-speccer-line-width)); transform: translateY(-50%) rotate(-90deg); } -.ph.speccer.measure.height.right { +.ph-speccer.speccer.measure.height.right { color: var(--ph-speccer-measure-color); border: var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color); border-left: none; width: var(--ph-speccer-measure-size); } -.ph.speccer.measure.height.right::after { +.ph-speccer.speccer.measure.height.right::after { content: attr(data-measure); position: absolute; top: 50%; left: calc(100% - var(--ph-speccer-measure-size)); transform: translateY(-50%) rotate(90deg); } -.ph.speccer.measure.subtle.width.top, -.ph.speccer.measure.subtle.width.bottom, -.ph.speccer.measure.subtle.height.right, -.ph.speccer.measure.subtle.height.left { +.ph-speccer.speccer.measure.subtle.width.top, +.ph-speccer.speccer.measure.subtle.width.bottom, +.ph-speccer.speccer.measure.subtle.height.right, +.ph-speccer.speccer.measure.subtle.height.left { border-style: dashed; } -.ph.speccer.measure.subtle.width.top { +.ph-speccer.speccer.measure.subtle.width.top { border-bottom: none; } -.ph.speccer.measure.subtle.width.bottom { +.ph-speccer.speccer.measure.subtle.width.bottom { border-top: none; } -.ph.speccer.measure.subtle.height.right { +.ph-speccer.speccer.measure.subtle.height.right { border-left: none; } -.ph.speccer.measure.subtle.height.left { +.ph-speccer.speccer.measure.subtle.height.left { border-right: none; } -.ph.speccer.mark { +.ph-speccer.speccer.mark { background-color: var(--ph-speccer-mark-background-color); border-color: var(--ph-speccer-mark-border-color); border-width: 1px; diff --git a/speccer.d.ts b/speccer.d.ts new file mode 100644 index 00000000..96b813ec --- /dev/null +++ b/speccer.d.ts @@ -0,0 +1,52 @@ +declare type SpeccerFunctionType = () => void; + +/** + * Extends the global Window interface to add custom properties. + */ +declare global { + interface Window { + /** + * Represents the DrawSVGCurlyBracket class for drawing curly brackets. + */ + DrawSVGCurlyBracket: any; + /** + * Represents the DrawSVGLine class for drawing lines. + */ + DrawSVGLine: any; + /** + * Represents the speccer object for additional functionality. + */ + speccer: any; + } +} +//# sourceMappingURL=global.d.ts.map + +declare const spacing: { + create: (text?: string | number, tag?: string) => HTMLElement; + element: (targetEl: HTMLElement) => Promise; +}; +declare const dissect: { + create: (textContent: string | undefined, area: string, n?: string) => HTMLElement; + element: (sectionEl: HTMLElement) => Promise; +}; +declare const measure: { + create: (text?: string | number, area?: string | null, tag?: string) => HTMLElement; + element: (targetEl: HTMLElement) => Promise; +}; +declare const mark: { + create: (n?: string) => HTMLElement; + element: (elementToMark: HTMLElement) => Promise; +}; +declare const typography: { + create: (html: string, area: string | null) => HTMLElement; + element: (targetEl: HTMLElement) => Promise; +}; +declare const modes: { + dom: (speccer: SpeccerFunctionType) => void; + lazy: () => void; + manual: (speccer: SpeccerFunctionType) => void; + activate: (speccer: SpeccerFunctionType) => void; +}; +declare const speccer: () => void; + +export { speccer as default, dissect, mark, measure, modes, spacing, typography }; diff --git a/speccer.js b/speccer.js index 1251916c..61f12a17 100644 --- a/speccer.js +++ b/speccer.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).speccer={})}(this,(function(t){"use strict";const e=(t,e,o="noop")=>{t&&(!e||e&&0===e.length||e.trim().split(" ").filter((t=>t!==o)).forEach((e=>t.classList.add(e))))},o=(t,e)=>t?e||"string"==typeof t?`${t} ${e?Object.keys(e).filter((t=>e[t])).join(" "):""}`.trim():`${Object.keys(t).filter((e=>t[e])).join(" ")}`.trim():"",i=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"],n=t=>parseInt(t,10),r=t=>n(getComputedStyle(t).getPropertyValue("--ph-speccer-pin-space"))||48,s=()=>new Promise(requestAnimationFrame),a=async(t,e)=>{!t||!e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e||Array.isArray(e)&&0===e.length||0===Object.keys(e).length&&e.constructor===Object||(await s(),Array.isArray(e)?e.forEach((e=>t.style[e.key]=e.value)):Object.keys(e).forEach((o=>t.style[o]=e[o])))},p=async t=>(await s(),getComputedStyle(t,null)),l=(t,e,o)=>t-e.width/2+o.width/2,c=(t,e,o)=>t-e.height/2+o.height/2,h=async t=>{await s();const e=t.getBoundingClientRect(),o=e.top+window.scrollY,i=e.left+window.scrollX;return{height:e.height,width:e.width,top:o,left:i}},d=async(t,e)=>{await s();const o=t.getBoundingClientRect(),i=await h(e),n=await(async(t,e)=>{await s();const o=t.getBoundingClientRect(),i=e.getBoundingClientRect(),n=i.top+window.scrollY,r=i.left+window.scrollX;return{height:i.height,width:i.width,top:c(n,o,i),left:l(r,o,i)}})(t,e),r=i.height,a=i.width,p=o.height,d=o.width;return{absolute:()=>({top:i.top,left:i.left,height:r,width:a}),toTop:({center:t=!1,sourceHeight:e=p,modifier:o=0}={})=>({top:i.top+e+o,left:t?n.left:i.left,height:r,width:a}),fromTop:({center:t=!1,sourceHeight:e=p,modifier:o=0}={})=>({top:i.top-e-o,left:t?n.left:i.left,height:r,width:a}),toBottom:({center:t=!1,sourceHeight:e=p,targetHeight:o=r,modifier:s=0}={})=>({top:i.top+o-(e+s),left:t?n.left:i.left,height:r,width:a}),fromBottom:({center:t=!1,targetHeight:e=r,modifier:o=0}={})=>({top:i.top+e+o,left:t?n.left:i.left,height:r,width:a}),toLeft:({center:t=!1,sourceWidth:e=d,modifier:o=0}={})=>({top:t?n.top:i.top,left:i.left+e+o,height:r,width:a}),fromLeft:({center:t=!1,sourceWidth:e=d,modifier:o=0}={})=>({top:t?n.top:i.top,left:i.left-e-o,height:r,width:a}),toRight:({center:t=!1,sourceWidth:e=d,targetWidth:o=a,modifier:s=0}={})=>({top:t?n.top:i.top,left:i.left+o-(e+s),height:r,width:a}),fromRight:({center:t=!1,targetWidth:e=a,modifier:o=0}={})=>({top:t?n.top:i.top,left:i.left+e+o,height:r,width:a})}},f=(t="",o="span")=>{const i=document.createElement(o),n=document.createTextNode(t+"");return i.appendChild(n),i.setAttribute("title",t+"px"),e(i,"ph speccer spacing"),i},u=async t=>{if(!t)return;const o=await p(t);if("none"===o.display||"0"===o.opacity||"hidden"===o.visibility)return;const i=(t=>{const{marginTop:e,marginBottom:o,marginLeft:i,marginRight:n,paddingTop:r,paddingBottom:s,paddingLeft:a,paddingRight:p}=t;return{marginTop:e,marginBottom:o,marginLeft:i,marginRight:n,paddingTop:r,paddingBottom:s,paddingLeft:a,paddingRight:p}})(o),r=Object.keys(i).filter((t=>"0px"!==i[t]));0!==r.length&&r.forEach((async o=>{const r=n(i[o]),p=f(r),l=(t=>-1!==t.indexOf("Top")?t.replace("Top"," top"):-1!==t.indexOf("Right")?t.replace("Right"," right"):-1!==t.indexOf("Bottom")?t.replace("Bottom"," bottom"):-1!==t.indexOf("Left")?t.replace("Left"," left"):"")(o);e(p,l),document.body.appendChild(p),t.classList.add("is-specced"),await(async(t,e,o,i)=>{await s();const n=i.getBoundingClientRect(),r=await h(i);"marginTop"===t&&a(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top-e+"px"}),"marginRight"===t&&a(o,{height:n.height+"px",width:`${e}px`,left:r.left+parseInt(n.width+"",10)+"px",top:r.top+"px"}),"marginBottom"===t&&a(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top+parseInt(n.height+"",10)+"px"}),"marginLeft"===t&&a(o,{height:n.height+"px",width:`${e}px`,left:r.left-e+"px",top:r.top+"px"}),"paddingTop"===t&&a(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top+"px"}),"paddingBottom"===t&&a(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top+(parseInt(n.height+"",10)-e)+"px"}),"paddingRight"===t&&a(o,{height:n.height+"px",width:`${e}px`,left:r.left+(parseInt(n.width+"",10)-e)+"px",top:r.top+"px"}),"paddingLeft"===t&&a(o,{height:n.height+"px",width:`${e}px`,left:r.left+"px",top:r.top+"px"})})(o,r,p,t)}))};var m,g,w;!function(t){t.Empty="",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(m||(m={})),function(t){t.Outline="outline",t.Enclose="enclose",t.Full="full",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top",t.SVG="svg",t.Curly="curly"}(g||(g={})),function(t){t.Width="width",t.Height="height",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(w||(w={}));const y=t=>t.split(" "),x=t=>y(t).includes(g.Right),b=t=>y(t).includes(g.Bottom),E=t=>y(t).includes(g.Full),$=t=>y(t).includes(g.Enclose),v=t=>t.includes(g.Curly)&&t.includes(g.Full),A=()=>"_"+Math.random().toString(36).substring(2,11),P=t=>t.top,S=t=>t.left+t.width,C=t=>t.top+t.height,B=t=>t.left+t.width/2,R=t=>t.top+t.height/2,L={center:t=>({x:B(t),y:R(t)}),top:t=>({x:B(t),y:P(t)}),right:t=>({x:S(t),y:R(t)}),bottom:t=>({x:B(t),y:C(t)})},O=async(t,e="center")=>{if(!e)throw new Error("No position given");if("string"!=typeof e)throw new Error("The position given is not the required type: pos: "+typeof e);const o=["center","left","right","top","bottom","right-top","right-bottom","left-top","left-bottom","top-left","top-right","bottom-left","bottom-right","top-center","right-center","bottom-center","left-center"];if(!o.includes(e))throw new Error(`The position given does not match allowed positions to use! Valid positions are: ${o.join(", ")}`);await s();const i=t.getBoundingClientRect();return L[e](i)},T=async(t,e,o="center",i="center")=>{if(!t||!e)throw new Error("No element given");const{x:n,y:r}=await O(t,o),{x:s,y:a}=await O(e,i);return{x1:n,y1:r,x2:s,y2:a}},N=(t,e)=>{const{x1:o,x2:i,y1:n,y2:r}=t,{direct:s=!1,firstSet:a=!1,direction:p}=e;let l={x:o+(i-o)/2,y:n},c={x:o+(i-o)/2,y:r};return s&&(a?"west"===p?(l={x:o-32,y:n-8},c={x:i+32,y:r}):"south"===p?(l={x:o-8,y:n+32},c={x:i,y:r-32}):"east"===p?(l={x:o+32,y:n-8},c={x:i-32,y:r}):(l={x:o-8,y:n-32},c={x:i,y:r+32}):"west"===p?(l={x:o-32,y:n+8},c={x:i+32,y:r}):"south"===p?(l={x:o+8,y:n+32},c={x:i,y:r-32}):"east"===p?(l={x:o+32,y:n+8},c={x:i-32,y:r}):(l={x:o+8,y:n-32},c={x:i,y:r+32})),{firstPoint:{x:o,y:n},firstControl:l,lastPoint:{x:i,y:r},lastControl:c}},M=async(t,e,o)=>{const{pos1:i,pos2:n,firstSet:r=!1,direction:s}=o,{x1:a,y1:p,x2:l,y2:c}=await T(t,e,i,n);let h=0,d=0;"north"==s?d=8:"west"==s?h=8:"east"==s?h=-8:"south"==s&&(d=-8);const f=N({x1:a+0,x2:l+h,y1:p+0,y2:c+d},{direct:!0,firstSet:r,direction:s}),{firstPoint:u,firstControl:m,lastControl:g,lastPoint:w}=f;return`M ${u.x} ${u.y}C ${m.x} ${m.y}, ${g.x} ${g.y}, ${w.x} ${w.y}`},I=async({start:t,stop:e,crude:o=!1})=>{const{x1:i,y1:n,x2:r,y2:s}=await T(t,e),a=((t,e,o,i,n=!0)=>{if(!(t&&e&&o&&i))throw new SyntaxError("Missing input for `angle`");if("number"!=typeof t||"number"!=typeof e||"number"!=typeof o||"number"!=typeof i)throw new TypeError(`Parameters for \`angle\` do not have the required type. Requires number! Got: ${typeof t} ${typeof e} ${typeof o} ${typeof i}`);const r=i-e,s=o-t;let a=Math.atan2(r,s);return a*=180/Math.PI,n&&a<0&&(a=360+a),a})(i,n,r,s);return o?(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=45&&t<=135?"south":t>135&&t<=225?"west":t>225&&t<=315?"north":"east"})(a):(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=0&&t<=22.5?"east":t>=22.5&&t<=67.5?"south-east":t>=67.5&&t<=112.5?"south":t>=112.5&&t<=157.5?"south-west":t>=157.5&&t<=202.5?"west":t>=202.5&&t<=247.5?"north-west":t>=247.5&&t<=292.5?"north":t>=292.5&&t<=337.5?"north-east":"east"})(a)};class k{#t;#e;startElement;stopElement;line;constructor(t,e){this.#o(t,e)}#o(t,e){if(!t||!e)throw new Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw new Error("stopElement is not in the DOM");if(!document.body.contains(t))throw new Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#e=document.getElementById("ph-speccer-path"),!this.#e||!this.#t)throw new Error("Missing required SVG element to draw lines. Please see the documentation");this.connect()}connect(){this.draw(this.#e)}async draw(t){if(!t)throw new Error("No path given to draw!");const e=`ph_draw_path-path-${A()}`,o=t.cloneNode(!1);if(o.setAttribute("id",e),o.setAttribute("data-start-el",this.startElement.getAttribute("id")||"no-id-found"),o.classList.remove("original"),o.classList.add("speccer"),!t.parentNode)throw new Error("No parentNode found for path");this.line=t.parentNode.insertBefore(o,t.nextSibling);const i=await I({start:this.startElement,stop:this.stopElement,crude:!0}),{pos1:n,pos2:r}=(t=>{let e,o;switch(t){case"east":e="right",o="left";break;case"south":e="bottom",o="top";break;case"west":e="left",o="right";break;default:e="top",o="bottom"}return{pos1:e,pos2:o}})(i),s=await(async(t,e,o)=>{const{pos1:i,pos2:n}=o,{x1:r,y1:s,x2:a,y2:p}=await T(t,e,i,n),l=N({x1:r,x2:a,y1:s,y2:p},{direction:""}),{firstPoint:c,firstControl:h,lastControl:d,lastPoint:f}=l;return`M ${c.x} ${c.y}C ${h.x} ${h.y}, ${d.x} ${d.y}, ${f.x} ${f.y}`})(this.startElement,this.stopElement,{pos1:n,pos2:r});this.line.setAttribute("data-direction",i),this.line.setAttribute("data-pos1",n),this.line.setAttribute("data-pos2",r),this.line.setAttribute("d",s)}}window.DrawSVGLine=k;class q{#t;#e;startElement;stopElement;firstPathElement;secondPathElement;constructor(t,e){this.#o(t,e)}#o(t,e){if(!t||!e)throw new Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw new Error("stopElement is not in the DOM");if(!document.body.contains(t))throw new Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#e=document.getElementById("ph-speccer-path"),!this.#e||!this.#t)throw new Error("Missing required SVG element to draw lines. Please see the documentation");this.connect()}connect(){this.draw(this.#e)}#i(t){if(!t)throw new Error("No path given to #getPathElement!");const e=`ph_draw_path-path-${A()}`,o=t.cloneNode(!1);return o.setAttribute("data-start-el",this.startElement.getAttribute("id")||"no-id-found"),o.setAttribute("id",e),o.classList.remove("original"),o.classList.add("speccer"),o}async draw(t){if(!t)throw new Error("No path given to draw!");const e=this.#i(t),o=this.#i(t);if(!t.parentNode)throw new Error("No parentNode found for path");this.firstPathElement=t.parentNode.insertBefore(e,t.nextSibling),this.secondPathElement=t.parentNode.insertBefore(o,t.nextSibling);const i=await I({stop:this.stopElement,start:this.startElement,crude:!0}),{path1pos1:n,path1pos2:r,path2pos1:s,path2pos2:a}=(t=>{let e,o,i,n;switch(t){case"east":e="right-top",o="left-center",i="right-bottom",n="left-center";break;case"south":e="bottom-left",o="top-center",i="bottom-right",n="top-center";break;case"west":e="left-top",o="right-center",i="left-bottom",n="right-center";break;default:e="top-left",o="bottom-center",i="top-right",n="bottom-center"}return{path1pos1:e,path1pos2:o,path2pos1:i,path2pos2:n}})(i),p=await M(this.startElement,this.stopElement,{pos1:n,pos2:r,firstSet:!0,direction:i}),l=await M(this.startElement,this.stopElement,{pos1:s,pos2:a,direction:i});this.firstPathElement.setAttribute("data-direction",i),this.firstPathElement.setAttribute("data-pos1",n),this.firstPathElement.setAttribute("data-pos2",r),this.firstPathElement.setAttribute("d",p),this.secondPathElement.setAttribute("data-direction",i),this.secondPathElement.setAttribute("data-pos1",s),this.secondPathElement.setAttribute("data-pos2",a),this.secondPathElement.setAttribute("d",l)}}window.DrawSVGCurlyBracket=q;const H=async(t,e,o,i)=>{const{isCurly:s=!1}=i||{},a=r(o),p=n(getComputedStyle(o).getPropertyValue("--ph-speccer-measure-size"))||8;const l=await d(o,e);if($(t)){const{left:t,top:e,height:o,width:i}=l.absolute();return{left:`${t}px`,top:`${e}px`,height:`${o}px`,width:`${i}px`}}if(y(t).includes(g.Left)){if(E(t)&&!s){const{left:t,top:e,height:o}=l.fromLeft({sourceWidth:p});return{left:`${t}px`,top:`${e}px`,height:`${o}px`}}{const{left:t,top:e}=l.fromLeft({center:!0,modifier:s?a/1.5:a});return{left:`${t}px`,top:`${e}px`}}}if(x(t)){if(E(t)&&!s){const{left:t,top:e,height:o}=l.fromRight({center:!1});return{left:`${t}px`,top:`${e}px`,height:`${o}px`}}{const{left:t,top:e}=l.fromRight({center:!0,modifier:s?a/1.5:a});return{left:`${t}px`,top:`${e}px`}}}if(b(t)){if(E(t)&&!s){const{left:t,top:e,width:o}=l.fromBottom({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${o}px`}}{const{left:t,top:e}=l.fromBottom({center:!0,modifier:s?a/1.5:a});return{left:`${t}px`,top:`${e}px`}}}if(E(t)&&!s){const{left:t,top:e,width:o}=l.fromTop({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${o}px`}}{const{left:t,top:e}=l.fromTop({center:!0,modifier:s?a/1.5:a});return{left:`${t}px`,top:`${e}px`}}},j=(t="",i,n="span")=>{const r=document.createElement(n),s=document.createTextNode(t),a={};null!==i&&""!==i&&(a[i]=!0),!E(i)&&!$(i)||E(i)&&v(i)?r.appendChild(s):(E(i)||$(i))&&r.setAttribute("data-dissection-counter",t);const p=o("ph speccer dissection",a);return e(r,p),r},V=t=>{if(!t)return Promise.resolve();const e=t.querySelectorAll("[data-anatomy]");if(e){let t=0;e.forEach((async(e,o)=>{if(!e)return Promise.resolve();const n=e.getAttribute("data-anatomy")||"";if(!n||""===n||-1===n.indexOf(g.Outline))return Promise.resolve();let r=i[o];r||(r=`${i[t]}${i[t].toLowerCase()}`,t++);const s=j(r,n);document.body.appendChild(s);const p=await H(n,e,s,{isCurly:v(n)});var l;await a(s,p),(l=n).includes(g.SVG)||l.includes(g.Curly)||l.includes(g.Full)||l.includes(g.Enclose)?new k(e,s):v(n)&&new q(e,s)}))}return Promise.resolve()},W=(t="",o="",i="span")=>{const n=document.createElement(i);return n.setAttribute("title",t+"px"),n.setAttribute("data-measure",parseInt(t+"",10)+"px"),e(n,`ph speccer measure ${o}`),n},z=async t=>{if(!t)return;const e=t.getAttribute("data-speccer-measure");if(""===e||!e)return;const o=await p(t);if("none"===o.display||"0"===o.opacity||"hidden"===o.visibility)return;await s();const i=t.getBoundingClientRect();if(y(e).includes(w.Width))if(b(e)){const o=W(i.width,e);document.body.appendChild(o);const n=await d(o,t),{left:r,top:s,width:p}=n.fromBottom({center:!1});await a(o,{left:`${r}px`,top:`${s}px`,width:`${p}px`})}else{const o=W(i.width,e);document.body.appendChild(o);const n=await d(o,t),{left:r,top:s,width:p}=n.fromTop({center:!1,modifier:-8});await a(o,{left:`${r}px`,top:`${s}px`,width:`${p}px`})}else if((t=>y(t).includes(w.Height))(e))if(x(e)){const o=W(i.height,e);document.body.appendChild(o);const n=await d(o,t),{left:r,top:s,height:p}=n.fromRight({center:!1});await a(o,{left:`${r}px`,top:`${s}px`,height:`${p}px`})}else{const o=W(i.height,e);document.body.appendChild(o);const n=await d(o,t),{left:r,top:s,height:p}=n.fromLeft({center:!1,modifier:-8});await a(o,{left:`${r}px`,top:`${s}px`,height:`${p}px`})}},F=(t="span")=>{const i=document.createElement(t),n=o("ph speccer mark");return e(i,n),i},D=async t=>{if(!t)return Promise.resolve();const e=F();document.body.appendChild(e);const o=await d(e,t),{left:i,top:n,height:r,width:s}=o.absolute(),p={left:`${i}px`,top:`${n}px`,height:`${r}px`,width:`${s}px`};await a(e,p)},G=(t,e=3)=>parseFloat(t+"").toFixed(e),_=(t,i)=>{const n=document.createElement("div"),r={};null!==i&&""!==i&&(r[i]=!0);const s=o("ph speccer typography",r);return n.innerHTML=t,e(n,s),n},X=async t=>{if(!t)return;const e=t.getAttribute("data-speccer-typography"),o=await p(t);if("none"===o.display||"0"===o.opacity||"hidden"===o.visibility)return;t.classList.add("is-specced");const i=await(async t=>{const e=(t=>{const{lineHeight:e,letterSpacing:o,fontFamily:i,fontSize:n,fontStyle:r,fontVariationSettings:s,fontWeight:a}=t;return{lineHeight:e,letterSpacing:o,fontFamily:i,fontSize:n,fontStyle:r,fontVariationSettings:s,fontWeight:a}})(await p(t)),o="normal"!==e.lineHeight?parseInt(e.lineHeight,10)/16+"rem":"normal";return`\nfont-styles: {
  • font-family: ${e.fontFamily};
  • font-size: ${e.fontSize} / ${parseInt(e.fontSize,10)/16}rem;
  • font-weight: ${e.fontWeight};
  • font-variation-settings: ${e.fontVariationSettings};
  • line-height: ${e.lineHeight} / ${o};
  • letter-spacing: ${e.letterSpacing};
  • font-style: ${e.fontStyle};
}`})(t),n=_(i,e);document.body.appendChild(n);const s=await(async(t,e,o)=>{const i=e.getBoundingClientRect(),n=r(o),s=o.getBoundingClientRect(),a=await h(e),p=a.left-s.width-n+"px",d=G(c(a.top,s,i))+"px",f=a.left+i.width+n+"px",u=G(c(a.top,s,i))+"px",g=G(l(a.left,s,i))+"px",w=a.top-s.height-n+"px",y=G(l(a.left,s,i))+"px",x=a.top+i.height+n+"px";let b={left:p,top:d};return t&&-1!==t.indexOf(m.Right)?b={left:f,top:u}:t&&-1!==t.indexOf(m.Top)?b={left:g,top:w}:t&&-1!==t.indexOf(m.Bottom)&&(b={left:y,top:x}),b})(e,t,n);a(n,s)},Y=t=>{const e=()=>((t,e,o=!1)=>{let i;return function(n,...r){const s=o&&!i;i&&clearTimeout(i),i=setTimeout((function(){i=null,o||t.apply(n,r)}),e),s&&t.apply(n,r)}})((()=>{t()}),300);window.removeEventListener("resize",e),window.addEventListener("resize",e)},J=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},K=()=>{const t=new IntersectionObserver(((t,e)=>{t.forEach((t=>{t.intersectionRatio>0&&(u(t.target),e.unobserve(t.target))}))}));document.querySelectorAll("[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)").forEach((e=>{t.observe(e)}));const e=new IntersectionObserver(((t,e)=>{t.forEach((t=>{t.intersectionRatio>0&&(z(t.target),e.unobserve(t.target))}))}));document.querySelectorAll("[data-speccer-measure]").forEach((t=>{e.observe(t)}));const o=new IntersectionObserver(((t,e)=>{t.forEach((t=>{t.intersectionRatio>0&&(V(t.target),e.unobserve(t.target))}))}));document.querySelectorAll("[data-anatomy-section]").forEach((t=>{o.observe(t)}))},Q=t=>{window.speccer=t},U=t=>{const e=document.currentScript;if(e){const o=e.getAttribute("src");!o||-1===o.indexOf("speccer.js")&&-1===o.indexOf("JaXpOK.js")||(e.hasAttribute("data-manual")?Q(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?J(t):e.hasAttribute("data-lazy")?K():J(t),e.hasAttribute("data-manual")||e.hasAttribute("data-lazy")||Y(t))}},Z={create:f,element:u},tt={create:j,element:V},et={create:W,element:z},ot={create:F,element:D},it={create:_,element:X},nt={dom:J,lazy:K,manual:Q,activate:U},rt=()=>{((t,e=document)=>{[].forEach.call(e.querySelectorAll(t),(function(t){t.remove()}))})(".speccer");const t=document.querySelectorAll("[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)"),e=document.querySelectorAll("[data-speccer-measure]"),o=document.querySelectorAll("[data-speccer-typography]"),i=document.querySelectorAll("[data-anatomy-section]");document.querySelectorAll("[data-speccer-mark]").forEach(D),t.forEach(u),e.forEach(z),o.forEach(X),i.forEach(V)};U(rt),t.default=rt,t.dissect=tt,t.mark=ot,t.measure=et,t.modes=nt,t.spacing=Z,t.typography=it,Object.defineProperty(t,"__esModule",{value:!0})})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).speccer={})}(this,(function(t){"use strict";const e=(t,e,o="noop")=>{t&&(!e||e&&0===e.length||e.trim().split(" ").filter((t=>t!==o)).forEach((e=>t.classList.add(e))))},o=(t,e)=>t?e||"string"==typeof t?`${t} ${e?Object.keys(e).filter((t=>e[t])).join(" "):""}`.trim():`${Object.keys(t).filter((e=>t[e])).join(" ")}`.trim():"",i=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"],n=t=>parseInt(t,10),r=t=>n(getComputedStyle(t).getPropertyValue("--ph-speccer-pin-space"))||48,s=()=>new Promise(requestAnimationFrame),a=async(t,e)=>{!t||!e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e||Array.isArray(e)&&0===e.length||0===Object.keys(e).length&&e.constructor===Object||(await s(),Array.isArray(e)?e.forEach((e=>t.style[e.key]=e.value)):Object.keys(e).forEach((o=>t.style[o]=e[o])))},p=async t=>(await s(),getComputedStyle(t,null)),c=(t,e,o)=>t-e.width/2+o.width/2,l=(t,e,o)=>t-e.height/2+o.height/2,h=async t=>{await s();const e=t.getBoundingClientRect(),o=e.top+window.scrollY,i=e.left+window.scrollX;return{height:e.height,width:e.width,top:o,left:i}},d=async(t,e)=>{await s();const o=t.getBoundingClientRect(),i=await h(e),n=await(async(t,e)=>{await s();const o=t.getBoundingClientRect(),i=e.getBoundingClientRect(),n=i.top+window.scrollY,r=i.left+window.scrollX;return{height:i.height,width:i.width,top:l(n,o,i),left:c(r,o,i)}})(t,e),r=i.height,a=i.width,p=o.height,d=o.width;return{absolute:()=>({top:i.top,left:i.left,height:r,width:a}),toTop:({center:t=!1,sourceHeight:e=p,modifier:o=0}={})=>({top:i.top+e+o,left:t?n.left:i.left,height:r,width:a}),fromTop:({center:t=!1,sourceHeight:e=p,modifier:o=0}={})=>({top:i.top-e-o,left:t?n.left:i.left,height:r,width:a}),toBottom:({center:t=!1,sourceHeight:e=p,targetHeight:o=r,modifier:s=0}={})=>({top:i.top+o-(e+s),left:t?n.left:i.left,height:r,width:a}),fromBottom:({center:t=!1,targetHeight:e=r,modifier:o=0}={})=>({top:i.top+e+o,left:t?n.left:i.left,height:r,width:a}),toLeft:({center:t=!1,sourceWidth:e=d,modifier:o=0}={})=>({top:t?n.top:i.top,left:i.left+e+o,height:r,width:a}),fromLeft:({center:t=!1,sourceWidth:e=d,modifier:o=0}={})=>({top:t?n.top:i.top,left:i.left-e-o,height:r,width:a}),toRight:({center:t=!1,sourceWidth:e=d,targetWidth:o=a,modifier:s=0}={})=>({top:t?n.top:i.top,left:i.left+o-(e+s),height:r,width:a}),fromRight:({center:t=!1,targetWidth:e=a,modifier:o=0}={})=>({top:t?n.top:i.top,left:i.left+e+o,height:r,width:a})}},f=(t="",o="span")=>{const i=document.createElement(o),n=document.createTextNode(t+"");return i.appendChild(n),i.setAttribute("title",t+"px"),e(i,"ph-speccer speccer spacing"),i},u=async t=>{if(!t)return;const o=await p(t);if("none"===o.display||"0"===o.opacity||"hidden"===o.visibility)return;const i=(t=>{const{marginTop:e,marginBottom:o,marginLeft:i,marginRight:n,paddingTop:r,paddingBottom:s,paddingLeft:a,paddingRight:p}=t;return{marginTop:e,marginBottom:o,marginLeft:i,marginRight:n,paddingTop:r,paddingBottom:s,paddingLeft:a,paddingRight:p}})(o),r=Object.keys(i).filter((t=>"0px"!==i[t]));0!==r.length&&r.forEach((async o=>{const r=n(i[o]),p=f(r),c=(t=>-1!==t.indexOf("Top")?t.replace("Top"," top"):-1!==t.indexOf("Right")?t.replace("Right"," right"):-1!==t.indexOf("Bottom")?t.replace("Bottom"," bottom"):-1!==t.indexOf("Left")?t.replace("Left"," left"):"")(o);e(p,c),document.body.appendChild(p),t.classList.add("is-specced"),await(async(t,e,o,i)=>{await s();const n=i.getBoundingClientRect(),r=await h(i);"marginTop"===t&&a(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top-e+"px"}),"marginRight"===t&&a(o,{height:n.height+"px",width:`${e}px`,left:r.left+parseInt(n.width+"",10)+"px",top:r.top+"px"}),"marginBottom"===t&&a(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top+parseInt(n.height+"",10)+"px"}),"marginLeft"===t&&a(o,{height:n.height+"px",width:`${e}px`,left:r.left-e+"px",top:r.top+"px"}),"paddingTop"===t&&a(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top+"px"}),"paddingBottom"===t&&a(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top+(parseInt(n.height+"",10)-e)+"px"}),"paddingRight"===t&&a(o,{height:n.height+"px",width:`${e}px`,left:r.left+(parseInt(n.width+"",10)-e)+"px",top:r.top+"px"}),"paddingLeft"===t&&a(o,{height:n.height+"px",width:`${e}px`,left:r.left+"px",top:r.top+"px"})})(o,r,p,t)}))};var m,g,w;!function(t){t.Empty="",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(m||(m={})),function(t){t.Outline="outline",t.Enclose="enclose",t.Full="full",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top",t.SVG="svg",t.Curly="curly"}(g||(g={})),function(t){t.Width="width",t.Height="height",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(w||(w={}));const y=t=>t.split(" "),x=t=>y(t).includes(g.Right),b=t=>y(t).includes(g.Bottom),E=t=>y(t).includes(g.Full),$=t=>y(t).includes(g.Enclose),v=t=>t.includes(g.Curly)&&t.includes(g.Full),A=()=>"_"+Math.random().toString(36).substring(2,11),P=t=>t.top,S=t=>t.left+t.width,C=t=>t.top+t.height,B=t=>t.left+t.width/2,R=t=>t.top+t.height/2,L={center:t=>({x:B(t),y:R(t)}),top:t=>({x:B(t),y:P(t)}),right:t=>({x:S(t),y:R(t)}),bottom:t=>({x:B(t),y:C(t)})},O=async(t,e="center")=>{if(!e)throw new Error("No position given");if("string"!=typeof e)throw new Error("The position given is not the required type: pos: "+typeof e);const o=["center","left","right","top","bottom","right-top","right-bottom","left-top","left-bottom","top-left","top-right","bottom-left","bottom-right","top-center","right-center","bottom-center","left-center"];if(!o.includes(e))throw new Error(`The position given does not match allowed positions to use! Valid positions are: ${o.join(", ")}`);await s();const i=t.getBoundingClientRect();return L[e](i)},T=async(t,e,o="center",i="center")=>{if(!t||!e)throw new Error("No element given");const{x:n,y:r}=await O(t,o),{x:s,y:a}=await O(e,i);return{x1:n,y1:r,x2:s,y2:a}},N=(t,e)=>{const{x1:o,x2:i,y1:n,y2:r}=t,{direct:s=!1,firstSet:a=!1,direction:p}=e;let c={x:o+(i-o)/2,y:n},l={x:o+(i-o)/2,y:r};return s&&(a?"west"===p?(c={x:o-32,y:n-8},l={x:i+32,y:r}):"south"===p?(c={x:o-8,y:n+32},l={x:i,y:r-32}):"east"===p?(c={x:o+32,y:n-8},l={x:i-32,y:r}):(c={x:o-8,y:n-32},l={x:i,y:r+32}):"west"===p?(c={x:o-32,y:n+8},l={x:i+32,y:r}):"south"===p?(c={x:o+8,y:n+32},l={x:i,y:r-32}):"east"===p?(c={x:o+32,y:n+8},l={x:i-32,y:r}):(c={x:o+8,y:n-32},l={x:i,y:r+32})),{firstPoint:{x:o,y:n},firstControl:c,lastPoint:{x:i,y:r},lastControl:l}},M=async(t,e,o)=>{const{pos1:i,pos2:n,firstSet:r=!1,direction:s}=o,{x1:a,y1:p,x2:c,y2:l}=await T(t,e,i,n);let h=0,d=0;"north"==s?d=8:"west"==s?h=8:"east"==s?h=-8:"south"==s&&(d=-8);const f=N({x1:a+0,x2:c+h,y1:p+0,y2:l+d},{direct:!0,firstSet:r,direction:s}),{firstPoint:u,firstControl:m,lastControl:g,lastPoint:w}=f;return`M ${u.x} ${u.y}C ${m.x} ${m.y}, ${g.x} ${g.y}, ${w.x} ${w.y}`},I=async({start:t,stop:e,crude:o=!1})=>{const{x1:i,y1:n,x2:r,y2:s}=await T(t,e),a=((t,e,o,i,n=!0)=>{if(!(t&&e&&o&&i))throw new SyntaxError("Missing input for `angle`");if("number"!=typeof t||"number"!=typeof e||"number"!=typeof o||"number"!=typeof i)throw new TypeError(`Parameters for \`angle\` do not have the required type. Requires number! Got: ${typeof t} ${typeof e} ${typeof o} ${typeof i}`);const r=i-e,s=o-t;let a=Math.atan2(r,s);return a*=180/Math.PI,n&&a<0&&(a=360+a),a})(i,n,r,s);return o?(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=45&&t<=135?"south":t>135&&t<=225?"west":t>225&&t<=315?"north":"east"})(a):(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=0&&t<=22.5?"east":t>=22.5&&t<=67.5?"south-east":t>=67.5&&t<=112.5?"south":t>=112.5&&t<=157.5?"south-west":t>=157.5&&t<=202.5?"west":t>=202.5&&t<=247.5?"north-west":t>=247.5&&t<=292.5?"north":t>=292.5&&t<=337.5?"north-east":"east"})(a)};class k{#t;#e;startElement;stopElement;line;constructor(t,e){this.#o(t,e)}#o(t,e){if(!t||!e)throw new Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw new Error("stopElement is not in the DOM");if(!document.body.contains(t))throw new Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#e=document.getElementById("ph-speccer-path"),!this.#e||!this.#t)throw new Error("Missing required SVG element to draw lines. Please see the documentation");this.connect()}connect(){this.draw(this.#e)}async draw(t){if(!t)throw new Error("No path given to draw!");const e=`ph_draw_path-path-${A()}`,o=t.cloneNode(!1);if(o.setAttribute("id",e),o.setAttribute("data-start-el",this.startElement.getAttribute("id")||"no-id-found"),o.classList.remove("original"),o.classList.add("speccer"),!t.parentNode)throw new Error("No parentNode found for path");this.line=t.parentNode.insertBefore(o,t.nextSibling);const i=await I({start:this.startElement,stop:this.stopElement,crude:!0}),{pos1:n,pos2:r}=(t=>{let e,o;switch(t){case"east":e="right",o="left";break;case"south":e="bottom",o="top";break;case"west":e="left",o="right";break;default:e="top",o="bottom"}return{pos1:e,pos2:o}})(i),s=await(async(t,e,o)=>{const{pos1:i,pos2:n}=o,{x1:r,y1:s,x2:a,y2:p}=await T(t,e,i,n),c=N({x1:r,x2:a,y1:s,y2:p},{direction:""}),{firstPoint:l,firstControl:h,lastControl:d,lastPoint:f}=c;return`M ${l.x} ${l.y}C ${h.x} ${h.y}, ${d.x} ${d.y}, ${f.x} ${f.y}`})(this.startElement,this.stopElement,{pos1:n,pos2:r});this.line.setAttribute("data-direction",i),this.line.setAttribute("data-pos1",n),this.line.setAttribute("data-pos2",r),this.line.setAttribute("d",s)}}window.DrawSVGLine=k;class q{#t;#e;startElement;stopElement;firstPathElement;secondPathElement;constructor(t,e){this.#o(t,e)}#o(t,e){if(!t||!e)throw new Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw new Error("stopElement is not in the DOM");if(!document.body.contains(t))throw new Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#e=document.getElementById("ph-speccer-path"),!this.#e||!this.#t)throw new Error("Missing required SVG element to draw lines. Please see the documentation");this.connect()}connect(){this.draw(this.#e)}#i(t){if(!t)throw new Error("No path given to #getPathElement!");const e=`ph_draw_path-path-${A()}`,o=t.cloneNode(!1);return o.setAttribute("data-start-el",this.startElement.getAttribute("id")||"no-id-found"),o.setAttribute("id",e),o.classList.remove("original"),o.classList.add("speccer"),o}async draw(t){if(!t)throw new Error("No path given to draw!");const e=this.#i(t),o=this.#i(t);if(!t.parentNode)throw new Error("No parentNode found for path");this.firstPathElement=t.parentNode.insertBefore(e,t.nextSibling),this.secondPathElement=t.parentNode.insertBefore(o,t.nextSibling);const i=await I({stop:this.stopElement,start:this.startElement,crude:!0}),{path1pos1:n,path1pos2:r,path2pos1:s,path2pos2:a}=(t=>{let e,o,i,n;switch(t){case"east":e="right-top",o="left-center",i="right-bottom",n="left-center";break;case"south":e="bottom-left",o="top-center",i="bottom-right",n="top-center";break;case"west":e="left-top",o="right-center",i="left-bottom",n="right-center";break;default:e="top-left",o="bottom-center",i="top-right",n="bottom-center"}return{path1pos1:e,path1pos2:o,path2pos1:i,path2pos2:n}})(i),p=await M(this.startElement,this.stopElement,{pos1:n,pos2:r,firstSet:!0,direction:i}),c=await M(this.startElement,this.stopElement,{pos1:s,pos2:a,direction:i});this.firstPathElement.setAttribute("data-direction",i),this.firstPathElement.setAttribute("data-pos1",n),this.firstPathElement.setAttribute("data-pos2",r),this.firstPathElement.setAttribute("d",p),this.secondPathElement.setAttribute("data-direction",i),this.secondPathElement.setAttribute("data-pos1",s),this.secondPathElement.setAttribute("data-pos2",a),this.secondPathElement.setAttribute("d",c)}}window.DrawSVGCurlyBracket=q;const H=async(t,e,o,i)=>{const{isCurly:s=!1}=i||{},a=r(o),p=n(getComputedStyle(o).getPropertyValue("--ph-speccer-measure-size"))||8;const c=await d(o,e);if($(t)){const{left:t,top:e,height:o,width:i}=c.absolute();return{left:`${t}px`,top:`${e}px`,height:`${o}px`,width:`${i}px`}}if(y(t).includes(g.Left)){if(E(t)&&!s){const{left:t,top:e,height:o}=c.fromLeft({sourceWidth:p});return{left:`${t}px`,top:`${e}px`,height:`${o}px`}}{const{left:t,top:e}=c.fromLeft({center:!0,modifier:s?a/1.5:a});return{left:`${t}px`,top:`${e}px`}}}if(x(t)){if(E(t)&&!s){const{left:t,top:e,height:o}=c.fromRight({center:!1});return{left:`${t}px`,top:`${e}px`,height:`${o}px`}}{const{left:t,top:e}=c.fromRight({center:!0,modifier:s?a/1.5:a});return{left:`${t}px`,top:`${e}px`}}}if(b(t)){if(E(t)&&!s){const{left:t,top:e,width:o}=c.fromBottom({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${o}px`}}{const{left:t,top:e}=c.fromBottom({center:!0,modifier:s?a/1.5:a});return{left:`${t}px`,top:`${e}px`}}}if(E(t)&&!s){const{left:t,top:e,width:o}=c.fromTop({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${o}px`}}{const{left:t,top:e}=c.fromTop({center:!0,modifier:s?a/1.5:a});return{left:`${t}px`,top:`${e}px`}}},j=(t="",i,n="span")=>{const r=document.createElement(n),s=document.createTextNode(t),a={};null!==i&&""!==i&&(a[i]=!0),!E(i)&&!$(i)||E(i)&&v(i)?r.appendChild(s):(E(i)||$(i))&&r.setAttribute("data-dissection-counter",t);const p=o("ph-speccer speccer dissection",a);return e(r,p),r},V=t=>{if(!t)return Promise.resolve();const e=t.querySelectorAll("[data-anatomy]");if(e){let t=0;e.forEach((async(e,o)=>{if(!e)return Promise.resolve();const n=e.getAttribute("data-anatomy")||"";if(!n||""===n||-1===n.indexOf(g.Outline))return Promise.resolve();let r=i[o];r||(r=`${i[t]}${i[t].toLowerCase()}`,t++);const s=j(r,n);document.body.appendChild(s);const p=await H(n,e,s,{isCurly:v(n)});var c;await a(s,p),(c=n).includes(g.SVG)||c.includes(g.Curly)||c.includes(g.Full)||c.includes(g.Enclose)?new k(e,s):v(n)&&new q(e,s)}))}return Promise.resolve()},W=(t="",o="",i="span")=>{const n=document.createElement(i);return n.setAttribute("title",t+"px"),n.setAttribute("data-measure",parseInt(t+"",10)+"px"),e(n,`ph-speccer speccer measure ${o}`),n},z=async t=>{if(!t)return;const e=t.getAttribute("data-speccer-measure");if(""===e||!e)return;const o=await p(t);if("none"===o.display||"0"===o.opacity||"hidden"===o.visibility)return;await s();const i=t.getBoundingClientRect();if(y(e).includes(w.Width))if(b(e)){const o=W(i.width,e);document.body.appendChild(o);const n=await d(o,t),{left:r,top:s,width:p}=n.fromBottom({center:!1});await a(o,{left:`${r}px`,top:`${s}px`,width:`${p}px`})}else{const o=W(i.width,e);document.body.appendChild(o);const n=await d(o,t),{left:r,top:s,width:p}=n.fromTop({center:!1,modifier:-8});await a(o,{left:`${r}px`,top:`${s}px`,width:`${p}px`})}else if((t=>y(t).includes(w.Height))(e))if(x(e)){const o=W(i.height,e);document.body.appendChild(o);const n=await d(o,t),{left:r,top:s,height:p}=n.fromRight({center:!1});await a(o,{left:`${r}px`,top:`${s}px`,height:`${p}px`})}else{const o=W(i.height,e);document.body.appendChild(o);const n=await d(o,t),{left:r,top:s,height:p}=n.fromLeft({center:!1,modifier:-8});await a(o,{left:`${r}px`,top:`${s}px`,height:`${p}px`})}},F=(t="span")=>{const i=document.createElement(t),n=o("ph-speccer speccer mark");return e(i,n),i},D=async t=>{if(!t)return Promise.resolve();const e=F();document.body.appendChild(e);const o=await d(e,t),{left:i,top:n,height:r,width:s}=o.absolute(),p={left:`${i}px`,top:`${n}px`,height:`${r}px`,width:`${s}px`};await a(e,p)},G=(t,e=3)=>parseFloat(t+"").toFixed(e),_=(t,i)=>{const n=document.createElement("div"),r={};null!==i&&""!==i&&(r[i]=!0);const s=o("ph-speccer speccer typography",r);return n.innerHTML=t,e(n,s),n},X=async t=>{if(!t)return;const e=t.getAttribute("data-speccer-typography"),o=await p(t);if("none"===o.display||"0"===o.opacity||"hidden"===o.visibility)return;t.classList.add("is-specced");const i=await(async t=>{const e=(t=>{const{lineHeight:e,letterSpacing:o,fontFamily:i,fontSize:n,fontStyle:r,fontVariationSettings:s,fontWeight:a}=t;return{lineHeight:e,letterSpacing:o,fontFamily:i,fontSize:n,fontStyle:r,fontVariationSettings:s,fontWeight:a}})(await p(t)),o="normal"!==e.lineHeight?parseInt(e.lineHeight,10)/16+"rem":"normal";return`\nfont-styles: {
  • font-family: ${e.fontFamily};
  • font-size: ${e.fontSize} / ${parseInt(e.fontSize,10)/16}rem;
  • font-weight: ${e.fontWeight};
  • font-variation-settings: ${e.fontVariationSettings};
  • line-height: ${e.lineHeight} / ${o};
  • letter-spacing: ${e.letterSpacing};
  • font-style: ${e.fontStyle};
}`})(t),n=_(i,e);document.body.appendChild(n);const s=await(async(t,e,o)=>{const i=e.getBoundingClientRect(),n=r(o),s=o.getBoundingClientRect(),a=await h(e),p=a.left-s.width-n+"px",d=G(l(a.top,s,i))+"px",f=a.left+i.width+n+"px",u=G(l(a.top,s,i))+"px",g=G(c(a.left,s,i))+"px",w=a.top-s.height-n+"px",y=G(c(a.left,s,i))+"px",x=a.top+i.height+n+"px";let b={left:p,top:d};return t&&-1!==t.indexOf(m.Right)?b={left:f,top:u}:t&&-1!==t.indexOf(m.Top)?b={left:g,top:w}:t&&-1!==t.indexOf(m.Bottom)&&(b={left:y,top:x}),b})(e,t,n);a(n,s)},Y=t=>{const e=()=>((t,e,o=!1)=>{let i;return function(n,...r){const s=o&&!i;i&&clearTimeout(i),i=setTimeout((function(){i=null,o||t.apply(n,r)}),e),s&&t.apply(n,r)}})((()=>{t()}),300);window.removeEventListener("resize",e),window.addEventListener("resize",e)},J=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},K=()=>{const t=new IntersectionObserver(((t,e)=>{t.forEach((t=>{t.intersectionRatio>0&&(u(t.target),e.unobserve(t.target))}))}));document.querySelectorAll("[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)").forEach((e=>{t.observe(e)}));const e=new IntersectionObserver(((t,e)=>{t.forEach((t=>{t.intersectionRatio>0&&(z(t.target),e.unobserve(t.target))}))}));document.querySelectorAll("[data-speccer-measure]").forEach((t=>{e.observe(t)}));const o=new IntersectionObserver(((t,e)=>{t.forEach((t=>{t.intersectionRatio>0&&(V(t.target),e.unobserve(t.target))}))}));document.querySelectorAll("[data-anatomy-section]").forEach((t=>{o.observe(t)}))},Q=t=>{window.speccer=t},U=t=>{const e=document.currentScript;if(e){const o=e.getAttribute("src");!o||-1===o.indexOf("speccer.js")&&-1===o.indexOf("JaXpOK.js")||(e.hasAttribute("data-manual")?Q(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?J(t):e.hasAttribute("data-lazy")?K():J(t),e.hasAttribute("data-manual")||e.hasAttribute("data-lazy")||Y(t))}},Z={create:f,element:u},tt={create:j,element:V},et={create:W,element:z},ot={create:F,element:D},it={create:_,element:X},nt={dom:J,lazy:K,manual:Q,activate:U},rt=()=>{((t,e=document)=>{[].forEach.call(e.querySelectorAll(t),(function(t){t.remove()}))})(".speccer");const t=document.querySelectorAll("[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)"),e=document.querySelectorAll("[data-speccer-measure]"),o=document.querySelectorAll("[data-speccer-typography]"),i=document.querySelectorAll("[data-anatomy-section]");document.querySelectorAll("[data-speccer-mark]").forEach(D),t.forEach(u),e.forEach(z),o.forEach(X),i.forEach(V)};U(rt),t.default=rt,t.dissect=tt,t.mark=ot,t.measure=et,t.modes=nt,t.spacing=Z,t.typography=it,Object.defineProperty(t,"__esModule",{value:!0})})); //# sourceMappingURL=speccer.js.map diff --git a/speccer.js.map b/speccer.js.map index c65b7628..7e7a19c2 100644 --- a/speccer.js.map +++ b/speccer.js.map @@ -1 +1 @@ -{"version":3,"file":"speccer.js","sources":["src/utils/node.ts","src/utils/classnames.ts","src/utils/constants.ts","src/utils/css.ts","src/utils/wait.ts","src/utils/styles.ts","src/utils/position.ts","src/features/spacing/index.ts","src/features/spacing/utils/position.ts","src/types/enums/area.ts","src/utils/area.ts","src/utils/id.ts","src/utils/coords.ts","src/utils/xy.ts","src/utils/intrinsic-coords.ts","src/utils/get-coords-pair-from-objects.ts","src/utils/bezier.ts","src/utils/direction-of-element.ts","src/utils/angle.ts","src/utils/cardinal.ts","src/utils/classes/DrawSVGLine.ts","src/utils/classes/DrawSVGCurlyBracket.ts","src/features/dissect/utils/styles.ts","src/features/dissect/index.ts","src/features/measure/index.ts","src/features/mark/index.ts","src/utils/number.ts","src/features/typography/index.ts","src/features/typography/utils/template.ts","src/features/typography/utils/position.ts","src/utils/resize.ts","src/utils/debounce.ts","src/config/browser.ts","src/main.ts"],"sourcesContent":["/**\n * Inserts an HTML element after another element in the DOM.\n *\n * @param {HTMLElement | null} el - The reference element after which the new element will be inserted.\n * @param {HTMLElement} newSibling - The new element to be inserted.\n * @returns {Element|null}\n *\n * @example\n * ```ts\n * // Insert an element after another element\n * const referenceElement = document.getElementById('reference-element');\n * const newElement = document.createElement('div');\n * after(referenceElement, newElement);\n */\nexport const after = (\n el: HTMLElement | null,\n newSibling: HTMLElement\n): Element | null => el && el.insertAdjacentElement('afterend', newSibling);\n\n/**\n * Removes all elements matching a selector from the DOM.\n *\n * @param {string} selector - The CSS selector used to select elements for removal.\n * @param {Document} el - The document context (default is the global `document` object).\n * @returns {void}\n *\n * @example\n * ```ts\n * // Remove all elements with a specific class from the document\n * removeAll('.my-class');\n * ```\n */\nexport const removeAll = (selector: string, el: Document = document): void => {\n [].forEach.call(el.querySelectorAll(selector), function (e: HTMLElement) {\n e.remove();\n });\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport { ClassNamesObjectMapInterface } from 'types/interfaces/classnames';\n\n/**\n * Add CSS classes to an HTML element.\n *\n * @param {HTMLElement} el - The HTML element to which classes should be added.\n * @param {string} cls - The CSS classes to add, separated by spaces.\n * @param {string} [avoid='noop'] - Classes to avoid adding.\n * @returns {void}\n * @example\n * ```ts\n * // Add classes to an HTML element\n * const element = document.getElementById('example');\n * set(element, 'class1 class2');\n * ```\n */\nexport const set = (el: HTMLElement, cls: string, avoid = 'noop') => {\n if (!el) return;\n\n if (!cls || (cls && cls.length === 0)) return;\n\n cls\n .trim()\n .split(' ')\n .filter((cl) => cl !== avoid)\n .forEach((cl) => el.classList.add(cl));\n};\n\n/**\n * Toggle CSS classes on an HTML element.\n *\n * @param {HTMLElement} el - The HTML element on which classes should be toggled.\n * @param {string} cls - The CSS classes to toggle, separated by spaces.\n * @param {string} [avoid='noop'] - Classes to avoid toggling.\n * @returns {void}\n * @example\n * ```ts\n * // Toggle classes on an HTML element\n * const element = document.getElementById('example');\n * toggle(element, 'class1 class2');\n * ```\n */\nexport const toggle = (el: HTMLElement, cls: string, avoid = 'noop') => {\n if (!el) return;\n\n if (!cls || (cls && cls.length === 0)) return;\n\n cls\n .trim()\n .split(' ')\n .filter((cl) => cl !== avoid)\n .forEach((cl) => el.classList.toggle(cl));\n};\n\n/**\n * Remove CSS classes from an HTML element.\n *\n * @param {HTMLElement} el - The HTML element from which classes should be removed.\n * @param {string} cls - The CSS classes to remove, separated by spaces.\n * @param {string} [avoid='noop'] - Classes to avoid removing.\n * @returns {void}\n * @example\n * ```ts\n * // Remove classes from an HTML element\n * const element = document.getElementById('example');\n * remove(element, 'class1 class2');\n * ```\n */\nexport const remove = (el: HTMLElement, cls: string, avoid = 'noop') => {\n if (!el) return;\n\n if (!cls || (cls && cls.length === 0)) return;\n\n cls\n .trim()\n .split(' ')\n .filter((cl) => cl !== avoid)\n .forEach((cl) => el.classList.remove(cl));\n};\n\n/**\n * Generate CSS classes from a string and an object.\n *\n * @param {string} cls - Additional CSS classes as a string.\n * @param {ClassNamesObjectMapInterface} cls_obj - A mapping of class names to boolean values.\n * @returns {string} - A space-separated string of CSS class names.\n * @example\n * ```ts\n * // Generate CSS classes from a string and an object\n * const classNames = cx('class1', { class2: true, class3: false });\n * console.log(classNames); // Example output: 'class1 class2'\n * ```\n */\nexport const cx = (\n cls: string,\n cls_obj?: ClassNamesObjectMapInterface\n): string => {\n if (!cls) return '';\n\n if (!cls_obj && typeof cls !== 'string') {\n return `${Object.keys(cls)\n .filter((classname) => cls[classname])\n .join(' ')}`.trim();\n }\n\n return `${cls} ${\n cls_obj\n ? Object.keys(cls_obj)\n .filter((classname) => cls_obj[classname])\n .join(' ')\n : ''\n }`.trim();\n};\n","/* eslint no-console:0 */\n'use strict';\n\n/**\n * Array of uppercase letters.\n *\n * @type {string[]}\n * @example\n * ```ts\n * // Access the array of uppercase letters\n * const letters = SPECCER_LITERALS;\n * console.log(letters); // Example output: ['A', 'B', 'C', ...]\n * ```\n */\nexport const SPECCER_LITERALS = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'];\n\n/**\n * Array of HTML tags to avoid when processing.\n *\n * @type {string[]}\n * @example\n * ```ts\n * // Access the array of tags to avoid\n * const tagsToAvoid = SPECCER_TAGS_TO_AVOID;\n * console.log(tagsToAvoid); // Example output: ['TR', 'TH', 'TD', ...]\n * ```\n */\nexport const SPECCER_TAGS_TO_AVOID = [\n 'TR',\n 'TH',\n 'TD',\n 'TBODY',\n 'THEAD',\n 'TFOOT'\n];\n\n/**\n * Default value for pin space.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the default pin space value\n * const defaultPinSpace = SPECCER_DEFAULT_PIN_SPACE;\n * console.log(defaultPinSpace); // Example output: 48\n * ```\n */\nexport const SPECCER_DEFAULT_PIN_SPACE = 48;\n\n/**\n * Negative default value for pin space.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the negative default pin space value\n * const negativeDefaultPinSpace = SPECCER_DEFAULT_PIN_SPACE_NEG;\n * console.log(negativeDefaultPinSpace); // Example output: -48\n * ```\n */\nexport const SPECCER_DEFAULT_PIN_SPACE_NEG = SPECCER_DEFAULT_PIN_SPACE * -1;\n\n/**\n * Default value for measure size.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the default measure size value\n * const defaultMeasureSize = SPECCER_DEFAULT_MEASURE_SIZE;\n * console.log(defaultMeasureSize); // Example output: 8\n * ```\n */\nexport const SPECCER_DEFAULT_MEASURE_SIZE = 8;\n\n/**\n * Negative default value for measure size.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the negative default measure size value\n * const negativeDefaultMeasureSize = SPECCER_DEFAULT_MEASURE_SIZE_NEG;\n * console.log(negativeDefaultMeasureSize); // Example output: -8\n * ```\n */\nexport const SPECCER_DEFAULT_MEASURE_SIZE_NEG =\n SPECCER_DEFAULT_MEASURE_SIZE * -1;\n\n/**\n * Default line width value.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the default line width value\n * const defaultLineWidth = SPECCER_DEFAULT_LINE_WIDTH;\n * console.log(defaultLineWidth); // Example output: 1\n * ```\n */\nexport const SPECCER_DEFAULT_LINE_WIDTH = 1;\n","/* eslint no-console:0 */\n'use strict';\nimport {\n SPECCER_DEFAULT_PIN_SPACE,\n SPECCER_DEFAULT_MEASURE_SIZE,\n SPECCER_DEFAULT_LINE_WIDTH\n} from './constants';\nimport {\n SpacingCSSPropertiesType,\n TypographyCSSPropertiesType\n} from '../types/css';\n\n/**\n * Parses a string value into an integer.\n *\n * @param {string} value - The string value to parse.\n * @returns {number} - The parsed integer value.\n *\n * @example\n * ```ts\n * // Parse a string value into an integer\n * const intValue = getNumberValue(\"42\");\n * console.log(intValue); // Example output: 42\n * ```\n */\nexport const getNumberValue = (value: string): number => parseInt(value, 10);\n\n/**\n * Normalizes a string or number value to ensure it's a valid number.\n * If the value is within the range [0, 1] or [-1, 0), it's normalized to 0.\n *\n * @param {string | number} value - The value to normalize.\n * @returns {number} - The normalized number value.\n *\n * @example\n * ```ts\n * // Normalize a value to ensure it's a valid number\n * const normalizedValue = normalizeNumberValue(\"0.5\");\n * console.log(normalizedValue); // Example output: 0.5\n * ```\n */\nexport const normalizeNumberValue = (value: string | number): number => {\n const _value = parseFloat(value + '');\n\n return (_value >= 0 && _value < 1) || (_value <= 0 && _value > -1)\n ? 0\n : _value;\n};\n\n/**\n * Converts a CSS property name with \"Top\", \"Right\", \"Bottom\", or \"Left\" into a class name.\n *\n * @param {string} property - The CSS property name.\n * @returns {string} - The corresponding class name.\n *\n * @example\n * ```ts\n * // Convert a CSS property name to a class name\n * const className = getClassNameFromCSSProperty(\"marginTop\");\n * console.log(className); // Example output: \"margin top\"\n * ```\n */\nexport const getClassNameFromCSSProperty = (property: string): string => {\n if (property.indexOf('Top') !== -1) {\n return property.replace('Top', ' top');\n } else if (property.indexOf('Right') !== -1) {\n return property.replace('Right', ' right');\n } else if (property.indexOf('Bottom') !== -1) {\n return property.replace('Bottom', ' bottom');\n } else if (property.indexOf('Left') !== -1) {\n return property.replace('Left', ' left');\n }\n\n return '';\n};\n\n/**\n * Extracts spacing-related CSS properties from a style object.\n *\n * @param {SpacingCSSPropertiesType} style - The style object.\n * @returns {SpacingCSSPropertiesType} - The extracted spacing-related properties.\n *\n * @example\n * ```ts\n * // Extract spacing-related properties from a style object\n * const spacing = getSpacing({\n * marginTop: \"10px\",\n * marginLeft: \"20px\",\n * });\n * console.log(spacing); // Example output: { marginTop: \"10px\", marginLeft: \"20px\" }\n * ```\n */\nexport const getSpacing = (\n style: SpacingCSSPropertiesType\n): SpacingCSSPropertiesType => {\n const {\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n paddingTop,\n paddingBottom,\n paddingLeft,\n paddingRight\n } = style;\n\n return {\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n paddingTop,\n paddingBottom,\n paddingLeft,\n paddingRight\n };\n};\n\n/**\n * Extracts typography-related CSS properties from a style object.\n *\n * @param {TypographyCSSPropertiesType} style - The style object.\n * @returns {TypographyCSSPropertiesType} - The extracted typography-related properties.\n *\n * @example\n * ```ts\n * // Extract typography-related properties from a style object\n * const typography = getTypography({\n * fontSize: \"16px\",\n * fontWeight: \"bold\",\n * });\n * console.log(typography); // Example output: { fontSize: \"16px\", fontWeight: \"bold\" }\n * ```\n */\nexport const getTypography = (\n style: TypographyCSSPropertiesType\n): TypographyCSSPropertiesType => {\n const {\n lineHeight,\n letterSpacing,\n fontFamily,\n fontSize,\n fontStyle,\n fontVariationSettings,\n fontWeight\n } = style;\n\n return {\n lineHeight,\n letterSpacing,\n fontFamily,\n fontSize,\n fontStyle,\n fontVariationSettings,\n fontWeight\n };\n};\n\n/**\n * Retrieves the value of a custom CSS property \"--ph-speccer-pin-space\" from an element.\n *\n * @param {HTMLElement} el - The HTML element.\n * @returns {number} - The parsed value of the CSS property or a default value.\n *\n * @example\n * ```ts\n * // Get the value of a custom CSS property from an element\n * const value = pinSpace(document.body);\n * console.log(value); // Example output: 10\n * ```\n */\nexport const pinSpace = (el: HTMLElement): number =>\n getNumberValue(\n getComputedStyle(el).getPropertyValue('--ph-speccer-pin-space')\n ) || SPECCER_DEFAULT_PIN_SPACE;\n\n/**\n * Retrieves the value of a custom CSS property \"--ph-speccer-measure-size\" from an element.\n *\n * @param {HTMLElement} el - The HTML element.\n * @returns {number} - The parsed value of the CSS property or a default value.\n *\n * @example\n * ```ts\n * // Get the value of a custom CSS property from an element\n * const value = measureSize(document.body);\n * console.log(value); // Example output: 20\n * ```\n */\nexport const measureSize = (el: HTMLElement): number =>\n getNumberValue(\n getComputedStyle(el).getPropertyValue('--ph-speccer-measure-size')\n ) || SPECCER_DEFAULT_MEASURE_SIZE;\n\n/**\n * Retrieves the value of a custom CSS property \"--ph-speccer-line-width\" from an element.\n *\n * @param {HTMLElement} el - The HTML element.\n * @returns {number} - The parsed value of the CSS property or a default value.\n *\n * @example\n * ```ts\n * // Get the value of a custom CSS property from an element\n * const value = lineWidth(document.body);\n * console.log(value); // Example output: 1.5\n * ```\n */\nexport const lineWidth = (el: HTMLElement): number =>\n getNumberValue(\n getComputedStyle(el).getPropertyValue('--ph-speccer-line-width')\n ) || SPECCER_DEFAULT_LINE_WIDTH;\n","/**\n * Waits for the specified amount of time in milliseconds.\n *\n * @param {number} ms - The number of milliseconds to wait.\n * @returns {Promise} - A Promise that resolves after the specified time.\n *\n * @example\n * ```ts\n * // Wait for 1 second (1000 milliseconds)\n * await waitFor(1000);\n * ```\n */\nexport const waitFor = (ms: number): Promise =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Waits for the next animation frame using requestAnimationFrame.\n *\n * @returns {Promise} - A Promise that resolves with the timestamp of the next animation frame.\n *\n * @example\n * ```ts\n * // Wait for the next animation frame and get the rect\n * await waitForFrame();\n * const rect = el.getBoundingClientRect();\n * // Wait for the next animation frame and get the timestamp\n * const timestamp = await waitForFrame();\n * ```\n */\nexport const waitForFrame = (): Promise =>\n new Promise(requestAnimationFrame);\n","/* eslint no-console:0 */\n'use strict';\nimport { waitForFrame } from './wait';\n\n/**\n * Adds CSS styles to an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to apply styles to.\n * @param {object | Array<{ key: string; value: string }>} styles - An object or an array of objects containing CSS styles to apply.\n * @returns {Promise} - A Promise that resolves after styles are applied.\n *\n * @example\n * ```ts\n * // Apply styles as an object\n * const element = document.getElementById('my-element');\n * await add(element, { color: 'red', fontSize: '16px' });\n *\n * // Apply styles as an array of objects\n * const styles = [\n * { key: 'color', value: 'blue' },\n * { key: 'backgroundColor', value: 'yellow' }\n * ];\n * await add(element, styles);\n * ```\n */\nexport const add = async (\n el: HTMLElement,\n styles: object | Array<{ key: string; value: string }>\n): Promise => {\n if (\n !el ||\n !styles ||\n typeof styles === 'string' ||\n typeof styles === 'number' ||\n typeof styles === 'boolean' ||\n (Array.isArray(styles) && styles.length === 0) ||\n (Object.keys(styles).length === 0 && styles.constructor === Object)\n ) {\n return;\n }\n\n await waitForFrame();\n\n if (Array.isArray(styles)) {\n styles.forEach(\n (style: { key: string; value: string }) =>\n (el.style[style.key] = style.value)\n );\n } else {\n Object.keys(styles).forEach((key) => (el.style[key] = styles[key]));\n }\n};\n\n/**\n * Gets the computed CSS styles of an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to get computed styles from.\n * @returns {Promise} - A Promise that resolves with the computed CSS styles.\n *\n * @example\n * ```ts\n * // Get computed styles of an element\n * const element = document.getElementById('my-element');\n * const computedStyles = await get(element);\n * console.log(computedStyles.color); // Logs the color property value\n * ```\n */\nexport const get = async (el: HTMLElement): Promise => {\n await waitForFrame();\n\n return getComputedStyle(el, null);\n};\n","import { waitForFrame } from './wait';\n\nimport { PositionPropertiesType, PositionInputType } from '../types/position';\nimport { GetRecPropertiesInterface } from 'types/interfaces/position';\n\n/**\n * Calculates the horizontal center of two elements.\n *\n * @param {number} modifier - A modifier value.\n * @param {DOMRect} startRect - The starting element's rectangle.\n * @param {DOMRect} targetRect - The target element's rectangle.\n * @returns {number} - The horizontal center position.\n *\n * @example\n * ```ts\n * // Calculate the horizontal center of two elements\n * const center = get_horizontal_center_of_els(0, startRect, targetRect);\n * ```\n */\nexport const get_horizontal_center_of_els = (\n modifier: number,\n startRect: DOMRect,\n targetRect: DOMRect\n): number => modifier - startRect.width / 2 + targetRect.width / 2;\n\n/**\n * Calculates the vertical center of two elements.\n *\n * @param {number} modifier - A modifier value.\n * @param {DOMRect} startRect - The starting element's rectangle.\n * @param {DOMRect} targetRect - The target element's rectangle.\n * @returns {number} - The vertical center position.\n *\n * @example\n * ```ts\n * // Calculate the vertical center of two elements\n * const center = get_vertical_center_of_els(0, startRect, targetRect);\n * ```\n */\nexport const get_vertical_center_of_els = (\n modifier: number,\n startRect: DOMRect,\n targetRect: DOMRect\n): number => modifier - startRect.height / 2 + targetRect.height / 2;\n\n/**\n * Gets the offset properties of an HTML element.\n *\n * @param {HTMLElement} targetEl - The target HTML element.\n * @returns {Promise} - A promise that resolves to the offset properties.\n *\n * @example\n * ```ts\n * // Get the offset properties of an element\n * const offsetProps = await offset(targetElement);\n * ```\n */\nexport const offset = async (\n targetEl: HTMLElement\n): Promise => {\n await waitForFrame();\n\n const _target_rect = targetEl.getBoundingClientRect();\n const _el_offset_top = _target_rect.top + window.scrollY;\n const _el_offset_left = _target_rect.left + window.scrollX;\n\n return {\n height: _target_rect.height,\n width: _target_rect.width,\n top: _el_offset_top,\n left: _el_offset_left\n };\n};\n\n/**\n * Gets the offset properties of an HTML element with its center aligned to another element.\n *\n * @param {HTMLElement} sourceEl - The source HTML element.\n * @param {HTMLElement} targetEl - The target HTML element.\n * @returns {Promise} - A promise that resolves to the offset properties.\n *\n * @example\n * ```ts\n * // Get the offset properties of an element with its center aligned to another element\n * const offsetProps = await offsetWithCenter(sourceElement, targetElement);\n * ```\n */\nexport const offsetWithCenter = async (\n sourceEl: HTMLElement,\n targetEl: HTMLElement\n): Promise => {\n await waitForFrame();\n\n const _source_rect = sourceEl.getBoundingClientRect();\n const _target_rect = targetEl.getBoundingClientRect();\n const _el_offset_top = _target_rect.top + window.scrollY;\n const _el_offset_left = _target_rect.left + window.scrollX;\n\n return {\n height: _target_rect.height,\n width: _target_rect.width,\n top: get_vertical_center_of_els(_el_offset_top, _source_rect, _target_rect),\n left: get_horizontal_center_of_els(\n _el_offset_left,\n _source_rect,\n _target_rect\n )\n };\n};\n\n/**\n * Gets various positioning properties between two HTML elements.\n *\n * @param {HTMLElement} sourceEl - The source HTML element.\n * @param {HTMLElement} targetEl - The target HTML element.\n * @returns {Promise} - A promise that resolves to an object with positioning functions.\n *\n * @example\n * ```ts\n * // Get positioning properties between two elements\n * const recProps = await getRec(sourceElement, targetElement);\n *\n * // Get the absolute position properties\n * const absoluteProps = recProps.absolute();\n *\n * // Get the position properties with the source element above the target element\n * const aboveProps = recProps.toTop();\n * ```\n */\nexport const getRec = async (\n sourceEl: HTMLElement,\n targetEl: HTMLElement\n): Promise => {\n await waitForFrame();\n\n const _source_rect = sourceEl.getBoundingClientRect();\n const _target_offset = await offset(targetEl);\n const _target_offset_center = await offsetWithCenter(sourceEl, targetEl);\n const _target_height = _target_offset.height;\n const _target_width = _target_offset.width;\n const _source_height = _source_rect.height;\n const _source_width = _source_rect.width;\n\n return {\n absolute: (): PositionPropertiesType => {\n return {\n top: _target_offset.top,\n left: _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n toTop: ({\n center = false,\n sourceHeight = _source_height,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: _target_offset.top + sourceHeight + modifier,\n left: center ? _target_offset_center.left : _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n\n fromTop: ({\n center = false,\n sourceHeight = _source_height,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: _target_offset.top - sourceHeight - modifier,\n left: center ? _target_offset_center.left : _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n\n toBottom: ({\n center = false,\n sourceHeight = _source_height,\n targetHeight = _target_height,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: _target_offset.top + targetHeight - (sourceHeight + modifier),\n left: center ? _target_offset_center.left : _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n fromBottom: ({\n center = false,\n targetHeight = _target_height,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: _target_offset.top + targetHeight + modifier,\n left: center ? _target_offset_center.left : _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n\n toLeft: ({\n center = false,\n sourceWidth = _source_width,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: center ? _target_offset_center.top : _target_offset.top,\n left: _target_offset.left + sourceWidth + modifier,\n height: _target_height,\n width: _target_width\n };\n },\n\n fromLeft: ({\n center = false,\n sourceWidth = _source_width,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: center ? _target_offset_center.top : _target_offset.top,\n left: _target_offset.left - sourceWidth - modifier,\n height: _target_height,\n width: _target_width\n };\n },\n\n toRight: ({\n center = false,\n sourceWidth = _source_width,\n targetWidth = _target_width,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: center ? _target_offset_center.top : _target_offset.top,\n left: _target_offset.left + targetWidth - (sourceWidth + modifier),\n height: _target_height,\n width: _target_width\n };\n },\n\n fromRight: ({\n center = false,\n targetWidth = _target_width,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: center ? _target_offset_center.top : _target_offset.top,\n left: _target_offset.left + targetWidth + modifier,\n height: _target_height,\n width: _target_width\n };\n }\n };\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport { set as setClassNames } from '../../utils/classnames';\nimport {\n getSpacing,\n getClassNameFromCSSProperty,\n getNumberValue\n} from '../../utils/css';\nimport { get as getStyles } from '../../utils/styles';\nimport { position } from './utils/position';\n\n/**\n * Create a spacing element with optional text content.\n *\n * @param {string | number} text - The optional text content for the spacing element.\n * @param {string} tag - The HTML tag for the element (default is 'span').\n * @returns {HTMLElement} - The created spacing element.\n *\n * @example\n * ```ts\n * const spacingElement = create(20, 'div');\n * document.body.appendChild(spacingElement);\n * ```\n */\nexport const create = (\n text: string | number = '',\n tag = 'span'\n): HTMLElement => {\n const _el = document.createElement(tag);\n const _text_content = document.createTextNode(text + '');\n\n _el.appendChild(_text_content);\n _el.setAttribute('title', text + 'px');\n setClassNames(_el, 'ph speccer spacing');\n\n return _el;\n};\n\n/**\n * Create and position spacing elements based on the target element's computed spacing styles.\n *\n * @param {HTMLElement} targetEl - The target element to create spacing elements for.\n * @returns {Promise} - A promise that resolves after creating and positioning the spacing elements.\n *\n * @example\n * ```ts\n * const targetElement = document.getElementById('target');\n * element(targetElement);\n * ```\n */\nexport const element = async (targetEl: HTMLElement): Promise => {\n if (!targetEl) return;\n\n const _target_styles = await getStyles(targetEl);\n\n if (\n _target_styles.display === 'none' ||\n _target_styles.opacity === '0' ||\n _target_styles.visibility === 'hidden'\n ) {\n return;\n }\n\n const _target_spacing_styles = getSpacing(_target_styles);\n const _target_pruned_spacing_styles = Object.keys(\n _target_spacing_styles\n ).filter((property) => {\n const _value = _target_spacing_styles[property];\n\n return _value !== '0px';\n });\n\n if (_target_pruned_spacing_styles.length === 0) return;\n\n _target_pruned_spacing_styles.forEach(async (property) => {\n const _value = getNumberValue(_target_spacing_styles[property]);\n const _speccer_el = create(_value);\n const _class_name = getClassNameFromCSSProperty(property);\n\n setClassNames(_speccer_el, _class_name);\n document.body.appendChild(_speccer_el);\n\n targetEl.classList.add('is-specced');\n await position(property, _value, _speccer_el, targetEl);\n });\n};\n","import { add as addStyles } from '../../../utils/styles';\nimport { offset } from '../../../utils/position';\nimport { waitForFrame } from '../../../utils/wait';\n\n/**\n * Set the position and dimensions of a spacing element relative to a target element.\n *\n * @param {string} property - The CSS property to set (e.g., 'marginTop', 'marginLeft', etc.).\n * @param {number} value - The value of the CSS property.\n * @param {HTMLElement} spacingEl - The spacing element.\n * @param {HTMLElement} targetEl - The target element.\n * @returns {Promise} - A promise that resolves after setting the position and dimensions.\n *\n * @example\n * ```ts\n * const spacingElement = document.getElementById('spacing');\n * const targetElement = document.getElementById('target');\n * position('marginTop', 20, spacingElement, targetElement);\n * ```\n */\nexport const position = async (\n property: string,\n value: number,\n spacingEl: HTMLElement,\n targetEl: HTMLElement\n): Promise => {\n await waitForFrame();\n\n const _target_rect = targetEl.getBoundingClientRect();\n const _target_offset = await offset(targetEl);\n\n if (property === 'marginTop') {\n addStyles(spacingEl, {\n height: `${value}px`,\n width: _target_rect.width + 'px',\n left: _target_offset.left + 'px',\n top: _target_offset.top - value + 'px'\n });\n }\n\n if (property === 'marginRight') {\n addStyles(spacingEl, {\n height: _target_rect.height + 'px',\n width: `${value}px`,\n left: _target_offset.left + parseInt(_target_rect.width + '', 10) + 'px',\n top: _target_offset.top + 'px'\n });\n }\n\n if (property === 'marginBottom') {\n addStyles(spacingEl, {\n height: `${value}px`,\n width: _target_rect.width + 'px',\n left: _target_offset.left + 'px',\n top: _target_offset.top + parseInt(_target_rect.height + '', 10) + 'px'\n });\n }\n\n if (property === 'marginLeft') {\n addStyles(spacingEl, {\n height: _target_rect.height + 'px',\n width: `${value}px`,\n left: _target_offset.left - value + 'px',\n top: _target_offset.top + 'px'\n });\n }\n\n if (property === 'paddingTop') {\n addStyles(spacingEl, {\n height: `${value}px`,\n width: _target_rect.width + 'px',\n left: _target_offset.left + 'px',\n top: _target_offset.top + 'px'\n });\n }\n\n if (property === 'paddingBottom') {\n addStyles(spacingEl, {\n height: `${value}px`,\n width: _target_rect.width + 'px',\n left: _target_offset.left + 'px',\n top:\n _target_offset.top +\n (parseInt(_target_rect.height + '', 10) - value) +\n 'px'\n });\n }\n\n if (property === 'paddingRight') {\n addStyles(spacingEl, {\n height: _target_rect.height + 'px',\n width: `${value}px`,\n left:\n _target_offset.left +\n (parseInt(_target_rect.width + '', 10) - value) +\n 'px',\n top: _target_offset.top + 'px'\n });\n }\n\n if (property === 'paddingLeft') {\n addStyles(spacingEl, {\n height: _target_rect.height + 'px',\n width: `${value}px`,\n left: _target_offset.left + 'px',\n top: _target_offset.top + 'px'\n });\n }\n};\n","/* eslint-disable no-unused-vars */\n\n/**\n * Enum representing different areas in Speccer.\n */\nexport enum SpeccerAreaEnum {\n Empty = '', // Represents an empty area\n Left = 'left', // Represents the left area\n Right = 'right', // Represents the right area\n Bottom = 'bottom',// Represents the bottom area\n Top = 'top', // Represents the top area\n}\n\n/**\n * Enum representing different areas in Dissect.\n */\nexport enum DissectAreaEnum {\n Outline = 'outline', // Represents an outline area\n Enclose = 'enclose', // Represents an enclose area\n Full = 'full', // Represents a full area\n Left = 'left', // Represents the left area\n Right = 'right', // Represents the right area\n Bottom = 'bottom', // Represents the bottom area\n Top = 'top', // Represents the top area\n SVG = 'svg', // Represents an SVG area\n Curly = 'curly', // Represents a curly area\n}\n\n/**\n * Enum representing different measurement areas.\n */\nexport enum MeasureAreaEnum {\n Width = 'width', // Represents the width measurement area\n Height = 'height', // Represents the height measurement area\n Left = 'left', // Represents the left measurement area\n Right = 'right', // Represents the right measurement area\n Bottom = 'bottom', // Represents the bottom measurement area\n Top = 'top', // Represents the top measurement area\n}\n","import { DissectAreaEnum, MeasureAreaEnum } from 'types/enums/area';\n\n/**\n * Splits a string containing areas into an array of strings.\n *\n * @param areaString - The string containing areas.\n * @returns An array of area strings.\n *\n * @example\n * ```ts\n * const areas = getAreasFromString('left right top');\n * // areas: ['left', 'right', 'top']\n * ```\n */\nexport const getAreasFromString = (areaString: string): string[] =>\n areaString.split(' ');\n\n/**\n * Checks if 'left' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'left' is present, otherwise `false`.\n */\nexport const isLeftArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Left);\n};\n\n/**\n * Checks if 'right' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'right' is present, otherwise `false`.\n */\nexport const isRightArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Right);\n};\n\n/**\n * Checks if 'top' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'top' is present, otherwise `false`.\n */\nexport const isTopArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Top);\n};\n\n/**\n * Checks if 'bottom' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'bottom' is present, otherwise `false`.\n */\nexport const isBottomArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Bottom);\n};\n\n/**\n * Checks if 'full' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'full' is present, otherwise `false`.\n */\nexport const isFullArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Full);\n};\n\n/**\n * Checks if 'enclose' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'enclose' is present, otherwise `false`.\n */\nexport const isEncloseArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Enclose);\n};\n\n/**\n * Checks if 'height' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'height' is present, otherwise `false`.\n */\nexport const isHeightArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(MeasureAreaEnum.Height);\n};\n\n/**\n * Checks if 'width' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'width' is present, otherwise `false`.\n */\nexport const isWidthArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(MeasureAreaEnum.Width);\n};\n\n/**\n * Checks if the provided areaString contains SVG-related areas.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if any SVG-related area is present, otherwise `false`.\n */\nexport const useSVG = (areaString: string): boolean =>\n areaString.includes(DissectAreaEnum.SVG) ||\n areaString.includes(DissectAreaEnum.Curly) ||\n areaString.includes(DissectAreaEnum.Full) ||\n areaString.includes(DissectAreaEnum.Enclose);\n\n/**\n * Checks if the provided areaString contains 'curly' and 'full' areas.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if both 'curly' and 'full' are present, otherwise `false`.\n */\nexport const isCurly = (areaString: string): boolean =>\n areaString.includes(DissectAreaEnum.Curly) &&\n areaString.includes(DissectAreaEnum.Full);\n","/* eslint no-console:0 */\n'use strict';\n\n/**\n * Generates a unique ID consisting of an underscore followed by a random alphanumeric string.\n *\n * @returns {string} - A unique ID.\n *\n * @example\n * ```ts\n * // Generate a unique ID\n * const id = uniqueID();\n * console.log(id); // Example output: \"_abc123def\"\n * ```\n */\nexport const uniqueID = (): string =>\n '_' + Math.random().toString(36).substring(2, 11);\n","/**\n * A set of functions to retrieve specific coordinates from a DOMRect.\n */\nexport const coords = {\n /**\n * Get the top coordinate of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the top coordinate from.\n * @returns {number} The top coordinate.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const topCoordinate = coords.top(rect);\n * ```\n */\n top: (rect: DOMRect): number => rect.top,\n\n /**\n * Get the right coordinate of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the right coordinate from.\n * @returns {number} The right coordinate.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const rightCoordinate = coords.right(rect);\n * ```\n */\n right: (rect: DOMRect): number => rect.left + rect.width,\n\n /**\n * Get the bottom coordinate of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the bottom coordinate from.\n * @returns {number} The bottom coordinate.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const bottomCoordinate = coords.bottom(rect);\n * ```\n */\n bottom: (rect: DOMRect): number => rect.top + rect.height,\n\n /**\n * Get the left coordinate of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the left coordinate from.\n * @returns {number} The left coordinate.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const leftCoordinate = coords.left(rect);\n * ```\n */\n left: (rect: DOMRect): number => rect.left,\n\n /**\n * Get the x-coordinate of the center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the x-coordinate of the center from.\n * @returns {number} The x-coordinate of the center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const centerXCoordinate = coords.center_x(rect);\n * ```\n */\n center_x: (rect: DOMRect): number => rect.left + rect.width / 2,\n\n /**\n * Get the y-coordinate of the center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the y-coordinate of the center from.\n * @returns {number} The y-coordinate of the center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const centerYCoordinate = coords.center_y(rect);\n * ```\n */\n center_y: (rect: DOMRect): number => rect.top + rect.height / 2\n};\n","import { coords } from './coords';\n\n/**\n * Object containing functions to retrieve specific x and y coordinates from a DOMRect.\n */\nexport const xy = {\n /**\n * Get the x and y coordinates of the center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the coordinates from.\n * @returns {{ x: number, y: number }} The x and y coordinates of the center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const centerCoordinates = xy.center(rect);\n * // centerCoordinates.x and centerCoordinates.y will contain the coordinates\n * ```\n */\n center: (rect: DOMRect): { x: number; y: number } => ({\n x: coords.center_x(rect),\n y: coords.center_y(rect)\n }),\n\n /**\n * Get the x and y coordinates of the top center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the coordinates from.\n * @returns {{ x: number, y: number }} The x and y coordinates of the top center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const topCenterCoordinates = xy.top(rect);\n * // topCenterCoordinates.x and topCenterCoordinates.y will contain the coordinates\n * ```\n */\n top: (rect: DOMRect): { x: number; y: number } => ({\n x: coords.center_x(rect),\n y: coords.top(rect)\n }),\n\n /**\n * Get the x and y coordinates of the right center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the coordinates from.\n * @returns {{ x: number, y: number }} The x and y coordinates of the right center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const rightCenterCoordinates = xy.right(rect);\n * // rightCenterCoordinates.x and rightCenterCoordinates.y will contain the coordinates\n * ```\n */\n right: (rect: DOMRect): { x: number; y: number } => ({\n x: coords.right(rect),\n y: coords.center_y(rect)\n }),\n\n /**\n * Get the x and y coordinates of the bottom center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the coordinates from.\n * @returns {{ x: number, y: number }} The x and y coordinates of the bottom center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const bottomCenterCoordinates = xy.bottom(rect);\n * // bottomCenterCoordinates.x and bottomCenterCoordinates.y will contain the coordinates\n * ```\n */\n bottom: (rect: DOMRect): { x: number; y: number } => ({\n x: coords.center_x(rect),\n y: coords.bottom(rect)\n })\n\n // Additional functions with x and y coordinates can be added here...\n};\n","import { waitForFrame } from './wait';\nimport { xy } from './xy';\n\n/**\n * Get the intrinsic coordinates of an element based on a specified position.\n *\n * @param {HTMLElement} el - The HTML element.\n * @param {string} [pos='center'] - The position to use.\n * @throws {Error} No position given.\n * @throws {Error} The position given is not the required type.\n * @returns {Promise<{ x: number, y: number }>} - An object containing the coordinates.\n * @example\n * ```ts\n * // Get intrinsic coordinates for an element\n * const element = document.getElementById('example');\n * const coordinates = await intrinsic_coords(element, 'top-left');\n * ```\n */\nexport const intrinsic_coords = async (\n el: HTMLElement,\n pos = 'center'\n): Promise<{ x: number; y: number }> => {\n if (!pos) {\n throw new Error('No position given');\n }\n\n if (typeof pos !== 'string') {\n throw new Error(\n `The position given is not the required type: pos: ${typeof pos}`\n );\n }\n\n const _allowed_positions = [\n 'center',\n 'left',\n 'right',\n 'top',\n 'bottom',\n 'right-top',\n 'right-bottom',\n 'left-top',\n 'left-bottom',\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n 'top-center',\n 'right-center',\n 'bottom-center',\n 'left-center'\n ];\n\n if (!_allowed_positions.includes(pos)) {\n throw new Error(\n `The position given does not match allowed positions to use! Valid positions are: ${_allowed_positions.join(\n ', '\n )}`\n );\n }\n\n await waitForFrame();\n\n const _el_rect = el.getBoundingClientRect();\n\n return xy[pos](_el_rect);\n};\n","import { intrinsic_coords } from './intrinsic-coords';\n\n/**\n * Get the x and y coordinates of two elements and return them as an object.\n *\n * @param {HTMLElement} el1 - The first HTML element.\n * @param {HTMLElement} el2 - The second HTML element.\n * @param {string} [pos1='center'] - The position to use for the first element.\n * @param {string} [pos2='center'] - The position to use for the second element.\n * @throws {Error} No element given.\n * @returns {Promise<{ x1: number, y1: number, x2: number, y2: number }>} - An object containing the coordinates.\n * @example\n * ```ts\n * // Get coordinates for two elements\n * const element1 = document.getElementById('element1');\n * const element2 = document.getElementById('element2');\n * const coordinates = await get_coords_pair_from_objects(element1, element2);\n * ```\n */\nexport const getCoordsPairFromObjects = async (\n el1: HTMLElement,\n el2: HTMLElement,\n pos1 = 'center',\n pos2 = 'center'\n): Promise<{ x1: number; y1: number; x2: number; y2: number }> => {\n if (!el1 || !el2) {\n throw new Error('No element given');\n }\n\n const { x: x1, y: y1 } = await intrinsic_coords(el1, pos1);\n const { x: x2, y: y2 } = await intrinsic_coords(el2, pos2);\n\n return {\n x1,\n y1,\n x2,\n y2\n };\n};\n","import {\n BezierPathOptionsType,\n CreateCoordinatesForCurveCoordParamType,\n CreateCoordinatesForCurveOptionsParamType,\n CurlyBezierPathOptionsType\n} from 'types/bezier';\nimport { getCoordsPairFromObjects } from './get-coords-pair-from-objects';\n\n/**\n * Calculates coordinates for a Bezier curve between two points.\n *\n * @param coords - The coordinates of the start and end points.\n * @param options - Options for controlling the curve's shape.\n * @returns Coordinates for the Bezier curve.\n *\n * @example\n * ```ts\n * const coordinates = createBezierCurveCoordinates(\n * { x1: 0, x2: 100, y1: 0, y2: 100 },\n * { direct: true, firstSet: true, direction: 'west' }\n * );\n * ```\n */\nexport const createBezierCurveCoordinates = (\n coords: CreateCoordinatesForCurveCoordParamType,\n options: CreateCoordinatesForCurveOptionsParamType\n) => {\n const { x1, x2, y1, y2 } = coords;\n const { direct = false, firstSet = false, direction } = options;\n const firstPoint = { x: x1, y: y1 }; // The first point of the curve\n const lastPoint = { x: x2, y: y2 }; // The last point of the curve\n\n let firstControl = { x: x1 + (x2 - x1) / 2, y: y1 }; // Control point for the first point\n let lastControl = { x: x1 + (x2 - x1) / 2, y: y2 }; // Control point for the last point\n\n if (direct) {\n if (firstSet) {\n if (direction === 'west') {\n firstControl = { x: x1 - 32, y: y1 - 16 / 2 };\n lastControl = { x: x2 + 32, y: y2 };\n } else if (direction === 'south') {\n firstControl = { x: x1 - 16 / 2, y: y1 + 32 };\n lastControl = { x: x2, y: y2 - 32 };\n } else if (direction === 'east') {\n firstControl = { x: x1 + 32, y: y1 - 16 / 2 };\n lastControl = { x: x2 - 32, y: y2 };\n } else {\n firstControl = { x: x1 - 16 / 2, y: y1 - 32 };\n lastControl = { x: x2, y: y2 + 32 };\n }\n } else {\n if (direction === 'west') {\n firstControl = { x: x1 - 32, y: y1 + 16 / 2 };\n lastControl = { x: x2 + 32, y: y2 };\n } else if (direction === 'south') {\n firstControl = { x: x1 + 16 / 2, y: y1 + 32 };\n lastControl = { x: x2, y: y2 - 32 };\n } else if (direction === 'east') {\n firstControl = { x: x1 + 32, y: y1 + 16 / 2 };\n lastControl = { x: x2 - 32, y: y2 };\n } else {\n firstControl = { x: x1 + 16 / 2, y: y1 - 32 };\n lastControl = { x: x2, y: y2 + 32 };\n }\n }\n }\n\n return {\n firstPoint,\n firstControl,\n lastPoint,\n lastControl\n };\n};\n\n/**\n * Generates an SVG path for a curved line between two HTML elements.\n *\n * @param startEl - The starting HTML element.\n * @param stopEl - The ending HTML element.\n * @param options - Options for controlling the curved line.\n * @returns The SVG path string for the curved line.\n *\n * @example\n * ```ts\n * const svgPath = getCurlySVGPath(startElement, stopElement, {\n * pos1: 'top',\n * pos2: 'bottom',\n * firstSet: true,\n * direction: 'south',\n * });\n * ```\n */\nexport const getCurlySVGPath = async (\n startEl: HTMLElement,\n stopEl: HTMLElement,\n options: CurlyBezierPathOptionsType\n) => {\n const { pos1, pos2, firstSet = false, direction } = options;\n const { x1, y1, x2, y2 } = await getCoordsPairFromObjects(\n startEl,\n stopEl,\n pos1,\n pos2\n );\n const x1modifier = 0;\n const y1modifier = 0;\n\n let x2modifier = 0;\n let y2modifier = 0;\n\n // Create a gap between the pin and the bracket center\n if (direction == 'north') {\n y2modifier = 8;\n } else if (direction == 'west') {\n x2modifier = 8;\n } else if (direction == 'east') {\n x2modifier = -8;\n } else if (direction == 'south') {\n y2modifier = -8;\n }\n\n const coordinates = createBezierCurveCoordinates(\n {\n x1: x1 + x1modifier,\n x2: x2 + x2modifier,\n y1: y1 + y1modifier,\n y2: y2 + y2modifier\n },\n {\n direct: true,\n firstSet,\n direction\n }\n );\n const { firstPoint, firstControl, lastControl, lastPoint } = coordinates;\n\n return (\n `M ${firstPoint.x} ${firstPoint.y}` +\n `C ${firstControl.x} ${firstControl.y}, ${lastControl.x} ${lastControl.y}, ${lastPoint.x} ${lastPoint.y}`\n );\n};\n\n/**\n * Generates an SVG path for a straight line between two HTML elements.\n *\n * @param startEl - The starting HTML element.\n * @param stopEl - The ending HTML element.\n * @param options - Options for controlling the straight line.\n * @returns The SVG path string for the straight line.\n *\n * @example\n * ```ts\n * const svgPath = getSVGPath(startElement, stopElement, {\n * pos1: 'left',\n * pos2: 'right',\n * });\n * ```\n */\nexport const getSVGPath = async (\n startEl: HTMLElement,\n stopEl: HTMLElement,\n options: BezierPathOptionsType\n) => {\n const { pos1, pos2 } = options;\n const { x1, y1, x2, y2 } = await getCoordsPairFromObjects(\n startEl,\n stopEl,\n pos1,\n pos2\n );\n const coordinates = createBezierCurveCoordinates(\n { x1, x2, y1, y2 },\n { direction: '' }\n );\n const { firstPoint, firstControl, lastControl, lastPoint } = coordinates;\n\n return (\n `M ${firstPoint.x} ${firstPoint.y}` +\n `C ${firstControl.x} ${firstControl.y}, ${lastControl.x} ${lastControl.y}, ${lastPoint.x} ${lastPoint.y}`\n );\n};\n\n/**\n * Returns positions for creating an SVG path based on a cardinal direction.\n *\n * @param direction - The cardinal direction ('east', 'west', 'south', 'north').\n * @returns Positions for creating an SVG path.\n *\n * @example\n * ```ts\n * const positions = getPositionsForSVGPath('east');\n * ```\n */\nexport const getPositionsForSVGPath = (direction: string) => {\n let pos1: string;\n let pos2: string;\n\n switch (direction) {\n case 'east':\n pos1 = 'right';\n pos2 = 'left';\n break;\n case 'south':\n pos1 = 'bottom';\n pos2 = 'top';\n break;\n case 'west':\n pos1 = 'left';\n pos2 = 'right';\n break;\n case 'north':\n default:\n pos1 = 'top';\n pos2 = 'bottom';\n break;\n }\n\n return { pos1, pos2 };\n};\n\n/**\n * Returns positions for creating an SVG path for a curved line based on a cardinal direction.\n *\n * @param direction - The cardinal direction ('east', 'west', 'south', 'north').\n * @returns Positions for creating an SVG path for a curved line.\n *\n * @example\n * ```ts\n * const positions = getPositionsForCurlySVGPath('west');\n * ```\n */\nexport const getPositionsForCurlySVGPath = (direction: string) => {\n let path1pos1: string;\n let path1pos2: string;\n let path2pos1: string;\n let path2pos2: string;\n\n switch (direction) {\n case 'east':\n path1pos1 = 'right-top';\n path1pos2 = 'left-center';\n path2pos1 = 'right-bottom';\n path2pos2 = 'left-center';\n break;\n case 'south':\n path1pos1 = 'bottom-left';\n path1pos2 = 'top-center';\n path2pos1 = 'bottom-right';\n path2pos2 = 'top-center';\n break;\n case 'west':\n path1pos1 = 'left-top';\n path1pos2 = 'right-center';\n path2pos1 = 'left-bottom';\n path2pos2 = 'right-center';\n break;\n case 'north':\n default:\n path1pos1 = 'top-left';\n path1pos2 = 'bottom-center';\n path2pos1 = 'top-right';\n path2pos2 = 'bottom-center';\n break;\n }\n\n return {\n path1pos1,\n path1pos2,\n path2pos1,\n path2pos2\n };\n};\n","import { angle } from './angle';\nimport { cardinal_direction, cardinal_direction_crude } from './cardinal';\nimport { getCoordsPairFromObjects } from './get-coords-pair-from-objects';\n\n/**\n * Get the direction of an element based on its position relative to another element.\n *\n * @param {Object} options - Options for direction calculation.\n * @param {HTMLElement} options.start - The starting HTML element.\n * @param {HTMLElement} options.stop - The stopping HTML element.\n * @param {boolean} [options.crude=false] - If the direction should be calculated crudely (NSEW).\n * @returns {Promise} - The calculated direction.\n * @example\n * ```ts\n * // Get the direction of one element relative to another\n * const startElement = document.getElementById('startElement');\n * const stopElement = document.getElementById('stopElement');\n * const direction = await direction_of_element({ start: startElement, stop: stopElement });\n * ```\n */\nexport const direction_of_element = async ({\n start,\n stop,\n crude = false\n}: {\n start: HTMLElement;\n stop: HTMLElement;\n crude?: boolean;\n}): Promise => {\n const { x1, y1, x2, y2 } = await getCoordsPairFromObjects(start, stop);\n const _angle = angle(x1, y1, x2, y2);\n const _direction = crude\n ? cardinal_direction_crude(_angle)\n : cardinal_direction(_angle);\n\n return _direction;\n};\n","/**\n * Returns the angle between two sets of coordinates.\n *\n * @param {number} cx - The x-coordinate of the first point.\n * @param {number} cy - The y-coordinate of the first point.\n * @param {number} ex - The x-coordinate of the second point.\n * @param {number} ey - The y-coordinate of the second point.\n * @param {boolean} [normalize=true] - If the angle output should be normalized to a value between 0° and 360°.\n * @throws {SyntaxError} Missing input for `angle`.\n * @throws {TypeError} Parameters for `angle` do not have the required type.\n * @returns {number} The angle between the given coordinates.\n * @example\n * ```ts\n * // Calculate the angle between two points\n * const angleValue = angle(0, 0, 3, 4);\n * ```\n */\nexport const angle = (\n cx: number,\n cy: number,\n ex: number,\n ey: number,\n normalize = true\n): number => {\n if (!cx || !cy || !ex || !ey) {\n throw new SyntaxError('Missing input for `angle`');\n }\n\n if (\n typeof cx !== 'number' ||\n typeof cy !== 'number' ||\n typeof ex !== 'number' ||\n typeof ey !== 'number'\n ) {\n throw new TypeError(\n `Parameters for \\`angle\\` do not have the required type. Requires number! Got: ${typeof cx} ${typeof cy} ${typeof ex} ${typeof ey}`\n );\n }\n\n const dy = ey - cy;\n const dx = ex - cx;\n\n let theta = Math.atan2(dy, dx); // range (-PI, PI]\n\n theta *= 180 / Math.PI; // radians to degrees, range (-180, 180]\n\n if (normalize && theta < 0) theta = 360 + theta; // range [0, 360)\n\n return theta;\n};\n","/* eslint no-console:0 */\n'use strict';\n\n/**\n * Gives you the cardinal direction based on degrees.\n * Note: The degrees start at 0, which is EAST (originally, north should be 0, but here, north is 270),\n * and we travel clockwise.\n *\n * @param {number} degrees - The angle in degrees.\n * @throws {RangeError} Parameter cannot exceed 360.\n * @throws {RangeError} Parameter cannot be lower than 0.\n * @returns {string} - The cardinal direction.\n * @example\n * ```ts\n * // Get the cardinal direction for an angle in degrees\n * const direction = cardinal_direction(45);\n * ```\n */\nexport const cardinal_direction = (degrees: number): string => {\n if (degrees > 360) throw new RangeError('Parameter cannot exceed 360');\n\n if (degrees < 0) throw new RangeError('Parameter cannot be lower than 0');\n\n if (degrees >= 0 && degrees <= 22.5) {\n return 'east';\n } else if (degrees >= 22.5 && degrees <= 67.5) {\n return 'south-east';\n } else if (degrees >= 67.5 && degrees <= 112.5) {\n return 'south';\n } else if (degrees >= 112.5 && degrees <= 157.5) {\n return 'south-west';\n } else if (degrees >= 157.5 && degrees <= 202.5) {\n return 'west';\n } else if (degrees >= 202.5 && degrees <= 247.5) {\n return 'north-west';\n } else if (degrees >= 247.5 && degrees <= 292.5) {\n return 'north';\n } else if (degrees >= 292.5 && degrees <= 337.5) {\n return 'north-east';\n } else {\n return 'east';\n }\n};\n\n/**\n * Gives you the cardinal direction based on degrees (crude version).\n * Note: The degrees start at 0, which is EAST (originally, north should be 0, but here, north is 270),\n * and we travel clockwise.\n *\n * @param {number} degrees - The angle in degrees.\n * @throws {RangeError} Parameter cannot exceed 360.\n * @throws {RangeError} Parameter cannot be lower than 0.\n * @returns {string} - The cardinal direction (NSEW).\n * @example\n * ```ts\n * // Get the cardinal direction (crude) for an angle in degrees\n * const direction = cardinal_direction_crude(45);\n * ```\n */\nexport const cardinal_direction_crude = (degrees: number): string => {\n if (degrees > 360) throw new RangeError('Parameter cannot exceed 360');\n\n if (degrees < 0) throw new RangeError('Parameter cannot be lower than 0');\n\n if (degrees >= 45 && degrees <= 135) {\n return 'south';\n } else if (degrees > 135 && degrees <= 225) {\n return 'west';\n } else if (degrees > 225 && degrees <= 315) {\n return 'north';\n } else if (degrees > 315) {\n return 'east';\n } else {\n return 'east';\n }\n};\n","'use strict';\n\nimport { uniqueID } from '../id';\nimport { getPositionsForSVGPath, getSVGPath } from '../bezier';\nimport { direction_of_element } from '../direction-of-element';\n\n/**\n * Class representing a DrawSVGLine instance.\n */\nexport class DrawSVGLine {\n #canvas: HTMLElement | SVGElement | null;\n #originalPathElement: HTMLElement | SVGPathElement | null;\n startElement: HTMLElement;\n stopElement: HTMLElement;\n line: SVGPathElement;\n\n /**\n * Creates a new DrawSVGLine instance.\n * @param startElement - The starting element for the line.\n * @param stopElement - The ending element for the line.\n */\n constructor(startElement: HTMLElement, stopElement: HTMLElement) {\n this.#init(startElement, stopElement);\n }\n\n /**\n * Initializes the DrawSVGLine instance.\n * @param startElement - The starting element for the line.\n * @param stopElement - The ending element for the line.\n * @throws Will throw an error if required elements are missing or not in the DOM.\n */\n #init(startElement: HTMLElement, stopElement: HTMLElement) {\n if (!startElement || !stopElement) {\n throw new Error('Missing inputs startElement and stopElement');\n }\n\n if (!document.body.contains(stopElement)) {\n throw new Error('stopElement is not in the DOM');\n }\n\n if (!document.body.contains(startElement)) {\n throw new Error('startElement is not in the DOM');\n }\n\n this.startElement = startElement;\n this.stopElement = stopElement;\n\n this.#canvas = document.getElementById('ph-speccer-svg');\n this.#originalPathElement = document.getElementById('ph-speccer-path');\n\n if (!this.#originalPathElement || !this.#canvas) {\n throw new Error(\n 'Missing required SVG element to draw lines. Please see the documentation'\n );\n }\n\n this.connect();\n }\n\n /**\n * Connects and draws the line.\n */\n connect() {\n this.draw(this.#originalPathElement as SVGPathElement);\n }\n\n /**\n * Draws the line based on the provided path.\n * @param path - The SVGPathElement to be used as the base path.\n * @throws Will throw an error if no path is provided.\n */\n async draw(path: SVGPathElement) {\n if (!path) {\n throw new Error('No path given to draw!');\n }\n\n const _id = uniqueID();\n const _path_el_id = `ph_draw_path-path-${_id}`;\n const _new_path = path.cloneNode(false) as SVGPathElement;\n\n _new_path.setAttribute('id', _path_el_id);\n _new_path.setAttribute(\n 'data-start-el',\n this.startElement.getAttribute('id') || 'no-id-found'\n );\n _new_path.classList.remove('original');\n _new_path.classList.add('speccer');\n\n if (path.parentNode) {\n this.line = path.parentNode.insertBefore(_new_path, path.nextSibling);\n } else {\n throw new Error('No parentNode found for path');\n }\n\n const _direction = await direction_of_element({\n start: this.startElement,\n stop: this.stopElement,\n crude: true\n });\n const { pos1, pos2 } = getPositionsForSVGPath(_direction);\n const _d = await getSVGPath(this.startElement, this.stopElement, {\n pos1,\n pos2\n });\n\n this.line.setAttribute('data-direction', _direction);\n this.line.setAttribute('data-pos1', pos1);\n this.line.setAttribute('data-pos2', pos2);\n\n this.line.setAttribute('d', _d); // SVG attributes\n }\n}\n\n// Exporting the class as a global object (if needed)\nwindow.DrawSVGLine = DrawSVGLine;\n","'use strict';\n\nimport { uniqueID } from '../id';\nimport { getCurlySVGPath, getPositionsForCurlySVGPath } from '../bezier';\nimport { direction_of_element } from '../direction-of-element';\n\n/**\n * Class representing a DrawSVGCurlyBracket instance.\n */\nexport class DrawSVGCurlyBracket {\n #canvas: HTMLElement | SVGElement | null;\n #originalPathElement: HTMLElement | SVGPathElement | null;\n startElement: HTMLElement;\n stopElement: HTMLElement;\n firstPathElement: SVGPathElement;\n secondPathElement: SVGPathElement;\n\n /**\n * Creates a new DrawSVGCurlyBracket instance.\n * @param startElement - The starting element for the bracket.\n * @param stopElement - The ending element for the bracket.\n */\n constructor(startElement: HTMLElement, stopElement: HTMLElement) {\n this.#init(startElement, stopElement);\n }\n\n /**\n * Initializes the DrawSVGCurlyBracket instance.\n * @param startElement - The starting element for the bracket.\n * @param stopElement - The ending element for the bracket.\n * @throws Will throw an error if required elements are missing or not in the DOM.\n */\n #init(startElement: HTMLElement, stopElement: HTMLElement) {\n if (!startElement || !stopElement) {\n throw new Error('Missing inputs startElement and stopElement');\n }\n\n if (!document.body.contains(stopElement)) {\n throw new Error('stopElement is not in the DOM');\n }\n\n if (!document.body.contains(startElement)) {\n throw new Error('startElement is not in the DOM');\n }\n\n this.startElement = startElement;\n this.stopElement = stopElement;\n\n this.#canvas = document.getElementById('ph-speccer-svg');\n this.#originalPathElement = document.getElementById('ph-speccer-path');\n\n if (!this.#originalPathElement || !this.#canvas) {\n throw new Error(\n 'Missing required SVG element to draw lines. Please see the documentation'\n );\n }\n\n this.connect();\n }\n\n /**\n * Connects and draws the curly bracket.\n */\n connect() {\n this.draw(this.#originalPathElement as SVGPathElement);\n }\n\n /**\n * Creates a new path element based on the provided path.\n * @param path - The SVGPathElement to be used as the base path.\n * @throws Will throw an error if no path is provided.\n * @returns A new SVGPathElement.\n */\n #getPathElement(path: SVGPathElement) {\n if (!path) {\n throw new Error('No path given to #getPathElement!');\n }\n\n const _id = uniqueID();\n const _path_el_id = `ph_draw_path-path-${_id}`;\n const _new_path = path.cloneNode(false) as SVGPathElement;\n\n _new_path.setAttribute(\n 'data-start-el',\n this.startElement.getAttribute('id') || 'no-id-found'\n );\n _new_path.setAttribute('id', _path_el_id);\n _new_path.classList.remove('original');\n _new_path.classList.add('speccer');\n\n return _new_path;\n }\n\n /**\n * Draws the curly bracket based on the provided path.\n * @param path - The SVGPathElement to be used as the base path.\n * @throws Will throw an error if no path is provided.\n */\n async draw(path: SVGPathElement) {\n if (!path) {\n throw new Error('No path given to draw!');\n }\n\n const _first_path_element = this.#getPathElement(path);\n const _second_path_element = this.#getPathElement(path);\n\n if (path.parentNode) {\n this.firstPathElement = path.parentNode.insertBefore(\n _first_path_element,\n path.nextSibling\n );\n this.secondPathElement = path.parentNode.insertBefore(\n _second_path_element,\n path.nextSibling\n );\n } else {\n throw new Error('No parentNode found for path');\n }\n\n const _direction = await direction_of_element({\n stop: this.stopElement,\n start: this.startElement,\n crude: true\n });\n const { path1pos1, path1pos2, path2pos1, path2pos2 } =\n getPositionsForCurlySVGPath(_direction);\n const _first_path_d = await getCurlySVGPath(\n this.startElement,\n this.stopElement,\n {\n pos1: path1pos1,\n pos2: path1pos2,\n firstSet: true,\n direction: _direction\n }\n );\n const _second_path_d = await getCurlySVGPath(\n this.startElement,\n this.stopElement,\n {\n pos1: path2pos1,\n pos2: path2pos2,\n direction: _direction\n }\n );\n\n this.firstPathElement.setAttribute('data-direction', _direction);\n this.firstPathElement.setAttribute('data-pos1', path1pos1);\n this.firstPathElement.setAttribute('data-pos2', path1pos2);\n this.firstPathElement.setAttribute('d', _first_path_d); // SVG attributes\n this.secondPathElement.setAttribute('data-direction', _direction);\n this.secondPathElement.setAttribute('data-pos1', path2pos1);\n this.secondPathElement.setAttribute('data-pos2', path2pos2);\n this.secondPathElement.setAttribute('d', _second_path_d); // SVG attributes\n }\n}\n\n// Exporting the class as a global object (if needed)\nwindow.DrawSVGCurlyBracket = DrawSVGCurlyBracket;\n","import { pinSpace, measureSize } from '../../../utils/css';\nimport { getRec } from '../../../utils/position';\nimport {\n isBottomArea,\n isEncloseArea,\n isFullArea,\n isLeftArea,\n isRightArea\n} from '../../../utils/area';\nimport { DissectStylesOptionsType } from 'types/bezier';\n\n/**\n * Get styles for dissected elements based on the specified area and options.\n *\n * @param {string} area - The area description.\n * @param {HTMLElement} targetEl - The target element.\n * @param {HTMLElement} dissectionEl - The dissection element.\n * @param {DissectStylesOptionsType} options - Optional styles options.\n * @returns {Promise<{ left: string; top: string; height?: string; width?: string }>} - The computed styles.\n *\n * @example\n * ```ts\n * const area = 'top-left';\n * const targetElement = document.getElementById('target');\n * const dissectionElement = document.getElementById('dissection');\n * const options = { isCurly: true };\n * const styles = await styles(area, targetElement, dissectionElement, options);\n * console.log(styles);\n * ```\n */\nexport const styles = async (\n area: string,\n targetEl: HTMLElement,\n dissectionEl: HTMLElement,\n options?: DissectStylesOptionsType\n): Promise<{ left: string; top: string; height?: string; width?: string }> => {\n const { isCurly = false } = options || {};\n const SPECCER_PIN_SPACE = pinSpace(dissectionEl);\n const SPECCER_MEASURE_SIZE = measureSize(dissectionEl);\n const _positional_styles = await getRec(dissectionEl, targetEl);\n\n if (isEncloseArea(area)) {\n const { left, top, height, width } = _positional_styles.absolute();\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`,\n width: `${width}px`\n };\n }\n\n if (isLeftArea(area)) {\n if (isFullArea(area) && !isCurly) {\n const { left, top, height } = _positional_styles.fromLeft({\n sourceWidth: SPECCER_MEASURE_SIZE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`\n };\n } else {\n const { left, top } = _positional_styles.fromLeft({\n center: true,\n modifier: isCurly ? SPECCER_PIN_SPACE / 1.5 : SPECCER_PIN_SPACE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`\n };\n }\n } else if (isRightArea(area)) {\n if (isFullArea(area) && !isCurly) {\n const { left, top, height } = _positional_styles.fromRight({\n center: false\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`\n };\n } else {\n const { left, top } = _positional_styles.fromRight({\n center: true,\n modifier: isCurly ? SPECCER_PIN_SPACE / 1.5 : SPECCER_PIN_SPACE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`\n };\n }\n } else if (isBottomArea(area)) {\n if (isFullArea(area) && !isCurly) {\n const { left, top, width } = _positional_styles.fromBottom({\n center: false\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`\n };\n } else {\n const { left, top } = _positional_styles.fromBottom({\n center: true,\n modifier: isCurly ? SPECCER_PIN_SPACE / 1.5 : SPECCER_PIN_SPACE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`\n };\n }\n } else {\n if (isFullArea(area) && !isCurly) {\n const { left, top, width } = _positional_styles.fromTop({\n center: false\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`\n };\n } else {\n const { left, top } = _positional_styles.fromTop({\n center: true,\n modifier: isCurly ? SPECCER_PIN_SPACE / 1.5 : SPECCER_PIN_SPACE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`\n };\n }\n }\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport { DissectAreaEnum } from '../../types/enums/area';\n\nimport { set as setClassNames, cx } from '../../utils/classnames';\nimport { SPECCER_LITERALS } from '../../utils/constants';\nimport { add } from '../../utils/styles';\nimport { isCurly, isEncloseArea, isFullArea, useSVG } from '../../utils/area';\nimport { DrawSVGLine } from '../../utils/classes/DrawSVGLine';\nimport { DrawSVGCurlyBracket } from '../../utils/classes/DrawSVGCurlyBracket';\n\nimport { styles } from './utils/styles';\n\n/**\n * Create a dissected element with optional text content, area description, and element type.\n *\n * @param {string} textContent - The text content to add to the element.\n * @param {string} area - The area description for styling.\n * @param {string} n - The element type.\n * @returns {HTMLElement} - The created dissected element.\n *\n * @example\n * ```ts\n * const dissectedElement = create('A', 'outline top', 'div');\n * document.body.appendChild(dissectedElement);\n * ```\n */\nexport const create = (\n textContent = '',\n area: string,\n n = 'span'\n): HTMLElement => {\n const _el = document.createElement(n);\n const _text_node = document.createTextNode(textContent);\n const _extra_class_names = {};\n\n if (area !== null && area !== '') {\n _extra_class_names[area] = true;\n }\n\n if (\n (!isFullArea(area) && !isEncloseArea(area)) ||\n (isFullArea(area) && isCurly(area))\n ) {\n _el.appendChild(_text_node);\n } else if (isFullArea(area) || isEncloseArea(area)) {\n _el.setAttribute('data-dissection-counter', textContent);\n }\n\n const _class_names = cx('ph speccer dissection', _extra_class_names);\n\n setClassNames(_el, _class_names);\n\n return _el;\n};\n\n/**\n * Create dissected elements based on the section element and its data-anatomy attributes.\n *\n * @param {HTMLElement} sectionEl - The section element containing dissected elements.\n * @returns {Promise} - A promise that resolves after creating dissected elements.\n *\n * @example\n * ```ts\n * const sectionElement = document.getElementById('section');\n * element(sectionElement);\n * ```\n */\nexport const element = (sectionEl: HTMLElement): Promise => {\n if (!sectionEl) return Promise.resolve();\n\n const _dissection_els = sectionEl.querySelectorAll('[data-anatomy]');\n\n if (_dissection_els) {\n let _index_to_use = 0;\n\n _dissection_els.forEach(async (targetEl: HTMLElement, targetIndex) => {\n if (!targetEl) return Promise.resolve();\n\n const _areas_string: string = targetEl.getAttribute('data-anatomy') || '';\n\n if (\n !_areas_string ||\n _areas_string === '' ||\n _areas_string.indexOf(DissectAreaEnum.Outline) === -1\n )\n return Promise.resolve();\n\n /**\n * If we're running out of literals to use,\n * make a new one with uppercase and lowercase pairs\n */\n let _literal_to_use = SPECCER_LITERALS[targetIndex];\n\n if (!_literal_to_use) {\n _literal_to_use = `${SPECCER_LITERALS[_index_to_use]}${SPECCER_LITERALS[\n _index_to_use\n ].toLowerCase()}`;\n _index_to_use++;\n }\n\n const _dissection_el = create(_literal_to_use, _areas_string);\n\n document.body.appendChild(_dissection_el);\n\n const _dissection_styles = await styles(\n _areas_string,\n targetEl,\n _dissection_el,\n {\n isCurly: isCurly(_areas_string)\n }\n );\n\n await add(_dissection_el, _dissection_styles);\n\n if (useSVG(_areas_string)) {\n new DrawSVGLine(targetEl, _dissection_el);\n } else if (isCurly(_areas_string)) {\n new DrawSVGCurlyBracket(targetEl, _dissection_el);\n }\n });\n }\n\n return Promise.resolve();\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport {\n isBottomArea,\n isHeightArea,\n isRightArea,\n isWidthArea\n} from 'utils/area';\nimport { set as setClassNames } from '../../utils/classnames';\nimport { get as getStyles, add as addStyles } from '../../utils/styles';\nimport { waitForFrame } from '../../utils/wait';\nimport { getRec } from '../../utils/position';\nimport { SPECCER_DEFAULT_MEASURE_SIZE_NEG } from 'utils/constants';\n\n/**\n * Create a measurement element with optional text, area, and element type.\n *\n * @param {string | number} text - The text to display on the element.\n * @param {string | null} area - The area to specify with CSS class.\n * @param {string} tag - The element type.\n * @returns {HTMLElement} - The created measurement element.\n *\n * @example\n * ```ts\n * const measurement = create(100, 'width bottom', 'div');\n * document.body.appendChild(measurement);\n * ```\n */\nexport const create = (\n text: string | number = '',\n area: string | null = '',\n tag = 'span'\n): HTMLElement => {\n const _el = document.createElement(tag);\n\n _el.setAttribute('title', text + 'px');\n _el.setAttribute('data-measure', parseInt(text + '', 10) + 'px');\n\n setClassNames(_el, `ph speccer measure ${area}`);\n\n return _el;\n};\n\n/**\n * Create a measurement element and add it to the body with styles matching a specified target element.\n *\n * @param {HTMLElement} targetEl - The target element to match styles with.\n * @returns {Promise} - A promise that resolves after creating and styling the measurement element.\n *\n * @example\n * ```ts\n * const targetElement = document.getElementById('target');\n * element(targetElement);\n * ```\n */\nexport const element = async (targetEl: HTMLElement): Promise => {\n if (!targetEl) return;\n\n const _areas_string: string | null = targetEl.getAttribute(\n 'data-speccer-measure'\n );\n\n if (_areas_string === '' || !_areas_string) {\n return;\n }\n\n const _target_styles = await getStyles(targetEl);\n\n if (\n _target_styles.display === 'none' ||\n _target_styles.opacity === '0' ||\n _target_styles.visibility === 'hidden'\n ) {\n return;\n }\n\n await waitForFrame();\n\n const _target_rect = targetEl.getBoundingClientRect();\n\n if (isWidthArea(_areas_string)) {\n if (isBottomArea(_areas_string)) {\n const _measure_el = create(_target_rect.width, _areas_string);\n\n document.body.appendChild(_measure_el);\n\n const _positional_styles = await getRec(_measure_el, targetEl);\n const { left, top, width } = _positional_styles.fromBottom({\n center: false\n });\n\n await addStyles(_measure_el, {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`\n });\n } else {\n const _measure_el = create(_target_rect.width, _areas_string);\n\n document.body.appendChild(_measure_el);\n\n const _positional_styles = await getRec(_measure_el, targetEl);\n const { left, top, width } = _positional_styles.fromTop({\n center: false,\n modifier: SPECCER_DEFAULT_MEASURE_SIZE_NEG\n });\n\n await addStyles(_measure_el, {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`\n });\n }\n } else if (isHeightArea(_areas_string)) {\n if (isRightArea(_areas_string)) {\n const _measure_el = create(_target_rect.height, _areas_string);\n\n document.body.appendChild(_measure_el);\n\n const _positional_styles = await getRec(_measure_el, targetEl);\n const { left, top, height } = _positional_styles.fromRight({\n center: false\n });\n\n await addStyles(_measure_el, {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`\n });\n } else {\n const _measure_el = create(_target_rect.height, _areas_string);\n\n document.body.appendChild(_measure_el);\n\n const _positional_styles = await getRec(_measure_el, targetEl);\n const { left, top, height } = _positional_styles.fromLeft({\n center: false,\n modifier: SPECCER_DEFAULT_MEASURE_SIZE_NEG\n });\n\n await addStyles(_measure_el, {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`\n });\n }\n }\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport { add as addStyles } from '../../utils/styles';\nimport { cx, set } from '../../utils/classnames';\nimport { getRec } from '../../utils/position';\n\n/**\n * Create a marker element with an optional element type.\n *\n * @param {string} n - The element type.\n * @returns {HTMLElement} - The created marker element.\n *\n * @example\n * ```typescript\n * const marker = create('div');\n * document.body.appendChild(marker);\n * ```\n */\nexport const create = (n = 'span'): HTMLElement => {\n const markElement = document.createElement(n);\n const classNames = cx('ph speccer mark');\n\n set(markElement, classNames);\n\n return markElement;\n};\n\n/**\n * Create a marker element and add it to the body with styles matching a specified element.\n *\n * @param {HTMLElement} elementToMark - The target element to match styles with.\n * @returns {Promise} - A promise that resolves after creating and styling the marker element.\n *\n * @example\n * ```typescript\n * const elementToMark = document.getElementById('target');\n * element(elementToMark);\n * ```\n */\nexport const element = async (elementToMark: HTMLElement): Promise => {\n if (!elementToMark) return Promise.resolve();\n\n const markElement = create();\n\n document.body.appendChild(markElement);\n\n const positionalStyles = await getRec(markElement, elementToMark);\n const { left, top, height, width } = positionalStyles.absolute();\n const markStyles = {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`,\n width: `${width}px`\n };\n\n await addStyles(markElement, markStyles);\n};\n","/* eslint no-console:0 */\n'use strict';\n\n/**\n * Converts a number to a string with a specified number of decimal places.\n *\n * @param {string | number} number - The number to convert.\n * @param {number} decimals - The number of decimal places (default is 3).\n * @returns {string} - The formatted number as a string.\n *\n * @example\n * ```ts\n * // Convert a number to a string with 2 decimal places\n * const formattedNumber = decimal(12.3456, 2); // \"12.34\"\n * ```\n */\nexport const decimal = (number: string | number, decimals = 3): string =>\n parseFloat(number + '').toFixed(decimals);\n","/* eslint no-console:0 */\n'use strict';\n\nimport { set as setClassNames, cx } from '../../utils/classnames';\nimport { add as addStyles, get as getStyles } from '../../utils/styles';\nimport { position } from './utils/position';\nimport { template } from './utils/template';\n\n/**\n * Create a DOM element with provided HTML and optional CSS class names.\n *\n * @param {string} html - The HTML content to be set in the created element.\n * @param {string | null} area - The optional CSS class names to add.\n * @returns {HTMLElement} - The created DOM element.\n *\n * @example\n * ```ts\n * const htmlContent = '

This is some HTML content.

';\n * const cssClass = 'custom-class';\n * const createdElement = create(htmlContent, cssClass);\n * document.body.appendChild(createdElement);\n * ```\n */\nexport const create = (html: string, area: string | null): HTMLElement => {\n const _el = document.createElement('div');\n const _extra_class_names = {};\n\n if (area !== null && area !== '') {\n _extra_class_names[area] = true;\n }\n\n const _class_names = cx('ph speccer typography', _extra_class_names);\n\n _el.innerHTML = html;\n\n setClassNames(_el, _class_names);\n\n return _el;\n};\n\n/**\n * Create a specced typography element for a given target element.\n *\n * @param {HTMLElement} targetEl - The target element to specc typography for.\n * @returns {Promise} - A promise that resolves once typography element is created and positioned.\n *\n * @example\n * ```ts\n * const targetElement = document.querySelector('.target');\n * if (targetElement) {\n * element(targetElement);\n * }\n * ```\n */\nexport const element = async (targetEl: HTMLElement): Promise => {\n if (!targetEl) return;\n\n const _area: string | null = targetEl.getAttribute('data-speccer-typography');\n const _target_styles = await getStyles(targetEl);\n\n if (\n _target_styles.display === 'none' ||\n _target_styles.opacity === '0' ||\n _target_styles.visibility === 'hidden'\n ) {\n return;\n }\n\n targetEl.classList.add('is-specced');\n\n const _html = await template(targetEl);\n const _speccer_el = create(_html, _area);\n\n document.body.appendChild(_speccer_el);\n\n const _position = await position(_area, targetEl, _speccer_el);\n\n addStyles(_speccer_el, _position);\n};\n","import { getTypography } from '../../../utils/css';\nimport { get as getStyles } from '../../../utils/styles';\n\n/**\n * Generate a HTML string for typography styles of a target element.\n *\n * @param {HTMLElement} targetEl - The target element for which to generate typography styles.\n * @returns {Promise} - A promise that resolves with the HTML string.\n *\n * @example\n * ```ts\n * const targetElement = document.getElementById('target');\n * const typographyStyles = await template(targetElement);\n * console.log(typographyStyles);\n * ```\n */\nexport const template = async (targetEl: HTMLElement): Promise => {\n const _target_styles = await getStyles(targetEl);\n const _styles = getTypography(_target_styles);\n const _line_height =\n _styles['lineHeight'] !== 'normal'\n ? parseInt(_styles['lineHeight'], 10) / 16 + 'rem'\n : 'normal';\n\n return (\n `\n` +\n 'font-styles: {' +\n '
    ' +\n `
  • font-family: ${_styles['fontFamily']};
  • ` +\n `
  • font-size: ${_styles['fontSize']} / ${\n parseInt(_styles['fontSize'], 10) / 16\n }rem;
  • ` +\n `
  • font-weight: ${_styles['fontWeight']};
  • ` +\n `
  • font-variation-settings: ${_styles['fontVariationSettings']};
  • ` +\n `
  • line-height: ${_styles['lineHeight']} / ${_line_height};
  • ` +\n `
  • letter-spacing: ${_styles['letterSpacing']};
  • ` +\n `
  • font-style: ${_styles['fontStyle']};
  • ` +\n '
' +\n '}'\n );\n};\n","import { pinSpace } from '../../../utils/css';\nimport { decimal } from '../../../utils/number';\nimport {\n get_horizontal_center_of_els,\n get_vertical_center_of_els,\n offset\n} from '../../../utils/position';\n\nimport { SpeccerAreaEnum } from '../../../types/enums/area';\n\n/**\n * Calculate the position for the speccer element relative to the target element.\n *\n * @param {string | null} area - The area information for positioning.\n * @param {HTMLElement} targetEl - The target element.\n * @param {HTMLElement} speccerEl - The speccer element to position.\n * @returns {Promise<{ left: string, top: string }>} - A promise that resolves with the calculated position.\n *\n * @example\n * ```ts\n * const targetElement = document.getElementById('target');\n * const speccerElement = document.getElementById('speccer');\n * const area = 'top';\n * const position = await position(area, targetElement, speccerElement);\n * console.log(position); // { left: '10px', top: '20px' }\n * ```\n */\nexport const position = async (\n area: string | null,\n targetEl: HTMLElement,\n speccerEl: HTMLElement\n): Promise<{ left: string; top: string }> => {\n const _target_rect = targetEl.getBoundingClientRect();\n const SPECCER_PIN_SPACE = pinSpace(speccerEl);\n const _speccer_el_rect = speccerEl.getBoundingClientRect();\n const _el_offset = await offset(targetEl);\n const _left_layout_position_left =\n _el_offset.left - _speccer_el_rect.width - SPECCER_PIN_SPACE + 'px';\n const _left_layout_position_top =\n decimal(\n get_vertical_center_of_els(_el_offset.top, _speccer_el_rect, _target_rect)\n ) + 'px';\n const _right_layout_position_left =\n _el_offset.left + _target_rect.width + SPECCER_PIN_SPACE + 'px';\n const _right_layout_position_top =\n decimal(\n get_vertical_center_of_els(_el_offset.top, _speccer_el_rect, _target_rect)\n ) + 'px';\n const _top_layout_position_left =\n decimal(\n get_horizontal_center_of_els(\n _el_offset.left,\n _speccer_el_rect,\n _target_rect\n )\n ) + 'px';\n const _top_layout_position_top =\n _el_offset.top - _speccer_el_rect.height - SPECCER_PIN_SPACE + 'px';\n const _bottom_layout_position_left =\n decimal(\n get_horizontal_center_of_els(\n _el_offset.left,\n _speccer_el_rect,\n _target_rect\n )\n ) + 'px';\n const _bottom_layout_position_top =\n _el_offset.top + _target_rect.height + SPECCER_PIN_SPACE + 'px';\n\n let _position = {\n left: _left_layout_position_left,\n top: _left_layout_position_top\n };\n\n if (area && area.indexOf(SpeccerAreaEnum.Right) !== -1) {\n _position = {\n left: _right_layout_position_left,\n top: _right_layout_position_top\n };\n } else if (area && area.indexOf(SpeccerAreaEnum.Top) !== -1) {\n _position = {\n left: _top_layout_position_left,\n top: _top_layout_position_top\n };\n } else if (area && area.indexOf(SpeccerAreaEnum.Bottom) !== -1) {\n _position = {\n left: _bottom_layout_position_left,\n top: _bottom_layout_position_top\n };\n }\n\n return _position;\n};\n","'use strict';\n\nimport { SpeccerFunctionType } from 'types/speccer';\n\nimport debounce from './debounce';\n\n/**\n * Attaches a debounced event listener to the window's resize event that triggers the provided function.\n *\n * @param {SpeccerFunctionType} speccer - The function to trigger when the window is resized.\n *\n * @example\n * ```ts\n * // Define a function to be triggered on window resize\n * const mySpeccer = () => {\n * // Your logic here\n * console.log('Window resized');\n * };\n *\n * // Activate the debounced event listener\n * activate(mySpeccer);\n * ```\n */\nexport const activate = (speccer: SpeccerFunctionType): void => {\n /**\n * The debounced event listener function.\n * @type {Function}\n */\n const speccerEventFunc = () =>\n debounce(() => {\n speccer();\n }, 300);\n\n // Remove any existing resize event listeners to prevent duplicates\n window.removeEventListener('resize', speccerEventFunc);\n\n // Add the debounced resize event listener\n window.addEventListener('resize', speccerEventFunc);\n};\n","/* eslint @typescript-eslint/no-explicit-any: [\"error\", { \"fixToUnknown\": true }] */\n'use strict';\n\nimport { DebounceAnyFunctionType } from 'types/debounce';\n\n/**\n * Creates a debounced version of a function that delays its execution until after a specified waiting time has elapsed since the last time the debounced function was invoked.\n *\n * @param {DebounceAnyFunctionType} func - The function to debounce.\n * @param {number} wait - The number of milliseconds to wait before invoking the function after the last call.\n * @param {boolean} [immediate=false] - If `true`, the function is invoked immediately after the first call.\n * @returns {DebounceAnyFunctionType} - The debounced function.\n *\n * @example\n * ```ts\n * // Create a debounced function\n * const debouncedFn = debounce((value) => {\n * console.log(value);\n * }, 500);\n *\n * // Call the debounced function\n * debouncedFn('Hello'); // This will not trigger immediate execution\n * debouncedFn('World'); // This will trigger immediate execution\n * ```\n */\nconst debounce = (\n func: DebounceAnyFunctionType,\n wait: number,\n immediate = false\n): DebounceAnyFunctionType => {\n let timeout: null | ReturnType;\n\n return function (context: unknown, ...args: unknown[]): void {\n const later = function (): void {\n timeout = null;\n\n if (!immediate) func.apply(context, args);\n };\n const callNow = immediate && !timeout;\n\n if (timeout) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(later, wait);\n\n if (callNow) func.apply(context, args);\n };\n};\n\nexport default debounce;\n","/* eslint no-console:0 */\n'use strict';\n\nimport { SpeccerFunctionType } from 'types/speccer';\n\nimport { activate as resizeActivate } from '../utils/resize';\n\nimport { element as specElement } from '../features/spacing';\nimport { element as measureElement } from '../features/measure';\nimport { element as dissectElement } from '../features/dissect';\n\n/**\n * A function to initialize speccer when the DOM is ready.\n *\n * @param {SpeccerFunctionType} speccer - The speccer function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // dom(mySpeccer);\n * ```\n */\nexport const dom = (speccer: SpeccerFunctionType): void => {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n speccer();\n });\n } else {\n // `DOMContentLoaded` already fired\n speccer();\n }\n};\n\n/**\n * A function to initialize lazy speccer functionality.\n *\n * @example\n * ```ts\n * // Usage example:\n * // lazy();\n * ```\n */\nexport const lazy = (): void => {\n const _spec_observer = new IntersectionObserver((els, observer) => {\n els.forEach((el: IntersectionObserverEntry) => {\n if (el.intersectionRatio > 0) {\n specElement(el.target as HTMLElement);\n observer.unobserve(el.target);\n }\n });\n });\n\n document\n .querySelectorAll(\n '[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)'\n )\n .forEach((el) => {\n _spec_observer.observe(el);\n });\n\n const _measure_observer = new IntersectionObserver((els, observer) => {\n els.forEach((el) => {\n if (el.intersectionRatio > 0) {\n measureElement(el.target as HTMLElement);\n observer.unobserve(el.target);\n }\n });\n });\n\n document.querySelectorAll('[data-speccer-measure]').forEach((el) => {\n _measure_observer.observe(el);\n });\n\n const _dissect_observer = new IntersectionObserver((els, observer) => {\n els.forEach((el) => {\n if (el.intersectionRatio > 0) {\n dissectElement(el.target as HTMLElement);\n observer.unobserve(el.target);\n }\n });\n });\n\n document.querySelectorAll('[data-anatomy-section]').forEach((el) => {\n _dissect_observer.observe(el);\n });\n};\n\n/**\n * A function to manually activate speccer.\n *\n * @param {SpeccerFunctionType} speccer - The speccer function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // manual(mySpeccer);\n * ```\n */\nexport const manual = (speccer: SpeccerFunctionType): void => {\n window.speccer = speccer;\n};\n\n/**\n * A function to activate speccer based on script attributes.\n *\n * @param {SpeccerFunctionType} speccer - The speccer function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // activate(mySpeccer);\n * ```\n */\nexport const activate = (speccer: SpeccerFunctionType): void => {\n const _script = document.currentScript;\n\n if (_script) {\n const _speccer_script_src = _script.getAttribute('src');\n\n if (\n _speccer_script_src &&\n (_speccer_script_src.indexOf('speccer.js') !== -1 ||\n // for codepen\n _speccer_script_src.indexOf('JaXpOK.js') !== -1)\n ) {\n if (_script.hasAttribute('data-manual')) {\n manual(speccer);\n } else if (_script.hasAttribute('data-instant')) {\n speccer();\n } else if (_script.hasAttribute('data-dom')) {\n dom(speccer);\n } else if (_script.hasAttribute('data-lazy')) {\n lazy();\n } else {\n dom(speccer);\n }\n\n if (\n !_script.hasAttribute('data-manual') &&\n !_script.hasAttribute('data-lazy')\n ) {\n resizeActivate(speccer);\n }\n }\n }\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport './types/interfaces/global';\nimport { removeAll } from './utils/node';\nimport {\n create as spacingCreate,\n element as spacingElement\n} from './features/spacing';\nimport {\n create as dissectCreate,\n element as dissectElement\n} from './features/dissect';\nimport {\n create as measureCreate,\n element as measureElement\n} from './features/measure';\nimport { create as markCreate, element as markElement } from './features/mark';\nimport {\n create as typographyCreate,\n element as typographyElement\n} from './features/typography';\nimport { dom, lazy, manual, activate } from './config/browser';\n\nexport const spacing = {\n create: spacingCreate,\n element: spacingElement\n};\n\nexport const dissect = {\n create: dissectCreate,\n element: dissectElement\n};\n\nexport const measure = {\n create: measureCreate,\n element: measureElement\n};\n\nexport const mark = {\n create: markCreate,\n element: markElement\n};\n\nexport const typography = {\n create: typographyCreate,\n element: typographyElement\n};\n\nexport const modes = {\n dom,\n lazy,\n manual,\n activate\n};\n\nconst speccer = () => {\n removeAll('.speccer');\n\n const elsToBeSpecced = document.querySelectorAll(\n '[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)'\n );\n const elsToBeMeasured = document.querySelectorAll('[data-speccer-measure]');\n const elsToBeTypographySpecced = document.querySelectorAll(\n '[data-speccer-typography]'\n );\n const elsToBeDissected = document.querySelectorAll('[data-anatomy-section]');\n const elsToBeMarked = document.querySelectorAll('[data-speccer-mark]');\n\n elsToBeMarked.forEach(markElement);\n elsToBeSpecced.forEach(spacingElement);\n elsToBeMeasured.forEach(measureElement);\n elsToBeTypographySpecced.forEach(typographyElement);\n elsToBeDissected.forEach(dissectElement);\n};\n\nexport default speccer;\n\nactivate(speccer);\n"],"names":["set","el","cls","avoid","length","trim","split","filter","cl","forEach","classList","add","cx","cls_obj","Object","keys","classname","join","SPECCER_LITERALS","getNumberValue","value","parseInt","pinSpace","getComputedStyle","getPropertyValue","waitForFrame","Promise","requestAnimationFrame","async","styles","Array","isArray","constructor","style","key","get","get_horizontal_center_of_els","modifier","startRect","targetRect","width","get_vertical_center_of_els","height","offset","targetEl","_target_rect","getBoundingClientRect","_el_offset_top","top","window","scrollY","_el_offset_left","left","scrollX","getRec","sourceEl","_source_rect","_target_offset","_target_offset_center","offsetWithCenter","_target_height","_target_width","_source_height","_source_width","absolute","toTop","center","sourceHeight","fromTop","toBottom","targetHeight","fromBottom","toLeft","sourceWidth","fromLeft","toRight","targetWidth","fromRight","create","text","tag","_el","document","createElement","_text_content","createTextNode","appendChild","setAttribute","setClassNames","element","_target_styles","getStyles","display","opacity","visibility","_target_spacing_styles","marginTop","marginBottom","marginLeft","marginRight","paddingTop","paddingBottom","paddingLeft","paddingRight","getSpacing","_target_pruned_spacing_styles","property","_value","_speccer_el","_class_name","indexOf","replace","getClassNameFromCSSProperty","body","spacingEl","addStyles","position","SpeccerAreaEnum","DissectAreaEnum","MeasureAreaEnum","getAreasFromString","areaString","isRightArea","includes","Right","isBottomArea","Bottom","isFullArea","Full","isEncloseArea","Enclose","isCurly","Curly","uniqueID","Math","random","toString","substring","coords","rect","xy","x","y","right","bottom","intrinsic_coords","pos","Error","_allowed_positions","_el_rect","getCoordsPairFromObjects","el1","el2","pos1","pos2","x1","y1","x2","y2","createBezierCurveCoordinates","options","direct","firstSet","direction","firstControl","lastControl","firstPoint","lastPoint","getCurlySVGPath","startEl","stopEl","x2modifier","y2modifier","coordinates","direction_of_element","start","stop","crude","_angle","cy","ex","ey","normalize","SyntaxError","TypeError","dy","dx","theta","atan2","PI","angle","degrees","RangeError","cardinal_direction_crude","cardinal_direction","DrawSVGLine","canvas","originalPathElement","startElement","stopElement","line","this","init","contains","getElementById","connect","draw","path","_path_el_id","_new_path","cloneNode","getAttribute","remove","parentNode","insertBefore","nextSibling","_direction","getPositionsForSVGPath","_d","getSVGPath","DrawSVGCurlyBracket","firstPathElement","secondPathElement","getPathElement","_first_path_element","_second_path_element","path1pos1","path1pos2","path2pos1","path2pos2","getPositionsForCurlySVGPath","_first_path_d","_second_path_d","area","dissectionEl","SPECCER_PIN_SPACE","SPECCER_MEASURE_SIZE","_positional_styles","Left","textContent","n","_text_node","_extra_class_names","_class_names","sectionEl","resolve","_dissection_els","querySelectorAll","_index_to_use","targetIndex","_areas_string","Outline","_literal_to_use","toLowerCase","_dissection_el","_dissection_styles","SVG","Width","_measure_el","SPECCER_DEFAULT_MEASURE_SIZE","Height","isHeightArea","markElement","classNames","elementToMark","positionalStyles","markStyles","decimal","number","decimals","parseFloat","toFixed","html","innerHTML","_area","_html","_styles","lineHeight","letterSpacing","fontFamily","fontSize","fontStyle","fontVariationSettings","fontWeight","getTypography","_line_height","template","_position","speccerEl","_speccer_el_rect","_el_offset","_left_layout_position_left","_left_layout_position_top","_right_layout_position_left","_right_layout_position_top","_top_layout_position_left","_top_layout_position_top","_bottom_layout_position_left","_bottom_layout_position_top","Top","activate","speccer","speccerEventFunc","func","wait","immediate","timeout","context","args","callNow","clearTimeout","setTimeout","apply","debounce","removeEventListener","addEventListener","dom","readyState","lazy","_spec_observer","IntersectionObserver","els","observer","intersectionRatio","specElement","target","unobserve","observe","_measure_observer","measureElement","_dissect_observer","dissectElement","manual","_script","currentScript","_speccer_script_src","hasAttribute","resizeActivate","spacing","spacingCreate","spacingElement","dissect","dissectCreate","measure","measureCreate","mark","markCreate","typography","typographyCreate","typographyElement","modes","selector","call","e","removeAll","elsToBeSpecced","elsToBeMeasured","elsToBeTypographySpecced","elsToBeDissected"],"mappings":"+OAgCO,MCbMA,EAAM,CAACC,EAAiBC,EAAaC,EAAQ,UACnDF,KAEAC,GAAQA,GAAsB,IAAfA,EAAIE,QAExBF,EACGG,OACAC,MAAM,KACNC,QAAQC,GAAOA,IAAOL,IACtBM,SAASD,GAAOP,EAAGS,UAAUC,IAAIH,KAAI,EAoE7BI,EAAK,CAChBV,EACAW,IAEKX,EAEAW,GAA0B,iBAARX,EAMhB,GAAGA,KACRW,EACIC,OAAOC,KAAKF,GACXN,QAAQS,GAAcH,EAAQG,KAC9BC,KAAK,KACN,KACHZ,OAXM,GAAGS,OAAOC,KAAKb,GACnBK,QAAQS,GAAcd,EAAIc,KAC1BC,KAAK,OAAOZ,OALA,GCtFNa,EAAmB,IAAI,8BCWvBC,EAAkBC,GAA0BC,SAASD,EAAO,IAkJ5DE,EAAYrB,GACvBkB,EACEI,iBAAiBtB,GAAIuB,iBAAiB,4BD9HD,GElB5BC,EAAe,IAC1B,IAAIC,QAAgBC,uBCLThB,EAAMiB,MACjB3B,EACA4B,MAGG5B,IACA4B,GACiB,iBAAXA,GACW,iBAAXA,GACW,kBAAXA,GACNC,MAAMC,QAAQF,IAA6B,IAAlBA,EAAOzB,QACD,IAA/BU,OAAOC,KAAKc,GAAQzB,QAAgByB,EAAOG,cAAgBlB,eAKxDW,IAEFK,MAAMC,QAAQF,GAChBA,EAAOpB,SACJwB,GACEhC,EAAGgC,MAAMA,EAAMC,KAAOD,EAAMb,QAGjCN,OAAOC,KAAKc,GAAQpB,SAASyB,GAASjC,EAAGgC,MAAMC,GAAOL,EAAOK,KAC9D,EAiBUC,EAAMP,MAAO3B,UAClBwB,IAECF,iBAAiBtB,EAAI,OCnDjBmC,EAA+B,CAC1CC,EACAC,EACAC,IACWF,EAAWC,EAAUE,MAAQ,EAAID,EAAWC,MAAQ,EAgBpDC,EAA6B,CACxCJ,EACAC,EACAC,IACWF,EAAWC,EAAUI,OAAS,EAAIH,EAAWG,OAAS,EActDC,EAASf,MACpBgB,UAEMnB,IAEN,MAAMoB,EAAeD,EAASE,wBACxBC,EAAiBF,EAAaG,IAAMC,OAAOC,QAC3CC,EAAkBN,EAAaO,KAAOH,OAAOI,QAEnD,MAAO,CACLX,OAAQG,EAAaH,OACrBF,MAAOK,EAAaL,MACpBQ,IAAKD,EACLK,KAAMD,EACP,EA0DUG,EAAS1B,MACpB2B,EACAX,WAEMnB,IAEN,MAAM+B,EAAeD,EAAST,wBACxBW,QAAuBd,EAAOC,GAC9Bc,OAlDwB9B,OAC9B2B,EACAX,WAEMnB,IAEN,MAAM+B,EAAeD,EAAST,wBACxBD,EAAeD,EAASE,wBACxBC,EAAiBF,EAAaG,IAAMC,OAAOC,QAC3CC,EAAkBN,EAAaO,KAAOH,OAAOI,QAEnD,MAAO,CACLX,OAAQG,EAAaH,OACrBF,MAAOK,EAAaL,MACpBQ,IAAKP,EAA2BM,EAAgBS,EAAcX,GAC9DO,KAAMhB,EACJe,EACAK,EACAX,GAEH,EA8BmCc,CAAiBJ,EAAUX,GACzDgB,EAAiBH,EAAef,OAChCmB,EAAgBJ,EAAejB,MAC/BsB,EAAiBN,EAAad,OAC9BqB,EAAgBP,EAAahB,MAEnC,MAAO,CACLwB,SAAU,KACD,CACLhB,IAAKS,EAAeT,IACpBI,KAAMK,EAAeL,KACrBV,OAAQkB,EACRpB,MAAOqB,IAGXI,MAAO,EACLC,UAAS,EACTC,eAAeL,EACfzB,WAAW,GACU,MACd,CACLW,IAAKS,EAAeT,IAAMmB,EAAe9B,EACzCe,KAAMc,EAASR,EAAsBN,KAAOK,EAAeL,KAC3DV,OAAQkB,EACRpB,MAAOqB,IAIXO,QAAS,EACPF,UAAS,EACTC,eAAeL,EACfzB,WAAW,GACU,MACd,CACLW,IAAKS,EAAeT,IAAMmB,EAAe9B,EACzCe,KAAMc,EAASR,EAAsBN,KAAOK,EAAeL,KAC3DV,OAAQkB,EACRpB,MAAOqB,IAIXQ,SAAU,EACRH,UAAS,EACTC,eAAeL,EACfQ,eAAeV,EACfvB,WAAW,GACU,CAAA,KACd,CACLW,IAAKS,EAAeT,IAAMsB,GAAgBH,EAAe9B,GACzDe,KAAMc,EAASR,EAAsBN,KAAOK,EAAeL,KAC3DV,OAAQkB,EACRpB,MAAOqB,IAGXU,WAAY,EACVL,UAAS,EACTI,eAAeV,EACfvB,WAAW,GACU,MACd,CACLW,IAAKS,EAAeT,IAAMsB,EAAejC,EACzCe,KAAMc,EAASR,EAAsBN,KAAOK,EAAeL,KAC3DV,OAAQkB,EACRpB,MAAOqB,IAIXW,OAAQ,EACNN,UAAS,EACTO,cAAcV,EACd1B,WAAW,GACU,MACd,CACLW,IAAKkB,EAASR,EAAsBV,IAAMS,EAAeT,IACzDI,KAAMK,EAAeL,KAAOqB,EAAcpC,EAC1CK,OAAQkB,EACRpB,MAAOqB,IAIXa,SAAU,EACRR,UAAS,EACTO,cAAcV,EACd1B,WAAW,GACU,MACd,CACLW,IAAKkB,EAASR,EAAsBV,IAAMS,EAAeT,IACzDI,KAAMK,EAAeL,KAAOqB,EAAcpC,EAC1CK,OAAQkB,EACRpB,MAAOqB,IAIXc,QAAS,EACPT,UAAS,EACTO,cAAcV,EACda,cAAcf,EACdxB,WAAW,GACU,CAAA,KACd,CACLW,IAAKkB,EAASR,EAAsBV,IAAMS,EAAeT,IACzDI,KAAMK,EAAeL,KAAOwB,GAAeH,EAAcpC,GACzDK,OAAQkB,EACRpB,MAAOqB,IAIXgB,UAAW,EACTX,UAAS,EACTU,cAAcf,EACdxB,WAAW,GACU,MACd,CACLW,IAAKkB,EAASR,EAAsBV,IAAMS,EAAeT,IACzDI,KAAMK,EAAeL,KAAOwB,EAAcvC,EAC1CK,OAAQkB,EACRpB,MAAOqB,IAGZ,ECvOUiB,EAAS,CACpBC,EAAwB,GACxBC,EAAM,UAEN,MAAMC,EAAMC,SAASC,cAAcH,GAC7BI,EAAgBF,SAASG,eAAeN,EAAO,IAMrD,OAJAE,EAAIK,YAAYF,GAChBH,EAAIM,aAAa,QAASR,EAAO,MACjCS,EAAcP,EAAK,sBAEZA,CAAG,EAeCQ,EAAU7D,MAAOgB,IAC5B,IAAKA,EAAU,OAEf,MAAM8C,QAAuBC,EAAU/C,GAEvC,GAC6B,SAA3B8C,EAAeE,SACY,MAA3BF,EAAeG,SACe,WAA9BH,EAAeI,WAEf,OAGF,MAAMC,EJ4BkB,CACxB9D,IAEA,MAAM+D,UACJA,EAASC,aACTA,EAAYC,WACZA,EAAUC,YACVA,EAAWC,WACXA,EAAUC,cACVA,EAAaC,YACbA,EAAWC,aACXA,GACEtE,EAEJ,MAAO,CACL+D,YACAC,eACAC,aACAC,cACAC,aACAC,gBACAC,cACAC,eACD,EInD8BC,CAAWd,GACpCe,EAAgC3F,OAAOC,KAC3CgF,GACAxF,QAAQmG,GAGU,QAFHX,EAAuBW,KAKK,IAAzCD,EAA8BrG,QAElCqG,EAA8BhG,SAAQmB,MAAO8E,IAC3C,MAAMC,EAASxF,EAAe4E,EAAuBW,IAC/CE,EAAc9B,EAAO6B,GACrBE,EJhBiC,CAACH,IACT,IAA7BA,EAASI,QAAQ,OACZJ,EAASK,QAAQ,MAAO,SACS,IAA/BL,EAASI,QAAQ,SACnBJ,EAASK,QAAQ,QAAS,WACQ,IAAhCL,EAASI,QAAQ,UACnBJ,EAASK,QAAQ,SAAU,YACK,IAA9BL,EAASI,QAAQ,QACnBJ,EAASK,QAAQ,OAAQ,SAG3B,GIKeC,CAA4BN,GAEhDlB,EAAcoB,EAAaC,GAC3B3B,SAAS+B,KAAK3B,YAAYsB,GAE1BhE,EAASlC,UAAUC,IAAI,mBC/DHiB,OACtB8E,EACAtF,EACA8F,EACAtE,WAEMnB,IAEN,MAAMoB,EAAeD,EAASE,wBACxBW,QAAuBd,EAAOC,GAEnB,cAAb8D,GACFS,EAAUD,EAAW,CACnBxE,OAAQ,GAAGtB,MACXoB,MAAOK,EAAaL,MAAQ,KAC5BY,KAAMK,EAAeL,KAAO,KAC5BJ,IAAKS,EAAeT,IAAM5B,EAAQ,OAIrB,gBAAbsF,GACFS,EAAUD,EAAW,CACnBxE,OAAQG,EAAaH,OAAS,KAC9BF,MAAO,GAAGpB,MACVgC,KAAMK,EAAeL,KAAO/B,SAASwB,EAAaL,MAAQ,GAAI,IAAM,KACpEQ,IAAKS,EAAeT,IAAM,OAIb,iBAAb0D,GACFS,EAAUD,EAAW,CACnBxE,OAAQ,GAAGtB,MACXoB,MAAOK,EAAaL,MAAQ,KAC5BY,KAAMK,EAAeL,KAAO,KAC5BJ,IAAKS,EAAeT,IAAM3B,SAASwB,EAAaH,OAAS,GAAI,IAAM,OAItD,eAAbgE,GACFS,EAAUD,EAAW,CACnBxE,OAAQG,EAAaH,OAAS,KAC9BF,MAAO,GAAGpB,MACVgC,KAAMK,EAAeL,KAAOhC,EAAQ,KACpC4B,IAAKS,EAAeT,IAAM,OAIb,eAAb0D,GACFS,EAAUD,EAAW,CACnBxE,OAAQ,GAAGtB,MACXoB,MAAOK,EAAaL,MAAQ,KAC5BY,KAAMK,EAAeL,KAAO,KAC5BJ,IAAKS,EAAeT,IAAM,OAIb,kBAAb0D,GACFS,EAAUD,EAAW,CACnBxE,OAAQ,GAAGtB,MACXoB,MAAOK,EAAaL,MAAQ,KAC5BY,KAAMK,EAAeL,KAAO,KAC5BJ,IACES,EAAeT,KACd3B,SAASwB,EAAaH,OAAS,GAAI,IAAMtB,GAC1C,OAIW,iBAAbsF,GACFS,EAAUD,EAAW,CACnBxE,OAAQG,EAAaH,OAAS,KAC9BF,MAAO,GAAGpB,MACVgC,KACEK,EAAeL,MACd/B,SAASwB,EAAaL,MAAQ,GAAI,IAAMpB,GACzC,KACF4B,IAAKS,EAAeT,IAAM,OAIb,gBAAb0D,GACFS,EAAUD,EAAW,CACnBxE,OAAQG,EAAaH,OAAS,KAC9BF,MAAO,GAAGpB,MACVgC,KAAMK,EAAeL,KAAO,KAC5BJ,IAAKS,EAAeT,IAAM,MAE7B,EDvBOoE,CAASV,EAAUC,EAAQC,EAAahE,EAAS,GACvD,EEhFJ,IAAYyE,EAWAC,EAeAC,GA1BZ,SAAYF,GACVA,EAAA,MAAA,GACAA,EAAA,KAAA,OACAA,EAAA,MAAA,QACAA,EAAA,OAAA,SACAA,EAAA,IAAA,KACD,CAND,CAAYA,IAAAA,EAMX,CAAA,IAKD,SAAYC,GACVA,EAAA,QAAA,UACAA,EAAA,QAAA,UACAA,EAAA,KAAA,OACAA,EAAA,KAAA,OACAA,EAAA,MAAA,QACAA,EAAA,OAAA,SACAA,EAAA,IAAA,MACAA,EAAA,IAAA,MACAA,EAAA,MAAA,OACD,CAVD,CAAYA,IAAAA,EAUX,CAAA,IAKD,SAAYC,GACVA,EAAA,MAAA,QACAA,EAAA,OAAA,SACAA,EAAA,KAAA,OACAA,EAAA,MAAA,QACAA,EAAA,OAAA,SACAA,EAAA,IAAA,KACD,CAPD,CAAYA,IAAAA,EAOX,CAAA,ICxBM,MAAMC,EAAsBC,GACjCA,EAAWnH,MAAM,KAoBNoH,EAAeD,GACZD,EAAmBC,GAEpBE,SAASL,EAAgBM,OAqB3BC,EAAgBJ,GACbD,EAAmBC,GAEpBE,SAASL,EAAgBQ,QAS3BC,EAAcN,GACXD,EAAmBC,GAEpBE,SAASL,EAAgBU,MAS3BC,EAAiBR,GACdD,EAAmBC,GAEpBE,SAASL,EAAgBY,SA6C3BC,EAAWV,GACtBA,EAAWE,SAASL,EAAgBc,QACpCX,EAAWE,SAASL,EAAgBU,MCtHzBK,EAAW,IACtB,IAAMC,KAAKC,SAASC,SAAS,IAAIC,UAAU,EAAG,ICbnCC,EAWLC,GAA0BA,EAAK3F,IAX1B0F,EAuBHC,GAA0BA,EAAKvF,KAAOuF,EAAKnG,MAvBxCkG,EAmCFC,GAA0BA,EAAK3F,IAAM2F,EAAKjG,OAnCxCgG,EA2DAC,GAA0BA,EAAKvF,KAAOuF,EAAKnG,MAAQ,EA3DnDkG,EAuEAC,GAA0BA,EAAK3F,IAAM2F,EAAKjG,OAAS,ECrEnDkG,EAAK,CAYhB1E,OAASyE,IAA6C,CACpDE,EAAGH,EAAgBC,GACnBG,EAAGJ,EAAgBC,KAcrB3F,IAAM2F,IAA6C,CACjDE,EAAGH,EAAgBC,GACnBG,EAAGJ,EAAWC,KAchBI,MAAQJ,IAA6C,CACnDE,EAAGH,EAAaC,GAChBG,EAAGJ,EAAgBC,KAcrBK,OAASL,IAA6C,CACpDE,EAAGH,EAAgBC,GACnBG,EAAGJ,EAAcC,MCjDRM,EAAmBrH,MAC9B3B,EACAiJ,EAAM,YAEN,IAAKA,EACH,MAAM,IAAIC,MAAM,qBAGlB,GAAmB,iBAARD,EACT,MAAM,IAAIC,MACR,4DAA4DD,GAIhE,MAAME,EAAqB,CACzB,SACA,OACA,QACA,MACA,SACA,YACA,eACA,WACA,cACA,WACA,YACA,cACA,eACA,aACA,eACA,gBACA,eAGF,IAAKA,EAAmBzB,SAASuB,GAC/B,MAAM,IAAIC,MACR,oFAAoFC,EAAmBnI,KACrG,eAKAQ,IAEN,MAAM4H,EAAWpJ,EAAG6C,wBAEpB,OAAO8F,EAAGM,GAAKG,EAAS,EC7CbC,EAA2B1H,MACtC2H,EACAC,EACAC,EAAO,SACPC,EAAO,YAEP,IAAKH,IAAQC,EACX,MAAM,IAAIL,MAAM,oBAGlB,MAAQN,EAAGc,EAAIb,EAAGc,SAAaX,EAAiBM,EAAKE,IAC7CZ,EAAGgB,EAAIf,EAAGgB,SAAab,EAAiBO,EAAKE,GAErD,MAAO,CACLC,KACAC,KACAC,KACAC,KACD,ECdUC,EAA+B,CAC1CrB,EACAsB,KAEA,MAAML,GAAEA,EAAEE,GAAEA,EAAED,GAAEA,EAAEE,GAAEA,GAAOpB,GACrBuB,OAAEA,GAAS,EAAKC,SAAEA,GAAW,EAAKC,UAAEA,GAAcH,EAIxD,IAAII,EAAe,CAAEvB,EAAGc,GAAME,EAAKF,GAAM,EAAGb,EAAGc,GAC3CS,EAAc,CAAExB,EAAGc,GAAME,EAAKF,GAAM,EAAGb,EAAGgB,GAkC9C,OAhCIG,IACEC,EACgB,SAAdC,GACFC,EAAe,CAAEvB,EAAGc,EAAK,GAAIb,EAAGc,EAAK,GACrCS,EAAc,CAAExB,EAAGgB,EAAK,GAAIf,EAAGgB,IACR,UAAdK,GACTC,EAAe,CAAEvB,EAAGc,EAAK,EAAQb,EAAGc,EAAK,IACzCS,EAAc,CAAExB,EAAGgB,EAAIf,EAAGgB,EAAK,KACR,SAAdK,GACTC,EAAe,CAAEvB,EAAGc,EAAK,GAAIb,EAAGc,EAAK,GACrCS,EAAc,CAAExB,EAAGgB,EAAK,GAAIf,EAAGgB,KAE/BM,EAAe,CAAEvB,EAAGc,EAAK,EAAQb,EAAGc,EAAK,IACzCS,EAAc,CAAExB,EAAGgB,EAAIf,EAAGgB,EAAK,KAGf,SAAdK,GACFC,EAAe,CAAEvB,EAAGc,EAAK,GAAIb,EAAGc,EAAK,GACrCS,EAAc,CAAExB,EAAGgB,EAAK,GAAIf,EAAGgB,IACR,UAAdK,GACTC,EAAe,CAAEvB,EAAGc,EAAK,EAAQb,EAAGc,EAAK,IACzCS,EAAc,CAAExB,EAAGgB,EAAIf,EAAGgB,EAAK,KACR,SAAdK,GACTC,EAAe,CAAEvB,EAAGc,EAAK,GAAIb,EAAGc,EAAK,GACrCS,EAAc,CAAExB,EAAGgB,EAAK,GAAIf,EAAGgB,KAE/BM,EAAe,CAAEvB,EAAGc,EAAK,EAAQb,EAAGc,EAAK,IACzCS,EAAc,CAAExB,EAAGgB,EAAIf,EAAGgB,EAAK,MAK9B,CACLQ,WAvCiB,CAAEzB,EAAGc,EAAIb,EAAGc,GAwC7BQ,eACAG,UAxCgB,CAAE1B,EAAGgB,EAAIf,EAAGgB,GAyC5BO,cACD,EAqBUG,EAAkB5I,MAC7B6I,EACAC,EACAV,KAEA,MAAMP,KAAEA,EAAIC,KAAEA,EAAIQ,SAAEA,GAAW,EAAKC,UAAEA,GAAcH,GAC9CL,GAAEA,EAAEC,GAAEA,EAAEC,GAAEA,EAAEC,GAAEA,SAAaR,EAC/BmB,EACAC,EACAjB,EACAC,GAKF,IAAIiB,EAAa,EACbC,EAAa,EAGA,SAAbT,EACFS,EAAa,EACS,QAAbT,EACTQ,EAAa,EACS,QAAbR,EACTQ,GAAc,EACQ,SAAbR,IACTS,GAAc,GAGhB,MAAMC,EAAcd,EAClB,CACEJ,GAAIA,EAnBW,EAoBfE,GAAIA,EAAKc,EACTf,GAAIA,EApBW,EAqBfE,GAAIA,EAAKc,GAEX,CACEX,QAAQ,EACRC,WACAC,eAGEG,WAAEA,EAAUF,aAAEA,EAAYC,YAAEA,EAAWE,UAAEA,GAAcM,EAE7D,MACE,KAAKP,EAAWzB,KAAKyB,EAAWxB,MAC3BsB,EAAavB,KAAKuB,EAAatB,MAAMuB,EAAYxB,KAAKwB,EAAYvB,MAAMyB,EAAU1B,KAAK0B,EAAUzB,GACtG,ECxHSgC,EAAuBlJ,OAClCmJ,QACAC,OACAC,SAAQ,MAMR,MAAMtB,GAAEA,EAAEC,GAAEA,EAAEC,GAAEA,EAAEC,GAAEA,SAAaR,EAAyByB,EAAOC,GAC3DE,ECba,EACnBtK,EACAuK,EACAC,EACAC,EACAC,GAAY,KAEZ,KAAK1K,GAAOuK,GAAOC,GAAOC,GACxB,MAAM,IAAIE,YAAY,6BAGxB,GACgB,iBAAP3K,GACO,iBAAPuK,GACO,iBAAPC,GACO,iBAAPC,EAEP,MAAM,IAAIG,UACR,wFAAwF5K,YAAauK,YAAaC,YAAaC,KAInI,MAAMI,EAAKJ,EAAKF,EACVO,EAAKN,EAAKxK,EAEhB,IAAI+K,EAAQrD,KAAKsD,MAAMH,EAAIC,GAM3B,OAJAC,GAAS,IAAMrD,KAAKuD,GAEhBP,GAAaK,EAAQ,IAAGA,EAAQ,IAAMA,GAEnCA,CAAK,EDlBGG,CAAMnC,EAAIC,EAAIC,EAAIC,GAKjC,OAJmBmB,EE4BmB,CAACc,IACvC,GAAIA,EAAU,IAAK,MAAM,IAAIC,WAAW,+BAExC,GAAID,EAAU,EAAG,MAAM,IAAIC,WAAW,oCAEtC,OAAID,GAAW,IAAMA,GAAW,IACvB,QACEA,EAAU,KAAOA,GAAW,IAC9B,OACEA,EAAU,KAAOA,GAAW,IAC9B,QAEA,MAGR,EF1CGE,CAAyBf,GEdG,CAACa,IACjC,GAAIA,EAAU,IAAK,MAAM,IAAIC,WAAW,+BAExC,GAAID,EAAU,EAAG,MAAM,IAAIC,WAAW,oCAEtC,OAAID,GAAW,GAAKA,GAAW,KACtB,OACEA,GAAW,MAAQA,GAAW,KAChC,aACEA,GAAW,MAAQA,GAAW,MAChC,QACEA,GAAW,OAASA,GAAW,MACjC,aACEA,GAAW,OAASA,GAAW,MACjC,OACEA,GAAW,OAASA,GAAW,MACjC,aACEA,GAAW,OAASA,GAAW,MACjC,QACEA,GAAW,OAASA,GAAW,MACjC,aAEA,MACR,EFRGG,CAAmBhB,EAEN,QG1BNiB,EACXC,GACAC,GACAC,aACAC,YACAC,KAOAxK,YAAYsK,EAA2BC,GACrCE,MAAKC,EAAMJ,EAAcC,EAC1B,CAQDG,GAAMJ,EAA2BC,GAC/B,IAAKD,IAAiBC,EACpB,MAAM,IAAIpD,MAAM,+CAGlB,IAAKjE,SAAS+B,KAAK0F,SAASJ,GAC1B,MAAM,IAAIpD,MAAM,iCAGlB,IAAKjE,SAAS+B,KAAK0F,SAASL,GAC1B,MAAM,IAAInD,MAAM,kCASlB,GANAsD,KAAKH,aAAeA,EACpBG,KAAKF,YAAcA,EAEnBE,MAAKL,EAAUlH,SAAS0H,eAAe,kBACvCH,MAAKJ,EAAuBnH,SAAS0H,eAAe,oBAE/CH,MAAKJ,IAAyBI,MAAKL,EACtC,MAAM,IAAIjD,MACR,4EAIJsD,KAAKI,SACN,CAKDA,UACEJ,KAAKK,KAAKL,MAAKJ,EAChB,CAODzK,WAAWmL,GACT,IAAKA,EACH,MAAM,IAAI5D,MAAM,0BAGlB,MACM6D,EAAc,qBADR3E,MAEN4E,EAAYF,EAAKG,WAAU,GAUjC,GARAD,EAAU1H,aAAa,KAAMyH,GAC7BC,EAAU1H,aACR,gBACAkH,KAAKH,aAAaa,aAAa,OAAS,eAE1CF,EAAUvM,UAAU0M,OAAO,YAC3BH,EAAUvM,UAAUC,IAAI,YAEpBoM,EAAKM,WAGP,MAAM,IAAIlE,MAAM,gCAFhBsD,KAAKD,KAAOO,EAAKM,WAAWC,aAAaL,EAAWF,EAAKQ,aAK3D,MAAMC,QAAmB1C,EAAqB,CAC5CC,MAAO0B,KAAKH,aACZtB,KAAMyB,KAAKF,YACXtB,OAAO,KAEHxB,KAAEA,EAAIC,KAAEA,GJ+FoB,CAACS,IACrC,IAAIV,EACAC,EAEJ,OAAQS,GACN,IAAK,OACHV,EAAO,QACPC,EAAO,OACP,MACF,IAAK,QACHD,EAAO,SACPC,EAAO,MACP,MACF,IAAK,OACHD,EAAO,OACPC,EAAO,QACP,MAEF,QACED,EAAO,MACPC,EAAO,SAIX,MAAO,CAAED,OAAMC,OAAM,EIvHI+D,CAAuBD,GACxCE,OJ2DgB9L,OACxB6I,EACAC,EACAV,KAEA,MAAMP,KAAEA,EAAIC,KAAEA,GAASM,GACjBL,GAAEA,EAAEC,GAAEA,EAAEC,GAAEA,EAAEC,GAAEA,SAAaR,EAC/BmB,EACAC,EACAjB,EACAC,GAEImB,EAAcd,EAClB,CAAEJ,KAAIE,KAAID,KAAIE,MACd,CAAEK,UAAW,MAETG,WAAEA,EAAUF,aAAEA,EAAYC,YAAEA,EAAWE,UAAEA,GAAcM,EAE7D,MACE,KAAKP,EAAWzB,KAAKyB,EAAWxB,MAC3BsB,EAAavB,KAAKuB,EAAatB,MAAMuB,EAAYxB,KAAKwB,EAAYvB,MAAMyB,EAAU1B,KAAK0B,EAAUzB,GACtG,EIhFiB6E,CAAWlB,KAAKH,aAAcG,KAAKF,YAAa,CAC/D9C,OACAC,SAGF+C,KAAKD,KAAKjH,aAAa,iBAAkBiI,GACzCf,KAAKD,KAAKjH,aAAa,YAAakE,GACpCgD,KAAKD,KAAKjH,aAAa,YAAamE,GAEpC+C,KAAKD,KAAKjH,aAAa,IAAKmI,EAC7B,EAIHzK,OAAOkJ,YAAcA,QCzGRyB,EACXxB,GACAC,GACAC,aACAC,YACAsB,iBACAC,kBAOA9L,YAAYsK,EAA2BC,GACrCE,MAAKC,EAAMJ,EAAcC,EAC1B,CAQDG,GAAMJ,EAA2BC,GAC/B,IAAKD,IAAiBC,EACpB,MAAM,IAAIpD,MAAM,+CAGlB,IAAKjE,SAAS+B,KAAK0F,SAASJ,GAC1B,MAAM,IAAIpD,MAAM,iCAGlB,IAAKjE,SAAS+B,KAAK0F,SAASL,GAC1B,MAAM,IAAInD,MAAM,kCASlB,GANAsD,KAAKH,aAAeA,EACpBG,KAAKF,YAAcA,EAEnBE,MAAKL,EAAUlH,SAAS0H,eAAe,kBACvCH,MAAKJ,EAAuBnH,SAAS0H,eAAe,oBAE/CH,MAAKJ,IAAyBI,MAAKL,EACtC,MAAM,IAAIjD,MACR,4EAIJsD,KAAKI,SACN,CAKDA,UACEJ,KAAKK,KAAKL,MAAKJ,EAChB,CAQD0B,GAAgBhB,GACd,IAAKA,EACH,MAAM,IAAI5D,MAAM,qCAGlB,MACM6D,EAAc,qBADR3E,MAEN4E,EAAYF,EAAKG,WAAU,GAUjC,OARAD,EAAU1H,aACR,gBACAkH,KAAKH,aAAaa,aAAa,OAAS,eAE1CF,EAAU1H,aAAa,KAAMyH,GAC7BC,EAAUvM,UAAU0M,OAAO,YAC3BH,EAAUvM,UAAUC,IAAI,WAEjBsM,CACR,CAODrL,WAAWmL,GACT,IAAKA,EACH,MAAM,IAAI5D,MAAM,0BAGlB,MAAM6E,EAAsBvB,MAAKsB,EAAgBhB,GAC3CkB,EAAuBxB,MAAKsB,EAAgBhB,GAElD,IAAIA,EAAKM,WAUP,MAAM,IAAIlE,MAAM,gCAThBsD,KAAKoB,iBAAmBd,EAAKM,WAAWC,aACtCU,EACAjB,EAAKQ,aAEPd,KAAKqB,kBAAoBf,EAAKM,WAAWC,aACvCW,EACAlB,EAAKQ,aAMT,MAAMC,QAAmB1C,EAAqB,CAC5CE,KAAMyB,KAAKF,YACXxB,MAAO0B,KAAKH,aACZrB,OAAO,KAEHiD,UAAEA,EAASC,UAAEA,EAASC,UAAEA,EAASC,UAAEA,GL4GF,CAAClE,IAC1C,IAAI+D,EACAC,EACAC,EACAC,EAEJ,OAAQlE,GACN,IAAK,OACH+D,EAAY,YACZC,EAAY,cACZC,EAAY,eACZC,EAAY,cACZ,MACF,IAAK,QACHH,EAAY,cACZC,EAAY,aACZC,EAAY,eACZC,EAAY,aACZ,MACF,IAAK,OACHH,EAAY,WACZC,EAAY,eACZC,EAAY,cACZC,EAAY,eACZ,MAEF,QACEH,EAAY,WACZC,EAAY,gBACZC,EAAY,YACZC,EAAY,gBAIhB,MAAO,CACLH,YACAC,YACAC,YACAC,YACD,EKlJGC,CAA4Bd,GACxBe,QAAsB/D,EAC1BiC,KAAKH,aACLG,KAAKF,YACL,CACE9C,KAAMyE,EACNxE,KAAMyE,EACNjE,UAAU,EACVC,UAAWqD,IAGTgB,QAAuBhE,EAC3BiC,KAAKH,aACLG,KAAKF,YACL,CACE9C,KAAM2E,EACN1E,KAAM2E,EACNlE,UAAWqD,IAIff,KAAKoB,iBAAiBtI,aAAa,iBAAkBiI,GACrDf,KAAKoB,iBAAiBtI,aAAa,YAAa2I,GAChDzB,KAAKoB,iBAAiBtI,aAAa,YAAa4I,GAChD1B,KAAKoB,iBAAiBtI,aAAa,IAAKgJ,GACxC9B,KAAKqB,kBAAkBvI,aAAa,iBAAkBiI,GACtDf,KAAKqB,kBAAkBvI,aAAa,YAAa6I,GACjD3B,KAAKqB,kBAAkBvI,aAAa,YAAa8I,GACjD5B,KAAKqB,kBAAkBvI,aAAa,IAAKiJ,EAC1C,EAIHvL,OAAO2K,oBAAsBA,EChItB,MAAM/L,EAASD,MACpB6M,EACA7L,EACA8L,EACA1E,KAEA,MAAM7B,QAAEA,GAAU,GAAU6B,GAAW,CAAA,EACjC2E,EAAoBrN,EAASoN,GAC7BE,EnBwJNzN,EACEI,iBmBzJuCmN,GnByJlBlN,iBAAiB,+BDtHE,EoBlC1C,MAAMqN,QAA2BvL,EAAOoL,EAAc9L,GAEtD,GAAIqF,EAAcwG,GAAO,CACvB,MAAMrL,KAAEA,EAAIJ,IAAEA,EAAGN,OAAEA,EAAMF,MAAEA,GAAUqM,EAAmB7K,WAExD,MAAO,CACLZ,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRN,OAAQ,GAAGA,MACXF,MAAO,GAAGA,MAEb,CAED,GZ5BcgF,EY4BCiH,GZ1BF9G,SAASL,EAAgBwH,MY0BhB,CACpB,GAAI/G,EAAW0G,KAAUtG,EAAS,CAChC,MAAM/E,KAAEA,EAAIJ,IAAEA,EAAGN,OAAEA,GAAWmM,EAAmBnK,SAAS,CACxDD,YAAamK,IAGf,MAAO,CACLxL,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRN,OAAQ,GAAGA,MAEd,CAAM,CACL,MAAMU,KAAEA,EAAIJ,IAAEA,GAAQ6L,EAAmBnK,SAAS,CAChDR,QAAQ,EACR7B,SAAU8F,EAAUwG,EAAoB,IAAMA,IAGhD,MAAO,CACLvL,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MAEX,CACF,CAAM,GAAI0E,EAAY+G,GAAO,CAC5B,GAAI1G,EAAW0G,KAAUtG,EAAS,CAChC,MAAM/E,KAAEA,EAAIJ,IAAEA,EAAGN,OAAEA,GAAWmM,EAAmBhK,UAAU,CACzDX,QAAQ,IAGV,MAAO,CACLd,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRN,OAAQ,GAAGA,MAEd,CAAM,CACL,MAAMU,KAAEA,EAAIJ,IAAEA,GAAQ6L,EAAmBhK,UAAU,CACjDX,QAAQ,EACR7B,SAAU8F,EAAUwG,EAAoB,IAAMA,IAGhD,MAAO,CACLvL,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MAEX,CACF,CAAM,GAAI6E,EAAa4G,GAAO,CAC7B,GAAI1G,EAAW0G,KAAUtG,EAAS,CAChC,MAAM/E,KAAEA,EAAIJ,IAAEA,EAAGR,MAAEA,GAAUqM,EAAmBtK,WAAW,CACzDL,QAAQ,IAGV,MAAO,CACLd,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRR,MAAO,GAAGA,MAEb,CAAM,CACL,MAAMY,KAAEA,EAAIJ,IAAEA,GAAQ6L,EAAmBtK,WAAW,CAClDL,QAAQ,EACR7B,SAAU8F,EAAUwG,EAAoB,IAAMA,IAGhD,MAAO,CACLvL,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MAEX,CACF,CACC,GAAI+E,EAAW0G,KAAUtG,EAAS,CAChC,MAAM/E,KAAEA,EAAIJ,IAAEA,EAAGR,MAAEA,GAAUqM,EAAmBzK,QAAQ,CACtDF,QAAQ,IAGV,MAAO,CACLd,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRR,MAAO,GAAGA,MAEb,CAAM,CACL,MAAMY,KAAEA,EAAIJ,IAAEA,GAAQ6L,EAAmBzK,QAAQ,CAC/CF,QAAQ,EACR7B,SAAU8F,EAAUwG,EAAoB,IAAMA,IAGhD,MAAO,CACLvL,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MAEX,CACF,EChHU8B,EAAS,CACpBiK,EAAc,GACdN,EACAO,EAAI,UAEJ,MAAM/J,EAAMC,SAASC,cAAc6J,GAC7BC,EAAa/J,SAASG,eAAe0J,GACrCG,EAAqB,CAAA,EAEd,OAATT,GAA0B,KAATA,IACnBS,EAAmBT,IAAQ,IAIzB1G,EAAW0G,KAAUxG,EAAcwG,IACpC1G,EAAW0G,IAAStG,EAAQsG,GAE7BxJ,EAAIK,YAAY2J,IACPlH,EAAW0G,IAASxG,EAAcwG,KAC3CxJ,EAAIM,aAAa,0BAA2BwJ,GAG9C,MAAMI,EAAevO,EAAG,wBAAyBsO,GAIjD,OAFA1J,EAAcP,EAAKkK,GAEZlK,CAAG,EAeCQ,EAAW2J,IACtB,IAAKA,EAAW,OAAO1N,QAAQ2N,UAE/B,MAAMC,EAAkBF,EAAUG,iBAAiB,kBAEnD,GAAID,EAAiB,CACnB,IAAIE,EAAgB,EAEpBF,EAAgB7O,SAAQmB,MAAOgB,EAAuB6M,KACpD,IAAK7M,EAAU,OAAOlB,QAAQ2N,UAE9B,MAAMK,EAAwB9M,EAASuK,aAAa,iBAAmB,GAEvE,IACGuC,GACiB,KAAlBA,IACoD,IAApDA,EAAc5I,QAAQQ,EAAgBqI,SAEtC,OAAOjO,QAAQ2N,UAMjB,IAAIO,EAAkB1O,EAAiBuO,GAElCG,IACHA,EAAkB,GAAG1O,EAAiBsO,KAAiBtO,EACrDsO,GACAK,gBACFL,KAGF,MAAMM,EAAiBhL,EAAO8K,EAAiBF,GAE/CxK,SAAS+B,KAAK3B,YAAYwK,GAE1B,MAAMC,QAA2BlO,EAC/B6N,EACA9M,EACAkN,EACA,CACE3H,QAASA,EAAQuH,KbQL,IAACjI,QaJX9G,EAAImP,EAAgBC,IbITtI,EaFNiI,GbGJ/H,SAASL,EAAgB0I,MACpCvI,EAAWE,SAASL,EAAgBc,QACpCX,EAAWE,SAASL,EAAgBU,OACpCP,EAAWE,SAASL,EAAgBY,SaL9B,IAAIiE,EAAYvJ,EAAUkN,GACjB3H,EAAQuH,IACjB,IAAI9B,EAAoBhL,EAAUkN,EACnC,GAEJ,CAED,OAAOpO,QAAQ2N,SAAS,EChGbvK,EAAS,CACpBC,EAAwB,GACxB0J,EAAsB,GACtBzJ,EAAM,UAEN,MAAMC,EAAMC,SAASC,cAAcH,GAOnC,OALAC,EAAIM,aAAa,QAASR,EAAO,MACjCE,EAAIM,aAAa,eAAgBlE,SAAS0D,EAAO,GAAI,IAAM,MAE3DS,EAAcP,EAAK,sBAAsBwJ,KAElCxJ,CAAG,EAeCQ,EAAU7D,MAAOgB,IAC5B,IAAKA,EAAU,OAEf,MAAM8M,EAA+B9M,EAASuK,aAC5C,wBAGF,GAAsB,KAAlBuC,IAAyBA,EAC3B,OAGF,MAAMhK,QAAuBC,EAAU/C,GAEvC,GAC6B,SAA3B8C,EAAeE,SACY,MAA3BF,EAAeG,SACe,WAA9BH,EAAeI,WAEf,aAGIrE,IAEN,MAAMoB,EAAeD,EAASE,wBAE9B,Gd2Bc0E,Ec3BEkI,Gd6BH/H,SAASJ,EAAgB0I,Oc5BpC,GAAIpI,EAAa6H,GAAgB,CAC/B,MAAMQ,EAAcpL,EAAOjC,EAAaL,MAAOkN,GAE/CxK,SAAS+B,KAAK3B,YAAY4K,GAE1B,MAAMrB,QAA2BvL,EAAO4M,EAAatN,IAC/CQ,KAAEA,EAAIJ,IAAEA,EAAGR,MAAEA,GAAUqM,EAAmBtK,WAAW,CACzDL,QAAQ,UAGJiD,EAAU+I,EAAa,CAC3B9M,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRR,MAAO,GAAGA,OAEb,KAAM,CACL,MAAM0N,EAAcpL,EAAOjC,EAAaL,MAAOkN,GAE/CxK,SAAS+B,KAAK3B,YAAY4K,GAE1B,MAAMrB,QAA2BvL,EAAO4M,EAAatN,IAC/CQ,KAAEA,EAAIJ,IAAEA,EAAGR,MAAEA,GAAUqM,EAAmBzK,QAAQ,CACtDF,QAAQ,EACR7B,UtBlBN8N,UsBqBUhJ,EAAU+I,EAAa,CAC3B9M,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRR,MAAO,GAAGA,OAEb,MACI,GdnBmB,CAACiF,GACbD,EAAmBC,GAEpBE,SAASJ,EAAgB6I,QcgB3BC,CAAaX,GACtB,GAAIhI,EAAYgI,GAAgB,CAC9B,MAAMQ,EAAcpL,EAAOjC,EAAaH,OAAQgN,GAEhDxK,SAAS+B,KAAK3B,YAAY4K,GAE1B,MAAMrB,QAA2BvL,EAAO4M,EAAatN,IAC/CQ,KAAEA,EAAIJ,IAAEA,EAAGN,OAAEA,GAAWmM,EAAmBhK,UAAU,CACzDX,QAAQ,UAGJiD,EAAU+I,EAAa,CAC3B9M,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRN,OAAQ,GAAGA,OAEd,KAAM,CACL,MAAMwN,EAAcpL,EAAOjC,EAAaH,OAAQgN,GAEhDxK,SAAS+B,KAAK3B,YAAY4K,GAE1B,MAAMrB,QAA2BvL,EAAO4M,EAAatN,IAC/CQ,KAAEA,EAAIJ,IAAEA,EAAGN,OAAEA,GAAWmM,EAAmBnK,SAAS,CACxDR,QAAQ,EACR7B,UtBnDN8N,UsBsDUhJ,EAAU+I,EAAa,CAC3B9M,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRN,OAAQ,GAAGA,OAEd,CACF,EChIUoC,EAAS,CAACkK,EAAI,UACzB,MAAMsB,EAAcpL,SAASC,cAAc6J,GACrCuB,EAAa3P,EAAG,mBAItB,OAFAZ,EAAIsQ,EAAaC,GAEVD,CAAW,EAeP7K,EAAU7D,MAAO4O,IAC5B,IAAKA,EAAe,OAAO9O,QAAQ2N,UAEnC,MAAMiB,EAAcxL,IAEpBI,SAAS+B,KAAK3B,YAAYgL,GAE1B,MAAMG,QAAyBnN,EAAOgN,EAAaE,IAC7CpN,KAAEA,EAAIJ,IAAEA,EAAGN,OAAEA,EAAMF,MAAEA,GAAUiO,EAAiBzM,WAChD0M,EAAa,CACjBtN,KAAM,GAAGA,MACTJ,IAAK,GAAGA,MACRN,OAAQ,GAAGA,MACXF,MAAO,GAAGA,aAGN2E,EAAUmJ,EAAaI,EAAW,ECxC7BC,EAAU,CAACC,EAAyBC,EAAW,IAC1DC,WAAWF,EAAS,IAAIG,QAAQF,GCMrB/L,EAAS,CAACkM,EAAcvC,KACnC,MAAMxJ,EAAMC,SAASC,cAAc,OAC7B+J,EAAqB,CAAA,EAEd,OAATT,GAA0B,KAATA,IACnBS,EAAmBT,IAAQ,GAG7B,MAAMU,EAAevO,EAAG,wBAAyBsO,GAMjD,OAJAjK,EAAIgM,UAAYD,EAEhBxL,EAAcP,EAAKkK,GAEZlK,CAAG,EAiBCQ,EAAU7D,MAAOgB,IAC5B,IAAKA,EAAU,OAEf,MAAMsO,EAAuBtO,EAASuK,aAAa,2BAC7CzH,QAAuBC,EAAU/C,GAEvC,GAC6B,SAA3B8C,EAAeE,SACY,MAA3BF,EAAeG,SACe,WAA9BH,EAAeI,WAEf,OAGFlD,EAASlC,UAAUC,IAAI,cAEvB,MAAMwQ,OCtDgBvP,OAAOgB,IAC7B,MACMwO,EzBoHqB,CAC3BnP,IAEA,MAAMoP,WACJA,EAAUC,cACVA,EAAaC,WACbA,EAAUC,SACVA,EAAQC,UACRA,EAASC,sBACTA,EAAqBC,WACrBA,GACE1P,EAEJ,MAAO,CACLoP,aACAC,gBACAC,aACAC,WACAC,YACAC,wBACAC,aACD,EyBzIeC,OADajM,EAAU/C,IAEjCiP,EACsB,WAA1BT,EAAoB,WAChB/P,SAAS+P,EAAoB,WAAG,IAAM,GAAK,MAC3C,SAEN,MAKE,+FAAoDA,EAAoB,kEACtBA,EAAkB,cAClE/P,SAAS+P,EAAkB,SAAG,IAAM,+DAEcA,EAAoB,gFACRA,EAA+B,+EAC3CA,EAAoB,gBAAOS,8DACxBT,EAAuB,sEAC3BA,EAAmB,uBAGtE,ED8BkBU,CAASlP,GACvBgE,EAAc9B,EAAOqM,EAAOD,GAElChM,SAAS+B,KAAK3B,YAAYsB,GAE1B,MAAMmL,OEhDgBnQ,OACtB6M,EACA7L,EACAoP,KAEA,MAAMnP,EAAeD,EAASE,wBACxB6L,EAAoBrN,EAAS0Q,GAC7BC,EAAmBD,EAAUlP,wBAC7BoP,QAAmBvP,EAAOC,GAC1BuP,EACJD,EAAW9O,KAAO6O,EAAiBzP,MAAQmM,EAAoB,KAC3DyD,EACJzB,EACElO,EAA2ByP,EAAWlP,IAAKiP,EAAkBpP,IAC3D,KACAwP,EACJH,EAAW9O,KAAOP,EAAaL,MAAQmM,EAAoB,KACvD2D,EACJ3B,EACElO,EAA2ByP,EAAWlP,IAAKiP,EAAkBpP,IAC3D,KACA0P,EACJ5B,EACEvO,EACE8P,EAAW9O,KACX6O,EACApP,IAEA,KACA2P,EACJN,EAAWlP,IAAMiP,EAAiBvP,OAASiM,EAAoB,KAC3D8D,EACJ9B,EACEvO,EACE8P,EAAW9O,KACX6O,EACApP,IAEA,KACA6P,EACJR,EAAWlP,IAAMH,EAAaH,OAASiM,EAAoB,KAE7D,IAAIoD,EAAY,CACd3O,KAAM+O,EACNnP,IAAKoP,GAoBP,OAjBI3D,IAAiD,IAAzCA,EAAK3H,QAAQO,EAAgBO,OACvCmK,EAAY,CACV3O,KAAMiP,EACNrP,IAAKsP,GAEE7D,IAA+C,IAAvCA,EAAK3H,QAAQO,EAAgBsL,KAC9CZ,EAAY,CACV3O,KAAMmP,EACNvP,IAAKwP,GAEE/D,IAAkD,IAA1CA,EAAK3H,QAAQO,EAAgBS,UAC9CiK,EAAY,CACV3O,KAAMqP,EACNzP,IAAK0P,IAIFX,CAAS,EFhBQ3K,CAAS8J,EAAOtO,EAAUgE,GAElDO,EAAUP,EAAamL,EAAU,EGtDtBa,EAAYC,IAKvB,MAAMC,EAAmB,ICHV,EACfC,EACAC,EACAC,GAAY,KAEZ,IAAIC,EAEJ,OAAO,SAAUC,KAAqBC,GACpC,MAKMC,EAAUJ,IAAcC,EAE1BA,GACFI,aAAaJ,GAGfA,EAAUK,YAXI,WACZL,EAAU,KAELD,GAAWF,EAAKS,MAAML,EAASC,EACtC,GAO4BJ,GAExBK,GAASN,EAAKS,MAAML,EAASC,EACnC,CAAC,EDlBCK,EAAS,KACPZ,GAAS,GACR,KAGL5P,OAAOyQ,oBAAoB,SAAUZ,GAGrC7P,OAAO0Q,iBAAiB,SAAUb,EAAiB,EEfxCc,EAAOf,IACU,YAAxB3N,SAAS2O,WACX3O,SAASyO,iBAAiB,oBAAoB,KAC5Cd,GAAS,IAIXA,GACD,EAYUiB,EAAO,KAClB,MAAMC,EAAiB,IAAIC,sBAAqB,CAACC,EAAKC,KACpDD,EAAIxT,SAASR,IACPA,EAAGkU,kBAAoB,IACzBC,EAAYnU,EAAGoU,QACfH,EAASI,UAAUrU,EAAGoU,QACvB,GACD,IAGJnP,SACGqK,iBACC,4FAED9O,SAASR,IACR8T,EAAeQ,QAAQtU,EAAG,IAG9B,MAAMuU,EAAoB,IAAIR,sBAAqB,CAACC,EAAKC,KACvDD,EAAIxT,SAASR,IACPA,EAAGkU,kBAAoB,IACzBM,EAAexU,EAAGoU,QAClBH,EAASI,UAAUrU,EAAGoU,QACvB,GACD,IAGJnP,SAASqK,iBAAiB,0BAA0B9O,SAASR,IAC3DuU,EAAkBD,QAAQtU,EAAG,IAG/B,MAAMyU,EAAoB,IAAIV,sBAAqB,CAACC,EAAKC,KACvDD,EAAIxT,SAASR,IACPA,EAAGkU,kBAAoB,IACzBQ,EAAe1U,EAAGoU,QAClBH,EAASI,UAAUrU,EAAGoU,QACvB,GACD,IAGJnP,SAASqK,iBAAiB,0BAA0B9O,SAASR,IAC3DyU,EAAkBH,QAAQtU,EAAG,GAC7B,EAcS2U,EAAU/B,IACrB5P,OAAO4P,QAAUA,CAAO,EAcbD,EAAYC,IACvB,MAAMgC,EAAU3P,SAAS4P,cAEzB,GAAID,EAAS,CACX,MAAME,EAAsBF,EAAQ1H,aAAa,QAG/C4H,IACgD,IAA/CA,EAAoBjO,QAAQ,gBAEmB,IAA9CiO,EAAoBjO,QAAQ,eAE1B+N,EAAQG,aAAa,eACvBJ,EAAO/B,GACEgC,EAAQG,aAAa,gBAC9BnC,IACSgC,EAAQG,aAAa,YAC9BpB,EAAIf,GACKgC,EAAQG,aAAa,aAC9BlB,IAEAF,EAAIf,GAIHgC,EAAQG,aAAa,gBACrBH,EAAQG,aAAa,cAEtBC,EAAepC,GAGpB,GCxHUqC,EAAU,CACrBpQ,OAAQqQ,EACR1P,QAAS2P,GAGEC,GAAU,CACrBvQ,OAAQwQ,EACR7P,QAASkP,GAGEY,GAAU,CACrBzQ,OAAQ0Q,EACR/P,QAASgP,GAGEgB,GAAO,CAClB3Q,OAAQ4Q,EACRjQ,QAAS6K,GAGEqF,GAAa,CACxB7Q,OAAQ8Q,EACRnQ,QAASoQ,GAGEC,GAAQ,CACnBlC,MACAE,OACAc,SACAhC,YAGIC,GAAU,KjCxBS,EAACkD,EAAkB9V,EAAeiF,YACzD,GAAGzE,QAAQuV,KAAK/V,EAAGsP,iBAAiBwG,IAAW,SAAUE,GACvDA,EAAE7I,QACJ,GAAE,EiCsBF8I,CAAU,YAEV,MAAMC,EAAiBjR,SAASqK,iBAC9B,4FAEI6G,EAAkBlR,SAASqK,iBAAiB,0BAC5C8G,EAA2BnR,SAASqK,iBACxC,6BAEI+G,EAAmBpR,SAASqK,iBAAiB,0BAC7BrK,SAASqK,iBAAiB,uBAElC9O,QAAQ6P,GACtB6F,EAAe1V,QAAQ2U,GACvBgB,EAAgB3V,QAAQgU,GACxB4B,EAAyB5V,QAAQoV,GACjCS,EAAiB7V,QAAQkU,EAAe,EAK1C/B,EAASC"} \ No newline at end of file +{"version":3,"file":"speccer.js","sources":["src/utils/node.ts","src/utils/classnames.ts","src/utils/constants.ts","src/utils/css.ts","src/utils/wait.ts","src/utils/styles.ts","src/utils/position.ts","src/features/spacing/index.ts","src/features/spacing/utils/position.ts","src/types/enums/area.ts","src/utils/area.ts","src/utils/id.ts","src/utils/coords.ts","src/utils/xy.ts","src/utils/intrinsic-coords.ts","src/utils/get-coords-pair-from-objects.ts","src/utils/bezier.ts","src/utils/direction-of-element.ts","src/utils/angle.ts","src/utils/cardinal.ts","src/utils/classes/DrawSVGLine.ts","src/utils/classes/DrawSVGCurlyBracket.ts","src/features/dissect/utils/styles.ts","src/features/dissect/index.ts","src/features/measure/index.ts","src/features/mark/index.ts","src/utils/number.ts","src/features/typography/index.ts","src/features/typography/utils/template.ts","src/features/typography/utils/position.ts","src/utils/resize.ts","src/utils/debounce.ts","src/config/browser.ts","src/main.ts"],"sourcesContent":["/**\n * Inserts an HTML element after another element in the DOM.\n *\n * @param {HTMLElement | null} el - The reference element after which the new element will be inserted.\n * @param {HTMLElement} newSibling - The new element to be inserted.\n * @returns {Element|null}\n *\n * @example\n * ```ts\n * // Insert an element after another element\n * const referenceElement = document.getElementById('reference-element');\n * const newElement = document.createElement('div');\n * after(referenceElement, newElement);\n */\nexport const after = (\n el: HTMLElement | null,\n newSibling: HTMLElement\n): Element | null => el && el.insertAdjacentElement('afterend', newSibling);\n\n/**\n * Removes all elements matching a selector from the DOM.\n *\n * @param {string} selector - The CSS selector used to select elements for removal.\n * @param {Document} el - The document context (default is the global `document` object).\n * @returns {void}\n *\n * @example\n * ```ts\n * // Remove all elements with a specific class from the document\n * removeAll('.my-class');\n * ```\n */\nexport const removeAll = (selector: string, el: Document = document): void => {\n [].forEach.call(el.querySelectorAll(selector), function (e: HTMLElement) {\n e.remove();\n });\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport { ClassNamesObjectMapInterface } from 'types/interfaces/classnames';\n\n/**\n * Add CSS classes to an HTML element.\n *\n * @param {HTMLElement} el - The HTML element to which classes should be added.\n * @param {string} cls - The CSS classes to add, separated by spaces.\n * @param {string} [avoid='noop'] - Classes to avoid adding.\n * @returns {void}\n * @example\n * ```ts\n * // Add classes to an HTML element\n * const element = document.getElementById('example');\n * set(element, 'class1 class2');\n * ```\n */\nexport const set = (el: HTMLElement, cls: string, avoid = 'noop') => {\n if (!el) return;\n\n if (!cls || (cls && cls.length === 0)) return;\n\n cls\n .trim()\n .split(' ')\n .filter((cl) => cl !== avoid)\n .forEach((cl) => el.classList.add(cl));\n};\n\n/**\n * Toggle CSS classes on an HTML element.\n *\n * @param {HTMLElement} el - The HTML element on which classes should be toggled.\n * @param {string} cls - The CSS classes to toggle, separated by spaces.\n * @param {string} [avoid='noop'] - Classes to avoid toggling.\n * @returns {void}\n * @example\n * ```ts\n * // Toggle classes on an HTML element\n * const element = document.getElementById('example');\n * toggle(element, 'class1 class2');\n * ```\n */\nexport const toggle = (el: HTMLElement, cls: string, avoid = 'noop') => {\n if (!el) return;\n\n if (!cls || (cls && cls.length === 0)) return;\n\n cls\n .trim()\n .split(' ')\n .filter((cl) => cl !== avoid)\n .forEach((cl) => el.classList.toggle(cl));\n};\n\n/**\n * Remove CSS classes from an HTML element.\n *\n * @param {HTMLElement} el - The HTML element from which classes should be removed.\n * @param {string} cls - The CSS classes to remove, separated by spaces.\n * @param {string} [avoid='noop'] - Classes to avoid removing.\n * @returns {void}\n * @example\n * ```ts\n * // Remove classes from an HTML element\n * const element = document.getElementById('example');\n * remove(element, 'class1 class2');\n * ```\n */\nexport const remove = (el: HTMLElement, cls: string, avoid = 'noop') => {\n if (!el) return;\n\n if (!cls || (cls && cls.length === 0)) return;\n\n cls\n .trim()\n .split(' ')\n .filter((cl) => cl !== avoid)\n .forEach((cl) => el.classList.remove(cl));\n};\n\n/**\n * Generate CSS classes from a string and an object.\n *\n * @param {string} cls - Additional CSS classes as a string.\n * @param {ClassNamesObjectMapInterface} cls_obj - A mapping of class names to boolean values.\n * @returns {string} - A space-separated string of CSS class names.\n * @example\n * ```ts\n * // Generate CSS classes from a string and an object\n * const classNames = cx('class1', { class2: true, class3: false });\n * console.log(classNames); // Example output: 'class1 class2'\n * ```\n */\nexport const cx = (\n cls: string,\n cls_obj?: ClassNamesObjectMapInterface\n): string => {\n if (!cls) return '';\n\n if (!cls_obj && typeof cls !== 'string') {\n return `${Object.keys(cls)\n .filter((classname) => cls[classname])\n .join(' ')}`.trim();\n }\n\n return `${cls} ${\n cls_obj\n ? Object.keys(cls_obj)\n .filter((classname) => cls_obj[classname])\n .join(' ')\n : ''\n }`.trim();\n};\n","/* eslint no-console:0 */\n'use strict';\n\n/**\n * Array of uppercase letters.\n *\n * @type {string[]}\n * @example\n * ```ts\n * // Access the array of uppercase letters\n * const letters = SPECCER_LITERALS;\n * console.log(letters); // Example output: ['A', 'B', 'C', ...]\n * ```\n */\nexport const SPECCER_LITERALS = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'];\n\n/**\n * Array of HTML tags to avoid when processing.\n *\n * @type {string[]}\n * @example\n * ```ts\n * // Access the array of tags to avoid\n * const tagsToAvoid = SPECCER_TAGS_TO_AVOID;\n * console.log(tagsToAvoid); // Example output: ['TR', 'TH', 'TD', ...]\n * ```\n */\nexport const SPECCER_TAGS_TO_AVOID = [\n 'TR',\n 'TH',\n 'TD',\n 'TBODY',\n 'THEAD',\n 'TFOOT'\n];\n\n/**\n * Default value for pin space.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the default pin space value\n * const defaultPinSpace = SPECCER_DEFAULT_PIN_SPACE;\n * console.log(defaultPinSpace); // Example output: 48\n * ```\n */\nexport const SPECCER_DEFAULT_PIN_SPACE = 48;\n\n/**\n * Negative default value for pin space.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the negative default pin space value\n * const negativeDefaultPinSpace = SPECCER_DEFAULT_PIN_SPACE_NEG;\n * console.log(negativeDefaultPinSpace); // Example output: -48\n * ```\n */\nexport const SPECCER_DEFAULT_PIN_SPACE_NEG = SPECCER_DEFAULT_PIN_SPACE * -1;\n\n/**\n * Default value for measure size.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the default measure size value\n * const defaultMeasureSize = SPECCER_DEFAULT_MEASURE_SIZE;\n * console.log(defaultMeasureSize); // Example output: 8\n * ```\n */\nexport const SPECCER_DEFAULT_MEASURE_SIZE = 8;\n\n/**\n * Negative default value for measure size.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the negative default measure size value\n * const negativeDefaultMeasureSize = SPECCER_DEFAULT_MEASURE_SIZE_NEG;\n * console.log(negativeDefaultMeasureSize); // Example output: -8\n * ```\n */\nexport const SPECCER_DEFAULT_MEASURE_SIZE_NEG =\n SPECCER_DEFAULT_MEASURE_SIZE * -1;\n\n/**\n * Default line width value.\n *\n * @type {number}\n * @example\n * ```ts\n * // Access the default line width value\n * const defaultLineWidth = SPECCER_DEFAULT_LINE_WIDTH;\n * console.log(defaultLineWidth); // Example output: 1\n * ```\n */\nexport const SPECCER_DEFAULT_LINE_WIDTH = 1;\n","/* eslint no-console:0 */\n'use strict';\nimport {\n SPECCER_DEFAULT_PIN_SPACE,\n SPECCER_DEFAULT_MEASURE_SIZE,\n SPECCER_DEFAULT_LINE_WIDTH\n} from './constants';\nimport {\n SpacingCSSPropertiesType,\n TypographyCSSPropertiesType\n} from '../types/css';\n\n/**\n * Parses a string value into an integer.\n *\n * @param {string} value - The string value to parse.\n * @returns {number} - The parsed integer value.\n *\n * @example\n * ```ts\n * // Parse a string value into an integer\n * const intValue = getNumberValue(\"42\");\n * console.log(intValue); // Example output: 42\n * ```\n */\nexport const getNumberValue = (value: string): number => parseInt(value, 10);\n\n/**\n * Normalizes a string or number value to ensure it's a valid number.\n * If the value is within the range [0, 1] or [-1, 0), it's normalized to 0.\n *\n * @param {string | number} value - The value to normalize.\n * @returns {number} - The normalized number value.\n *\n * @example\n * ```ts\n * // Normalize a value to ensure it's a valid number\n * const normalizedValue = normalizeNumberValue(\"0.5\");\n * console.log(normalizedValue); // Example output: 0.5\n * ```\n */\nexport const normalizeNumberValue = (value: string | number): number => {\n const _value = parseFloat(value + '');\n\n return (_value >= 0 && _value < 1) || (_value <= 0 && _value > -1)\n ? 0\n : _value;\n};\n\n/**\n * Converts a CSS property name with \"Top\", \"Right\", \"Bottom\", or \"Left\" into a class name.\n *\n * @param {string} property - The CSS property name.\n * @returns {string} - The corresponding class name.\n *\n * @example\n * ```ts\n * // Convert a CSS property name to a class name\n * const className = getClassNameFromCSSProperty(\"marginTop\");\n * console.log(className); // Example output: \"margin top\"\n * ```\n */\nexport const getClassNameFromCSSProperty = (property: string): string => {\n if (property.indexOf('Top') !== -1) {\n return property.replace('Top', ' top');\n } else if (property.indexOf('Right') !== -1) {\n return property.replace('Right', ' right');\n } else if (property.indexOf('Bottom') !== -1) {\n return property.replace('Bottom', ' bottom');\n } else if (property.indexOf('Left') !== -1) {\n return property.replace('Left', ' left');\n }\n\n return '';\n};\n\n/**\n * Extracts spacing-related CSS properties from a style object.\n *\n * @param {SpacingCSSPropertiesType} style - The style object.\n * @returns {SpacingCSSPropertiesType} - The extracted spacing-related properties.\n *\n * @example\n * ```ts\n * // Extract spacing-related properties from a style object\n * const spacing = getSpacing({\n * marginTop: \"10px\",\n * marginLeft: \"20px\",\n * });\n * console.log(spacing); // Example output: { marginTop: \"10px\", marginLeft: \"20px\" }\n * ```\n */\nexport const getSpacing = (\n style: SpacingCSSPropertiesType\n): SpacingCSSPropertiesType => {\n const {\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n paddingTop,\n paddingBottom,\n paddingLeft,\n paddingRight\n } = style;\n\n return {\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n paddingTop,\n paddingBottom,\n paddingLeft,\n paddingRight\n };\n};\n\n/**\n * Extracts typography-related CSS properties from a style object.\n *\n * @param {TypographyCSSPropertiesType} style - The style object.\n * @returns {TypographyCSSPropertiesType} - The extracted typography-related properties.\n *\n * @example\n * ```ts\n * // Extract typography-related properties from a style object\n * const typography = getTypography({\n * fontSize: \"16px\",\n * fontWeight: \"bold\",\n * });\n * console.log(typography); // Example output: { fontSize: \"16px\", fontWeight: \"bold\" }\n * ```\n */\nexport const getTypography = (\n style: TypographyCSSPropertiesType\n): TypographyCSSPropertiesType => {\n const {\n lineHeight,\n letterSpacing,\n fontFamily,\n fontSize,\n fontStyle,\n fontVariationSettings,\n fontWeight\n } = style;\n\n return {\n lineHeight,\n letterSpacing,\n fontFamily,\n fontSize,\n fontStyle,\n fontVariationSettings,\n fontWeight\n };\n};\n\n/**\n * Retrieves the value of a custom CSS property \"--ph-speccer-pin-space\" from an element.\n *\n * @param {HTMLElement} el - The HTML element.\n * @returns {number} - The parsed value of the CSS property or a default value.\n *\n * @example\n * ```ts\n * // Get the value of a custom CSS property from an element\n * const value = pinSpace(document.body);\n * console.log(value); // Example output: 10\n * ```\n */\nexport const pinSpace = (el: HTMLElement): number =>\n getNumberValue(\n getComputedStyle(el).getPropertyValue('--ph-speccer-pin-space')\n ) || SPECCER_DEFAULT_PIN_SPACE;\n\n/**\n * Retrieves the value of a custom CSS property \"--ph-speccer-measure-size\" from an element.\n *\n * @param {HTMLElement} el - The HTML element.\n * @returns {number} - The parsed value of the CSS property or a default value.\n *\n * @example\n * ```ts\n * // Get the value of a custom CSS property from an element\n * const value = measureSize(document.body);\n * console.log(value); // Example output: 20\n * ```\n */\nexport const measureSize = (el: HTMLElement): number =>\n getNumberValue(\n getComputedStyle(el).getPropertyValue('--ph-speccer-measure-size')\n ) || SPECCER_DEFAULT_MEASURE_SIZE;\n\n/**\n * Retrieves the value of a custom CSS property \"--ph-speccer-line-width\" from an element.\n *\n * @param {HTMLElement} el - The HTML element.\n * @returns {number} - The parsed value of the CSS property or a default value.\n *\n * @example\n * ```ts\n * // Get the value of a custom CSS property from an element\n * const value = lineWidth(document.body);\n * console.log(value); // Example output: 1.5\n * ```\n */\nexport const lineWidth = (el: HTMLElement): number =>\n getNumberValue(\n getComputedStyle(el).getPropertyValue('--ph-speccer-line-width')\n ) || SPECCER_DEFAULT_LINE_WIDTH;\n","/**\n * Waits for the specified amount of time in milliseconds.\n *\n * @param {number} ms - The number of milliseconds to wait.\n * @returns {Promise} - A Promise that resolves after the specified time.\n *\n * @example\n * ```ts\n * // Wait for 1 second (1000 milliseconds)\n * await waitFor(1000);\n * ```\n */\nexport const waitFor = (ms: number): Promise =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Waits for the next animation frame using requestAnimationFrame.\n *\n * @returns {Promise} - A Promise that resolves with the timestamp of the next animation frame.\n *\n * @example\n * ```ts\n * // Wait for the next animation frame and get the rect\n * await waitForFrame();\n * const rect = el.getBoundingClientRect();\n * // Wait for the next animation frame and get the timestamp\n * const timestamp = await waitForFrame();\n * ```\n */\nexport const waitForFrame = (): Promise =>\n new Promise(requestAnimationFrame);\n","/* eslint no-console:0 */\n'use strict';\nimport { waitForFrame } from './wait';\n\n/**\n * Adds CSS styles to an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to apply styles to.\n * @param {object | Array<{ key: string; value: string }>} styles - An object or an array of objects containing CSS styles to apply.\n * @returns {Promise} - A Promise that resolves after styles are applied.\n *\n * @example\n * ```ts\n * // Apply styles as an object\n * const element = document.getElementById('my-element');\n * await add(element, { color: 'red', fontSize: '16px' });\n *\n * // Apply styles as an array of objects\n * const styles = [\n * { key: 'color', value: 'blue' },\n * { key: 'backgroundColor', value: 'yellow' }\n * ];\n * await add(element, styles);\n * ```\n */\nexport const add = async (\n el: HTMLElement,\n styles: object | Array<{ key: string; value: string }>\n): Promise => {\n if (\n !el ||\n !styles ||\n typeof styles === 'string' ||\n typeof styles === 'number' ||\n typeof styles === 'boolean' ||\n (Array.isArray(styles) && styles.length === 0) ||\n (Object.keys(styles).length === 0 && styles.constructor === Object)\n ) {\n return;\n }\n\n await waitForFrame();\n\n if (Array.isArray(styles)) {\n styles.forEach(\n (style: { key: string; value: string }) =>\n (el.style[style.key] = style.value)\n );\n } else {\n Object.keys(styles).forEach((key) => (el.style[key] = styles[key]));\n }\n};\n\n/**\n * Gets the computed CSS styles of an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to get computed styles from.\n * @returns {Promise} - A Promise that resolves with the computed CSS styles.\n *\n * @example\n * ```ts\n * // Get computed styles of an element\n * const element = document.getElementById('my-element');\n * const computedStyles = await get(element);\n * console.log(computedStyles.color); // Logs the color property value\n * ```\n */\nexport const get = async (el: HTMLElement): Promise => {\n await waitForFrame();\n\n return getComputedStyle(el, null);\n};\n","import { waitForFrame } from './wait';\n\nimport { PositionPropertiesType, PositionInputType } from '../types/position';\nimport { GetRecPropertiesInterface } from 'types/interfaces/position';\n\n/**\n * Calculates the horizontal center of two elements.\n *\n * @param {number} modifier - A modifier value.\n * @param {DOMRect} startRect - The starting element's rectangle.\n * @param {DOMRect} targetRect - The target element's rectangle.\n * @returns {number} - The horizontal center position.\n *\n * @example\n * ```ts\n * // Calculate the horizontal center of two elements\n * const center = get_horizontal_center_of_els(0, startRect, targetRect);\n * ```\n */\nexport const get_horizontal_center_of_els = (\n modifier: number,\n startRect: DOMRect,\n targetRect: DOMRect\n): number => modifier - startRect.width / 2 + targetRect.width / 2;\n\n/**\n * Calculates the vertical center of two elements.\n *\n * @param {number} modifier - A modifier value.\n * @param {DOMRect} startRect - The starting element's rectangle.\n * @param {DOMRect} targetRect - The target element's rectangle.\n * @returns {number} - The vertical center position.\n *\n * @example\n * ```ts\n * // Calculate the vertical center of two elements\n * const center = get_vertical_center_of_els(0, startRect, targetRect);\n * ```\n */\nexport const get_vertical_center_of_els = (\n modifier: number,\n startRect: DOMRect,\n targetRect: DOMRect\n): number => modifier - startRect.height / 2 + targetRect.height / 2;\n\n/**\n * Gets the offset properties of an HTML element.\n *\n * @param {HTMLElement} targetEl - The target HTML element.\n * @returns {Promise} - A promise that resolves to the offset properties.\n *\n * @example\n * ```ts\n * // Get the offset properties of an element\n * const offsetProps = await offset(targetElement);\n * ```\n */\nexport const offset = async (\n targetEl: HTMLElement\n): Promise => {\n await waitForFrame();\n\n const _target_rect = targetEl.getBoundingClientRect();\n const _el_offset_top = _target_rect.top + window.scrollY;\n const _el_offset_left = _target_rect.left + window.scrollX;\n\n return {\n height: _target_rect.height,\n width: _target_rect.width,\n top: _el_offset_top,\n left: _el_offset_left\n };\n};\n\n/**\n * Gets the offset properties of an HTML element with its center aligned to another element.\n *\n * @param {HTMLElement} sourceEl - The source HTML element.\n * @param {HTMLElement} targetEl - The target HTML element.\n * @returns {Promise} - A promise that resolves to the offset properties.\n *\n * @example\n * ```ts\n * // Get the offset properties of an element with its center aligned to another element\n * const offsetProps = await offsetWithCenter(sourceElement, targetElement);\n * ```\n */\nexport const offsetWithCenter = async (\n sourceEl: HTMLElement,\n targetEl: HTMLElement\n): Promise => {\n await waitForFrame();\n\n const _source_rect = sourceEl.getBoundingClientRect();\n const _target_rect = targetEl.getBoundingClientRect();\n const _el_offset_top = _target_rect.top + window.scrollY;\n const _el_offset_left = _target_rect.left + window.scrollX;\n\n return {\n height: _target_rect.height,\n width: _target_rect.width,\n top: get_vertical_center_of_els(_el_offset_top, _source_rect, _target_rect),\n left: get_horizontal_center_of_els(\n _el_offset_left,\n _source_rect,\n _target_rect\n )\n };\n};\n\n/**\n * Gets various positioning properties between two HTML elements.\n *\n * @param {HTMLElement} sourceEl - The source HTML element.\n * @param {HTMLElement} targetEl - The target HTML element.\n * @returns {Promise} - A promise that resolves to an object with positioning functions.\n *\n * @example\n * ```ts\n * // Get positioning properties between two elements\n * const recProps = await getRec(sourceElement, targetElement);\n *\n * // Get the absolute position properties\n * const absoluteProps = recProps.absolute();\n *\n * // Get the position properties with the source element above the target element\n * const aboveProps = recProps.toTop();\n * ```\n */\nexport const getRec = async (\n sourceEl: HTMLElement,\n targetEl: HTMLElement\n): Promise => {\n await waitForFrame();\n\n const _source_rect = sourceEl.getBoundingClientRect();\n const _target_offset = await offset(targetEl);\n const _target_offset_center = await offsetWithCenter(sourceEl, targetEl);\n const _target_height = _target_offset.height;\n const _target_width = _target_offset.width;\n const _source_height = _source_rect.height;\n const _source_width = _source_rect.width;\n\n return {\n absolute: (): PositionPropertiesType => {\n return {\n top: _target_offset.top,\n left: _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n toTop: ({\n center = false,\n sourceHeight = _source_height,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: _target_offset.top + sourceHeight + modifier,\n left: center ? _target_offset_center.left : _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n\n fromTop: ({\n center = false,\n sourceHeight = _source_height,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: _target_offset.top - sourceHeight - modifier,\n left: center ? _target_offset_center.left : _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n\n toBottom: ({\n center = false,\n sourceHeight = _source_height,\n targetHeight = _target_height,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: _target_offset.top + targetHeight - (sourceHeight + modifier),\n left: center ? _target_offset_center.left : _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n fromBottom: ({\n center = false,\n targetHeight = _target_height,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: _target_offset.top + targetHeight + modifier,\n left: center ? _target_offset_center.left : _target_offset.left,\n height: _target_height,\n width: _target_width\n };\n },\n\n toLeft: ({\n center = false,\n sourceWidth = _source_width,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: center ? _target_offset_center.top : _target_offset.top,\n left: _target_offset.left + sourceWidth + modifier,\n height: _target_height,\n width: _target_width\n };\n },\n\n fromLeft: ({\n center = false,\n sourceWidth = _source_width,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: center ? _target_offset_center.top : _target_offset.top,\n left: _target_offset.left - sourceWidth - modifier,\n height: _target_height,\n width: _target_width\n };\n },\n\n toRight: ({\n center = false,\n sourceWidth = _source_width,\n targetWidth = _target_width,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: center ? _target_offset_center.top : _target_offset.top,\n left: _target_offset.left + targetWidth - (sourceWidth + modifier),\n height: _target_height,\n width: _target_width\n };\n },\n\n fromRight: ({\n center = false,\n targetWidth = _target_width,\n modifier = 0\n }: PositionInputType = {}): PositionPropertiesType => {\n return {\n top: center ? _target_offset_center.top : _target_offset.top,\n left: _target_offset.left + targetWidth + modifier,\n height: _target_height,\n width: _target_width\n };\n }\n };\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport { set as setClassNames } from '../../utils/classnames';\nimport {\n getSpacing,\n getClassNameFromCSSProperty,\n getNumberValue\n} from '../../utils/css';\nimport { get as getStyles } from '../../utils/styles';\nimport { position } from './utils/position';\n\n/**\n * Create a spacing element with optional text content.\n *\n * @param {string | number} text - The optional text content for the spacing element.\n * @param {string} tag - The HTML tag for the element (default is 'span').\n * @returns {HTMLElement} - The created spacing element.\n *\n * @example\n * ```ts\n * const spacingElement = create(20, 'div');\n * document.body.appendChild(spacingElement);\n * ```\n */\nexport const create = (\n text: string | number = '',\n tag = 'span'\n): HTMLElement => {\n const _el = document.createElement(tag);\n const _text_content = document.createTextNode(text + '');\n\n _el.appendChild(_text_content);\n _el.setAttribute('title', text + 'px');\n setClassNames(_el, 'ph-speccer speccer spacing');\n\n return _el;\n};\n\n/**\n * Create and position spacing elements based on the target element's computed spacing styles.\n *\n * @param {HTMLElement} targetEl - The target element to create spacing elements for.\n * @returns {Promise} - A promise that resolves after creating and positioning the spacing elements.\n *\n * @example\n * ```ts\n * const targetElement = document.getElementById('target');\n * element(targetElement);\n * ```\n */\nexport const element = async (targetEl: HTMLElement): Promise => {\n if (!targetEl) return;\n\n const _target_styles = await getStyles(targetEl);\n\n if (\n _target_styles.display === 'none' ||\n _target_styles.opacity === '0' ||\n _target_styles.visibility === 'hidden'\n ) {\n return;\n }\n\n const _target_spacing_styles = getSpacing(_target_styles);\n const _target_pruned_spacing_styles = Object.keys(\n _target_spacing_styles\n ).filter((property) => {\n const _value = _target_spacing_styles[property];\n\n return _value !== '0px';\n });\n\n if (_target_pruned_spacing_styles.length === 0) return;\n\n _target_pruned_spacing_styles.forEach(async (property) => {\n const _value = getNumberValue(_target_spacing_styles[property]);\n const _speccer_el = create(_value);\n const _class_name = getClassNameFromCSSProperty(property);\n\n setClassNames(_speccer_el, _class_name);\n document.body.appendChild(_speccer_el);\n\n targetEl.classList.add('is-specced');\n await position(property, _value, _speccer_el, targetEl);\n });\n};\n","import { add as addStyles } from '../../../utils/styles';\nimport { offset } from '../../../utils/position';\nimport { waitForFrame } from '../../../utils/wait';\n\n/**\n * Set the position and dimensions of a spacing element relative to a target element.\n *\n * @param {string} property - The CSS property to set (e.g., 'marginTop', 'marginLeft', etc.).\n * @param {number} value - The value of the CSS property.\n * @param {HTMLElement} spacingEl - The spacing element.\n * @param {HTMLElement} targetEl - The target element.\n * @returns {Promise} - A promise that resolves after setting the position and dimensions.\n *\n * @example\n * ```ts\n * const spacingElement = document.getElementById('spacing');\n * const targetElement = document.getElementById('target');\n * position('marginTop', 20, spacingElement, targetElement);\n * ```\n */\nexport const position = async (\n property: string,\n value: number,\n spacingEl: HTMLElement,\n targetEl: HTMLElement\n): Promise => {\n await waitForFrame();\n\n const _target_rect = targetEl.getBoundingClientRect();\n const _target_offset = await offset(targetEl);\n\n if (property === 'marginTop') {\n addStyles(spacingEl, {\n height: `${value}px`,\n width: _target_rect.width + 'px',\n left: _target_offset.left + 'px',\n top: _target_offset.top - value + 'px'\n });\n }\n\n if (property === 'marginRight') {\n addStyles(spacingEl, {\n height: _target_rect.height + 'px',\n width: `${value}px`,\n left: _target_offset.left + parseInt(_target_rect.width + '', 10) + 'px',\n top: _target_offset.top + 'px'\n });\n }\n\n if (property === 'marginBottom') {\n addStyles(spacingEl, {\n height: `${value}px`,\n width: _target_rect.width + 'px',\n left: _target_offset.left + 'px',\n top: _target_offset.top + parseInt(_target_rect.height + '', 10) + 'px'\n });\n }\n\n if (property === 'marginLeft') {\n addStyles(spacingEl, {\n height: _target_rect.height + 'px',\n width: `${value}px`,\n left: _target_offset.left - value + 'px',\n top: _target_offset.top + 'px'\n });\n }\n\n if (property === 'paddingTop') {\n addStyles(spacingEl, {\n height: `${value}px`,\n width: _target_rect.width + 'px',\n left: _target_offset.left + 'px',\n top: _target_offset.top + 'px'\n });\n }\n\n if (property === 'paddingBottom') {\n addStyles(spacingEl, {\n height: `${value}px`,\n width: _target_rect.width + 'px',\n left: _target_offset.left + 'px',\n top:\n _target_offset.top +\n (parseInt(_target_rect.height + '', 10) - value) +\n 'px'\n });\n }\n\n if (property === 'paddingRight') {\n addStyles(spacingEl, {\n height: _target_rect.height + 'px',\n width: `${value}px`,\n left:\n _target_offset.left +\n (parseInt(_target_rect.width + '', 10) - value) +\n 'px',\n top: _target_offset.top + 'px'\n });\n }\n\n if (property === 'paddingLeft') {\n addStyles(spacingEl, {\n height: _target_rect.height + 'px',\n width: `${value}px`,\n left: _target_offset.left + 'px',\n top: _target_offset.top + 'px'\n });\n }\n};\n","/* eslint-disable no-unused-vars */\n\n/**\n * Enum representing different areas in Speccer.\n */\nexport enum SpeccerAreaEnum {\n Empty = '', // Represents an empty area\n Left = 'left', // Represents the left area\n Right = 'right', // Represents the right area\n Bottom = 'bottom',// Represents the bottom area\n Top = 'top', // Represents the top area\n}\n\n/**\n * Enum representing different areas in Dissect.\n */\nexport enum DissectAreaEnum {\n Outline = 'outline', // Represents an outline area\n Enclose = 'enclose', // Represents an enclose area\n Full = 'full', // Represents a full area\n Left = 'left', // Represents the left area\n Right = 'right', // Represents the right area\n Bottom = 'bottom', // Represents the bottom area\n Top = 'top', // Represents the top area\n SVG = 'svg', // Represents an SVG area\n Curly = 'curly', // Represents a curly area\n}\n\n/**\n * Enum representing different measurement areas.\n */\nexport enum MeasureAreaEnum {\n Width = 'width', // Represents the width measurement area\n Height = 'height', // Represents the height measurement area\n Left = 'left', // Represents the left measurement area\n Right = 'right', // Represents the right measurement area\n Bottom = 'bottom', // Represents the bottom measurement area\n Top = 'top', // Represents the top measurement area\n}\n","import { DissectAreaEnum, MeasureAreaEnum } from 'types/enums/area';\n\n/**\n * Splits a string containing areas into an array of strings.\n *\n * @param areaString - The string containing areas.\n * @returns An array of area strings.\n *\n * @example\n * ```ts\n * const areas = getAreasFromString('left right top');\n * // areas: ['left', 'right', 'top']\n * ```\n */\nexport const getAreasFromString = (areaString: string): string[] =>\n areaString.split(' ');\n\n/**\n * Checks if 'left' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'left' is present, otherwise `false`.\n */\nexport const isLeftArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Left);\n};\n\n/**\n * Checks if 'right' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'right' is present, otherwise `false`.\n */\nexport const isRightArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Right);\n};\n\n/**\n * Checks if 'top' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'top' is present, otherwise `false`.\n */\nexport const isTopArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Top);\n};\n\n/**\n * Checks if 'bottom' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'bottom' is present, otherwise `false`.\n */\nexport const isBottomArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Bottom);\n};\n\n/**\n * Checks if 'full' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'full' is present, otherwise `false`.\n */\nexport const isFullArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Full);\n};\n\n/**\n * Checks if 'enclose' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'enclose' is present, otherwise `false`.\n */\nexport const isEncloseArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(DissectAreaEnum.Enclose);\n};\n\n/**\n * Checks if 'height' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'height' is present, otherwise `false`.\n */\nexport const isHeightArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(MeasureAreaEnum.Height);\n};\n\n/**\n * Checks if 'width' area is present in the provided areaString.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if 'width' is present, otherwise `false`.\n */\nexport const isWidthArea = (areaString: string): boolean => {\n const areas = getAreasFromString(areaString);\n\n return areas.includes(MeasureAreaEnum.Width);\n};\n\n/**\n * Checks if the provided areaString contains SVG-related areas.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if any SVG-related area is present, otherwise `false`.\n */\nexport const useSVG = (areaString: string): boolean =>\n areaString.includes(DissectAreaEnum.SVG) ||\n areaString.includes(DissectAreaEnum.Curly) ||\n areaString.includes(DissectAreaEnum.Full) ||\n areaString.includes(DissectAreaEnum.Enclose);\n\n/**\n * Checks if the provided areaString contains 'curly' and 'full' areas.\n *\n * @param areaString - The string containing areas.\n * @returns `true` if both 'curly' and 'full' are present, otherwise `false`.\n */\nexport const isCurly = (areaString: string): boolean =>\n areaString.includes(DissectAreaEnum.Curly) &&\n areaString.includes(DissectAreaEnum.Full);\n","/* eslint no-console:0 */\n'use strict';\n\n/**\n * Generates a unique ID consisting of an underscore followed by a random alphanumeric string.\n *\n * @returns {string} - A unique ID.\n *\n * @example\n * ```ts\n * // Generate a unique ID\n * const id = uniqueID();\n * console.log(id); // Example output: \"_abc123def\"\n * ```\n */\nexport const uniqueID = (): string =>\n '_' + Math.random().toString(36).substring(2, 11);\n","/**\n * A set of functions to retrieve specific coordinates from a DOMRect.\n */\nexport const coords = {\n /**\n * Get the top coordinate of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the top coordinate from.\n * @returns {number} The top coordinate.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const topCoordinate = coords.top(rect);\n * ```\n */\n top: (rect: DOMRect): number => rect.top,\n\n /**\n * Get the right coordinate of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the right coordinate from.\n * @returns {number} The right coordinate.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const rightCoordinate = coords.right(rect);\n * ```\n */\n right: (rect: DOMRect): number => rect.left + rect.width,\n\n /**\n * Get the bottom coordinate of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the bottom coordinate from.\n * @returns {number} The bottom coordinate.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const bottomCoordinate = coords.bottom(rect);\n * ```\n */\n bottom: (rect: DOMRect): number => rect.top + rect.height,\n\n /**\n * Get the left coordinate of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the left coordinate from.\n * @returns {number} The left coordinate.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const leftCoordinate = coords.left(rect);\n * ```\n */\n left: (rect: DOMRect): number => rect.left,\n\n /**\n * Get the x-coordinate of the center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the x-coordinate of the center from.\n * @returns {number} The x-coordinate of the center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const centerXCoordinate = coords.center_x(rect);\n * ```\n */\n center_x: (rect: DOMRect): number => rect.left + rect.width / 2,\n\n /**\n * Get the y-coordinate of the center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the y-coordinate of the center from.\n * @returns {number} The y-coordinate of the center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const centerYCoordinate = coords.center_y(rect);\n * ```\n */\n center_y: (rect: DOMRect): number => rect.top + rect.height / 2\n};\n","import { coords } from './coords';\n\n/**\n * Object containing functions to retrieve specific x and y coordinates from a DOMRect.\n */\nexport const xy = {\n /**\n * Get the x and y coordinates of the center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the coordinates from.\n * @returns {{ x: number, y: number }} The x and y coordinates of the center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const centerCoordinates = xy.center(rect);\n * // centerCoordinates.x and centerCoordinates.y will contain the coordinates\n * ```\n */\n center: (rect: DOMRect): { x: number; y: number } => ({\n x: coords.center_x(rect),\n y: coords.center_y(rect)\n }),\n\n /**\n * Get the x and y coordinates of the top center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the coordinates from.\n * @returns {{ x: number, y: number }} The x and y coordinates of the top center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const topCenterCoordinates = xy.top(rect);\n * // topCenterCoordinates.x and topCenterCoordinates.y will contain the coordinates\n * ```\n */\n top: (rect: DOMRect): { x: number; y: number } => ({\n x: coords.center_x(rect),\n y: coords.top(rect)\n }),\n\n /**\n * Get the x and y coordinates of the right center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the coordinates from.\n * @returns {{ x: number, y: number }} The x and y coordinates of the right center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const rightCenterCoordinates = xy.right(rect);\n * // rightCenterCoordinates.x and rightCenterCoordinates.y will contain the coordinates\n * ```\n */\n right: (rect: DOMRect): { x: number; y: number } => ({\n x: coords.right(rect),\n y: coords.center_y(rect)\n }),\n\n /**\n * Get the x and y coordinates of the bottom center of a DOMRect.\n * @param {DOMRect} rect - The DOMRect to retrieve the coordinates from.\n * @returns {{ x: number, y: number }} The x and y coordinates of the bottom center.\n * @example\n * ```ts\n * const rect = element.getBoundingClientRect();\n * const bottomCenterCoordinates = xy.bottom(rect);\n * // bottomCenterCoordinates.x and bottomCenterCoordinates.y will contain the coordinates\n * ```\n */\n bottom: (rect: DOMRect): { x: number; y: number } => ({\n x: coords.center_x(rect),\n y: coords.bottom(rect)\n })\n\n // Additional functions with x and y coordinates can be added here...\n};\n","import { waitForFrame } from './wait';\nimport { xy } from './xy';\n\n/**\n * Get the intrinsic coordinates of an element based on a specified position.\n *\n * @param {HTMLElement} el - The HTML element.\n * @param {string} [pos='center'] - The position to use.\n * @throws {Error} No position given.\n * @throws {Error} The position given is not the required type.\n * @returns {Promise<{ x: number, y: number }>} - An object containing the coordinates.\n * @example\n * ```ts\n * // Get intrinsic coordinates for an element\n * const element = document.getElementById('example');\n * const coordinates = await intrinsic_coords(element, 'top-left');\n * ```\n */\nexport const intrinsic_coords = async (\n el: HTMLElement,\n pos = 'center'\n): Promise<{ x: number; y: number }> => {\n if (!pos) {\n throw new Error('No position given');\n }\n\n if (typeof pos !== 'string') {\n throw new Error(\n `The position given is not the required type: pos: ${typeof pos}`\n );\n }\n\n const _allowed_positions = [\n 'center',\n 'left',\n 'right',\n 'top',\n 'bottom',\n 'right-top',\n 'right-bottom',\n 'left-top',\n 'left-bottom',\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n 'top-center',\n 'right-center',\n 'bottom-center',\n 'left-center'\n ];\n\n if (!_allowed_positions.includes(pos)) {\n throw new Error(\n `The position given does not match allowed positions to use! Valid positions are: ${_allowed_positions.join(\n ', '\n )}`\n );\n }\n\n await waitForFrame();\n\n const _el_rect = el.getBoundingClientRect();\n\n return xy[pos](_el_rect);\n};\n","import { intrinsic_coords } from './intrinsic-coords';\n\n/**\n * Get the x and y coordinates of two elements and return them as an object.\n *\n * @param {HTMLElement} el1 - The first HTML element.\n * @param {HTMLElement} el2 - The second HTML element.\n * @param {string} [pos1='center'] - The position to use for the first element.\n * @param {string} [pos2='center'] - The position to use for the second element.\n * @throws {Error} No element given.\n * @returns {Promise<{ x1: number, y1: number, x2: number, y2: number }>} - An object containing the coordinates.\n * @example\n * ```ts\n * // Get coordinates for two elements\n * const element1 = document.getElementById('element1');\n * const element2 = document.getElementById('element2');\n * const coordinates = await get_coords_pair_from_objects(element1, element2);\n * ```\n */\nexport const getCoordsPairFromObjects = async (\n el1: HTMLElement,\n el2: HTMLElement,\n pos1 = 'center',\n pos2 = 'center'\n): Promise<{ x1: number; y1: number; x2: number; y2: number }> => {\n if (!el1 || !el2) {\n throw new Error('No element given');\n }\n\n const { x: x1, y: y1 } = await intrinsic_coords(el1, pos1);\n const { x: x2, y: y2 } = await intrinsic_coords(el2, pos2);\n\n return {\n x1,\n y1,\n x2,\n y2\n };\n};\n","import {\n BezierPathOptionsType,\n CreateCoordinatesForCurveCoordParamType,\n CreateCoordinatesForCurveOptionsParamType,\n CurlyBezierPathOptionsType\n} from 'types/bezier';\nimport { getCoordsPairFromObjects } from './get-coords-pair-from-objects';\n\n/**\n * Calculates coordinates for a Bezier curve between two points.\n *\n * @param coords - The coordinates of the start and end points.\n * @param options - Options for controlling the curve's shape.\n * @returns Coordinates for the Bezier curve.\n *\n * @example\n * ```ts\n * const coordinates = createBezierCurveCoordinates(\n * { x1: 0, x2: 100, y1: 0, y2: 100 },\n * { direct: true, firstSet: true, direction: 'west' }\n * );\n * ```\n */\nexport const createBezierCurveCoordinates = (\n coords: CreateCoordinatesForCurveCoordParamType,\n options: CreateCoordinatesForCurveOptionsParamType\n) => {\n const { x1, x2, y1, y2 } = coords;\n const { direct = false, firstSet = false, direction } = options;\n const firstPoint = { x: x1, y: y1 }; // The first point of the curve\n const lastPoint = { x: x2, y: y2 }; // The last point of the curve\n\n let firstControl = { x: x1 + (x2 - x1) / 2, y: y1 }; // Control point for the first point\n let lastControl = { x: x1 + (x2 - x1) / 2, y: y2 }; // Control point for the last point\n\n if (direct) {\n if (firstSet) {\n if (direction === 'west') {\n firstControl = { x: x1 - 32, y: y1 - 16 / 2 };\n lastControl = { x: x2 + 32, y: y2 };\n } else if (direction === 'south') {\n firstControl = { x: x1 - 16 / 2, y: y1 + 32 };\n lastControl = { x: x2, y: y2 - 32 };\n } else if (direction === 'east') {\n firstControl = { x: x1 + 32, y: y1 - 16 / 2 };\n lastControl = { x: x2 - 32, y: y2 };\n } else {\n firstControl = { x: x1 - 16 / 2, y: y1 - 32 };\n lastControl = { x: x2, y: y2 + 32 };\n }\n } else {\n if (direction === 'west') {\n firstControl = { x: x1 - 32, y: y1 + 16 / 2 };\n lastControl = { x: x2 + 32, y: y2 };\n } else if (direction === 'south') {\n firstControl = { x: x1 + 16 / 2, y: y1 + 32 };\n lastControl = { x: x2, y: y2 - 32 };\n } else if (direction === 'east') {\n firstControl = { x: x1 + 32, y: y1 + 16 / 2 };\n lastControl = { x: x2 - 32, y: y2 };\n } else {\n firstControl = { x: x1 + 16 / 2, y: y1 - 32 };\n lastControl = { x: x2, y: y2 + 32 };\n }\n }\n }\n\n return {\n firstPoint,\n firstControl,\n lastPoint,\n lastControl\n };\n};\n\n/**\n * Generates an SVG path for a curved line between two HTML elements.\n *\n * @param startEl - The starting HTML element.\n * @param stopEl - The ending HTML element.\n * @param options - Options for controlling the curved line.\n * @returns The SVG path string for the curved line.\n *\n * @example\n * ```ts\n * const svgPath = getCurlySVGPath(startElement, stopElement, {\n * pos1: 'top',\n * pos2: 'bottom',\n * firstSet: true,\n * direction: 'south',\n * });\n * ```\n */\nexport const getCurlySVGPath = async (\n startEl: HTMLElement,\n stopEl: HTMLElement,\n options: CurlyBezierPathOptionsType\n) => {\n const { pos1, pos2, firstSet = false, direction } = options;\n const { x1, y1, x2, y2 } = await getCoordsPairFromObjects(\n startEl,\n stopEl,\n pos1,\n pos2\n );\n const x1modifier = 0;\n const y1modifier = 0;\n\n let x2modifier = 0;\n let y2modifier = 0;\n\n // Create a gap between the pin and the bracket center\n if (direction == 'north') {\n y2modifier = 8;\n } else if (direction == 'west') {\n x2modifier = 8;\n } else if (direction == 'east') {\n x2modifier = -8;\n } else if (direction == 'south') {\n y2modifier = -8;\n }\n\n const coordinates = createBezierCurveCoordinates(\n {\n x1: x1 + x1modifier,\n x2: x2 + x2modifier,\n y1: y1 + y1modifier,\n y2: y2 + y2modifier\n },\n {\n direct: true,\n firstSet,\n direction\n }\n );\n const { firstPoint, firstControl, lastControl, lastPoint } = coordinates;\n\n return (\n `M ${firstPoint.x} ${firstPoint.y}` +\n `C ${firstControl.x} ${firstControl.y}, ${lastControl.x} ${lastControl.y}, ${lastPoint.x} ${lastPoint.y}`\n );\n};\n\n/**\n * Generates an SVG path for a straight line between two HTML elements.\n *\n * @param startEl - The starting HTML element.\n * @param stopEl - The ending HTML element.\n * @param options - Options for controlling the straight line.\n * @returns The SVG path string for the straight line.\n *\n * @example\n * ```ts\n * const svgPath = getSVGPath(startElement, stopElement, {\n * pos1: 'left',\n * pos2: 'right',\n * });\n * ```\n */\nexport const getSVGPath = async (\n startEl: HTMLElement,\n stopEl: HTMLElement,\n options: BezierPathOptionsType\n) => {\n const { pos1, pos2 } = options;\n const { x1, y1, x2, y2 } = await getCoordsPairFromObjects(\n startEl,\n stopEl,\n pos1,\n pos2\n );\n const coordinates = createBezierCurveCoordinates(\n { x1, x2, y1, y2 },\n { direction: '' }\n );\n const { firstPoint, firstControl, lastControl, lastPoint } = coordinates;\n\n return (\n `M ${firstPoint.x} ${firstPoint.y}` +\n `C ${firstControl.x} ${firstControl.y}, ${lastControl.x} ${lastControl.y}, ${lastPoint.x} ${lastPoint.y}`\n );\n};\n\n/**\n * Returns positions for creating an SVG path based on a cardinal direction.\n *\n * @param direction - The cardinal direction ('east', 'west', 'south', 'north').\n * @returns Positions for creating an SVG path.\n *\n * @example\n * ```ts\n * const positions = getPositionsForSVGPath('east');\n * ```\n */\nexport const getPositionsForSVGPath = (direction: string) => {\n let pos1: string;\n let pos2: string;\n\n switch (direction) {\n case 'east':\n pos1 = 'right';\n pos2 = 'left';\n break;\n case 'south':\n pos1 = 'bottom';\n pos2 = 'top';\n break;\n case 'west':\n pos1 = 'left';\n pos2 = 'right';\n break;\n case 'north':\n default:\n pos1 = 'top';\n pos2 = 'bottom';\n break;\n }\n\n return { pos1, pos2 };\n};\n\n/**\n * Returns positions for creating an SVG path for a curved line based on a cardinal direction.\n *\n * @param direction - The cardinal direction ('east', 'west', 'south', 'north').\n * @returns Positions for creating an SVG path for a curved line.\n *\n * @example\n * ```ts\n * const positions = getPositionsForCurlySVGPath('west');\n * ```\n */\nexport const getPositionsForCurlySVGPath = (direction: string) => {\n let path1pos1: string;\n let path1pos2: string;\n let path2pos1: string;\n let path2pos2: string;\n\n switch (direction) {\n case 'east':\n path1pos1 = 'right-top';\n path1pos2 = 'left-center';\n path2pos1 = 'right-bottom';\n path2pos2 = 'left-center';\n break;\n case 'south':\n path1pos1 = 'bottom-left';\n path1pos2 = 'top-center';\n path2pos1 = 'bottom-right';\n path2pos2 = 'top-center';\n break;\n case 'west':\n path1pos1 = 'left-top';\n path1pos2 = 'right-center';\n path2pos1 = 'left-bottom';\n path2pos2 = 'right-center';\n break;\n case 'north':\n default:\n path1pos1 = 'top-left';\n path1pos2 = 'bottom-center';\n path2pos1 = 'top-right';\n path2pos2 = 'bottom-center';\n break;\n }\n\n return {\n path1pos1,\n path1pos2,\n path2pos1,\n path2pos2\n };\n};\n","import { angle } from './angle';\nimport { cardinal_direction, cardinal_direction_crude } from './cardinal';\nimport { getCoordsPairFromObjects } from './get-coords-pair-from-objects';\n\n/**\n * Get the direction of an element based on its position relative to another element.\n *\n * @param {Object} options - Options for direction calculation.\n * @param {HTMLElement} options.start - The starting HTML element.\n * @param {HTMLElement} options.stop - The stopping HTML element.\n * @param {boolean} [options.crude=false] - If the direction should be calculated crudely (NSEW).\n * @returns {Promise} - The calculated direction.\n * @example\n * ```ts\n * // Get the direction of one element relative to another\n * const startElement = document.getElementById('startElement');\n * const stopElement = document.getElementById('stopElement');\n * const direction = await direction_of_element({ start: startElement, stop: stopElement });\n * ```\n */\nexport const direction_of_element = async ({\n start,\n stop,\n crude = false\n}: {\n start: HTMLElement;\n stop: HTMLElement;\n crude?: boolean;\n}): Promise => {\n const { x1, y1, x2, y2 } = await getCoordsPairFromObjects(start, stop);\n const _angle = angle(x1, y1, x2, y2);\n const _direction = crude\n ? cardinal_direction_crude(_angle)\n : cardinal_direction(_angle);\n\n return _direction;\n};\n","/**\n * Returns the angle between two sets of coordinates.\n *\n * @param {number} cx - The x-coordinate of the first point.\n * @param {number} cy - The y-coordinate of the first point.\n * @param {number} ex - The x-coordinate of the second point.\n * @param {number} ey - The y-coordinate of the second point.\n * @param {boolean} [normalize=true] - If the angle output should be normalized to a value between 0° and 360°.\n * @throws {SyntaxError} Missing input for `angle`.\n * @throws {TypeError} Parameters for `angle` do not have the required type.\n * @returns {number} The angle between the given coordinates.\n * @example\n * ```ts\n * // Calculate the angle between two points\n * const angleValue = angle(0, 0, 3, 4);\n * ```\n */\nexport const angle = (\n cx: number,\n cy: number,\n ex: number,\n ey: number,\n normalize = true\n): number => {\n if (!cx || !cy || !ex || !ey) {\n throw new SyntaxError('Missing input for `angle`');\n }\n\n if (\n typeof cx !== 'number' ||\n typeof cy !== 'number' ||\n typeof ex !== 'number' ||\n typeof ey !== 'number'\n ) {\n throw new TypeError(\n `Parameters for \\`angle\\` do not have the required type. Requires number! Got: ${typeof cx} ${typeof cy} ${typeof ex} ${typeof ey}`\n );\n }\n\n const dy = ey - cy;\n const dx = ex - cx;\n\n let theta = Math.atan2(dy, dx); // range (-PI, PI]\n\n theta *= 180 / Math.PI; // radians to degrees, range (-180, 180]\n\n if (normalize && theta < 0) theta = 360 + theta; // range [0, 360)\n\n return theta;\n};\n","/* eslint no-console:0 */\n'use strict';\n\n/**\n * Gives you the cardinal direction based on degrees.\n * Note: The degrees start at 0, which is EAST (originally, north should be 0, but here, north is 270),\n * and we travel clockwise.\n *\n * @param {number} degrees - The angle in degrees.\n * @throws {RangeError} Parameter cannot exceed 360.\n * @throws {RangeError} Parameter cannot be lower than 0.\n * @returns {string} - The cardinal direction.\n * @example\n * ```ts\n * // Get the cardinal direction for an angle in degrees\n * const direction = cardinal_direction(45);\n * ```\n */\nexport const cardinal_direction = (degrees: number): string => {\n if (degrees > 360) throw new RangeError('Parameter cannot exceed 360');\n\n if (degrees < 0) throw new RangeError('Parameter cannot be lower than 0');\n\n if (degrees >= 0 && degrees <= 22.5) {\n return 'east';\n } else if (degrees >= 22.5 && degrees <= 67.5) {\n return 'south-east';\n } else if (degrees >= 67.5 && degrees <= 112.5) {\n return 'south';\n } else if (degrees >= 112.5 && degrees <= 157.5) {\n return 'south-west';\n } else if (degrees >= 157.5 && degrees <= 202.5) {\n return 'west';\n } else if (degrees >= 202.5 && degrees <= 247.5) {\n return 'north-west';\n } else if (degrees >= 247.5 && degrees <= 292.5) {\n return 'north';\n } else if (degrees >= 292.5 && degrees <= 337.5) {\n return 'north-east';\n } else {\n return 'east';\n }\n};\n\n/**\n * Gives you the cardinal direction based on degrees (crude version).\n * Note: The degrees start at 0, which is EAST (originally, north should be 0, but here, north is 270),\n * and we travel clockwise.\n *\n * @param {number} degrees - The angle in degrees.\n * @throws {RangeError} Parameter cannot exceed 360.\n * @throws {RangeError} Parameter cannot be lower than 0.\n * @returns {string} - The cardinal direction (NSEW).\n * @example\n * ```ts\n * // Get the cardinal direction (crude) for an angle in degrees\n * const direction = cardinal_direction_crude(45);\n * ```\n */\nexport const cardinal_direction_crude = (degrees: number): string => {\n if (degrees > 360) throw new RangeError('Parameter cannot exceed 360');\n\n if (degrees < 0) throw new RangeError('Parameter cannot be lower than 0');\n\n if (degrees >= 45 && degrees <= 135) {\n return 'south';\n } else if (degrees > 135 && degrees <= 225) {\n return 'west';\n } else if (degrees > 225 && degrees <= 315) {\n return 'north';\n } else if (degrees > 315) {\n return 'east';\n } else {\n return 'east';\n }\n};\n","'use strict';\n\nimport { uniqueID } from '../id';\nimport { getPositionsForSVGPath, getSVGPath } from '../bezier';\nimport { direction_of_element } from '../direction-of-element';\n\n/**\n * Class representing a DrawSVGLine instance.\n */\nexport class DrawSVGLine {\n #canvas: HTMLElement | SVGElement | null;\n #originalPathElement: HTMLElement | SVGPathElement | null;\n startElement: HTMLElement;\n stopElement: HTMLElement;\n line: SVGPathElement;\n\n /**\n * Creates a new DrawSVGLine instance.\n * @param startElement - The starting element for the line.\n * @param stopElement - The ending element for the line.\n */\n constructor(startElement: HTMLElement, stopElement: HTMLElement) {\n this.#init(startElement, stopElement);\n }\n\n /**\n * Initializes the DrawSVGLine instance.\n * @param startElement - The starting element for the line.\n * @param stopElement - The ending element for the line.\n * @throws Will throw an error if required elements are missing or not in the DOM.\n */\n #init(startElement: HTMLElement, stopElement: HTMLElement) {\n if (!startElement || !stopElement) {\n throw new Error('Missing inputs startElement and stopElement');\n }\n\n if (!document.body.contains(stopElement)) {\n throw new Error('stopElement is not in the DOM');\n }\n\n if (!document.body.contains(startElement)) {\n throw new Error('startElement is not in the DOM');\n }\n\n this.startElement = startElement;\n this.stopElement = stopElement;\n\n this.#canvas = document.getElementById('ph-speccer-svg');\n this.#originalPathElement = document.getElementById('ph-speccer-path');\n\n if (!this.#originalPathElement || !this.#canvas) {\n throw new Error(\n 'Missing required SVG element to draw lines. Please see the documentation'\n );\n }\n\n this.connect();\n }\n\n /**\n * Connects and draws the line.\n */\n connect() {\n this.draw(this.#originalPathElement as SVGPathElement);\n }\n\n /**\n * Draws the line based on the provided path.\n * @param path - The SVGPathElement to be used as the base path.\n * @throws Will throw an error if no path is provided.\n */\n async draw(path: SVGPathElement) {\n if (!path) {\n throw new Error('No path given to draw!');\n }\n\n const _id = uniqueID();\n const _path_el_id = `ph_draw_path-path-${_id}`;\n const _new_path = path.cloneNode(false) as SVGPathElement;\n\n _new_path.setAttribute('id', _path_el_id);\n _new_path.setAttribute(\n 'data-start-el',\n this.startElement.getAttribute('id') || 'no-id-found'\n );\n _new_path.classList.remove('original');\n _new_path.classList.add('speccer');\n\n if (path.parentNode) {\n this.line = path.parentNode.insertBefore(_new_path, path.nextSibling);\n } else {\n throw new Error('No parentNode found for path');\n }\n\n const _direction = await direction_of_element({\n start: this.startElement,\n stop: this.stopElement,\n crude: true\n });\n const { pos1, pos2 } = getPositionsForSVGPath(_direction);\n const _d = await getSVGPath(this.startElement, this.stopElement, {\n pos1,\n pos2\n });\n\n this.line.setAttribute('data-direction', _direction);\n this.line.setAttribute('data-pos1', pos1);\n this.line.setAttribute('data-pos2', pos2);\n\n this.line.setAttribute('d', _d); // SVG attributes\n }\n}\n\n// Exporting the class as a global object (if needed)\nwindow.DrawSVGLine = DrawSVGLine;\n","'use strict';\n\nimport { uniqueID } from '../id';\nimport { getCurlySVGPath, getPositionsForCurlySVGPath } from '../bezier';\nimport { direction_of_element } from '../direction-of-element';\n\n/**\n * Class representing a DrawSVGCurlyBracket instance.\n */\nexport class DrawSVGCurlyBracket {\n #canvas: HTMLElement | SVGElement | null;\n #originalPathElement: HTMLElement | SVGPathElement | null;\n startElement: HTMLElement;\n stopElement: HTMLElement;\n firstPathElement: SVGPathElement;\n secondPathElement: SVGPathElement;\n\n /**\n * Creates a new DrawSVGCurlyBracket instance.\n * @param startElement - The starting element for the bracket.\n * @param stopElement - The ending element for the bracket.\n */\n constructor(startElement: HTMLElement, stopElement: HTMLElement) {\n this.#init(startElement, stopElement);\n }\n\n /**\n * Initializes the DrawSVGCurlyBracket instance.\n * @param startElement - The starting element for the bracket.\n * @param stopElement - The ending element for the bracket.\n * @throws Will throw an error if required elements are missing or not in the DOM.\n */\n #init(startElement: HTMLElement, stopElement: HTMLElement) {\n if (!startElement || !stopElement) {\n throw new Error('Missing inputs startElement and stopElement');\n }\n\n if (!document.body.contains(stopElement)) {\n throw new Error('stopElement is not in the DOM');\n }\n\n if (!document.body.contains(startElement)) {\n throw new Error('startElement is not in the DOM');\n }\n\n this.startElement = startElement;\n this.stopElement = stopElement;\n\n this.#canvas = document.getElementById('ph-speccer-svg');\n this.#originalPathElement = document.getElementById('ph-speccer-path');\n\n if (!this.#originalPathElement || !this.#canvas) {\n throw new Error(\n 'Missing required SVG element to draw lines. Please see the documentation'\n );\n }\n\n this.connect();\n }\n\n /**\n * Connects and draws the curly bracket.\n */\n connect() {\n this.draw(this.#originalPathElement as SVGPathElement);\n }\n\n /**\n * Creates a new path element based on the provided path.\n * @param path - The SVGPathElement to be used as the base path.\n * @throws Will throw an error if no path is provided.\n * @returns A new SVGPathElement.\n */\n #getPathElement(path: SVGPathElement) {\n if (!path) {\n throw new Error('No path given to #getPathElement!');\n }\n\n const _id = uniqueID();\n const _path_el_id = `ph_draw_path-path-${_id}`;\n const _new_path = path.cloneNode(false) as SVGPathElement;\n\n _new_path.setAttribute(\n 'data-start-el',\n this.startElement.getAttribute('id') || 'no-id-found'\n );\n _new_path.setAttribute('id', _path_el_id);\n _new_path.classList.remove('original');\n _new_path.classList.add('speccer');\n\n return _new_path;\n }\n\n /**\n * Draws the curly bracket based on the provided path.\n * @param path - The SVGPathElement to be used as the base path.\n * @throws Will throw an error if no path is provided.\n */\n async draw(path: SVGPathElement) {\n if (!path) {\n throw new Error('No path given to draw!');\n }\n\n const _first_path_element = this.#getPathElement(path);\n const _second_path_element = this.#getPathElement(path);\n\n if (path.parentNode) {\n this.firstPathElement = path.parentNode.insertBefore(\n _first_path_element,\n path.nextSibling\n );\n this.secondPathElement = path.parentNode.insertBefore(\n _second_path_element,\n path.nextSibling\n );\n } else {\n throw new Error('No parentNode found for path');\n }\n\n const _direction = await direction_of_element({\n stop: this.stopElement,\n start: this.startElement,\n crude: true\n });\n const { path1pos1, path1pos2, path2pos1, path2pos2 } =\n getPositionsForCurlySVGPath(_direction);\n const _first_path_d = await getCurlySVGPath(\n this.startElement,\n this.stopElement,\n {\n pos1: path1pos1,\n pos2: path1pos2,\n firstSet: true,\n direction: _direction\n }\n );\n const _second_path_d = await getCurlySVGPath(\n this.startElement,\n this.stopElement,\n {\n pos1: path2pos1,\n pos2: path2pos2,\n direction: _direction\n }\n );\n\n this.firstPathElement.setAttribute('data-direction', _direction);\n this.firstPathElement.setAttribute('data-pos1', path1pos1);\n this.firstPathElement.setAttribute('data-pos2', path1pos2);\n this.firstPathElement.setAttribute('d', _first_path_d); // SVG attributes\n this.secondPathElement.setAttribute('data-direction', _direction);\n this.secondPathElement.setAttribute('data-pos1', path2pos1);\n this.secondPathElement.setAttribute('data-pos2', path2pos2);\n this.secondPathElement.setAttribute('d', _second_path_d); // SVG attributes\n }\n}\n\n// Exporting the class as a global object (if needed)\nwindow.DrawSVGCurlyBracket = DrawSVGCurlyBracket;\n","import { pinSpace, measureSize } from '../../../utils/css';\nimport { getRec } from '../../../utils/position';\nimport {\n isBottomArea,\n isEncloseArea,\n isFullArea,\n isLeftArea,\n isRightArea\n} from '../../../utils/area';\nimport { DissectStylesOptionsType } from 'types/bezier';\n\n/**\n * Get styles for dissected elements based on the specified area and options.\n *\n * @param {string} area - The area description.\n * @param {HTMLElement} targetEl - The target element.\n * @param {HTMLElement} dissectionEl - The dissection element.\n * @param {DissectStylesOptionsType} options - Optional styles options.\n * @returns {Promise<{ left: string; top: string; height?: string; width?: string }>} - The computed styles.\n *\n * @example\n * ```ts\n * const area = 'top-left';\n * const targetElement = document.getElementById('target');\n * const dissectionElement = document.getElementById('dissection');\n * const options = { isCurly: true };\n * const styles = await styles(area, targetElement, dissectionElement, options);\n * console.log(styles);\n * ```\n */\nexport const styles = async (\n area: string,\n targetEl: HTMLElement,\n dissectionEl: HTMLElement,\n options?: DissectStylesOptionsType\n): Promise<{ left: string; top: string; height?: string; width?: string }> => {\n const { isCurly = false } = options || {};\n const SPECCER_PIN_SPACE = pinSpace(dissectionEl);\n const SPECCER_MEASURE_SIZE = measureSize(dissectionEl);\n const _positional_styles = await getRec(dissectionEl, targetEl);\n\n if (isEncloseArea(area)) {\n const { left, top, height, width } = _positional_styles.absolute();\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`,\n width: `${width}px`\n };\n }\n\n if (isLeftArea(area)) {\n if (isFullArea(area) && !isCurly) {\n const { left, top, height } = _positional_styles.fromLeft({\n sourceWidth: SPECCER_MEASURE_SIZE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`\n };\n } else {\n const { left, top } = _positional_styles.fromLeft({\n center: true,\n modifier: isCurly ? SPECCER_PIN_SPACE / 1.5 : SPECCER_PIN_SPACE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`\n };\n }\n } else if (isRightArea(area)) {\n if (isFullArea(area) && !isCurly) {\n const { left, top, height } = _positional_styles.fromRight({\n center: false\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`\n };\n } else {\n const { left, top } = _positional_styles.fromRight({\n center: true,\n modifier: isCurly ? SPECCER_PIN_SPACE / 1.5 : SPECCER_PIN_SPACE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`\n };\n }\n } else if (isBottomArea(area)) {\n if (isFullArea(area) && !isCurly) {\n const { left, top, width } = _positional_styles.fromBottom({\n center: false\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`\n };\n } else {\n const { left, top } = _positional_styles.fromBottom({\n center: true,\n modifier: isCurly ? SPECCER_PIN_SPACE / 1.5 : SPECCER_PIN_SPACE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`\n };\n }\n } else {\n if (isFullArea(area) && !isCurly) {\n const { left, top, width } = _positional_styles.fromTop({\n center: false\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`\n };\n } else {\n const { left, top } = _positional_styles.fromTop({\n center: true,\n modifier: isCurly ? SPECCER_PIN_SPACE / 1.5 : SPECCER_PIN_SPACE\n });\n\n return {\n left: `${left}px`,\n top: `${top}px`\n };\n }\n }\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport { DissectAreaEnum } from '../../types/enums/area';\n\nimport { set as setClassNames, cx } from '../../utils/classnames';\nimport { SPECCER_LITERALS } from '../../utils/constants';\nimport { add } from '../../utils/styles';\nimport { isCurly, isEncloseArea, isFullArea, useSVG } from '../../utils/area';\nimport { DrawSVGLine } from '../../utils/classes/DrawSVGLine';\nimport { DrawSVGCurlyBracket } from '../../utils/classes/DrawSVGCurlyBracket';\n\nimport { styles } from './utils/styles';\n\n/**\n * Create a dissected element with optional text content, area description, and element type.\n *\n * @param {string} textContent - The text content to add to the element.\n * @param {string} area - The area description for styling.\n * @param {string} n - The element type.\n * @returns {HTMLElement} - The created dissected element.\n *\n * @example\n * ```ts\n * const dissectedElement = create('A', 'outline top', 'div');\n * document.body.appendChild(dissectedElement);\n * ```\n */\nexport const create = (\n textContent = '',\n area: string,\n n = 'span'\n): HTMLElement => {\n const _el = document.createElement(n);\n const _text_node = document.createTextNode(textContent);\n const _extra_class_names = {};\n\n if (area !== null && area !== '') {\n _extra_class_names[area] = true;\n }\n\n if (\n (!isFullArea(area) && !isEncloseArea(area)) ||\n (isFullArea(area) && isCurly(area))\n ) {\n _el.appendChild(_text_node);\n } else if (isFullArea(area) || isEncloseArea(area)) {\n _el.setAttribute('data-dissection-counter', textContent);\n }\n\n const _class_names = cx('ph-speccer speccer dissection', _extra_class_names);\n\n setClassNames(_el, _class_names);\n\n return _el;\n};\n\n/**\n * Create dissected elements based on the section element and its data-anatomy attributes.\n *\n * @param {HTMLElement} sectionEl - The section element containing dissected elements.\n * @returns {Promise} - A promise that resolves after creating dissected elements.\n *\n * @example\n * ```ts\n * const sectionElement = document.getElementById('section');\n * element(sectionElement);\n * ```\n */\nexport const element = (sectionEl: HTMLElement): Promise => {\n if (!sectionEl) return Promise.resolve();\n\n const _dissection_els = sectionEl.querySelectorAll('[data-anatomy]');\n\n if (_dissection_els) {\n let _index_to_use = 0;\n\n _dissection_els.forEach(async (targetEl: HTMLElement, targetIndex) => {\n if (!targetEl) return Promise.resolve();\n\n const _areas_string: string = targetEl.getAttribute('data-anatomy') || '';\n\n if (\n !_areas_string ||\n _areas_string === '' ||\n _areas_string.indexOf(DissectAreaEnum.Outline) === -1\n )\n return Promise.resolve();\n\n /**\n * If we're running out of literals to use,\n * make a new one with uppercase and lowercase pairs\n */\n let _literal_to_use = SPECCER_LITERALS[targetIndex];\n\n if (!_literal_to_use) {\n _literal_to_use = `${SPECCER_LITERALS[_index_to_use]}${SPECCER_LITERALS[\n _index_to_use\n ].toLowerCase()}`;\n _index_to_use++;\n }\n\n const _dissection_el = create(_literal_to_use, _areas_string);\n\n document.body.appendChild(_dissection_el);\n\n const _dissection_styles = await styles(\n _areas_string,\n targetEl,\n _dissection_el,\n {\n isCurly: isCurly(_areas_string)\n }\n );\n\n await add(_dissection_el, _dissection_styles);\n\n if (useSVG(_areas_string)) {\n new DrawSVGLine(targetEl, _dissection_el);\n } else if (isCurly(_areas_string)) {\n new DrawSVGCurlyBracket(targetEl, _dissection_el);\n }\n });\n }\n\n return Promise.resolve();\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport {\n isBottomArea,\n isHeightArea,\n isRightArea,\n isWidthArea\n} from 'utils/area';\nimport { set as setClassNames } from '../../utils/classnames';\nimport { get as getStyles, add as addStyles } from '../../utils/styles';\nimport { waitForFrame } from '../../utils/wait';\nimport { getRec } from '../../utils/position';\nimport { SPECCER_DEFAULT_MEASURE_SIZE_NEG } from 'utils/constants';\n\n/**\n * Create a measurement element with optional text, area, and element type.\n *\n * @param {string | number} text - The text to display on the element.\n * @param {string | null} area - The area to specify with CSS class.\n * @param {string} tag - The element type.\n * @returns {HTMLElement} - The created measurement element.\n *\n * @example\n * ```ts\n * const measurement = create(100, 'width bottom', 'div');\n * document.body.appendChild(measurement);\n * ```\n */\nexport const create = (\n text: string | number = '',\n area: string | null = '',\n tag = 'span'\n): HTMLElement => {\n const _el = document.createElement(tag);\n\n _el.setAttribute('title', text + 'px');\n _el.setAttribute('data-measure', parseInt(text + '', 10) + 'px');\n\n setClassNames(_el, `ph-speccer speccer measure ${area}`);\n\n return _el;\n};\n\n/**\n * Create a measurement element and add it to the body with styles matching a specified target element.\n *\n * @param {HTMLElement} targetEl - The target element to match styles with.\n * @returns {Promise} - A promise that resolves after creating and styling the measurement element.\n *\n * @example\n * ```ts\n * const targetElement = document.getElementById('target');\n * element(targetElement);\n * ```\n */\nexport const element = async (targetEl: HTMLElement): Promise => {\n if (!targetEl) return;\n\n const _areas_string: string | null = targetEl.getAttribute(\n 'data-speccer-measure'\n );\n\n if (_areas_string === '' || !_areas_string) {\n return;\n }\n\n const _target_styles = await getStyles(targetEl);\n\n if (\n _target_styles.display === 'none' ||\n _target_styles.opacity === '0' ||\n _target_styles.visibility === 'hidden'\n ) {\n return;\n }\n\n await waitForFrame();\n\n const _target_rect = targetEl.getBoundingClientRect();\n\n if (isWidthArea(_areas_string)) {\n if (isBottomArea(_areas_string)) {\n const _measure_el = create(_target_rect.width, _areas_string);\n\n document.body.appendChild(_measure_el);\n\n const _positional_styles = await getRec(_measure_el, targetEl);\n const { left, top, width } = _positional_styles.fromBottom({\n center: false\n });\n\n await addStyles(_measure_el, {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`\n });\n } else {\n const _measure_el = create(_target_rect.width, _areas_string);\n\n document.body.appendChild(_measure_el);\n\n const _positional_styles = await getRec(_measure_el, targetEl);\n const { left, top, width } = _positional_styles.fromTop({\n center: false,\n modifier: SPECCER_DEFAULT_MEASURE_SIZE_NEG\n });\n\n await addStyles(_measure_el, {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`\n });\n }\n } else if (isHeightArea(_areas_string)) {\n if (isRightArea(_areas_string)) {\n const _measure_el = create(_target_rect.height, _areas_string);\n\n document.body.appendChild(_measure_el);\n\n const _positional_styles = await getRec(_measure_el, targetEl);\n const { left, top, height } = _positional_styles.fromRight({\n center: false\n });\n\n await addStyles(_measure_el, {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`\n });\n } else {\n const _measure_el = create(_target_rect.height, _areas_string);\n\n document.body.appendChild(_measure_el);\n\n const _positional_styles = await getRec(_measure_el, targetEl);\n const { left, top, height } = _positional_styles.fromLeft({\n center: false,\n modifier: SPECCER_DEFAULT_MEASURE_SIZE_NEG\n });\n\n await addStyles(_measure_el, {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`\n });\n }\n }\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport { add as addStyles } from '../../utils/styles';\nimport { cx, set } from '../../utils/classnames';\nimport { getRec } from '../../utils/position';\n\n/**\n * Create a marker element with an optional element type.\n *\n * @param {string} n - The element type.\n * @returns {HTMLElement} - The created marker element.\n *\n * @example\n * ```typescript\n * const marker = create('div');\n * document.body.appendChild(marker);\n * ```\n */\nexport const create = (n = 'span'): HTMLElement => {\n const markElement = document.createElement(n);\n const classNames = cx('ph-speccer speccer mark');\n\n set(markElement, classNames);\n\n return markElement;\n};\n\n/**\n * Create a marker element and add it to the body with styles matching a specified element.\n *\n * @param {HTMLElement} elementToMark - The target element to match styles with.\n * @returns {Promise} - A promise that resolves after creating and styling the marker element.\n *\n * @example\n * ```typescript\n * const elementToMark = document.getElementById('target');\n * element(elementToMark);\n * ```\n */\nexport const element = async (elementToMark: HTMLElement): Promise => {\n if (!elementToMark) return Promise.resolve();\n\n const markElement = create();\n\n document.body.appendChild(markElement);\n\n const positionalStyles = await getRec(markElement, elementToMark);\n const { left, top, height, width } = positionalStyles.absolute();\n const markStyles = {\n left: `${left}px`,\n top: `${top}px`,\n height: `${height}px`,\n width: `${width}px`\n };\n\n await addStyles(markElement, markStyles);\n};\n","/* eslint no-console:0 */\n'use strict';\n\n/**\n * Converts a number to a string with a specified number of decimal places.\n *\n * @param {string | number} number - The number to convert.\n * @param {number} decimals - The number of decimal places (default is 3).\n * @returns {string} - The formatted number as a string.\n *\n * @example\n * ```ts\n * // Convert a number to a string with 2 decimal places\n * const formattedNumber = decimal(12.3456, 2); // \"12.34\"\n * ```\n */\nexport const decimal = (number: string | number, decimals = 3): string =>\n parseFloat(number + '').toFixed(decimals);\n","/* eslint no-console:0 */\n'use strict';\n\nimport { set as setClassNames, cx } from '../../utils/classnames';\nimport { add as addStyles, get as getStyles } from '../../utils/styles';\nimport { position } from './utils/position';\nimport { template } from './utils/template';\n\n/**\n * Create a DOM element with provided HTML and optional CSS class names.\n *\n * @param {string} html - The HTML content to be set in the created element.\n * @param {string | null} area - The optional CSS class names to add.\n * @returns {HTMLElement} - The created DOM element.\n *\n * @example\n * ```ts\n * const htmlContent = '

This is some HTML content.

';\n * const cssClass = 'custom-class';\n * const createdElement = create(htmlContent, cssClass);\n * document.body.appendChild(createdElement);\n * ```\n */\nexport const create = (html: string, area: string | null): HTMLElement => {\n const _el = document.createElement('div');\n const _extra_class_names = {};\n\n if (area !== null && area !== '') {\n _extra_class_names[area] = true;\n }\n\n const _class_names = cx('ph-speccer speccer typography', _extra_class_names);\n\n _el.innerHTML = html;\n\n setClassNames(_el, _class_names);\n\n return _el;\n};\n\n/**\n * Create a specced typography element for a given target element.\n *\n * @param {HTMLElement} targetEl - The target element to specc typography for.\n * @returns {Promise} - A promise that resolves once typography element is created and positioned.\n *\n * @example\n * ```ts\n * const targetElement = document.querySelector('.target');\n * if (targetElement) {\n * element(targetElement);\n * }\n * ```\n */\nexport const element = async (targetEl: HTMLElement): Promise => {\n if (!targetEl) return;\n\n const _area: string | null = targetEl.getAttribute('data-speccer-typography');\n const _target_styles = await getStyles(targetEl);\n\n if (\n _target_styles.display === 'none' ||\n _target_styles.opacity === '0' ||\n _target_styles.visibility === 'hidden'\n ) {\n return;\n }\n\n targetEl.classList.add('is-specced');\n\n const _html = await template(targetEl);\n const _speccer_el = create(_html, _area);\n\n document.body.appendChild(_speccer_el);\n\n const _position = await position(_area, targetEl, _speccer_el);\n\n addStyles(_speccer_el, _position);\n};\n","import { getTypography } from '../../../utils/css';\nimport { get as getStyles } from '../../../utils/styles';\n\n/**\n * Generate a HTML string for typography styles of a target element.\n *\n * @param {HTMLElement} targetEl - The target element for which to generate typography styles.\n * @returns {Promise} - A promise that resolves with the HTML string.\n *\n * @example\n * ```ts\n * const targetElement = document.getElementById('target');\n * const typographyStyles = await template(targetElement);\n * console.log(typographyStyles);\n * ```\n */\nexport const template = async (targetEl: HTMLElement): Promise => {\n const _target_styles = await getStyles(targetEl);\n const _styles = getTypography(_target_styles);\n const _line_height =\n _styles['lineHeight'] !== 'normal'\n ? parseInt(_styles['lineHeight'], 10) / 16 + 'rem'\n : 'normal';\n\n return (\n `\n` +\n 'font-styles: {' +\n '
    ' +\n `
  • font-family: ${_styles['fontFamily']};
  • ` +\n `
  • font-size: ${_styles['fontSize']} / ${\n parseInt(_styles['fontSize'], 10) / 16\n }rem;
  • ` +\n `
  • font-weight: ${_styles['fontWeight']};
  • ` +\n `
  • font-variation-settings: ${_styles['fontVariationSettings']};
  • ` +\n `
  • line-height: ${_styles['lineHeight']} / ${_line_height};
  • ` +\n `
  • letter-spacing: ${_styles['letterSpacing']};
  • ` +\n `
  • font-style: ${_styles['fontStyle']};
  • ` +\n '
' +\n '}'\n );\n};\n","import { pinSpace } from '../../../utils/css';\nimport { decimal } from '../../../utils/number';\nimport {\n get_horizontal_center_of_els,\n get_vertical_center_of_els,\n offset\n} from '../../../utils/position';\n\nimport { SpeccerAreaEnum } from '../../../types/enums/area';\n\n/**\n * Calculate the position for the speccer element relative to the target element.\n *\n * @param {string | null} area - The area information for positioning.\n * @param {HTMLElement} targetEl - The target element.\n * @param {HTMLElement} speccerEl - The speccer element to position.\n * @returns {Promise<{ left: string, top: string }>} - A promise that resolves with the calculated position.\n *\n * @example\n * ```ts\n * const targetElement = document.getElementById('target');\n * const speccerElement = document.getElementById('speccer');\n * const area = 'top';\n * const position = await position(area, targetElement, speccerElement);\n * console.log(position); // { left: '10px', top: '20px' }\n * ```\n */\nexport const position = async (\n area: string | null,\n targetEl: HTMLElement,\n speccerEl: HTMLElement\n): Promise<{ left: string; top: string }> => {\n const _target_rect = targetEl.getBoundingClientRect();\n const SPECCER_PIN_SPACE = pinSpace(speccerEl);\n const _speccer_el_rect = speccerEl.getBoundingClientRect();\n const _el_offset = await offset(targetEl);\n const _left_layout_position_left =\n _el_offset.left - _speccer_el_rect.width - SPECCER_PIN_SPACE + 'px';\n const _left_layout_position_top =\n decimal(\n get_vertical_center_of_els(_el_offset.top, _speccer_el_rect, _target_rect)\n ) + 'px';\n const _right_layout_position_left =\n _el_offset.left + _target_rect.width + SPECCER_PIN_SPACE + 'px';\n const _right_layout_position_top =\n decimal(\n get_vertical_center_of_els(_el_offset.top, _speccer_el_rect, _target_rect)\n ) + 'px';\n const _top_layout_position_left =\n decimal(\n get_horizontal_center_of_els(\n _el_offset.left,\n _speccer_el_rect,\n _target_rect\n )\n ) + 'px';\n const _top_layout_position_top =\n _el_offset.top - _speccer_el_rect.height - SPECCER_PIN_SPACE + 'px';\n const _bottom_layout_position_left =\n decimal(\n get_horizontal_center_of_els(\n _el_offset.left,\n _speccer_el_rect,\n _target_rect\n )\n ) + 'px';\n const _bottom_layout_position_top =\n _el_offset.top + _target_rect.height + SPECCER_PIN_SPACE + 'px';\n\n let _position = {\n left: _left_layout_position_left,\n top: _left_layout_position_top\n };\n\n if (area && area.indexOf(SpeccerAreaEnum.Right) !== -1) {\n _position = {\n left: _right_layout_position_left,\n top: _right_layout_position_top\n };\n } else if (area && area.indexOf(SpeccerAreaEnum.Top) !== -1) {\n _position = {\n left: _top_layout_position_left,\n top: _top_layout_position_top\n };\n } else if (area && area.indexOf(SpeccerAreaEnum.Bottom) !== -1) {\n _position = {\n left: _bottom_layout_position_left,\n top: _bottom_layout_position_top\n };\n }\n\n return _position;\n};\n","'use strict';\n\nimport { SpeccerFunctionType } from 'types/speccer';\n\nimport debounce from './debounce';\n\n/**\n * Attaches a debounced event listener to the window's resize event that triggers the provided function.\n *\n * @param {SpeccerFunctionType} speccer - The function to trigger when the window is resized.\n *\n * @example\n * ```ts\n * // Define a function to be triggered on window resize\n * const mySpeccer = () => {\n * // Your logic here\n * console.log('Window resized');\n * };\n *\n * // Activate the debounced event listener\n * activate(mySpeccer);\n * ```\n */\nexport const activate = (speccer: SpeccerFunctionType): void => {\n /**\n * The debounced event listener function.\n * @type {Function}\n */\n const speccerEventFunc = () =>\n debounce(() => {\n speccer();\n }, 300);\n\n // Remove any existing resize event listeners to prevent duplicates\n window.removeEventListener('resize', speccerEventFunc);\n\n // Add the debounced resize event listener\n window.addEventListener('resize', speccerEventFunc);\n};\n","/* eslint @typescript-eslint/no-explicit-any: [\"error\", { \"fixToUnknown\": true }] */\n'use strict';\n\nimport { DebounceAnyFunctionType } from 'types/debounce';\n\n/**\n * Creates a debounced version of a function that delays its execution until after a specified waiting time has elapsed since the last time the debounced function was invoked.\n *\n * @param {DebounceAnyFunctionType} func - The function to debounce.\n * @param {number} wait - The number of milliseconds to wait before invoking the function after the last call.\n * @param {boolean} [immediate=false] - If `true`, the function is invoked immediately after the first call.\n * @returns {DebounceAnyFunctionType} - The debounced function.\n *\n * @example\n * ```ts\n * // Create a debounced function\n * const debouncedFn = debounce((value) => {\n * console.log(value);\n * }, 500);\n *\n * // Call the debounced function\n * debouncedFn('Hello'); // This will not trigger immediate execution\n * debouncedFn('World'); // This will trigger immediate execution\n * ```\n */\nconst debounce = (\n func: DebounceAnyFunctionType,\n wait: number,\n immediate = false\n): DebounceAnyFunctionType => {\n let timeout: null | ReturnType;\n\n return function (context: unknown, ...args: unknown[]): void {\n const later = function (): void {\n timeout = null;\n\n if (!immediate) func.apply(context, args);\n };\n const callNow = immediate && !timeout;\n\n if (timeout) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(later, wait);\n\n if (callNow) func.apply(context, args);\n };\n};\n\nexport default debounce;\n","/* eslint no-console:0 */\n'use strict';\n\nimport { SpeccerFunctionType } from 'types/speccer';\n\nimport { activate as resizeActivate } from '../utils/resize';\n\nimport { element as specElement } from '../features/spacing';\nimport { element as measureElement } from '../features/measure';\nimport { element as dissectElement } from '../features/dissect';\n\n/**\n * A function to initialize speccer when the DOM is ready.\n *\n * @param {SpeccerFunctionType} speccer - The speccer function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // dom(mySpeccer);\n * ```\n */\nexport const dom = (speccer: SpeccerFunctionType): void => {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n speccer();\n });\n } else {\n // `DOMContentLoaded` already fired\n speccer();\n }\n};\n\n/**\n * A function to initialize lazy speccer functionality.\n *\n * @example\n * ```ts\n * // Usage example:\n * // lazy();\n * ```\n */\nexport const lazy = (): void => {\n const _spec_observer = new IntersectionObserver((els, observer) => {\n els.forEach((el: IntersectionObserverEntry) => {\n if (el.intersectionRatio > 0) {\n specElement(el.target as HTMLElement);\n observer.unobserve(el.target);\n }\n });\n });\n\n document\n .querySelectorAll(\n '[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)'\n )\n .forEach((el) => {\n _spec_observer.observe(el);\n });\n\n const _measure_observer = new IntersectionObserver((els, observer) => {\n els.forEach((el) => {\n if (el.intersectionRatio > 0) {\n measureElement(el.target as HTMLElement);\n observer.unobserve(el.target);\n }\n });\n });\n\n document.querySelectorAll('[data-speccer-measure]').forEach((el) => {\n _measure_observer.observe(el);\n });\n\n const _dissect_observer = new IntersectionObserver((els, observer) => {\n els.forEach((el) => {\n if (el.intersectionRatio > 0) {\n dissectElement(el.target as HTMLElement);\n observer.unobserve(el.target);\n }\n });\n });\n\n document.querySelectorAll('[data-anatomy-section]').forEach((el) => {\n _dissect_observer.observe(el);\n });\n};\n\n/**\n * A function to manually activate speccer.\n *\n * @param {SpeccerFunctionType} speccer - The speccer function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // manual(mySpeccer);\n * ```\n */\nexport const manual = (speccer: SpeccerFunctionType): void => {\n window.speccer = speccer;\n};\n\n/**\n * A function to activate speccer based on script attributes.\n *\n * @param {SpeccerFunctionType} speccer - The speccer function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // activate(mySpeccer);\n * ```\n */\nexport const activate = (speccer: SpeccerFunctionType): void => {\n const _script = document.currentScript;\n\n if (_script) {\n const _speccer_script_src = _script.getAttribute('src');\n\n if (\n _speccer_script_src &&\n (_speccer_script_src.indexOf('speccer.js') !== -1 ||\n // for codepen\n _speccer_script_src.indexOf('JaXpOK.js') !== -1)\n ) {\n if (_script.hasAttribute('data-manual')) {\n manual(speccer);\n } else if (_script.hasAttribute('data-instant')) {\n speccer();\n } else if (_script.hasAttribute('data-dom')) {\n dom(speccer);\n } else if (_script.hasAttribute('data-lazy')) {\n lazy();\n } else {\n dom(speccer);\n }\n\n if (\n !_script.hasAttribute('data-manual') &&\n !_script.hasAttribute('data-lazy')\n ) {\n resizeActivate(speccer);\n }\n }\n }\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport './types/interfaces/global';\nimport { removeAll } from './utils/node';\nimport {\n create as spacingCreate,\n element as spacingElement\n} from './features/spacing';\nimport {\n create as dissectCreate,\n element as dissectElement\n} from './features/dissect';\nimport {\n create as measureCreate,\n element as measureElement\n} from './features/measure';\nimport { create as markCreate, element as markElement } from './features/mark';\nimport {\n create as typographyCreate,\n element as typographyElement\n} from './features/typography';\nimport { dom, lazy, manual, activate } from './config/browser';\n\nexport const spacing = {\n create: spacingCreate,\n element: spacingElement\n};\n\nexport const dissect = {\n create: dissectCreate,\n element: dissectElement\n};\n\nexport const measure = {\n create: measureCreate,\n element: measureElement\n};\n\nexport const mark = {\n create: markCreate,\n element: markElement\n};\n\nexport const typography = {\n create: typographyCreate,\n element: typographyElement\n};\n\nexport const modes = {\n dom,\n lazy,\n manual,\n activate\n};\n\nconst speccer = () => {\n removeAll('.speccer');\n\n const elsToBeSpecced = document.querySelectorAll(\n '[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)'\n );\n const elsToBeMeasured = document.querySelectorAll('[data-speccer-measure]');\n const elsToBeTypographySpecced = document.querySelectorAll(\n '[data-speccer-typography]'\n );\n const elsToBeDissected = document.querySelectorAll('[data-anatomy-section]');\n const elsToBeMarked = document.querySelectorAll('[data-speccer-mark]');\n\n elsToBeMarked.forEach(markElement);\n elsToBeSpecced.forEach(spacingElement);\n elsToBeMeasured.forEach(measureElement);\n elsToBeTypographySpecced.forEach(typographyElement);\n elsToBeDissected.forEach(dissectElement);\n};\n\nexport default speccer;\n\nactivate(speccer);\n"],"names":["set","el","cls","avoid","length","trim","split","filter","cl","forEach","classList","add","cx","cls_obj","Object","keys","classname","join","SPECCER_LITERALS","getNumberValue","value","parseInt","pinSpace","getComputedStyle","getPropertyValue","waitForFrame","Promise","requestAnimationFrame","async","styles","Array","isArray","constructor","style","key","get","get_horizontal_center_of_els","modifier","startRect","targetRect","width","get_vertical_center_of_els","height","offset","targetEl","_target_rect","getBoundingClientRect","_el_offset_top","top","window","scrollY","_el_offset_left","left","scrollX","getRec","sourceEl","_source_rect","_target_offset","_target_offset_center","offsetWithCenter","_target_height","_target_width","_source_height","_source_width","absolute","toTop","center","sourceHeight","fromTop","toBottom","targetHeight","fromBottom","toLeft","sourceWidth","fromLeft","toRight","targetWidth","fromRight","create","text","tag","_el","document","createElement","_text_content","createTextNode","appendChild","setAttribute","setClassNames","element","_target_styles","getStyles","display","opacity","visibility","_target_spacing_styles","marginTop","marginBottom","marginLeft","marginRight","paddingTop","paddingBottom","paddingLeft","paddingRight","getSpacing","_target_pruned_spacing_styles","property","_value","_speccer_el","_class_name","indexOf","replace","getClassNameFromCSSProperty","body","spacingEl","addStyles","position","SpeccerAreaEnum","DissectAreaEnum","MeasureAreaEnum","getAreasFromString","areaString","isRightArea","includes","Right","isBottomArea","Bottom","isFullArea","Full","isEncloseArea","Enclose","isCurly","Curly","uniqueID","Math","random","toString","substring","coords","rect","xy","x","y","right","bottom","intrinsic_coords","pos","Error","_allowed_positions","_el_rect","getCoordsPairFromObjects","el1","el2","pos1","pos2","x1","y1","x2","y2","createBezierCurveCoordinates","options","direct","firstSet","direction","firstControl","lastControl","firstPoint","lastPoint","getCurlySVGPath","startEl","stopEl","x2modifier","y2modifier","coordinates","direction_of_element","start","stop","crude","_angle","cy","ex","ey","normalize","SyntaxError","TypeError","dy","dx","theta","atan2","PI","angle","degrees","RangeError","cardinal_direction_crude","cardinal_direction","DrawSVGLine","canvas","originalPathElement","startElement","stopElement","line","this","init","contains","getElementById","connect","draw","path","_path_el_id","_new_path","cloneNode","getAttribute","remove","parentNode","insertBefore","nextSibling","_direction","getPositionsForSVGPath","_d","getSVGPath","DrawSVGCurlyBracket","firstPathElement","secondPathElement","getPathElement","_first_path_element","_second_path_element","path1pos1","path1pos2","path2pos1","path2pos2","getPositionsForCurlySVGPath","_first_path_d","_second_path_d","area","dissectionEl","SPECCER_PIN_SPACE","SPECCER_MEASURE_SIZE","_positional_styles","Left","textContent","n","_text_node","_extra_class_names","_class_names","sectionEl","resolve","_dissection_els","querySelectorAll","_index_to_use","targetIndex","_areas_string","Outline","_literal_to_use","toLowerCase","_dissection_el","_dissection_styles","SVG","Width","_measure_el","SPECCER_DEFAULT_MEASURE_SIZE","Height","isHeightArea","markElement","classNames","elementToMark","positionalStyles","markStyles","decimal","number","decimals","parseFloat","toFixed","html","innerHTML","_area","_html","_styles","lineHeight","letterSpacing","fontFamily","fontSize","fontStyle","fontVariationSettings","fontWeight","getTypography","_line_height","template","_position","speccerEl","_speccer_el_rect","_el_offset","_left_layout_position_left","_left_layout_position_top","_right_layout_position_left","_right_layout_position_top","_top_layout_position_left","_top_layout_position_top","_bottom_layout_position_left","_bottom_layout_position_top","Top","activate","speccer","speccerEventFunc","func","wait","immediate","timeout","context","args","callNow","clearTimeout","setTimeout","apply","debounce","removeEventListener","addEventListener","dom","readyState","lazy","_spec_observer","IntersectionObserver","els","observer","intersectionRatio","specElement","target","unobserve","observe","_measure_observer","measureElement","_dissect_observer","dissectElement","manual","_script","currentScript","_speccer_script_src","hasAttribute","resizeActivate","spacing","spacingCreate","spacingElement","dissect","dissectCreate","measure","measureCreate","mark","markCreate","typography","typographyCreate","typographyElement","modes","selector","call","e","removeAll","elsToBeSpecced","elsToBeMeasured","elsToBeTypographySpecced","elsToBeDissected"],"mappings":"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"} \ No newline at end of file diff --git a/speccer.min.css b/speccer.min.css index 5030cc7c..96cc8112 100644 --- a/speccer.min.css +++ b/speccer.min.css @@ -1 +1 @@ -.ph.speccer{--ph-speccer-color-padding:#db6fff66;--ph-speccer-color-padding-hover:#db6fff;--ph-speccer-color-margin:#fff76f66;--ph-speccer-color-margin-hover:#fff76f;--ph-speccer-color-text-light:#fff;--ph-speccer-color-text-dark:#333;--ph-speccer-color-contrast:#ff3aa8;--ph-speccer-mark-background-color:#ff3aa833;--ph-speccer-mark-border-color:#ff3aa8;--ph-speccer-spacing-color:var(--ph-speccer-color-contrast);--ph-speccer-measure-color:red;--ph-speccer-pin-color:var(--ph-speccer-color-contrast);--ph-speccer-typography-background-color:#fff;--ph-speccer-typography-color-property:#3f85f2;--ph-speccer-typography-color-text:#57575b;--ph-speccer-typography-color-value:var(--ph-speccer-color-contrast);--ph-speccer-depth-opacity-400:0.4;--ph-speccer-font-family:"Menlo for Powerline","Menlo Regular for Powerline","DejaVu Sans Mono",Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;--ph-speccer-font-size:12px;--ph-speccer-line-height:12px;--ph-speccer-pin-size:24px;--ph-speccer-pin-space:48px;--ph-speccer-line-width:1px;--ph-speccer-line-width-negative:-1px;--ph-speccer-measure-size:8px}.ph.speccer,.ph.speccer:after,.ph.speccer:before,svg.ph{box-sizing:border-box;pointer-events:none;user-select:none}.ph.speccer:after,.ph.speccer:before,.ph.speccer:not(path){align-items:center;display:flex;font-family:var(--ph-speccer-font-family)!important;font-size:12px;justify-content:center;line-height:12px;position:absolute;z-index:99999}#ph-speccer-svg{height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%;z-index:3}svg.ph .ph.path{color:var(--ph-speccer-color-contrast,#ff3aa8)}.ph.speccer.dissection{align-items:center;background-color:var(--ph-speccer-pin-color);border-radius:100%;color:var(--ph-speccer-color-text-light);display:flex;font-family:sans-serif;font-size:16px;font-weight:400;height:var(--ph-speccer-pin-size);justify-content:center;line-height:150%;position:absolute;width:var(--ph-speccer-pin-size);z-index:100000}.ph.speccer.dissection.curly:after,.ph.speccer.dissection.svg:after{content:none!important}.ph.speccer.dissection.outline.left:after{right:auto}.ph.speccer.dissection.outline.right:after{left:auto}.ph.speccer.dissection:after{background-color:var(--ph-speccer-pin-color);content:"";height:var(--ph-speccer-pin-space);position:absolute;top:100%;width:var(--ph-speccer-line-width);z-index:99999}.ph.speccer.dissection.outline.left:after{height:var(--ph-speccer-line-width);left:100%;top:50%;width:var(--ph-speccer-pin-space)}.ph.speccer.dissection.outline.right:after{height:var(--ph-speccer-line-width);right:100%;top:50%;width:var(--ph-speccer-pin-space)}.ph.speccer.dissection.outline.enclose{background-color:initial;border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-radius:0;color:var(--ph-speccer-measure-color)}.ph.speccer.dissection.outline.enclose:after{bottom:auto;top:calc(var(--ph-speccer-line-width-negative) - var(--ph-speccer-pin-size) - var(--ph-speccer-pin-space))}.ph.speccer.dissection.outline.enclose:before{bottom:100%;top:auto}.ph.speccer.dissection.outline.enclose.right:after{left:calc(100% + var(--ph-speccer-pin-space) + var(--ph-speccer-line-width));right:auto}.ph.speccer.dissection.outline.enclose.right:before{left:100%;right:auto}.ph.speccer.dissection.outline.enclose.left:after{left:calc(var(--ph-speccer-line-width-negative) - var(--ph-speccer-pin-size) - var(--ph-speccer-pin-space));right:auto}.ph.speccer.dissection.outline.enclose.left:before{left:auto;right:100%}.ph.speccer.dissection.outline.enclose.top:after{bottom:auto;top:calc(var(--ph-speccer-line-width-negative) - var(--ph-speccer-pin-size) - var(--ph-speccer-pin-space))}.ph.speccer.dissection.outline.enclose.top:before{bottom:100%;top:auto}.ph.speccer.dissection.outline.enclose.bottom:after{bottom:auto;top:calc(100% + var(--ph-speccer-pin-space) + var(--ph-speccer-line-width))}.ph.speccer.dissection.outline.enclose.bottom:before{bottom:auto;top:100%}.ph.speccer.dissection.outline.full:not(.curly){background-color:initial;border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-bottom:none;border-radius:0;color:var(--ph-speccer-measure-color)}.ph.speccer.dissection.outline.full:not(.curly):after{top:calc(-8px - var(--ph-speccer-pin-space))}.ph.speccer.dissection.outline.full:not(.curly):before{bottom:100%}.ph.speccer.dissection.outline.full:not(.curly).right{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-left:none}.ph.speccer.dissection.outline.full:not(.curly).right:after{left:calc(8px + var(--ph-speccer-pin-space))}.ph.speccer.dissection.outline.full:not(.curly).right:before{left:100%;right:auto}.ph.speccer.dissection.outline.full:not(.curly).left{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-right:none}.ph.speccer.dissection.outline.full:not(.curly).left:after{left:calc(-8px - var(--ph-speccer-pin-space))}.ph.speccer.dissection.outline.full:not(.curly).left:before{left:auto;right:100%}.ph.speccer.dissection.outline.full:not(.curly).top{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-bottom:none}.ph.speccer.dissection.outline.full:not(.curly).top:after{top:calc(-8px - var(--ph-speccer-pin-space))}.ph.speccer.dissection.outline.full:not(.curly).top:before{bottom:100%}.ph.speccer.dissection.outline.full:not(.curly).bottom{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-top:none}.ph.speccer.dissection.outline.full:not(.curly).bottom:after{top:calc(8px + var(--ph-speccer-pin-space))}.ph.speccer.dissection.outline.full:not(.curly).bottom:before{top:100%}.ph.speccer.dissection.outline.bottom:after{height:var(--ph-speccer-pin-space);right:50%;top:calc(-100% - var(--ph-speccer-pin-space)/2);width:var(--ph-speccer-line-width)}.ph.speccer.dissection.outline.top:after,.ph.speccer.dissection.outline:after{height:var(--ph-speccer-pin-space);right:50%;top:100%;width:var(--ph-speccer-line-width)}[data-anatomy-section]{counter-reset:type}.ph.speccer.dissection.outline.full.left:not(.curly),.ph.speccer.dissection.outline.full.right:not(.curly){width:8px}.ph.speccer.dissection.outline.full.bottom:not(.curly),.ph.speccer.dissection.outline.full.top:not(.curly),.ph.speccer.dissection.outline.full:not(.curly){height:8px}.ph.speccer.dissection.outline.full.bottom:not(.curly):after,.ph.speccer.dissection.outline.full.left:not(.curly):after,.ph.speccer.dissection.outline.full.right:not(.curly):after,.ph.speccer.dissection.outline.full.top:not(.curly):after,.ph.speccer.dissection.outline.full:not(.curly):after{align-items:center;background-color:var(--ph-speccer-pin-color);border-radius:100%;color:var(--ph-speccer-color-text-light);content:attr(data-dissection-counter);display:flex;font-size:16px;height:var(--ph-speccer-pin-size);justify-content:center;line-height:150%;position:absolute;width:var(--ph-speccer-pin-size);z-index:100000}.ph.speccer.dissection.outline.full.left:not(.curly):after,.ph.speccer.dissection.outline.full.right:not(.curly):after{top:50%;transform:translateY(-50%)}.ph.speccer.dissection.outline.full.bottom:not(.curly):after,.ph.speccer.dissection.outline.full.top:not(.curly):after,.ph.speccer.dissection.outline.full:not(.curly):after{left:50%;transform:translateX(-50%)}.ph.speccer.dissection.outline.full.bottom:not(.curly):before,.ph.speccer.dissection.outline.full.left:not(.curly):before,.ph.speccer.dissection.outline.full.right:not(.curly):before,.ph.speccer.dissection.outline.full.top:not(.curly):before,.ph.speccer.dissection.outline.full:not(.curly):before{background-color:var(--ph-speccer-pin-color);content:"";display:block;position:absolute;z-index:100000}.ph.speccer.dissection.outline.full.left:not(.curly):before,.ph.speccer.dissection.outline.full.right:not(.curly):before{height:var(--ph-speccer-line-width);top:50%;transform:translateY(-50%);width:calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width))}.ph.speccer.dissection.outline.full.bottom:not(.curly):before,.ph.speccer.dissection.outline.full.top:not(.curly):before,.ph.speccer.dissection.outline.full:not(.curly):before{height:calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width));left:50%;transform:translateX(-50%);width:var(--ph-speccer-line-width)}.ph.speccer.dissection.outline.enclose.left,.ph.speccer.dissection.outline.enclose.right{width:8px}.ph.speccer.dissection.outline.enclose,.ph.speccer.dissection.outline.enclose.bottom,.ph.speccer.dissection.outline.enclose.top{height:8px}.ph.speccer.dissection.outline.enclose.bottom:after,.ph.speccer.dissection.outline.enclose.left:after,.ph.speccer.dissection.outline.enclose.right:after,.ph.speccer.dissection.outline.enclose.top:after,.ph.speccer.dissection.outline.enclose:after{align-items:center;background-color:var(--ph-speccer-pin-color);border-radius:100%;color:var(--ph-speccer-color-text-light);content:attr(data-dissection-counter);display:flex;font-size:16px;height:var(--ph-speccer-pin-size);justify-content:center;line-height:150%;position:absolute;width:var(--ph-speccer-pin-size);z-index:100000}.ph.speccer.dissection.outline.enclose.left:after,.ph.speccer.dissection.outline.enclose.right:after{top:50%;transform:translateY(-50%)}.ph.speccer.dissection.outline.enclose.bottom:after,.ph.speccer.dissection.outline.enclose.top:after,.ph.speccer.dissection.outline.enclose:after{left:50%;transform:translateX(-50%)}.ph.speccer.dissection.outline.enclose.bottom:before,.ph.speccer.dissection.outline.enclose.left:before,.ph.speccer.dissection.outline.enclose.right:before,.ph.speccer.dissection.outline.enclose.top:before,.ph.speccer.dissection.outline.enclose:before{background-color:var(--ph-speccer-pin-color);content:"";display:block;position:absolute;z-index:100000}.ph.speccer.dissection.outline.enclose.left:before,.ph.speccer.dissection.outline.enclose.right:before{height:var(--ph-speccer-line-width);top:50%;transform:translateY(-50%);width:calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width))}.ph.speccer.dissection.outline.enclose.bottom:before,.ph.speccer.dissection.outline.enclose.top:before,.ph.speccer.dissection.outline.enclose:before{height:calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width));left:50%;transform:translateX(-50%);width:var(--ph-speccer-line-width)}.ph.speccer.dissection.outline.subtle{background-color:var(--ph-speccer-color-text-light);border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);color:var(--ph-speccer-pin-color)}.ph.speccer.dissection.outline.subtle.bottom:after,.ph.speccer.dissection.outline.subtle.top:after{background-color:initial;border-right:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);width:0}.ph.speccer.dissection.outline.subtle.left:after,.ph.speccer.dissection.outline.subtle.right:after{background-color:initial;border-top:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);height:0}.ph.speccer.dissection.outline.full.subtle:not(.curly){background-color:initial}.ph.speccer.dissection.outline.full.subtle:not(.curly),.ph.speccer.dissection.outline.full.subtle:not(.curly).top{border:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);border-bottom:none}.ph.speccer.dissection.outline.full.subtle:not(.curly).bottom{border:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);border-top:none}.ph.speccer.dissection.outline.full.subtle:not(.curly).right{border:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);border-left:none}.ph.speccer.dissection.outline.full.subtle:not(.curly).left{border:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);border-right:none}.ph.speccer.dissection.outline.full.subtle:not(.curly):after{background-color:var(--ph-speccer-color-text-light);border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);color:var(--ph-speccer-pin-color);height:var(--ph-speccer-pin-size);width:var(--ph-speccer-pin-size)}.ph.speccer.dissection.outline.full.subtle:not(.curly).bottom:before,.ph.speccer.dissection.outline.full.subtle:not(.curly).top:before{background-color:initial;border-right:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);width:0}.ph.speccer.dissection.outline.full.subtle:not(.curly).left:before,.ph.speccer.dissection.outline.full.subtle:not(.curly).right:before{background-color:initial;border-top:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);height:0}.ph.speccer.dissection.outline.enclose.subtle{border-style:dashed}.ph.speccer.dissection.outline.enclose.subtle:after{background-color:var(--ph-speccer-color-text-light);border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);color:var(--ph-speccer-pin-color);height:var(--ph-speccer-pin-size);width:var(--ph-speccer-pin-size)}.ph.speccer.dissection.outline.enclose.subtle.bottom:before,.ph.speccer.dissection.outline.enclose.subtle.top:before{background-color:initial;border-right:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);width:0}.ph.speccer.dissection.outline.enclose.subtle.left:before,.ph.speccer.dissection.outline.enclose.subtle.right:before{background-color:initial;border-top:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);height:0}.ph.speccer.spacing{border:var(--ph-speccer-line-width) solid #0000;pointer-events:auto;transition:none}.ph.speccer.spacing:hover{border:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark)}.ph.speccer.spacing.margin{background-color:var(--ph-speccer-color-margin);color:var(--ph-speccer-color-text-dark)}.ph.speccer.spacing.padding{background-color:var(--ph-speccer-color-padding);color:var(--ph-speccer-spacing-color)}.ph.speccer.spacing.margin.bottom:after,.ph.speccer.spacing.margin.top:after{border-bottom:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);border-top:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);content:"";height:100%;left:40%;position:absolute;transition:none;width:9px}.ph.speccer.spacing.margin.bottom:before,.ph.speccer.spacing.margin.top:before{border-left:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);content:"";height:100%;left:40%;margin-left:4px;position:absolute;transition:none;width:0}.ph.speccer.spacing.margin.left:after,.ph.speccer.spacing.margin.right:after{border-left:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);border-right:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);content:"";height:9px;position:absolute;top:10%;transition:none;width:100%}.ph.speccer.spacing.margin.left:before,.ph.speccer.spacing.margin.right:before{border-top:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);content:"";height:0;margin-top:4px;position:absolute;top:10%;transition:none;width:100%}.ph.speccer.spacing.padding.bottom:after,.ph.speccer.spacing.padding.top:after{border-bottom:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);border-top:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);content:"";height:100%;left:40%;position:absolute;transition:none;width:9px}.ph.speccer.spacing.padding.bottom:before,.ph.speccer.spacing.padding.top:before{border-left:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);content:"";height:100%;left:40%;margin-left:4px;position:absolute;transition:none;width:0}.ph.speccer.spacing.padding.left:after,.ph.speccer.spacing.padding.right:after{border-left:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);border-right:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);content:"";height:9px;position:absolute;top:10%;transition:none;width:100%}.ph.speccer.spacing.padding.left:before,.ph.speccer.spacing.padding.right:before{border-top:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);content:"";height:0;margin-top:4px;position:absolute;top:10%;transition:none;width:100%}.ph.speccer.typography{background-color:var(--ph-speccer-typography-background-color);color:var(--ph-speccer-typography-color-text);display:block;font-size:10px;line-height:140%;max-width:none;padding:8px;text-align:left;width:auto}.ph.speccer.typography,.ph.speccer.typography:hover{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color)}.ph.speccer.typography:after{background-color:var(--ph-speccer-pin-color);content:"";display:block;position:absolute}.ph.speccer.typography.left:after,.ph.speccer.typography:after{left:100%}.ph.speccer.typography.left:after,.ph.speccer.typography.right:after,.ph.speccer.typography:after{height:var(--ph-speccer-line-width);top:50%;transform:translateY(-50%);width:var(--ph-speccer-pin-space)}.ph.speccer.typography.right:after{left:auto;right:100%}.ph.speccer.typography.top:after{top:100%}.ph.speccer.typography.bottom:after,.ph.speccer.typography.top:after{height:var(--ph-speccer-pin-space);left:50%;right:auto;transform:translateX(-50%);width:var(--ph-speccer-line-width)}.ph.speccer.typography.bottom:after{bottom:100%;top:auto}.ph.speccer.typography .speccer-styles{font-size:10px;line-height:140%;list-style:none;margin:0;padding:0 0 0 8px;width:100%}.ph.speccer.typography .speccer-styles .property{color:var(--ph-speccer-typography-color-property);font-size:10px;font-weight:400;margin:0;padding:0;text-align:left}.ph.speccer.typography .speccer-styles>li{border:none;color:var(--ph-speccer-typography-color-value);font-size:10px;font-weight:400;list-style:none;margin:0;padding:0;text-align:left}.ph.speccer.measure{display:flex}.ph.speccer.measure.width{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-bottom:none;color:var(--ph-speccer-measure-color);height:var(--ph-speccer-measure-size)}.ph.speccer.measure.width:after{content:attr(data-measure);position:absolute;top:calc(-100% - 10px)}.ph.speccer.measure.width.bottom{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-top:none;color:var(--ph-speccer-measure-color)}.ph.speccer.measure.width.bottom:after{content:attr(data-measure);position:absolute;top:calc(100% + 5px)}.ph.speccer.measure.width.top{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-bottom:none;color:var(--ph-speccer-measure-color)}.ph.speccer.measure.width.top:after{bottom:calc(100% + 5px);content:attr(data-measure);position:absolute}.ph.speccer.measure.height.left{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-right:none;color:var(--ph-speccer-measure-color);width:var(--ph-speccer-measure-size)}.ph.speccer.measure.height.left:after{content:attr(data-measure);left:calc(-100% - 20px - var(--ph-speccer-line-width));position:absolute;top:50%;transform:translateY(-50%) rotate(-90deg)}.ph.speccer.measure.height.right{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-left:none;color:var(--ph-speccer-measure-color);width:var(--ph-speccer-measure-size)}.ph.speccer.measure.height.right:after{content:attr(data-measure);left:calc(100% - var(--ph-speccer-measure-size));position:absolute;top:50%;transform:translateY(-50%) rotate(90deg)}.ph.speccer.measure.subtle.height.left,.ph.speccer.measure.subtle.height.right,.ph.speccer.measure.subtle.width.bottom,.ph.speccer.measure.subtle.width.top{border-style:dashed}.ph.speccer.measure.subtle.width.top{border-bottom:none}.ph.speccer.measure.subtle.width.bottom{border-top:none}.ph.speccer.measure.subtle.height.right{border-left:none}.ph.speccer.measure.subtle.height.left{border-right:none}.ph.speccer.mark{background-color:var(--ph-speccer-mark-background-color);border-color:var(--ph-speccer-mark-border-color);border-style:solid;border-width:1px;position:absolute} \ No newline at end of file +.ph-speccer.speccer{--ph-speccer-color-padding:#db6fff66;--ph-speccer-color-padding-hover:#db6fff;--ph-speccer-color-margin:#fff76f66;--ph-speccer-color-margin-hover:#fff76f;--ph-speccer-color-text-light:#fff;--ph-speccer-color-text-dark:#333;--ph-speccer-color-contrast:#ff3aa8;--ph-speccer-mark-background-color:#ff3aa833;--ph-speccer-mark-border-color:#ff3aa8;--ph-speccer-spacing-color:var(--ph-speccer-color-contrast);--ph-speccer-measure-color:red;--ph-speccer-pin-color:var(--ph-speccer-color-contrast);--ph-speccer-typography-background-color:#fff;--ph-speccer-typography-color-property:#3f85f2;--ph-speccer-typography-color-text:#57575b;--ph-speccer-typography-color-value:var(--ph-speccer-color-contrast);--ph-speccer-depth-opacity-400:0.4;--ph-speccer-font-family:"Menlo for Powerline","Menlo Regular for Powerline","DejaVu Sans Mono",Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;--ph-speccer-font-size:12px;--ph-speccer-line-height:12px;--ph-speccer-pin-size:24px;--ph-speccer-pin-space:48px;--ph-speccer-line-width:1px;--ph-speccer-line-width-negative:-1px;--ph-speccer-measure-size:8px}.ph-speccer.speccer,.ph-speccer.speccer:after,.ph-speccer.speccer:before,svg.ph-speccer{box-sizing:border-box;pointer-events:none;user-select:none}.ph-speccer.speccer:after,.ph-speccer.speccer:before,.ph-speccer.speccer:not(path){align-items:center;display:flex;font-family:var(--ph-speccer-font-family)!important;font-size:12px;justify-content:center;line-height:12px;position:absolute;z-index:99999}#ph-speccer-svg{height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%;z-index:3}svg.ph-speccer .ph-speccer.path{color:var(--ph-speccer-color-contrast,#ff3aa8)}.ph-speccer.speccer.dissection{align-items:center;background-color:var(--ph-speccer-pin-color);border-radius:100%;color:var(--ph-speccer-color-text-light);display:flex;font-family:sans-serif;font-size:16px;font-weight:400;height:var(--ph-speccer-pin-size);justify-content:center;line-height:150%;position:absolute;width:var(--ph-speccer-pin-size);z-index:100000}.ph-speccer.speccer.dissection.curly:after,.ph-speccer.speccer.dissection.svg:after{content:none!important}.ph-speccer.speccer.dissection.outline.left:after{right:auto}.ph-speccer.speccer.dissection.outline.right:after{left:auto}.ph-speccer.speccer.dissection:after{background-color:var(--ph-speccer-pin-color);content:"";height:var(--ph-speccer-pin-space);position:absolute;top:100%;width:var(--ph-speccer-line-width);z-index:99999}.ph-speccer.speccer.dissection.outline.left:after{height:var(--ph-speccer-line-width);left:100%;top:50%;width:var(--ph-speccer-pin-space)}.ph-speccer.speccer.dissection.outline.right:after{height:var(--ph-speccer-line-width);right:100%;top:50%;width:var(--ph-speccer-pin-space)}.ph-speccer.speccer.dissection.outline.enclose{background-color:initial;border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-radius:0;color:var(--ph-speccer-measure-color)}.ph-speccer.speccer.dissection.outline.enclose:after{bottom:auto;top:calc(var(--ph-speccer-line-width-negative) - var(--ph-speccer-pin-size) - var(--ph-speccer-pin-space))}.ph-speccer.speccer.dissection.outline.enclose:before{bottom:100%;top:auto}.ph-speccer.speccer.dissection.outline.enclose.right:after{left:calc(100% + var(--ph-speccer-pin-space) + var(--ph-speccer-line-width));right:auto}.ph-speccer.speccer.dissection.outline.enclose.right:before{left:100%;right:auto}.ph-speccer.speccer.dissection.outline.enclose.left:after{left:calc(var(--ph-speccer-line-width-negative) - var(--ph-speccer-pin-size) - var(--ph-speccer-pin-space));right:auto}.ph-speccer.speccer.dissection.outline.enclose.left:before{left:auto;right:100%}.ph-speccer.speccer.dissection.outline.enclose.top:after{bottom:auto;top:calc(var(--ph-speccer-line-width-negative) - var(--ph-speccer-pin-size) - var(--ph-speccer-pin-space))}.ph-speccer.speccer.dissection.outline.enclose.top:before{bottom:100%;top:auto}.ph-speccer.speccer.dissection.outline.enclose.bottom:after{bottom:auto;top:calc(100% + var(--ph-speccer-pin-space) + var(--ph-speccer-line-width))}.ph-speccer.speccer.dissection.outline.enclose.bottom:before{bottom:auto;top:100%}.ph-speccer.speccer.dissection.outline.full:not(.curly){background-color:initial;border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-bottom:none;border-radius:0;color:var(--ph-speccer-measure-color)}.ph-speccer.speccer.dissection.outline.full:not(.curly):after{top:calc(-8px - var(--ph-speccer-pin-space))}.ph-speccer.speccer.dissection.outline.full:not(.curly):before{bottom:100%}.ph-speccer.speccer.dissection.outline.full:not(.curly).right{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-left:none}.ph-speccer.speccer.dissection.outline.full:not(.curly).right:after{left:calc(8px + var(--ph-speccer-pin-space))}.ph-speccer.speccer.dissection.outline.full:not(.curly).right:before{left:100%;right:auto}.ph-speccer.speccer.dissection.outline.full:not(.curly).left{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-right:none}.ph-speccer.speccer.dissection.outline.full:not(.curly).left:after{left:calc(-8px - var(--ph-speccer-pin-space))}.ph-speccer.speccer.dissection.outline.full:not(.curly).left:before{left:auto;right:100%}.ph-speccer.speccer.dissection.outline.full:not(.curly).top{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-bottom:none}.ph-speccer.speccer.dissection.outline.full:not(.curly).top:after{top:calc(-8px - var(--ph-speccer-pin-space))}.ph-speccer.speccer.dissection.outline.full:not(.curly).top:before{bottom:100%}.ph-speccer.speccer.dissection.outline.full:not(.curly).bottom{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);border-top:none}.ph-speccer.speccer.dissection.outline.full:not(.curly).bottom:after{top:calc(8px + var(--ph-speccer-pin-space))}.ph-speccer.speccer.dissection.outline.full:not(.curly).bottom:before{top:100%}.ph-speccer.speccer.dissection.outline.bottom:after{height:var(--ph-speccer-pin-space);right:50%;top:calc(-100% - var(--ph-speccer-pin-space)/2);width:var(--ph-speccer-line-width)}.ph-speccer.speccer.dissection.outline.top:after,.ph-speccer.speccer.dissection.outline:after{height:var(--ph-speccer-pin-space);right:50%;top:100%;width:var(--ph-speccer-line-width)}[data-anatomy-section]{counter-reset:type}.ph-speccer.speccer.dissection.outline.full.left:not(.curly),.ph-speccer.speccer.dissection.outline.full.right:not(.curly){width:8px}.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly),.ph-speccer.speccer.dissection.outline.full.top:not(.curly),.ph-speccer.speccer.dissection.outline.full:not(.curly){height:8px}.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly):after,.ph-speccer.speccer.dissection.outline.full.left:not(.curly):after,.ph-speccer.speccer.dissection.outline.full.right:not(.curly):after,.ph-speccer.speccer.dissection.outline.full.top:not(.curly):after,.ph-speccer.speccer.dissection.outline.full:not(.curly):after{align-items:center;background-color:var(--ph-speccer-pin-color);border-radius:100%;color:var(--ph-speccer-color-text-light);content:attr(data-dissection-counter);display:flex;font-size:16px;height:var(--ph-speccer-pin-size);justify-content:center;line-height:150%;position:absolute;width:var(--ph-speccer-pin-size);z-index:100000}.ph-speccer.speccer.dissection.outline.full.left:not(.curly):after,.ph-speccer.speccer.dissection.outline.full.right:not(.curly):after{top:50%;transform:translateY(-50%)}.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly):after,.ph-speccer.speccer.dissection.outline.full.top:not(.curly):after,.ph-speccer.speccer.dissection.outline.full:not(.curly):after{left:50%;transform:translateX(-50%)}.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly):before,.ph-speccer.speccer.dissection.outline.full.left:not(.curly):before,.ph-speccer.speccer.dissection.outline.full.right:not(.curly):before,.ph-speccer.speccer.dissection.outline.full.top:not(.curly):before,.ph-speccer.speccer.dissection.outline.full:not(.curly):before{background-color:var(--ph-speccer-pin-color);content:"";display:block;position:absolute;z-index:100000}.ph-speccer.speccer.dissection.outline.full.left:not(.curly):before,.ph-speccer.speccer.dissection.outline.full.right:not(.curly):before{height:var(--ph-speccer-line-width);top:50%;transform:translateY(-50%);width:calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width))}.ph-speccer.speccer.dissection.outline.full.bottom:not(.curly):before,.ph-speccer.speccer.dissection.outline.full.top:not(.curly):before,.ph-speccer.speccer.dissection.outline.full:not(.curly):before{height:calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width));left:50%;transform:translateX(-50%);width:var(--ph-speccer-line-width)}.ph-speccer.speccer.dissection.outline.enclose.left,.ph-speccer.speccer.dissection.outline.enclose.right{width:8px}.ph-speccer.speccer.dissection.outline.enclose,.ph-speccer.speccer.dissection.outline.enclose.bottom,.ph-speccer.speccer.dissection.outline.enclose.top{height:8px}.ph-speccer.speccer.dissection.outline.enclose.bottom:after,.ph-speccer.speccer.dissection.outline.enclose.left:after,.ph-speccer.speccer.dissection.outline.enclose.right:after,.ph-speccer.speccer.dissection.outline.enclose.top:after,.ph-speccer.speccer.dissection.outline.enclose:after{align-items:center;background-color:var(--ph-speccer-pin-color);border-radius:100%;color:var(--ph-speccer-color-text-light);content:attr(data-dissection-counter);display:flex;font-size:16px;height:var(--ph-speccer-pin-size);justify-content:center;line-height:150%;position:absolute;width:var(--ph-speccer-pin-size);z-index:100000}.ph-speccer.speccer.dissection.outline.enclose.left:after,.ph-speccer.speccer.dissection.outline.enclose.right:after{top:50%;transform:translateY(-50%)}.ph-speccer.speccer.dissection.outline.enclose.bottom:after,.ph-speccer.speccer.dissection.outline.enclose.top:after,.ph-speccer.speccer.dissection.outline.enclose:after{left:50%;transform:translateX(-50%)}.ph-speccer.speccer.dissection.outline.enclose.bottom:before,.ph-speccer.speccer.dissection.outline.enclose.left:before,.ph-speccer.speccer.dissection.outline.enclose.right:before,.ph-speccer.speccer.dissection.outline.enclose.top:before,.ph-speccer.speccer.dissection.outline.enclose:before{background-color:var(--ph-speccer-pin-color);content:"";display:block;position:absolute;z-index:100000}.ph-speccer.speccer.dissection.outline.enclose.left:before,.ph-speccer.speccer.dissection.outline.enclose.right:before{height:var(--ph-speccer-line-width);top:50%;transform:translateY(-50%);width:calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width))}.ph-speccer.speccer.dissection.outline.enclose.bottom:before,.ph-speccer.speccer.dissection.outline.enclose.top:before,.ph-speccer.speccer.dissection.outline.enclose:before{height:calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width));left:50%;transform:translateX(-50%);width:var(--ph-speccer-line-width)}.ph-speccer.speccer.dissection.outline.subtle{background-color:var(--ph-speccer-color-text-light);border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);color:var(--ph-speccer-pin-color)}.ph-speccer.speccer.dissection.outline.subtle.bottom:after,.ph-speccer.speccer.dissection.outline.subtle.top:after{background-color:initial;border-right:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);width:0}.ph-speccer.speccer.dissection.outline.subtle.left:after,.ph-speccer.speccer.dissection.outline.subtle.right:after{background-color:initial;border-top:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);height:0}.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly){background-color:initial}.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly),.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).top{border:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);border-bottom:none}.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).bottom{border:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);border-top:none}.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).right{border:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);border-left:none}.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).left{border:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);border-right:none}.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly):after{background-color:var(--ph-speccer-color-text-light);border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);color:var(--ph-speccer-pin-color);height:var(--ph-speccer-pin-size);width:var(--ph-speccer-pin-size)}.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).bottom:before,.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).top:before{background-color:initial;border-right:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);width:0}.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).left:before,.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly).right:before{background-color:initial;border-top:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);height:0}.ph-speccer.speccer.dissection.outline.enclose.subtle{border-style:dashed}.ph-speccer.speccer.dissection.outline.enclose.subtle:after{background-color:var(--ph-speccer-color-text-light);border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color);color:var(--ph-speccer-pin-color);height:var(--ph-speccer-pin-size);width:var(--ph-speccer-pin-size)}.ph-speccer.speccer.dissection.outline.enclose.subtle.bottom:before,.ph-speccer.speccer.dissection.outline.enclose.subtle.top:before{background-color:initial;border-right:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);width:0}.ph-speccer.speccer.dissection.outline.enclose.subtle.left:before,.ph-speccer.speccer.dissection.outline.enclose.subtle.right:before{background-color:initial;border-top:var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color);height:0}.ph-speccer.speccer.spacing{border:var(--ph-speccer-line-width) solid #0000;pointer-events:auto;transition:none}.ph-speccer.speccer.spacing:hover{border:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark)}.ph-speccer.speccer.spacing.margin{background-color:var(--ph-speccer-color-margin);color:var(--ph-speccer-color-text-dark)}.ph-speccer.speccer.spacing.padding{background-color:var(--ph-speccer-color-padding);color:var(--ph-speccer-spacing-color)}.ph-speccer.speccer.spacing.margin.bottom:after,.ph-speccer.speccer.spacing.margin.top:after{border-bottom:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);border-top:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);content:"";height:100%;left:40%;position:absolute;transition:none;width:9px}.ph-speccer.speccer.spacing.margin.bottom:before,.ph-speccer.speccer.spacing.margin.top:before{border-left:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);content:"";height:100%;left:40%;margin-left:4px;position:absolute;transition:none;width:0}.ph-speccer.speccer.spacing.margin.left:after,.ph-speccer.speccer.spacing.margin.right:after{border-left:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);border-right:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);content:"";height:9px;position:absolute;top:10%;transition:none;width:100%}.ph-speccer.speccer.spacing.margin.left:before,.ph-speccer.speccer.spacing.margin.right:before{border-top:var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark);content:"";height:0;margin-top:4px;position:absolute;top:10%;transition:none;width:100%}.ph-speccer.speccer.spacing.padding.bottom:after,.ph-speccer.speccer.spacing.padding.top:after{border-bottom:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);border-top:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);content:"";height:100%;left:40%;position:absolute;transition:none;width:9px}.ph-speccer.speccer.spacing.padding.bottom:before,.ph-speccer.speccer.spacing.padding.top:before{border-left:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);content:"";height:100%;left:40%;margin-left:4px;position:absolute;transition:none;width:0}.ph-speccer.speccer.spacing.padding.left:after,.ph-speccer.speccer.spacing.padding.right:after{border-left:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);border-right:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);content:"";height:9px;position:absolute;top:10%;transition:none;width:100%}.ph-speccer.speccer.spacing.padding.left:before,.ph-speccer.speccer.spacing.padding.right:before{border-top:var(--ph-speccer-line-width) solid var(--ph-speccer-spacing-color);content:"";height:0;margin-top:4px;position:absolute;top:10%;transition:none;width:100%}.ph-speccer.speccer.typography{background-color:var(--ph-speccer-typography-background-color);color:var(--ph-speccer-typography-color-text);display:block;font-size:10px;line-height:140%;max-width:none;padding:8px;text-align:left;width:auto}.ph-speccer.speccer.typography,.ph-speccer.speccer.typography:hover{border:var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color)}.ph-speccer.speccer.typography:after{background-color:var(--ph-speccer-pin-color);content:"";display:block;position:absolute}.ph-speccer.speccer.typography.left:after,.ph-speccer.speccer.typography:after{height:var(--ph-speccer-line-width);left:100%;top:50%;transform:translateY(-50%);width:var(--ph-speccer-pin-space)}.ph-speccer.speccer.typography.right:after{height:var(--ph-speccer-line-width);left:auto;right:100%;top:50%;transform:translateY(-50%);width:var(--ph-speccer-pin-space)}.ph-speccer.speccer.typography.top:after{top:100%}.ph-speccer.speccer.typography.bottom:after,.ph-speccer.speccer.typography.top:after{height:var(--ph-speccer-pin-space);left:50%;right:auto;transform:translateX(-50%);width:var(--ph-speccer-line-width)}.ph-speccer.speccer.typography.bottom:after{bottom:100%;top:auto}.ph-speccer.speccer.typography .speccer-styles{font-size:10px;line-height:140%;list-style:none;margin:0;padding:0 0 0 8px;width:100%}.ph-speccer.speccer.typography .speccer-styles .property{color:var(--ph-speccer-typography-color-property);font-size:10px;font-weight:400;margin:0;padding:0;text-align:left}.ph-speccer.speccer.typography .speccer-styles>li{border:none;color:var(--ph-speccer-typography-color-value);font-size:10px;font-weight:400;list-style:none;margin:0;padding:0;text-align:left}.ph-speccer.speccer.measure{display:flex}.ph-speccer.speccer.measure.width{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-bottom:none;color:var(--ph-speccer-measure-color);height:var(--ph-speccer-measure-size)}.ph-speccer.speccer.measure.width:after{content:attr(data-measure);position:absolute;top:calc(-100% - 10px)}.ph-speccer.speccer.measure.width.bottom{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-top:none;color:var(--ph-speccer-measure-color)}.ph-speccer.speccer.measure.width.bottom:after{content:attr(data-measure);position:absolute;top:calc(100% + 5px)}.ph-speccer.speccer.measure.width.top{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-bottom:none;color:var(--ph-speccer-measure-color)}.ph-speccer.speccer.measure.width.top:after{bottom:calc(100% + 5px);content:attr(data-measure);position:absolute}.ph-speccer.speccer.measure.height.left{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-right:none;color:var(--ph-speccer-measure-color);width:var(--ph-speccer-measure-size)}.ph-speccer.speccer.measure.height.left:after{content:attr(data-measure);left:calc(-100% - 20px - var(--ph-speccer-line-width));position:absolute;top:50%;transform:translateY(-50%) rotate(-90deg)}.ph-speccer.speccer.measure.height.right{border:var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color);border-left:none;color:var(--ph-speccer-measure-color);width:var(--ph-speccer-measure-size)}.ph-speccer.speccer.measure.height.right:after{content:attr(data-measure);left:calc(100% - var(--ph-speccer-measure-size));position:absolute;top:50%;transform:translateY(-50%) rotate(90deg)}.ph-speccer.speccer.measure.subtle.height.left,.ph-speccer.speccer.measure.subtle.height.right,.ph-speccer.speccer.measure.subtle.width.bottom,.ph-speccer.speccer.measure.subtle.width.top{border-style:dashed}.ph-speccer.speccer.measure.subtle.width.top{border-bottom:none}.ph-speccer.speccer.measure.subtle.width.bottom{border-top:none}.ph-speccer.speccer.measure.subtle.height.right{border-left:none}.ph-speccer.speccer.measure.subtle.height.left{border-right:none}.ph-speccer.speccer.mark{background-color:var(--ph-speccer-mark-background-color);border-color:var(--ph-speccer-mark-border-color);border-style:solid;border-width:1px;position:absolute} \ No newline at end of file diff --git a/src/features/dissect/index.ts b/src/features/dissect/index.ts index e2111e8b..8242bf7d 100644 --- a/src/features/dissect/index.ts +++ b/src/features/dissect/index.ts @@ -48,7 +48,7 @@ export const create = ( _el.setAttribute('data-dissection-counter', textContent); } - const _class_names = cx('ph speccer dissection', _extra_class_names); + const _class_names = cx('ph-speccer speccer dissection', _extra_class_names); setClassNames(_el, _class_names); diff --git a/src/features/mark/index.ts b/src/features/mark/index.ts index 21bf62f4..29d3c0fe 100644 --- a/src/features/mark/index.ts +++ b/src/features/mark/index.ts @@ -19,7 +19,7 @@ import { getRec } from '../../utils/position'; */ export const create = (n = 'span'): HTMLElement => { const markElement = document.createElement(n); - const classNames = cx('ph speccer mark'); + const classNames = cx('ph-speccer speccer mark'); set(markElement, classNames); diff --git a/src/features/measure/index.ts b/src/features/measure/index.ts index 05190613..383f343c 100644 --- a/src/features/measure/index.ts +++ b/src/features/measure/index.ts @@ -37,7 +37,7 @@ export const create = ( _el.setAttribute('title', text + 'px'); _el.setAttribute('data-measure', parseInt(text + '', 10) + 'px'); - setClassNames(_el, `ph speccer measure ${area}`); + setClassNames(_el, `ph-speccer speccer measure ${area}`); return _el; }; diff --git a/src/features/spacing/index.ts b/src/features/spacing/index.ts index 231623a2..7b74b8fb 100644 --- a/src/features/spacing/index.ts +++ b/src/features/spacing/index.ts @@ -32,7 +32,7 @@ export const create = ( _el.appendChild(_text_content); _el.setAttribute('title', text + 'px'); - setClassNames(_el, 'ph speccer spacing'); + setClassNames(_el, 'ph-speccer speccer spacing'); return _el; }; diff --git a/src/features/typography/index.ts b/src/features/typography/index.ts index 54c8631b..33256029 100644 --- a/src/features/typography/index.ts +++ b/src/features/typography/index.ts @@ -29,7 +29,7 @@ export const create = (html: string, area: string | null): HTMLElement => { _extra_class_names[area] = true; } - const _class_names = cx('ph speccer typography', _extra_class_names); + const _class_names = cx('ph-speccer speccer typography', _extra_class_names); _el.innerHTML = html; diff --git a/src/styles/anatomy.styl b/src/styles/anatomy.styl index dad820dd..8e8f3a7a 100644 --- a/src/styles/anatomy.styl +++ b/src/styles/anatomy.styl @@ -1,4 +1,4 @@ -.ph.speccer.dissection +.ph-speccer.speccer.dissection font-family sans-serif height var(--ph-speccer-pin-size) width var(--ph-speccer-pin-size) @@ -16,7 +16,7 @@ -.ph.speccer.dissection::after +.ph-speccer.speccer.dissection::after content "" position absolute height var(--ph-speccer-pin-space) @@ -26,39 +26,39 @@ z-index 99999 -.ph.speccer.dissection.svg::after, -.ph.speccer.dissection.curly::after +.ph-speccer.speccer.dissection.svg::after, +.ph-speccer.speccer.dissection.curly::after content none !important -.ph.speccer.dissection.outline::after, -.ph.speccer.dissection.outline.top::after +.ph-speccer.speccer.dissection.outline::after, +.ph-speccer.speccer.dissection.outline.top::after height var(--ph-speccer-pin-space) width var(--ph-speccer-line-width) top 100% right 50% -.ph.speccer.dissection.outline.left::after +.ph-speccer.speccer.dissection.outline.left::after height var(--ph-speccer-line-width) width var(--ph-speccer-pin-space) top 50% left 100% right auto -.ph.speccer.dissection.outline.right::after +.ph-speccer.speccer.dissection.outline.right::after height var(--ph-speccer-line-width) width var(--ph-speccer-pin-space) top 50% left auto right 100% -.ph.speccer.dissection.outline.bottom::after +.ph-speccer.speccer.dissection.outline.bottom::after height var(--ph-speccer-pin-space) width var(--ph-speccer-line-width) top calc(-100% - (var(--ph-speccer-pin-space) / 2)) right 50% -.ph.speccer.dissection +.ph-speccer.speccer.dissection &::after content "" position absolute @@ -168,8 +168,8 @@ right 50% -.ph.speccer.dissection.outline.top::after, -.ph.speccer.dissection.outline::after +.ph-speccer.speccer.dissection.outline.top::after, +.ph-speccer.speccer.dissection.outline::after height var(--ph-speccer-pin-space) width var(--ph-speccer-line-width) top 100% @@ -178,22 +178,22 @@ [data-anatomy-section] counter-reset type -.ph.speccer.dissection.outline.full.right, -.ph.speccer.dissection.outline.full.left +.ph-speccer.speccer.dissection.outline.full.right, +.ph-speccer.speccer.dissection.outline.full.left &:not(.curly) width 8px -.ph.speccer.dissection.outline.full, -.ph.speccer.dissection.outline.full.top, -.ph.speccer.dissection.outline.full.bottom +.ph-speccer.speccer.dissection.outline.full, +.ph-speccer.speccer.dissection.outline.full.top, +.ph-speccer.speccer.dissection.outline.full.bottom &:not(.curly) height 8px -.ph.speccer.dissection.outline.full, -.ph.speccer.dissection.outline.full.right, -.ph.speccer.dissection.outline.full.left, -.ph.speccer.dissection.outline.full.top, -.ph.speccer.dissection.outline.full.bottom +.ph-speccer.speccer.dissection.outline.full, +.ph-speccer.speccer.dissection.outline.full.right, +.ph-speccer.speccer.dissection.outline.full.left, +.ph-speccer.speccer.dissection.outline.full.top, +.ph-speccer.speccer.dissection.outline.full.bottom &:not(.curly) &::after content attr(data-dissection-counter) @@ -210,26 +210,26 @@ font-size 16px z-index 100000 -.ph.speccer.dissection.outline.full.right, -.ph.speccer.dissection.outline.full.left +.ph-speccer.speccer.dissection.outline.full.right, +.ph-speccer.speccer.dissection.outline.full.left &:not(.curly) &::after top 50% transform translateY(-50%) -.ph.speccer.dissection.outline.full, -.ph.speccer.dissection.outline.full.top, -.ph.speccer.dissection.outline.full.bottom +.ph-speccer.speccer.dissection.outline.full, +.ph-speccer.speccer.dissection.outline.full.top, +.ph-speccer.speccer.dissection.outline.full.bottom &:not(.curly) &::after left 50% transform translateX(-50%) -.ph.speccer.dissection.outline.full, -.ph.speccer.dissection.outline.full.right, -.ph.speccer.dissection.outline.full.left, -.ph.speccer.dissection.outline.full.top, -.ph.speccer.dissection.outline.full.bottom +.ph-speccer.speccer.dissection.outline.full, +.ph-speccer.speccer.dissection.outline.full.right, +.ph-speccer.speccer.dissection.outline.full.left, +.ph-speccer.speccer.dissection.outline.full.top, +.ph-speccer.speccer.dissection.outline.full.bottom &:not(.curly) &::before content "" @@ -238,8 +238,8 @@ z-index 100000 display block -.ph.speccer.dissection.outline.full.right, -.ph.speccer.dissection.outline.full.left +.ph-speccer.speccer.dissection.outline.full.right, +.ph-speccer.speccer.dissection.outline.full.left &:not(.curly) &::before top 50% @@ -247,9 +247,9 @@ height var(--ph-speccer-line-width) width calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width)) -.ph.speccer.dissection.outline.full, -.ph.speccer.dissection.outline.full.top, -.ph.speccer.dissection.outline.full.bottom +.ph-speccer.speccer.dissection.outline.full, +.ph-speccer.speccer.dissection.outline.full.top, +.ph-speccer.speccer.dissection.outline.full.bottom &:not(.curly) &::before left 50% @@ -259,20 +259,20 @@ -.ph.speccer.dissection.outline.enclose.right, -.ph.speccer.dissection.outline.enclose.left +.ph-speccer.speccer.dissection.outline.enclose.right, +.ph-speccer.speccer.dissection.outline.enclose.left width 8px -.ph.speccer.dissection.outline.enclose, -.ph.speccer.dissection.outline.enclose.top, -.ph.speccer.dissection.outline.enclose.bottom +.ph-speccer.speccer.dissection.outline.enclose, +.ph-speccer.speccer.dissection.outline.enclose.top, +.ph-speccer.speccer.dissection.outline.enclose.bottom height 8px -.ph.speccer.dissection.outline.enclose::after, -.ph.speccer.dissection.outline.enclose.right::after, -.ph.speccer.dissection.outline.enclose.left::after, -.ph.speccer.dissection.outline.enclose.top::after, -.ph.speccer.dissection.outline.enclose.bottom::after +.ph-speccer.speccer.dissection.outline.enclose::after, +.ph-speccer.speccer.dissection.outline.enclose.right::after, +.ph-speccer.speccer.dissection.outline.enclose.left::after, +.ph-speccer.speccer.dissection.outline.enclose.top::after, +.ph-speccer.speccer.dissection.outline.enclose.bottom::after content attr(data-dissection-counter) height var(--ph-speccer-pin-size) width var(--ph-speccer-pin-size) @@ -287,45 +287,45 @@ font-size 16px z-index 100000 -.ph.speccer.dissection.outline.enclose.right::after, -.ph.speccer.dissection.outline.enclose.left::after +.ph-speccer.speccer.dissection.outline.enclose.right::after, +.ph-speccer.speccer.dissection.outline.enclose.left::after top 50% transform translateY(-50%) -.ph.speccer.dissection.outline.enclose::after, -.ph.speccer.dissection.outline.enclose.top::after, -.ph.speccer.dissection.outline.enclose.bottom::after +.ph-speccer.speccer.dissection.outline.enclose::after, +.ph-speccer.speccer.dissection.outline.enclose.top::after, +.ph-speccer.speccer.dissection.outline.enclose.bottom::after left 50% transform translateX(-50%) -.ph.speccer.dissection.outline.enclose::before, -.ph.speccer.dissection.outline.enclose.right::before, -.ph.speccer.dissection.outline.enclose.left::before, -.ph.speccer.dissection.outline.enclose.top::before, -.ph.speccer.dissection.outline.enclose.bottom::before +.ph-speccer.speccer.dissection.outline.enclose::before, +.ph-speccer.speccer.dissection.outline.enclose.right::before, +.ph-speccer.speccer.dissection.outline.enclose.left::before, +.ph-speccer.speccer.dissection.outline.enclose.top::before, +.ph-speccer.speccer.dissection.outline.enclose.bottom::before content "" position absolute background-color var(--ph-speccer-pin-color) z-index 100000 display block -.ph.speccer.dissection.outline.enclose.right::before, -.ph.speccer.dissection.outline.enclose.left::before +.ph-speccer.speccer.dissection.outline.enclose.right::before, +.ph-speccer.speccer.dissection.outline.enclose.left::before top 50% transform translateY(-50%) height var(--ph-speccer-line-width) width calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width)) -.ph.speccer.dissection.outline.enclose::before, -.ph.speccer.dissection.outline.enclose.top::before, -.ph.speccer.dissection.outline.enclose.bottom::before +.ph-speccer.speccer.dissection.outline.enclose::before, +.ph-speccer.speccer.dissection.outline.enclose.top::before, +.ph-speccer.speccer.dissection.outline.enclose.bottom::before left 50% transform translateX(-50%) width var(--ph-speccer-line-width) height calc(var(--ph-speccer-pin-space) + var(--ph-speccer-line-width)) -.ph.speccer.dissection.outline.subtle +.ph-speccer.speccer.dissection.outline.subtle border var(--ph-speccer-line-width) solid var(--ph-speccer-pin-color) background-color var(--ph-speccer-color-text-light) color var(--ph-speccer-pin-color) @@ -342,7 +342,7 @@ background-color transparent border-top var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color) -.ph.speccer.dissection.outline.full.subtle:not(.curly) +.ph-speccer.speccer.dissection.outline.full.subtle:not(.curly) border var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color) background-color transparent border-bottom none @@ -378,7 +378,7 @@ border-top var(--ph-speccer-line-width) dashed var(--ph-speccer-pin-color) -.ph.speccer.dissection.outline.enclose.subtle +.ph-speccer.speccer.dissection.outline.enclose.subtle border-style dashed &::after height var(--ph-speccer-pin-size) diff --git a/src/styles/index.styl b/src/styles/index.styl index 59033c1c..d7f6a292 100644 --- a/src/styles/index.styl +++ b/src/styles/index.styl @@ -25,7 +25,7 @@ $ph-speccer-line-width-negative = -1px $ph-speccer-measure-size = 8px -.ph.speccer +.ph-speccer.speccer --ph-speccer-color-padding: $ph-speccer-color-padding; --ph-speccer-color-padding-hover: $ph-speccer-color-padding-hover; --ph-speccer-color-margin: $ph-speccer-color-margin; @@ -53,18 +53,18 @@ $ph-speccer-measure-size = 8px --ph-speccer-measure-size: $ph-speccer-measure-size; -svg.ph, -.ph.speccer, -.ph.speccer::after, -.ph.speccer::before +svg.ph-speccer, +.ph-speccer.speccer, +.ph-speccer.speccer::after, +.ph-speccer.speccer::before pointer-events none user-select none box-sizing border-box -.ph.speccer:not(path), -.ph.speccer::after, -.ph.speccer::before +.ph-speccer.speccer:not(path), +.ph-speccer.speccer::after, +.ph-speccer.speccer::before font-family var(--ph-speccer-font-family) !important justify-content center align-items center @@ -83,7 +83,7 @@ svg.ph, pointer-events none z-index 3 -svg.ph .ph.path +svg.ph-speccer .ph-speccer.path color var(--ph-speccer-color-contrast,$ph-speccer-color-contrast ) @require './anatomy.styl' diff --git a/src/styles/mark.styl b/src/styles/mark.styl index 3532f9c8..15321a1f 100644 --- a/src/styles/mark.styl +++ b/src/styles/mark.styl @@ -1,4 +1,4 @@ -.ph.speccer.mark +.ph-speccer.speccer.mark background-color var(--ph-speccer-mark-background-color) border-color var(--ph-speccer-mark-border-color) border-width 1px diff --git a/src/styles/measure.styl b/src/styles/measure.styl index 06fd1039..f45f7ed5 100644 --- a/src/styles/measure.styl +++ b/src/styles/measure.styl @@ -1,7 +1,7 @@ -.ph.speccer.measure +.ph-speccer.speccer.measure display flex -.ph.speccer.measure +.ph-speccer.speccer.measure &.width color var(--ph-speccer-measure-color) border var(--ph-speccer-line-width) solid var(--ph-speccer-measure-color) @@ -9,7 +9,7 @@ height var(--ph-speccer-measure-size) -.ph.speccer.measure +.ph-speccer.speccer.measure &.width &::after content attr(data-measure) @@ -17,7 +17,7 @@ top calc(-100% - 10px) -.ph.speccer.measure +.ph-speccer.speccer.measure &.width &.bottom color var(--ph-speccer-measure-color) @@ -25,7 +25,7 @@ border-top none -.ph.speccer.measure +.ph-speccer.speccer.measure &.width &.bottom &::after @@ -34,7 +34,7 @@ top calc(100% + 5px) -.ph.speccer.measure +.ph-speccer.speccer.measure &.width &.top color var(--ph-speccer-measure-color) @@ -42,7 +42,7 @@ border-bottom none -.ph.speccer.measure +.ph-speccer.speccer.measure &.width &.top &::after @@ -51,7 +51,7 @@ bottom calc(100% + 5px) -.ph.speccer.measure +.ph-speccer.speccer.measure &.height &.left color var(--ph-speccer-measure-color) @@ -60,7 +60,7 @@ width var(--ph-speccer-measure-size) -.ph.speccer.measure +.ph-speccer.speccer.measure &.height &.left &::after @@ -71,7 +71,7 @@ transform translateY(-50%) rotate(-90deg) -.ph.speccer.measure +.ph-speccer.speccer.measure &.height &.right color var(--ph-speccer-measure-color) @@ -80,7 +80,7 @@ width var(--ph-speccer-measure-size) -.ph.speccer.measure +.ph-speccer.speccer.measure &.height &.right &::after @@ -91,13 +91,13 @@ transform translateY(-50%) rotate(90deg) -.ph.speccer.measure.subtle.width.top, -.ph.speccer.measure.subtle.width.bottom, -.ph.speccer.measure.subtle.height.right, -.ph.speccer.measure.subtle.height.left +.ph-speccer.speccer.measure.subtle.width.top, +.ph-speccer.speccer.measure.subtle.width.bottom, +.ph-speccer.speccer.measure.subtle.height.right, +.ph-speccer.speccer.measure.subtle.height.left border-style dashed -.ph.speccer.measure.subtle +.ph-speccer.speccer.measure.subtle &.width.top border-bottom none &.width.bottom diff --git a/src/styles/spacing.styl b/src/styles/spacing.styl index da956aef..10354dd8 100644 --- a/src/styles/spacing.styl +++ b/src/styles/spacing.styl @@ -1,4 +1,4 @@ -.ph.speccer.spacing +.ph-speccer.speccer.spacing pointer-events auto transition none border var(--ph-speccer-line-width) solid transparent @@ -6,19 +6,19 @@ border var(--ph-speccer-line-width) solid var(--ph-speccer-color-text-dark) -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.margin background-color var(--ph-speccer-color-margin) color var(--ph-speccer-color-text-dark) -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.padding background-color var(--ph-speccer-color-padding) color var(--ph-speccer-spacing-color) -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.margin &.bottom, &.top @@ -33,7 +33,7 @@ left 40% -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.margin &.bottom, &.top @@ -48,7 +48,7 @@ left 40% -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.margin &.left, &.right @@ -63,7 +63,7 @@ top 10% -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.margin &.left, &.right @@ -78,7 +78,7 @@ top 10% -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.padding &.bottom, &.top @@ -93,7 +93,7 @@ left 40% -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.padding &.bottom, &.top @@ -108,7 +108,7 @@ left 40% -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.padding &.left, &.right @@ -123,7 +123,7 @@ top 10% -.ph.speccer.spacing +.ph-speccer.speccer.spacing &.padding &.left, &.right diff --git a/src/styles/typography.styl b/src/styles/typography.styl index 431d3a92..0d669ea0 100644 --- a/src/styles/typography.styl +++ b/src/styles/typography.styl @@ -1,4 +1,4 @@ -.ph.speccer.typography +.ph-speccer.speccer.typography background-color var(--ph-speccer-typography-background-color) color var(--ph-speccer-typography-color-text) font-size 10px