bobinamoe's picture
Upload 1664 files
baac5bb verified
import { $el, getActionEls } from "../../common/utils_dom.js";
import { bind } from "../utils_templates.js";
const CSS_STYLE_SHEETS = new Map();
const CSS_STYLE_SHEETS_ADDED = new Map();
const HTML_TEMPLATE_FILES = new Map();
function getCommonPath(name, extension) {
return `rgthree/common/components/${name.replace("rgthree-", "").replace(/\-/g, "_")}.${extension}`;
}
async function getStyleSheet(name, markupOrPath) {
if (markupOrPath.includes("{")) {
return markupOrPath;
}
if (!CSS_STYLE_SHEETS.has(name)) {
try {
const path = markupOrPath || getCommonPath(name, "css");
const text = await (await fetch(path)).text();
CSS_STYLE_SHEETS.set(name, text);
}
catch (e) {
}
}
return CSS_STYLE_SHEETS.get(name);
}
async function addStyleSheet(name, markupOrPath) {
if (markupOrPath.includes("{")) {
throw new Error("Page-level stylesheets should be passed a path.");
}
if (!CSS_STYLE_SHEETS_ADDED.has(name)) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = markupOrPath;
document.head.appendChild(link);
CSS_STYLE_SHEETS_ADDED.set(name, link);
}
return CSS_STYLE_SHEETS_ADDED.get(name);
}
async function getTemplateMarkup(name, markupOrPath) {
if (markupOrPath.includes("<template")) {
return markupOrPath;
}
if (!HTML_TEMPLATE_FILES.has(name)) {
try {
const path = markupOrPath || getCommonPath(name, "html");
const text = await (await fetch(path)).text();
HTML_TEMPLATE_FILES.set(name, text);
}
catch (e) {
}
}
return HTML_TEMPLATE_FILES.get(name);
}
export class RgthreeCustomElement extends HTMLElement {
constructor() {
super(...arguments);
this.ctor = this.constructor;
this.hasBeenConnected = false;
this.connected = false;
this.templates = new Map();
this.firstConnectedPromise = new Promise((resolve) => (this.firstConnectedPromiseResolver = resolve));
this.eventElements = new Map();
}
static create() {
if (this.NAME === "rgthree-override") {
throw new Error("Must override component NAME");
}
if (!window.customElements.get(this.NAME)) {
window.customElements.define(this.NAME, this);
}
return document.createElement(this.NAME);
}
onFirstConnected() {
}
onReconnected() {
}
onConnected() {
}
onDisconnected() {
}
onAction(action, e) {
console.log("onAction", action, e);
}
getElement(query) {
const el = this.querySelector(query);
if (!el) {
throw new Error("No element found for query: " + query);
}
return el;
}
onActionInternal(action, e) {
if (typeof this[action] === "function") {
this[action](e);
}
else {
this.onAction(action, e);
}
}
onConnectedInternal() {
this.connectActionElements();
this.onConnected();
}
onDisconnectedInternal() {
this.disconnectActionElements();
this.onDisconnected();
}
async connectedCallback() {
const elementName = this.ctor.NAME;
const wasConnected = this.connected;
if (!wasConnected) {
this.connected = true;
}
if (!this.hasBeenConnected) {
const [stylesheet, markup] = await Promise.all([
this.ctor.USE_SHADOW
? getStyleSheet(elementName, this.ctor.CSS)
: addStyleSheet(elementName, this.ctor.CSS),
getTemplateMarkup(elementName, this.ctor.TEMPLATES),
]);
if (markup) {
const temp = $el("div");
const templatesMarkup = markup.match(/<template[^]*?<\/template>/gm) || [];
for (const markup of templatesMarkup) {
temp.innerHTML = markup;
const template = temp.children[0];
if (!(template instanceof HTMLTemplateElement)) {
throw new Error("Not a template element.");
}
let id = template.getAttribute("id");
if (!id) {
id = this.ctor.NAME;
}
this.templates.set(id, template);
}
}
if (this.ctor.USE_SHADOW) {
this.root = this.attachShadow({ mode: "open" });
if (typeof stylesheet === "string") {
const sheet = new CSSStyleSheet();
sheet.replaceSync(stylesheet);
this.root.adoptedStyleSheets = [sheet];
}
}
else {
this.root = this;
}
let template;
if (this.templates.has(elementName)) {
template = this.templates.get(elementName);
}
else if (this.templates.has(elementName.replace("rgthree-", ""))) {
template = this.templates.get(elementName.replace("rgthree-", ""));
}
if (template) {
this.root.appendChild(template.content.cloneNode(true));
for (const name of template.getAttributeNames()) {
if (name != "id" && template.getAttribute(name)) {
this.setAttribute(name, template.getAttribute(name));
}
}
}
this.onFirstConnected();
this.hasBeenConnected = true;
this.firstConnectedPromiseResolver();
}
else {
this.onReconnected();
}
this.onConnectedInternal();
}
disconnectedCallback() {
this.connected = false;
this.onDisconnected();
}
connectActionElements() {
const data = getActionEls(this);
for (const dataItem of Object.values(data)) {
const mapItem = this.eventElements.get(dataItem.el) || {};
for (const [event, action] of Object.entries(dataItem.actions)) {
if (mapItem[event]) {
console.warn(`Element already has an event for ${event}`);
continue;
}
mapItem[event] = (e) => {
this.onActionInternal(action, e);
};
dataItem.el.addEventListener(event, mapItem[event]);
}
}
}
disconnectActionElements() {
for (const [el, eventData] of this.eventElements.entries()) {
for (const [event, fn] of Object.entries(eventData)) {
el.removeEventListener(event, fn);
}
}
}
async bindWhenConnected(data, el) {
await this.firstConnectedPromise;
this.bind(data, el);
}
bind(data, el) {
bind(el || this.root, data);
}
}
RgthreeCustomElement.NAME = "rgthree-override";
RgthreeCustomElement.USE_SHADOW = true;
RgthreeCustomElement.TEMPLATES = "";
RgthreeCustomElement.CSS = "";