Skip to content

Commit b010039

Browse files
committed
1.10.0
1 parent 72ce7a0 commit b010039

File tree

4 files changed

+44
-16
lines changed

4 files changed

+44
-16
lines changed

dist/lego.js

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -633,18 +633,36 @@ function render(vnode, parentDomNode, options = {}) {
633633
}
634634

635635
function toCamelCase(name) {
636-
if (!name.includes("-")) return name
636+
if (!name.includes('-')) return name
637637
return name.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase())
638638
}
639+
640+
function sanitizeAttribute(attrType, attrValue) {
641+
if (attrType === 'object') return sanitizeJsonAttribute(attrValue)
642+
if (attrType === 'boolean') return attrValue === "" || !!attrValue
643+
if (attrType === 'number') return Number(attrValue)
644+
return attrValue
645+
}
646+
647+
function sanitizeJsonAttribute(attrValue) {
648+
try {
649+
return JSON.parse(attrValue)
650+
} catch (_) {
651+
return attrValue
652+
}
653+
}
654+
639655
class Component extends HTMLElement {
640656
state = {}
641657
useShadowDOM = true
658+
#watchProps = []
642659
#isConnected = false
643660
#isInitialized = false
661+
#customEvents = []
644662

645663
#ready() {
646664
this.init?.();
647-
this.watchProps = Object.keys(this.state);
665+
this.#watchProps = Object.keys(this.state);
648666
this.#syncAttributesToState();
649667
this.document = this.useShadowDOM
650668
? this.attachShadow({ mode: "open" })
@@ -654,10 +672,14 @@ class Component extends HTMLElement {
654672

655673
#syncAttributesToState() {
656674
this.state = Array.from(this.attributes).reduce(
657-
(state, attr) => ({
658-
...state,
659-
[toCamelCase(attr.name)]: attr.value,
660-
}),
675+
(state, attr) => {
676+
const camelCaseName = toCamelCase(attr.name);
677+
const attrType = typeof this.state[camelCaseName];
678+
return {
679+
...state,
680+
[camelCaseName]: sanitizeAttribute(attrType, attr.value),
681+
}
682+
},
661683
this.state
662684
);
663685
}
@@ -671,17 +693,19 @@ class Component extends HTMLElement {
671693
}
672694

673695
setAttribute(name, value) {
674-
super.setAttribute(name, value);
696+
if (name.match(/@[a-z]+(?:-[a-z]+)*/)) return this.#customEvents.push([name.slice(1), value])
697+
super.setAttribute(name, typeof value === 'object' ? JSON.stringify(value) : value);
675698
const prop = toCamelCase(name);
676-
if (this.watchProps.includes(prop)) this.render({ [prop]: value });
699+
const attrType = typeof this.state[prop];
700+
if (this.#watchProps.includes(prop)) this.render({ [prop]: sanitizeAttribute(attrType, value) });
677701
}
678702

679703
removeAttribute(name) {
680704
super.removeAttribute(name);
681705
const prop = toCamelCase(name);
682-
if (this.watchProps.includes(prop) && prop in this.state) {
683-
this.render({ [prop]: null });
684-
delete this.state[prop];
706+
const attrType = typeof this.state[prop];
707+
if (this.#watchProps.includes(prop) && prop in this.state) {
708+
this.render({ [prop]: sanitizeAttribute(attrType, null) });
685709
}
686710
}
687711

@@ -690,11 +714,13 @@ class Component extends HTMLElement {
690714
this.#isConnected = true;
691715
// Load the DOM
692716
this.render();
717+
this.#customEvents.forEach(([customEvent, listener]) => this.addEventListener(customEvent, listener));
693718
this.connected?.();
694719
}
695720

696721
disconnectedCallback() {
697722
this.#isConnected = false;
723+
this.#customEvents.forEach(([customEvent, listener]) => this.removeEventListener(customEvent, listener));
698724
this.disconnected?.();
699725
}
700726

@@ -712,13 +738,15 @@ class Component extends HTMLElement {
712738
}
713739

714740
render(state) {
715-
this.setState(state);
741+
if (state) this.setState(state);
716742
if (!this.#isConnected) return
717743

718-
return render(
744+
render(
719745
[this.vdom({ state: this.state }), this.vstyle({ state: this.state })],
720746
this.document
721-
)
747+
);
748+
749+
this.rendered?.(state);
722750
}
723751
}
724752

dist/lego.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/lego.min.js.gz

170 Bytes
Binary file not shown.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@polight/lego",
3-
"version": "1.9.2",
3+
"version": "1.10.0",
44
"description": "Tiny Web-Components lib for future-proof HTML mentors",
55
"main": "index.js",
66
"type": "module",

0 commit comments

Comments
 (0)