-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
158 lines (158 loc) · 4.57 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// A simple, portable webcomponent on the go. Refer to docs for more info https://github.com/teamdunno/elemxx#readme
/**
* @author teamdunno <https://github.com/teamdunno>
* @version 0.5.3
* @license MIT
*/ /**
* Detach reference from existing object (only function that returns the same reference)
*
* @param val The object
* @returns New reference from the object
* @throws TypeError on worse case (if `typeof value` dosent provide anything, or forcefully put the value as `function`)
*/ export function detachRef(val) {
switch(typeof val){
case "function":
{
return val;
}
case "string":
{
return val.valueOf();
}
case "number":
{
return val.valueOf();
}
case "bigint":
{
return val.valueOf();
}
case "boolean":
{
return val.valueOf();
}
case "symbol":
{
return val.valueOf();
}
case "undefined":
{
return undefined;
}
case "object":
{
switch(Array.isArray(val)){
case true:
{
return [
...val
];
}
default:
{
if (val === null) {
return null;
}
return {
...val
};
}
}
}
default:
{
throw new TypeError("elemxx detachRef: typeof keyword dosent provide anything to detach from");
}
}
}
/** A simple, portable webcomponent on the go */ export class Elemxx extends HTMLElement {
/** CSS string for the elem. It would be appended to DOM if set */ static css = undefined;
/** Attribute list. If defined, {@link Track} will be added alongside the name to the {@link Elemxx.attrs}, and not cleaned on unmounted */ static attrList = undefined;
/** Detect if element was mounted */ mounted = false;
/** use {@link Elemxx.attrs} insead */ static observedAttributes = this.attrList;
/** Attributes that are defined in {@link Elemxx.attrList}. Not cleaned when unmounted unlike normal trackers on {@link Elemxx.track} */ attrs = {};
_EXX_TRACKERS = [];
/** Run this function on mounted */ onMount() {}
/** Run this function on unmounted */ onUnmount() {}
constructor(){
super();
}
/** use {@link Elemxx.attrs} instead */ attributeChangedCallback(k, _, n) {
if (typeof this.attrs[k] === "undefined") return;
this.attrs[k].value = n;
}
/**
* ⚠️ **Note**: This is different than `this.attrs`
*
* Shorthand for `Object.values(this.attrs)`
*/ eachAttrs() {
return Object.values(this.attrs);
}
/**
* Track the changes of value
*
* @param value The value
* @param keep (default: `false`) Prevent removal of events when elem was unmounted
* @returns [{@link Track}] object
*/ track(value, keep = false) {
let evs = [];
let v = value;
const t = {
get value () {
return v;
},
set value (newValue){
v = newValue;
if (evs.length > 0) for(let i = 0; i < evs.length; i++)evs[i](value);
},
watch: function(func) {
evs.push(func);
},
observe: function(func) {
func(v);
evs.push(func);
},
remove: function(func) {
evs = evs.filter((t)=>t !== func);
},
removeAll: function() {
evs = [];
}
};
if (!keep) {
this._EXX_TRACKERS.push(t);
}
return t;
}
/** use {@link Elemxx.onMount} instead */ connectedCallback() {
// https://stackoverflow.com/a/73551405/22147523
// weird solution, but it works
const proto = Object.fromEntries(Object.entries(this.constructor));
if (proto.attrList && proto.attrList.length > 0) {
const attrList = proto.attrList;
for(let i = 0; i < attrList.length; i++){
const name = attrList[i];
const obj = this.attrs[name];
const value = this.getAttribute(name);
if (typeof obj === "object") obj.value = value;
else this.attrs[name] = this.track(value, true);
}
}
if (proto.css) {
proto.css = proto.css.replace(/:me/g, this.localName);
const stychild = document.createElement("style");
stychild.innerHTML = proto.css;
this.appendChild(stychild);
}
this.onMount();
}
/** use {@link Elemxx.onUnmount} instead */ disconnectedCallback() {
this.mounted = false;
if (this._EXX_TRACKERS.length > 0) {
for(let i = 0; i < this._EXX_TRACKERS.length; i++){
this._EXX_TRACKERS[i].removeAll();
}
}
this.onUnmount();
}
} // done