mirror of
https://github.com/Theodor-Springmann-Stiftung/lenz-web.git
synced 2025-10-29 09:15:33 +00:00
entwurf kennzeichnen
This commit is contained in:
5
helpers/functions/math.go
Normal file
5
helpers/functions/math.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package functions
|
||||||
|
|
||||||
|
func Minus(a, b int) int {
|
||||||
|
return a - b
|
||||||
|
}
|
||||||
@@ -124,6 +124,9 @@ func (e *Engine) funcs() error {
|
|||||||
e.AddFunc("Today", functions.Today)
|
e.AddFunc("Today", functions.Today)
|
||||||
e.AddFunc("GetMonth", functions.GetMonth)
|
e.AddFunc("GetMonth", functions.GetMonth)
|
||||||
|
|
||||||
|
// Math
|
||||||
|
e.AddFunc("Minus", functions.Minus)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15370,76 +15370,6 @@ class Previewer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
EventEmitter(Previewer.prototype);
|
EventEmitter(Previewer.prototype);
|
||||||
const ATTR_XSLT_ONLOAD = "script[xslt-onload]", ATTR_XSLT_TEMPLATE = "xslt-template", ATTR_XSLT_STATE = "xslt-transformed", SCROLL_BUTTON_ELEMENT = "scroll-button", TOOLTIP_ELEMENT = "tool-tip";
|
|
||||||
var ji, oa, ro;
|
|
||||||
class XSLTParseProcess {
|
|
||||||
constructor() {
|
|
||||||
Da(this, oa);
|
|
||||||
Da(this, ji);
|
|
||||||
eo(this, ji, /* @__PURE__ */ new Map());
|
|
||||||
}
|
|
||||||
setup() {
|
|
||||||
let ze = htmx.findAll(ATTR_XSLT_ONLOAD);
|
|
||||||
for (let Wr of ze)
|
|
||||||
to(this, oa, ro).call(this, Wr);
|
|
||||||
}
|
|
||||||
hookupHTMX() {
|
|
||||||
htmx.on("htmx:load", (ze) => {
|
|
||||||
this.setup();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ji = new WeakMap(), oa = new WeakSet(), ro = function(ze) {
|
|
||||||
if (ze.getAttribute(ATTR_XSLT_STATE) === "true" || !ze.hasAttribute(ATTR_XSLT_TEMPLATE))
|
|
||||||
return;
|
|
||||||
let Wr = "#" + ze.getAttribute(ATTR_XSLT_TEMPLATE), Yr = Na(this, ji).get(Wr);
|
|
||||||
if (!Yr) {
|
|
||||||
let en = htmx.find(Wr);
|
|
||||||
if (en) {
|
|
||||||
let tn = en.innerHTML ? new DOMParser().parseFromString(en.innerHTML, "application/xml") : en.contentDocument;
|
|
||||||
Yr = new XSLTProcessor(), Yr.importStylesheet(tn), Na(this, ji).set(Wr, Yr);
|
|
||||||
} else
|
|
||||||
throw new Error("Unknown XSLT template: " + Wr);
|
|
||||||
}
|
|
||||||
let Qr = new DOMParser().parseFromString(ze.innerHTML, "application/xml"), Kr = Yr.transformToFragment(Qr, document), Zr = new XMLSerializer().serializeToString(Kr);
|
|
||||||
ze.outerHTML = Zr;
|
|
||||||
};
|
|
||||||
class ScrollButton extends HTMLElement {
|
|
||||||
constructor() {
|
|
||||||
super(), this.handleScroll = this.handleScroll.bind(this), this.scrollToTop = this.scrollToTop.bind(this);
|
|
||||||
}
|
|
||||||
connectedCallback() {
|
|
||||||
this.innerHTML = `
|
|
||||||
<button
|
|
||||||
class="
|
|
||||||
scroll-to-top
|
|
||||||
fixed bottom-5 right-5
|
|
||||||
hidden
|
|
||||||
bg-gray-800 text-white
|
|
||||||
p-2
|
|
||||||
rounded-md
|
|
||||||
cursor-pointer
|
|
||||||
text-2xl
|
|
||||||
hover:opacity-80
|
|
||||||
transition-opacity
|
|
||||||
border-0
|
|
||||||
"
|
|
||||||
aria-label="Scroll to top"
|
|
||||||
>
|
|
||||||
<i class="ri-arrow-up-double-line"></i>
|
|
||||||
</button>
|
|
||||||
`, this._button = this.querySelector(".scroll-to-top"), window.addEventListener("scroll", this.handleScroll), this._button.addEventListener("click", this.scrollToTop);
|
|
||||||
}
|
|
||||||
disconnectedCallback() {
|
|
||||||
window.removeEventListener("scroll", this.handleScroll), this._button.removeEventListener("click", this.scrollToTop);
|
|
||||||
}
|
|
||||||
handleScroll() {
|
|
||||||
(window.scrollY || document.documentElement.scrollTop) > 300 ? this._button.classList.remove("hidden") : this._button.classList.add("hidden");
|
|
||||||
}
|
|
||||||
scrollToTop() {
|
|
||||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class ToolTip extends HTMLElement {
|
class ToolTip extends HTMLElement {
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
return ["position", "timeout"];
|
return ["position", "timeout"];
|
||||||
@@ -15448,14 +15378,7 @@ class ToolTip extends HTMLElement {
|
|||||||
super(), this._tooltipBox = null, this._timeout = 200, this._hideTimeout = null, this._hiddenTimeout = null;
|
super(), this._tooltipBox = null, this._timeout = 200, this._hideTimeout = null, this._hiddenTimeout = null;
|
||||||
}
|
}
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this.classList.add(
|
this.classList.add("relative", "block", "leading-none", "[&>*]:leading-normal");
|
||||||
"w-full",
|
|
||||||
"h-full",
|
|
||||||
"relative",
|
|
||||||
"block",
|
|
||||||
"leading-none",
|
|
||||||
"[&>*]:leading-normal"
|
|
||||||
);
|
|
||||||
const ze = this.querySelector(".data-tip"), Wr = ze ? ze.innerHTML : "Tooltip";
|
const ze = this.querySelector(".data-tip"), Wr = ze ? ze.innerHTML : "Tooltip";
|
||||||
ze && ze.classList.add("hidden"), this._tooltipBox = document.createElement("div"), this._tooltipBox.innerHTML = Wr, this._tooltipBox.className = [
|
ze && ze.classList.add("hidden"), this._tooltipBox = document.createElement("div"), this._tooltipBox.innerHTML = Wr, this._tooltipBox.className = [
|
||||||
"opacity-0",
|
"opacity-0",
|
||||||
@@ -15548,6 +15471,76 @@ class ToolTip extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const ATTR_XSLT_ONLOAD = "script[xslt-onload]", ATTR_XSLT_TEMPLATE = "xslt-template", ATTR_XSLT_STATE = "xslt-transformed", SCROLL_BUTTON_ELEMENT = "scroll-button", TOOLTIP_ELEMENT = "tool-tip";
|
||||||
|
var ji, oa, ro;
|
||||||
|
class XSLTParseProcess {
|
||||||
|
constructor() {
|
||||||
|
Da(this, oa);
|
||||||
|
Da(this, ji);
|
||||||
|
eo(this, ji, /* @__PURE__ */ new Map());
|
||||||
|
}
|
||||||
|
setup() {
|
||||||
|
let ze = htmx.findAll(ATTR_XSLT_ONLOAD);
|
||||||
|
for (let Wr of ze)
|
||||||
|
to(this, oa, ro).call(this, Wr);
|
||||||
|
}
|
||||||
|
hookupHTMX() {
|
||||||
|
htmx.on("htmx:load", (ze) => {
|
||||||
|
this.setup();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ji = new WeakMap(), oa = new WeakSet(), ro = function(ze) {
|
||||||
|
if (ze.getAttribute(ATTR_XSLT_STATE) === "true" || !ze.hasAttribute(ATTR_XSLT_TEMPLATE))
|
||||||
|
return;
|
||||||
|
let Wr = "#" + ze.getAttribute(ATTR_XSLT_TEMPLATE), Yr = Na(this, ji).get(Wr);
|
||||||
|
if (!Yr) {
|
||||||
|
let en = htmx.find(Wr);
|
||||||
|
if (en) {
|
||||||
|
let tn = en.innerHTML ? new DOMParser().parseFromString(en.innerHTML, "application/xml") : en.contentDocument;
|
||||||
|
Yr = new XSLTProcessor(), Yr.importStylesheet(tn), Na(this, ji).set(Wr, Yr);
|
||||||
|
} else
|
||||||
|
throw new Error("Unknown XSLT template: " + Wr);
|
||||||
|
}
|
||||||
|
let Qr = new DOMParser().parseFromString(ze.innerHTML, "application/xml"), Kr = Yr.transformToFragment(Qr, document), Zr = new XMLSerializer().serializeToString(Kr);
|
||||||
|
ze.outerHTML = Zr;
|
||||||
|
};
|
||||||
|
class ScrollButton extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super(), this.handleScroll = this.handleScroll.bind(this), this.scrollToTop = this.scrollToTop.bind(this);
|
||||||
|
}
|
||||||
|
connectedCallback() {
|
||||||
|
this.innerHTML = `
|
||||||
|
<button
|
||||||
|
class="
|
||||||
|
scroll-to-top
|
||||||
|
fixed bottom-5 right-5
|
||||||
|
hidden
|
||||||
|
bg-gray-800 text-white
|
||||||
|
p-2
|
||||||
|
rounded-md
|
||||||
|
cursor-pointer
|
||||||
|
text-2xl
|
||||||
|
hover:opacity-80
|
||||||
|
transition-opacity
|
||||||
|
border-0
|
||||||
|
"
|
||||||
|
aria-label="Scroll to top"
|
||||||
|
>
|
||||||
|
<i class="ri-arrow-up-double-line"></i>
|
||||||
|
</button>
|
||||||
|
`, this._button = this.querySelector(".scroll-to-top"), window.addEventListener("scroll", this.handleScroll), this._button.addEventListener("click", this.scrollToTop);
|
||||||
|
}
|
||||||
|
disconnectedCallback() {
|
||||||
|
window.removeEventListener("scroll", this.handleScroll), this._button.removeEventListener("click", this.scrollToTop);
|
||||||
|
}
|
||||||
|
handleScroll() {
|
||||||
|
(window.scrollY || document.documentElement.scrollTop) > 300 ? this._button.classList.remove("hidden") : this._button.classList.add("hidden");
|
||||||
|
}
|
||||||
|
scrollToTop() {
|
||||||
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
|
}
|
||||||
|
}
|
||||||
function Startup() {
|
function Startup() {
|
||||||
let Gr = null;
|
let Gr = null;
|
||||||
const ze = [];
|
const ze = [];
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -6,31 +6,47 @@
|
|||||||
<div class="mr-4 text-6xl">{{ $model.Letter }}</div>
|
<div class="mr-4 text-6xl">{{ $model.Letter }}</div>
|
||||||
-->
|
-->
|
||||||
<div class="pt-0.5">
|
<div class="pt-0.5">
|
||||||
<div class="italic">{{ $model.Earliest.Text -}}</div>
|
<div class="flex flex-row">
|
||||||
|
<div class="italic">{{ $model.Earliest.Text -}}</div>
|
||||||
|
{{- if $model.IsDraft.IsTrue -}}
|
||||||
|
<tool-tip position="top">
|
||||||
|
<div class="ml-3 text-gray-500 align-middle"><i class="ri-draft-line"></i></div>
|
||||||
|
<div class="data-tip">Entwurf</div>
|
||||||
|
</tool-tip>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
{{- range $sr := $model.SendReceivedPairs -}}
|
{{- range $sr := $model.SendReceivedPairs -}}
|
||||||
<div class="flex flex-row">
|
<div class="flex flex-row">
|
||||||
<div>
|
<div>
|
||||||
{{- range $i, $p := $sr.Sent.Persons -}}
|
{{- range $i, $p := $sr.Sent.Persons -}}
|
||||||
<div class="inline-block">
|
{{ if and $i (eq $i (Minus (len $sr.Sent.Persons) 1)) }}
|
||||||
{{- if $i -}}
|
und
|
||||||
,
|
{{ else if $i }}
|
||||||
{{ end -}}
|
,
|
||||||
{{- $person := Person $p.Reference -}}
|
{{ end }}
|
||||||
{{- $person.Name -}}
|
{{- $person := Person $p.Reference -}}
|
||||||
</div>
|
{{- $person.Name -}}
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
<div class="mx-3">
|
||||||
|
{{- if $model.IsDraft.IsTrue -}}
|
||||||
|
<div class="diagonal-strike">
|
||||||
|
<i class="ri-arrow-right-long-line"></i>
|
||||||
|
</div>
|
||||||
|
{{- else -}}
|
||||||
|
<i class="ri-arrow-right-long-line"></i>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
<div class="mx-2"><i class="ri-arrow-right-long-line"></i></div>
|
|
||||||
{{- if $sr.Received -}}
|
{{- if $sr.Received -}}
|
||||||
<div>
|
<div>
|
||||||
{{- range $i, $p := $sr.Received.Persons -}}
|
{{- range $i, $p := $sr.Received.Persons -}}
|
||||||
<div class="inline-block">
|
{{ if and $i (eq $i (Minus (len $sr.Received.Persons) 1)) }}
|
||||||
{{- if $i -}}
|
und
|
||||||
,
|
{{ else if $i }}
|
||||||
{{ end -}}
|
,
|
||||||
{{- $person := Person $p.Reference -}}
|
{{ end }}
|
||||||
{{- $person.Name -}}
|
{{- $person := Person $p.Reference -}}
|
||||||
</div>
|
{{- $person.Name -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import "../public/js/alpine.min.js";
|
|||||||
import "../public/js/htmx.min.js";
|
import "../public/js/htmx.min.js";
|
||||||
import "../public/js/htmx-response-targets.js";
|
import "../public/js/htmx-response-targets.js";
|
||||||
import { Previewer } from "pagedjs";
|
import { Previewer } from "pagedjs";
|
||||||
|
import { ToolTip } from "./tool-tip.js";
|
||||||
|
|
||||||
const ATTR_XSLT_ONLOAD = "script[xslt-onload]";
|
const ATTR_XSLT_ONLOAD = "script[xslt-onload]";
|
||||||
const ATTR_XSLT_TEMPLATE = "xslt-template";
|
const ATTR_XSLT_TEMPLATE = "xslt-template";
|
||||||
@@ -157,152 +158,6 @@ class ScrollButton extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToolTip extends HTMLElement {
|
|
||||||
static get observedAttributes() {
|
|
||||||
return ["position", "timeout"];
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this._tooltipBox = null;
|
|
||||||
this._timeout = 200;
|
|
||||||
this._hideTimeout = null;
|
|
||||||
this._hiddenTimeout = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
connectedCallback() {
|
|
||||||
this.classList.add(
|
|
||||||
"w-full",
|
|
||||||
"h-full",
|
|
||||||
"relative",
|
|
||||||
"block",
|
|
||||||
"leading-none",
|
|
||||||
"[&>*]:leading-normal",
|
|
||||||
);
|
|
||||||
const dataTipElem = this.querySelector(".data-tip");
|
|
||||||
const tipContent = dataTipElem ? dataTipElem.innerHTML : "Tooltip";
|
|
||||||
|
|
||||||
if (dataTipElem) {
|
|
||||||
dataTipElem.classList.add("hidden");
|
|
||||||
}
|
|
||||||
|
|
||||||
this._tooltipBox = document.createElement("div");
|
|
||||||
this._tooltipBox.innerHTML = tipContent;
|
|
||||||
this._tooltipBox.className = [
|
|
||||||
"opacity-0",
|
|
||||||
"hidden",
|
|
||||||
"absolute",
|
|
||||||
"px-2",
|
|
||||||
"py-1",
|
|
||||||
"text-sm",
|
|
||||||
"text-white",
|
|
||||||
"bg-gray-900",
|
|
||||||
"rounded",
|
|
||||||
"shadow",
|
|
||||||
"z-10",
|
|
||||||
"whitespace-nowrap",
|
|
||||||
"transition-all",
|
|
||||||
"duration-200",
|
|
||||||
"font-sans",
|
|
||||||
].join(" ");
|
|
||||||
|
|
||||||
this.appendChild(this._tooltipBox);
|
|
||||||
|
|
||||||
this._updatePosition();
|
|
||||||
|
|
||||||
this.addEventListener("mouseenter", () => this._showTooltip());
|
|
||||||
this.addEventListener("mouseleave", () => this._hideTooltip());
|
|
||||||
}
|
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
|
||||||
if (name === "position" && this._tooltipBox) {
|
|
||||||
this._updatePosition();
|
|
||||||
}
|
|
||||||
if (name === "timeout" && newValue) {
|
|
||||||
this._timeout = parseInt(newValue) || 200;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_showTooltip() {
|
|
||||||
clearTimeout(this._hideTimeout);
|
|
||||||
clearTimeout(this._hiddenTimeout);
|
|
||||||
this._tooltipBox.classList.remove("hidden");
|
|
||||||
setTimeout(() => {
|
|
||||||
this._tooltipBox.classList.remove("opacity-0");
|
|
||||||
this._tooltipBox.classList.add("opacity-100");
|
|
||||||
}, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
_hideTooltip() {
|
|
||||||
this._hideTimeout = setTimeout(() => {
|
|
||||||
this._tooltipBox.classList.remove("opacity-100");
|
|
||||||
this._tooltipBox.classList.add("opacity-0");
|
|
||||||
this._hiddenTimeout = setTimeout(() => {
|
|
||||||
this._tooltipBox.classList.add("hidden");
|
|
||||||
}, this._timeout + 100);
|
|
||||||
}, this._timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
_updatePosition() {
|
|
||||||
this._tooltipBox.classList.remove(
|
|
||||||
"bottom-full",
|
|
||||||
"left-1/2",
|
|
||||||
"-translate-x-1/2",
|
|
||||||
"mb-2", // top
|
|
||||||
"top-full",
|
|
||||||
"mt-2", // bottom
|
|
||||||
"right-full",
|
|
||||||
"-translate-y-1/2",
|
|
||||||
"mr-2",
|
|
||||||
"top-1/2", // left
|
|
||||||
"left-full",
|
|
||||||
"ml-2", // right
|
|
||||||
);
|
|
||||||
|
|
||||||
const pos = this.getAttribute("position") || "top";
|
|
||||||
|
|
||||||
switch (pos) {
|
|
||||||
case "bottom":
|
|
||||||
this._tooltipBox.classList.add(
|
|
||||||
"top-full",
|
|
||||||
"left-1/2",
|
|
||||||
"transform",
|
|
||||||
"-translate-x-1/2",
|
|
||||||
"mt-0.5",
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "left":
|
|
||||||
this._tooltipBox.classList.add(
|
|
||||||
"right-full",
|
|
||||||
"top-1/2",
|
|
||||||
"transform",
|
|
||||||
"-translate-y-1/2",
|
|
||||||
"mr-0.5",
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "right":
|
|
||||||
this._tooltipBox.classList.add(
|
|
||||||
"left-full",
|
|
||||||
"top-1/2",
|
|
||||||
"transform",
|
|
||||||
"-translate-y-1/2",
|
|
||||||
"ml-0.5",
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "top":
|
|
||||||
default:
|
|
||||||
// top as default
|
|
||||||
this._tooltipBox.classList.add(
|
|
||||||
"bottom-full",
|
|
||||||
"left-1/2",
|
|
||||||
"transform",
|
|
||||||
"-translate-x-1/2",
|
|
||||||
"mb-0.5",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Startup() {
|
function Startup() {
|
||||||
let pagedPreviewer = null;
|
let pagedPreviewer = null;
|
||||||
const positionedIntervals = [];
|
const positionedIntervals = [];
|
||||||
|
|||||||
@@ -87,6 +87,26 @@
|
|||||||
@apply font-bold text-red-500;
|
@apply font-bold text-red-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.diagonal-strike {
|
||||||
|
@apply relative inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diagonal-strike::before {
|
||||||
|
@apply border-slate-50 border-t-[3px];
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
left: 10%;
|
||||||
|
top: 50%;
|
||||||
|
right: 0;
|
||||||
|
width: 60%;
|
||||||
|
|
||||||
|
-webkit-transform: rotate(-65deg);
|
||||||
|
-moz-transform: rotate(-65deg);
|
||||||
|
-ms-transform: rotate(-65deg);
|
||||||
|
-o-transform: rotate(-65deg);
|
||||||
|
transform: rotate(-65deg);
|
||||||
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
@apply font-serif relative;
|
@apply font-serif relative;
|
||||||
}
|
}
|
||||||
|
|||||||
138
views/transform/tool-tip.js
Normal file
138
views/transform/tool-tip.js
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
export class ToolTip extends HTMLElement {
|
||||||
|
static get observedAttributes() {
|
||||||
|
return ["position", "timeout"];
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._tooltipBox = null;
|
||||||
|
this._timeout = 200;
|
||||||
|
this._hideTimeout = null;
|
||||||
|
this._hiddenTimeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.classList.add("relative", "block", "leading-none", "[&>*]:leading-normal");
|
||||||
|
const dataTipElem = this.querySelector(".data-tip");
|
||||||
|
const tipContent = dataTipElem ? dataTipElem.innerHTML : "Tooltip";
|
||||||
|
|
||||||
|
if (dataTipElem) {
|
||||||
|
dataTipElem.classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
this._tooltipBox = document.createElement("div");
|
||||||
|
this._tooltipBox.innerHTML = tipContent;
|
||||||
|
this._tooltipBox.className = [
|
||||||
|
"opacity-0",
|
||||||
|
"hidden",
|
||||||
|
"absolute",
|
||||||
|
"px-2",
|
||||||
|
"py-1",
|
||||||
|
"text-sm",
|
||||||
|
"text-white",
|
||||||
|
"bg-gray-900",
|
||||||
|
"rounded",
|
||||||
|
"shadow",
|
||||||
|
"z-10",
|
||||||
|
"whitespace-nowrap",
|
||||||
|
"transition-all",
|
||||||
|
"duration-200",
|
||||||
|
"font-sans",
|
||||||
|
].join(" ");
|
||||||
|
|
||||||
|
this.appendChild(this._tooltipBox);
|
||||||
|
|
||||||
|
this._updatePosition();
|
||||||
|
|
||||||
|
this.addEventListener("mouseenter", () => this._showTooltip());
|
||||||
|
this.addEventListener("mouseleave", () => this._hideTooltip());
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeChangedCallback(name, oldValue, newValue) {
|
||||||
|
if (name === "position" && this._tooltipBox) {
|
||||||
|
this._updatePosition();
|
||||||
|
}
|
||||||
|
if (name === "timeout" && newValue) {
|
||||||
|
this._timeout = parseInt(newValue) || 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_showTooltip() {
|
||||||
|
clearTimeout(this._hideTimeout);
|
||||||
|
clearTimeout(this._hiddenTimeout);
|
||||||
|
this._tooltipBox.classList.remove("hidden");
|
||||||
|
setTimeout(() => {
|
||||||
|
this._tooltipBox.classList.remove("opacity-0");
|
||||||
|
this._tooltipBox.classList.add("opacity-100");
|
||||||
|
}, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
_hideTooltip() {
|
||||||
|
this._hideTimeout = setTimeout(() => {
|
||||||
|
this._tooltipBox.classList.remove("opacity-100");
|
||||||
|
this._tooltipBox.classList.add("opacity-0");
|
||||||
|
this._hiddenTimeout = setTimeout(() => {
|
||||||
|
this._tooltipBox.classList.add("hidden");
|
||||||
|
}, this._timeout + 100);
|
||||||
|
}, this._timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updatePosition() {
|
||||||
|
this._tooltipBox.classList.remove(
|
||||||
|
"bottom-full",
|
||||||
|
"left-1/2",
|
||||||
|
"-translate-x-1/2",
|
||||||
|
"mb-2", // top
|
||||||
|
"top-full",
|
||||||
|
"mt-2", // bottom
|
||||||
|
"right-full",
|
||||||
|
"-translate-y-1/2",
|
||||||
|
"mr-2",
|
||||||
|
"top-1/2", // left
|
||||||
|
"left-full",
|
||||||
|
"ml-2", // right
|
||||||
|
);
|
||||||
|
|
||||||
|
const pos = this.getAttribute("position") || "top";
|
||||||
|
|
||||||
|
switch (pos) {
|
||||||
|
case "bottom":
|
||||||
|
this._tooltipBox.classList.add(
|
||||||
|
"top-full",
|
||||||
|
"left-1/2",
|
||||||
|
"transform",
|
||||||
|
"-translate-x-1/2",
|
||||||
|
"mt-0.5",
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "left":
|
||||||
|
this._tooltipBox.classList.add(
|
||||||
|
"right-full",
|
||||||
|
"top-1/2",
|
||||||
|
"transform",
|
||||||
|
"-translate-y-1/2",
|
||||||
|
"mr-0.5",
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "right":
|
||||||
|
this._tooltipBox.classList.add(
|
||||||
|
"left-full",
|
||||||
|
"top-1/2",
|
||||||
|
"transform",
|
||||||
|
"-translate-y-1/2",
|
||||||
|
"ml-0.5",
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "top":
|
||||||
|
default:
|
||||||
|
// top as default
|
||||||
|
this._tooltipBox.classList.add(
|
||||||
|
"bottom-full",
|
||||||
|
"left-1/2",
|
||||||
|
"transform",
|
||||||
|
"-translate-x-1/2",
|
||||||
|
"mb-0.5",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,14 @@ const (
|
|||||||
False
|
False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (b OptionalBool) IsTrue() bool {
|
||||||
|
return b == True
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b OptionalBool) IsFalse() bool {
|
||||||
|
return b == False || b == Unspecified
|
||||||
|
}
|
||||||
|
|
||||||
func (b *OptionalBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
func (b *OptionalBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
var attr struct {
|
var attr struct {
|
||||||
Value string `xml:"value,attr"`
|
Value string `xml:"value,attr"`
|
||||||
|
|||||||
Reference in New Issue
Block a user