Page MenuHomeSealhub

component-debugger.stimulus.ts
No OneTemporary

component-debugger.stimulus.ts

/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/consistent-type-assertions */
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
import { Controller } from "stimulus";
export default class ComponentDebugger extends Controller {
declare sizeSelectTarget: HTMLSelectElement;
declare gutterTarget: HTMLDivElement;
declare checkboxTarget: HTMLInputElement;
declare checkboxTargets: HTMLInputElement[];
declare previewTarget: HTMLDivElement;
declare componentBlockTargets: HTMLDivElement[];
static targets = [
"gutter",
"componentBlock",
"checkbox",
"preview",
"sizeSelect",
];
id: string;
main_form: HTMLFormElement;
origin_x: number;
origin_width: number;
connect() {
const main_form = document
.querySelector("#component-debugger")
?.closest("form");
if (!main_form) {
throw new Error("No main form");
}
this.main_form = main_form;
document.documentElement.addEventListener("ts-rebuilt", () => {
this.main_form.requestSubmit();
});
this.main_form.addEventListener("turbo:submit-end", () => {
// this clears the values of file inputs, so they don't get unecessarily
// re-uploaded on future submissions - the file is alreade there on the server
this.main_form
.querySelectorAll("input[type=file]")
.forEach((input: HTMLInputElement) => (input.value = ""));
});
window.addEventListener("load", () => {
this.update_width_display();
});
document.addEventListener("turbo:render", () => {
// not calling that to see if that improves performance
// console.log("UWD because of render event");
// this.update_width_display();
});
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const gutter = this.gutterTarget;
gutter.addEventListener("mousedown", (e) => {
this.origin_x = e.clientX;
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const resizable = this.targets.find("preview") as HTMLSpanElement;
this.origin_width = resizable.getBoundingClientRect().width;
const handler = (e: MouseEvent) => this.resizeHandler(e);
document.addEventListener("mousemove", handler);
const remove_move_listener = () => {
document.removeEventListener("mousemove", handler);
document.removeEventListener("mouseup", remove_move_listener);
document.dispatchEvent(
new Event("component-debugger--resize-done")
);
};
document.addEventListener("mouseup", remove_move_listener);
e.preventDefault();
});
}
update_width_display() {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
console.log("uwd");
const preview = this.targets.find("preview") as HTMLSpanElement;
const component_width = preview.offsetWidth;
this.sizeSelectTarget
.querySelectorAll("option")
.forEach((e) => e.removeAttribute("selected"));
let option: HTMLOptionElement | null =
this.sizeSelectTarget.querySelector("option.dynamic");
if (!option) {
option = document.createElement("option");
option.classList.add("dynamic");
option.setAttribute("selected", "");
this.sizeSelectTarget.insertBefore(
option,
this.sizeSelectTarget.childNodes[0]!
);
}
option.setAttribute("selected", "");
option.innerHTML = `${component_width} px`;
option.value = String(component_width);
this.sizeSelectTarget.value = String(component_width);
}
resizeHandler(e: MouseEvent) {
const width_offset = this.origin_x - e.clientX;
const new_width = Math.max(this.origin_width + width_offset, 1);
this.setPreviewWidth(new_width);
this.update_width_display();
document.dispatchEvent(new Event("component-debugger--resize"));
}
setPreviewWidth(width: number) {
document
.getElementById("component-debugger")
?.style.setProperty(
"--resizable-column-width",
width.toString() + "px"
);
this.update_width_display();
}
handleWidthDropdown() {
const value = this.sizeSelectTarget.value;
this.setPreviewWidth(parseInt(value));
}
handleBlockHover(e: MouseEvent) {
const index = parseInt(
(e.target as HTMLDivElement)
.closest(".jdd-editor__component-block")
?.getAttribute("data-component-index") || "0"
);
this.element
.querySelector(`.component-number-${index}`)
?.classList.add("highlighted");
}
handleBlockUnhover(e: MouseEvent) {
const index = parseInt(
(e.target as HTMLDivElement)
.closest(".jdd-editor__component-block")
?.getAttribute("data-component-index") || ""
);
this.element
.querySelectorAll(`.component-number-${index}.highlighted`)
.forEach((e) => e.classList.remove("highlighted"));
}
componentBlockTargetConnected(block_element: HTMLDivElement) {
const index = parseInt(
block_element.getAttribute("data-component-index") || "0"
);
block_element.addEventListener("focusin", () => {
this.scrollToComponentPreview(index);
});
const summary = block_element.querySelector("summary");
if (summary) {
summary.addEventListener(
"mouseenter",
this.handleBlockHover.bind(this)
);
summary.addEventListener(
"mouseleave",
this.handleBlockUnhover.bind(this)
);
}
}
previewTargetConnected(preview_element: HTMLDivElement) {
preview_element.addEventListener("click", ({ target }) => {
if (!(target instanceof HTMLElement)) {
return;
}
const closest = target.closest(".jdd-component");
if (!closest) {
return;
}
const index = parseInt(
String(
Array.from(closest.classList)
.find((c) => c.startsWith("component-number-"))
?.replace("component-number-", "")
)
);
if (isNaN(index)) {
return;
}
this.focusComponentBlock(index);
});
}
focusComponentBlock(index: number) {
const block = this.componentBlockTargets[index];
if (!block) {
return;
}
this.checkboxTargets[index]!.checked = true;
this.checkboxTargets[index]!.dispatchEvent(new Event("change")); // to help with refreshing markdown editor
block.scrollIntoView({ behavior: "smooth" });
(
block.querySelector(
".component-preview-parameters input"
) as HTMLInputElement
)?.focus();
}
getIndex(block_element: HTMLDivElement) {
const index = parseInt(
String(block_element.getAttribute("data-component-index"))
);
return index;
}
labelClicked(element: MouseEvent) {
const block_element = (element.target as HTMLDivElement).closest(
`[data-component-debugger-target="componentBlock"]`
) as HTMLDivElement;
const index = this.getIndex(block_element);
if (!this.checkboxTargets?.[index]?.checked) {
this.scrollToComponentPreview(index);
}
}
getPreviewElementForComponentIndex(index: number) {
const element = this.element.querySelector(
`.component-number-${index}`
) as HTMLDialogElement;
return element;
}
scrollToComponentPreview(index: number) {
const element = this.getPreviewElementForComponentIndex(index);
if (!element) {
return;
}
const preview_element =
this.element.querySelector(".component-preview");
if (!preview_element) {
throw new Error("Missing preview element!");
}
if (element.clientHeight > preview_element.clientHeight) {
preview_element.scrollTop = element.offsetTop - 44;
} else {
preview_element.scrollTop =
element.offsetTop -
(preview_element.clientHeight - element.clientHeight) / 2 -
44;
}
}
}

File Metadata

Mime Type
text/x-java
Expires
Fri, Jul 4, 08:31 (5 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
789339
Default Alt Text
component-debugger.stimulus.ts (7 KB)

Event Timeline