mirror of
https://github.com/ae-utbm/sith.git
synced 2024-12-22 15:51:19 +00:00
Add register decorator for web components and a better inheriting system for html elements
This commit is contained in:
parent
cac185634d
commit
4165f8d4af
@ -1,16 +1,17 @@
|
||||
import "tom-select/dist/css/tom-select.css";
|
||||
import { InheritedComponent } from "#core:utils/web-components";
|
||||
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components";
|
||||
import TomSelect from "tom-select";
|
||||
import type { TomItem, TomLoadCallback, TomOption } from "tom-select/dist/types/types";
|
||||
import type { escape_html } from "tom-select/dist/types/utils";
|
||||
import { type UserProfileSchema, userSearchUsers } from "#openapi";
|
||||
|
||||
export class AjaxSelect extends InheritedComponent<"select"> {
|
||||
widget: TomSelect;
|
||||
filter?: <T>(items: T[]) => T[];
|
||||
@registerComponent("ajax-select")
|
||||
export class AjaxSelect extends inheritHtmlElement("select") {
|
||||
public widget: TomSelect;
|
||||
public filter?: <T>(items: T[]) => T[];
|
||||
|
||||
constructor() {
|
||||
super("select");
|
||||
super();
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
this.loadTomSelect();
|
||||
@ -90,5 +91,3 @@ export class AjaxSelect extends InheritedComponent<"select"> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define("ajax-select", AjaxSelect);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// biome-ignore lint/correctness/noUndeclaredDependencies: shipped by easymde
|
||||
import "codemirror/lib/codemirror.css";
|
||||
import "easymde/src/css/easymde.css";
|
||||
import { InheritedComponent } from "#core:utils/web-components";
|
||||
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components";
|
||||
// biome-ignore lint/correctness/noUndeclaredDependencies: Imported by EasyMDE
|
||||
import type CodeMirror from "codemirror";
|
||||
// biome-ignore lint/style/useNamingConvention: This is how they called their namespace
|
||||
@ -9,7 +9,7 @@ import EasyMDE from "easymde";
|
||||
import { markdownRenderMarkdown } from "#openapi";
|
||||
|
||||
const loadEasyMde = (textarea: HTMLTextAreaElement) => {
|
||||
const easyMde = new EasyMDE({
|
||||
new EasyMDE({
|
||||
element: textarea,
|
||||
spellChecker: false,
|
||||
autoDownloadFontAwesome: false,
|
||||
@ -183,12 +183,10 @@ const loadEasyMde = (textarea: HTMLTextAreaElement) => {
|
||||
}
|
||||
};
|
||||
|
||||
class MarkdownInput extends InheritedComponent<"textarea"> {
|
||||
@registerComponent("markdown-input")
|
||||
class MarkdownInput extends inheritHtmlElement("textarea") {
|
||||
constructor() {
|
||||
super("textarea");
|
||||
|
||||
super();
|
||||
window.addEventListener("DOMContentLoaded", () => loadEasyMde(this.node));
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define("markdown-input", MarkdownInput);
|
||||
|
@ -1,3 +1,15 @@
|
||||
/**
|
||||
* Class decorator to register components easily
|
||||
* It's a wrapper around window.customElements.define
|
||||
* What's nice about it is that you don't separate the component registration
|
||||
* and the class definition
|
||||
**/
|
||||
export function registerComponent(name: string, options?: ElementDefinitionOptions) {
|
||||
return (component: CustomElementConstructor) => {
|
||||
window.customElements.define(name, component, options);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Safari doesn't support inheriting from HTML tags on web components
|
||||
* The technique is to:
|
||||
@ -6,28 +18,33 @@
|
||||
* pass all attributes to the child component
|
||||
* store is at as `node` inside the parent
|
||||
*
|
||||
* To use this, you must use the tag name twice, once for creating the class
|
||||
* and the second time while calling super to pass it to the constructor
|
||||
* Since we can't use the generic type to instantiate the node, we create a generator function
|
||||
*
|
||||
* ```js
|
||||
* class MyClass extends inheritHtmlElement("select") {
|
||||
* // do whatever
|
||||
* }
|
||||
* ```
|
||||
**/
|
||||
export class InheritedComponent<
|
||||
K extends keyof HTMLElementTagNameMap,
|
||||
> extends HTMLElement {
|
||||
node: HTMLElementTagNameMap[K];
|
||||
export function inheritHtmlElement<K extends keyof HTMLElementTagNameMap>(tagName: K) {
|
||||
return class Inherited extends HTMLElement {
|
||||
protected node: HTMLElementTagNameMap[K];
|
||||
|
||||
constructor(tagName: K) {
|
||||
super();
|
||||
this.node = document.createElement(tagName);
|
||||
const attributes: Attr[] = []; // We need to make a copy to delete while iterating
|
||||
for (const attr of this.attributes) {
|
||||
if (attr.name in this.node) {
|
||||
attributes.push(attr);
|
||||
constructor() {
|
||||
super();
|
||||
this.node = document.createElement(tagName);
|
||||
const attributes: Attr[] = []; // We need to make a copy to delete while iterating
|
||||
for (const attr of this.attributes) {
|
||||
if (attr.name in this.node) {
|
||||
attributes.push(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const attr of attributes) {
|
||||
this.removeAttributeNode(attr);
|
||||
this.node.setAttributeNode(attr);
|
||||
for (const attr of attributes) {
|
||||
this.removeAttributeNode(attr);
|
||||
this.node.setAttributeNode(attr);
|
||||
}
|
||||
this.appendChild(this.node);
|
||||
}
|
||||
this.appendChild(this.node);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
"target": "es6",
|
||||
"allowJs": true,
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"types": ["jquery", "alpinejs"],
|
||||
|
Loading…
Reference in New Issue
Block a user