@reddigital/quickstart
Version:
Frontend island architecture for Adonisjs
116 lines (114 loc) • 3.22 kB
JavaScript
// src/web_component/utils.ts
var resetInputs = ({ element }) => {
return new Promise((resolve) => {
if (window.performance?.navigation?.type === performance.navigation.TYPE_RELOAD || window.performance?.navigation?.type === performance.navigation.TYPE_BACK_FORWARD) {
element.querySelectorAll("input").forEach((el) => {
switch (el.type) {
case "checkbox":
case "radio":
el.checked = el.defaultChecked;
break;
case "file":
el.value = "";
break;
default:
el.value = el.defaultValue;
}
});
element.querySelectorAll("textarea").forEach((el) => {
el.value = el.defaultValue;
});
element.querySelectorAll("select").forEach((select) => {
if (select.multiple) {
Array.from(select.options).forEach((opt) => {
opt.selected = opt.defaultSelected;
});
} else {
const defaultIndex = Array.from(select.options).findIndex((opt) => opt.defaultSelected);
select.selectedIndex = defaultIndex > -1 ? defaultIndex : -1;
}
});
}
resolve();
});
};
var visible = ({ element }) => {
return new Promise((resolve) => {
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
observer.disconnect();
resolve(true);
}
}
});
observer.observe(element);
});
};
var media = ({
query,
onMatch,
onUnmatch
}) => {
const handleChange = (event) => {
if (event.matches) {
onMatch?.();
} else {
onUnmatch?.();
}
};
const mediaQuery = window.matchMedia(query);
if (mediaQuery.matches) {
onMatch?.();
} else {
onUnmatch?.();
}
mediaQuery.addEventListener("change", handleChange);
return () => {
mediaQuery.removeEventListener("change", handleChange);
};
};
var safeJsonParse = (json) => {
try {
return JSON.parse(json);
} catch (error) {
console.warn("Invalid JSON in data-props attribute:", error);
return {};
}
};
// src/web_component/init.ts
function init({ resolve, hydrate }) {
class Quickstart extends HTMLElement {
cleanupMediaListener;
async connectedCallback() {
await resetInputs({ element: this });
if (this.hasAttribute("client:lazy")) {
await visible({ element: this });
}
if (this.hasAttribute("client:media")) {
const query = this.getAttribute("client:media") ?? "";
this.cleanupMediaListener = media({
query,
onMatch: async () => await this.hydrate(),
onUnmatch: () => this.innerHTML = ""
});
} else {
await this.hydrate();
}
}
disconnectedCallback() {
this.cleanupMediaListener?.();
}
async hydrate() {
const src = this.getAttribute("src") ?? "";
const propsData = this.getAttribute("data-props");
const props = propsData ? safeJsonParse(propsData) : {};
const Component = await resolve(src);
hydrate(Component, { target: this, props });
}
}
customElements.define("quick-start", Quickstart);
}
export {
init
};