@twobirds/microcomponents 0.0.79 → 0.0.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MC.js +379 -0
- package/dist/McEvent.js +71 -0
- package/dist/elements.js +48 -0
- package/dist/formValues.js +162 -0
- package/dist/helpers.js +113 -0
- package/dist/observables.js +249 -0
- package/dist/selectors.js +971 -0
- package/package.json +2 -2
- package/public/typedoc/classes/MC.DC.html +2 -2
- package/public/typedoc/classes/MC.MC.html +2 -2
- package/public/typedoc/classes/MC.McBase.html +2 -2
- package/public/typedoc/classes/MC.McEvent.html +2 -2
- package/public/typedoc/functions/MC.addListener.html +1 -1
- package/public/typedoc/functions/MC.autoload.html +1 -1
- package/public/typedoc/functions/MC.removeListener.html +1 -1
- package/public/typedoc/functions/elements.defineCE.html +1 -1
- package/public/typedoc/functions/elements.getCE.html +1 -1
- package/public/typedoc/functions/formValues.formValues.html +1 -1
- package/public/typedoc/functions/observables.observe.html +1 -1
- package/public/typedoc/interfaces/MC.HTMLMcElement.html +2 -2
- package/public/typedoc/modules/MC.html +1 -1
- package/public/typedoc/modules/elements.html +1 -1
- package/public/typedoc/modules/formValues.html +1 -1
- package/public/typedoc/modules/observables.html +1 -1
- package/public/typedoc/types/observables.Observable.html +1 -1
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
export function isNativeObject(value) {
|
|
3
|
+
return value && value['constructor'] && value.constructor === Object;
|
|
4
|
+
}
|
|
5
|
+
export function sortObject(o) {
|
|
6
|
+
let result = {}, keys = [...Object.keys(o)].sort();
|
|
7
|
+
keys.forEach((key) => {
|
|
8
|
+
if (isNativeObject(o[key])) {
|
|
9
|
+
result[key] = sortObject(o[key]);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
result[key] = o[key];
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
export function flattenObject(o, doSort = true) {
|
|
18
|
+
let result = {};
|
|
19
|
+
[...Object.getOwnPropertyNames(o)].forEach((propName) => {
|
|
20
|
+
if (o[propName] &&
|
|
21
|
+
o[propName]['constructor'] &&
|
|
22
|
+
o[propName].constructor === Object) {
|
|
23
|
+
const temp = flattenObject(o[propName], false);
|
|
24
|
+
for (const j in temp) {
|
|
25
|
+
result[propName + '.' + j] = temp[j];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
result[propName] = o[propName];
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return doSort ? sortObject(result) : result;
|
|
33
|
+
}
|
|
34
|
+
export function deepEqual(o1, o2) {
|
|
35
|
+
return (JSON.stringify(flattenObject(o1)) === JSON.stringify(flattenObject(o2)));
|
|
36
|
+
}
|
|
37
|
+
export function nameSpace(ns, obj = {}) {
|
|
38
|
+
let nsa = ns.constructor === String ? ns.split('.') : ns;
|
|
39
|
+
if (!obj || !nsa[0] || !obj[nsa[0]]) {
|
|
40
|
+
console.warn('ns', nsa[0], 'not in', obj);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (obj[nsa[0]].constructor === Object && nsa.length > 1) {
|
|
44
|
+
return nameSpace(nsa.splice(1), obj[nsa[0]]);
|
|
45
|
+
}
|
|
46
|
+
return obj[nsa[0]];
|
|
47
|
+
}
|
|
48
|
+
export function parse(what, parseThis) {
|
|
49
|
+
var args = Array.from(arguments);
|
|
50
|
+
if (args.length > 2) {
|
|
51
|
+
while (args.length > 1) {
|
|
52
|
+
args[0] = parse(args[0], args[1]);
|
|
53
|
+
args.splice(1, 1);
|
|
54
|
+
}
|
|
55
|
+
return args[0];
|
|
56
|
+
}
|
|
57
|
+
if (typeof what === 'string') {
|
|
58
|
+
what.match(/\{[^\{\}]*\}/g)?.forEach(function (pPropname) {
|
|
59
|
+
var propname = pPropname.substring(1, pPropname.length - 1), value = nameSpace(propname, parseThis);
|
|
60
|
+
if (typeof value !== 'undefined') {
|
|
61
|
+
what = what.replace(pPropname, value);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
else if (isNativeObject(what)) {
|
|
66
|
+
switch (what.constructor) {
|
|
67
|
+
case Object:
|
|
68
|
+
Object.keys(what).forEach(function (pKey) {
|
|
69
|
+
if (what.hasOwnProperty(pKey)) {
|
|
70
|
+
what[pKey] = parse(what[pKey], parseThis);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
break;
|
|
74
|
+
case Array:
|
|
75
|
+
what.forEach(function (pValue, pKey, original) {
|
|
76
|
+
original[pKey] = parse(what[pKey], parseThis);
|
|
77
|
+
});
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return what;
|
|
82
|
+
}
|
|
83
|
+
export function kebabToPascal(str) {
|
|
84
|
+
return str
|
|
85
|
+
.split('-')
|
|
86
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
87
|
+
.join('');
|
|
88
|
+
}
|
|
89
|
+
export function debounce(func, milliseconds) {
|
|
90
|
+
let timeout;
|
|
91
|
+
return () => {
|
|
92
|
+
clearTimeout(timeout);
|
|
93
|
+
timeout = setTimeout(function () {
|
|
94
|
+
func(...arguments);
|
|
95
|
+
}, milliseconds);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function htmlToElements(html) {
|
|
99
|
+
let template = document.createElement('template');
|
|
100
|
+
html = html.replace(/<([A-Za-z0-9\-]*)([^>\/]*)(\/>)/gi, '<$1$2></$1>');
|
|
101
|
+
template.innerHTML = html;
|
|
102
|
+
template.content.normalize();
|
|
103
|
+
return Array.from(template.content.childNodes);
|
|
104
|
+
}
|
|
105
|
+
export function copyGettersSetters(source, target) {
|
|
106
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
107
|
+
for (const [key, descriptor] of Object.entries(descriptors)) {
|
|
108
|
+
if ('get' in descriptor || 'set' in descriptor) {
|
|
109
|
+
Object.defineProperty(target, key, descriptor);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
import { debounce, deepEqual, flattenObject, copyGettersSetters, } from './helpers.js';
|
|
3
|
+
import { DC } from './MC.js';
|
|
4
|
+
function isObservableObject(value) {
|
|
5
|
+
return value != null && typeof value === 'object';
|
|
6
|
+
}
|
|
7
|
+
function getPlaceholders(target) {
|
|
8
|
+
let placeholders = new Set(), regEx = /\{[^\{\}]*\}/g;
|
|
9
|
+
target
|
|
10
|
+
.getAttributeNames()
|
|
11
|
+
.filter((attr) => target.getAttribute(attr)?.match(regEx))
|
|
12
|
+
.forEach((attr) => {
|
|
13
|
+
let phs = new Set(target.getAttribute(attr)?.match(regEx));
|
|
14
|
+
phs.forEach((placeholder) => placeholders.add(placeholder.replace(/[\{\}]/g, '')));
|
|
15
|
+
});
|
|
16
|
+
[...target.childNodes]
|
|
17
|
+
.filter((childNode) => {
|
|
18
|
+
return (childNode.nodeType === 3 &&
|
|
19
|
+
(childNode.nodeValue || '').match(regEx));
|
|
20
|
+
})
|
|
21
|
+
.forEach((childNode) => {
|
|
22
|
+
(childNode.nodeValue || '')
|
|
23
|
+
.match(regEx)
|
|
24
|
+
.forEach((placeholder) => {
|
|
25
|
+
placeholders.add(placeholder.replace(/[\{\}]/g, ''));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
return [...placeholders].map((placeholder) => placeholder.replace(/[\{\}]/g, ''));
|
|
29
|
+
}
|
|
30
|
+
const inputs = [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement];
|
|
31
|
+
class Placeholders extends DC {
|
|
32
|
+
data = {};
|
|
33
|
+
oldDisplay = '';
|
|
34
|
+
constructor(target) {
|
|
35
|
+
super(target);
|
|
36
|
+
let that = this;
|
|
37
|
+
getPlaceholders(target).forEach((property) => (that.data[property] = ''));
|
|
38
|
+
observe(that);
|
|
39
|
+
that.#attachCallbacks();
|
|
40
|
+
delete that._mc;
|
|
41
|
+
}
|
|
42
|
+
#attachCallbacks() {
|
|
43
|
+
let that = this, target = that.target, hide = false;
|
|
44
|
+
target
|
|
45
|
+
.getAttributeNames()
|
|
46
|
+
.filter((attr) => target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g))
|
|
47
|
+
.forEach((attr) => {
|
|
48
|
+
let phs = new Set(target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g));
|
|
49
|
+
that.data.observe(((template) => (data) => {
|
|
50
|
+
let result = template;
|
|
51
|
+
phs.forEach((placeholder) => {
|
|
52
|
+
result = result.replace(placeholder, data[placeholder.replace(/[\{\}]/g, '')]);
|
|
53
|
+
});
|
|
54
|
+
target.setAttribute(attr, result);
|
|
55
|
+
})(target.getAttribute(attr)));
|
|
56
|
+
});
|
|
57
|
+
[...target.childNodes]
|
|
58
|
+
.filter((childNode) => {
|
|
59
|
+
return (childNode.nodeType === 3 &&
|
|
60
|
+
(childNode.nodeValue || '').match(/\{[^\{\}]*\}/g));
|
|
61
|
+
})
|
|
62
|
+
.forEach((childNode) => {
|
|
63
|
+
hide = true;
|
|
64
|
+
let phs = new Set(childNode.nodeValue.match(/\{[^\{\}]*\}/g));
|
|
65
|
+
that.data.observe(((template) => (data) => {
|
|
66
|
+
let result = template;
|
|
67
|
+
phs.forEach((placeholder) => {
|
|
68
|
+
result = result.replace(placeholder, data[placeholder.replace(/[\{\}]/g, '')]);
|
|
69
|
+
});
|
|
70
|
+
if (Object.keys(data).some((key) => {
|
|
71
|
+
return !!data[key];
|
|
72
|
+
})) {
|
|
73
|
+
if (!!that.oldDisplay) {
|
|
74
|
+
target.style = that.oldDisplay;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
target.removeAttribute('style');
|
|
78
|
+
}
|
|
79
|
+
delete that.oldDisplay;
|
|
80
|
+
}
|
|
81
|
+
childNode.nodeValue = result;
|
|
82
|
+
})(childNode.nodeValue));
|
|
83
|
+
that.oldDisplay = target.getAttribute('style)') || '';
|
|
84
|
+
if (hide &&
|
|
85
|
+
!inputs.includes(target.constructor) &&
|
|
86
|
+
target.tagName !== 'FIELDSET') {
|
|
87
|
+
target.style.display = 'none';
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
onData(ev) {
|
|
92
|
+
let that = this, data = {};
|
|
93
|
+
Object.keys(ev.data).forEach((key) => {
|
|
94
|
+
if (that.data.hasOwnProperty(key))
|
|
95
|
+
data[key] = ev.data[key];
|
|
96
|
+
});
|
|
97
|
+
if (JSON.stringify(data) !== JSON.stringify(that.data))
|
|
98
|
+
Object.assign(that.data, data);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function getPlaceholderElements(target) {
|
|
102
|
+
let elements = (target instanceof HTMLElement ? [target] : [])
|
|
103
|
+
.concat([...target.querySelectorAll('*')])
|
|
104
|
+
.filter((e) => !!getPlaceholders(e).length)
|
|
105
|
+
.filter((e) => e.tagName !== 'STYLE');
|
|
106
|
+
return elements;
|
|
107
|
+
}
|
|
108
|
+
function makePlaceholders(element) {
|
|
109
|
+
getPlaceholderElements(element).forEach((e) => {
|
|
110
|
+
if (e?._mc?._placeholders)
|
|
111
|
+
return;
|
|
112
|
+
DC.add(e, '_placeholders', new Placeholders(e));
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const classRepo = {};
|
|
116
|
+
function makeObservable(val) {
|
|
117
|
+
const Constructor = val.constructor, ConstructorName = Constructor.name;
|
|
118
|
+
let ObservableClass = class extends Constructor {
|
|
119
|
+
#notify = true;
|
|
120
|
+
#callbacks = [];
|
|
121
|
+
constructor(val) {
|
|
122
|
+
super(val);
|
|
123
|
+
this.constructor.callbacks = [];
|
|
124
|
+
if (isObservableObject(val)) {
|
|
125
|
+
Object.getOwnPropertyNames(val).forEach((key) => {
|
|
126
|
+
this[key] = val[key];
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
get callbacks() {
|
|
131
|
+
return this.#callbacks;
|
|
132
|
+
}
|
|
133
|
+
set callbacks(callbacks) {
|
|
134
|
+
this.#callbacks = callbacks;
|
|
135
|
+
}
|
|
136
|
+
observe(f) {
|
|
137
|
+
this.#callbacks.push(f);
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
bind(target) {
|
|
141
|
+
const that = this, iso = isObservableObject(that.valueOf());
|
|
142
|
+
if (iso) {
|
|
143
|
+
makePlaceholders(target);
|
|
144
|
+
const placeholders = [
|
|
145
|
+
...target.querySelectorAll('[_mc]'),
|
|
146
|
+
].filter((e) => !!e?._mc?._placeholders);
|
|
147
|
+
const func = function callback(data) {
|
|
148
|
+
let d = flattenObject(data);
|
|
149
|
+
placeholders.forEach((e) => {
|
|
150
|
+
if (!e)
|
|
151
|
+
return;
|
|
152
|
+
e._mc.trigger('data', d);
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
that.#callbacks.push(func);
|
|
156
|
+
that.notify();
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
console.warn('IGNORED - cannot bind a non-Object to the dom, IS:', typeof that.valueOf(), that);
|
|
160
|
+
}
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
163
|
+
notify(notify) {
|
|
164
|
+
let that = this, data = isObservableObject(that.valueOf()) &&
|
|
165
|
+
that.valueOf() instanceof Array === false
|
|
166
|
+
? structuredClone(Object.assign({}, that))
|
|
167
|
+
: that.valueOf();
|
|
168
|
+
if (notify !== undefined) {
|
|
169
|
+
that.#notify = notify;
|
|
170
|
+
}
|
|
171
|
+
that.#callbacks.forEach((f) => {
|
|
172
|
+
f(data);
|
|
173
|
+
});
|
|
174
|
+
return that;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
classRepo[ConstructorName] = ObservableClass;
|
|
178
|
+
return ObservableClass;
|
|
179
|
+
}
|
|
180
|
+
function getConstructor(val) {
|
|
181
|
+
let key = val.constructor.name;
|
|
182
|
+
return classRepo[key] || makeObservable(val);
|
|
183
|
+
}
|
|
184
|
+
export const observe = (target, propertyName) => {
|
|
185
|
+
let keys = !propertyName
|
|
186
|
+
? [...Object.getOwnPropertyNames(target)]
|
|
187
|
+
: [propertyName];
|
|
188
|
+
keys.forEach((key) => {
|
|
189
|
+
if (target.hasOwnProperty(key)
|
|
190
|
+
&& typeof target[key] !== 'function'
|
|
191
|
+
&& !target?.[key]?.constructor?.prototype?.observe) {
|
|
192
|
+
if (key[0] === '_' || target?.[key] === undefined)
|
|
193
|
+
return target;
|
|
194
|
+
let val = target[key];
|
|
195
|
+
let o = new (getConstructor(val))(val);
|
|
196
|
+
Object.defineProperty(target, key, {
|
|
197
|
+
enumerable: true,
|
|
198
|
+
get() {
|
|
199
|
+
if (isObservableObject(o.valueOf())) {
|
|
200
|
+
let check = structuredClone(Object.assign({}, o));
|
|
201
|
+
setTimeout(debounce(function checkChanges() {
|
|
202
|
+
let state = structuredClone(Object.assign({}, o));
|
|
203
|
+
if (!deepEqual(state, check)) {
|
|
204
|
+
o.notify();
|
|
205
|
+
}
|
|
206
|
+
}, 0), 0);
|
|
207
|
+
}
|
|
208
|
+
return o;
|
|
209
|
+
},
|
|
210
|
+
set(val) {
|
|
211
|
+
if (typeof val === typeof o.valueOf()) {
|
|
212
|
+
let iso = isObservableObject(o.valueOf()) &&
|
|
213
|
+
o.valueOf() instanceof Array === false;
|
|
214
|
+
if (iso) {
|
|
215
|
+
let old = structuredClone(Object.assign({}, o));
|
|
216
|
+
if (o?.constructor?.prototype?.observe === undefined) {
|
|
217
|
+
o = new (getConstructor(val))(structuredClone(Object.assign({}, val)));
|
|
218
|
+
copyGettersSetters(val, o);
|
|
219
|
+
o.seal();
|
|
220
|
+
}
|
|
221
|
+
Object.assign(o, val);
|
|
222
|
+
setTimeout(debounce(function checkChanges() {
|
|
223
|
+
let state = structuredClone(Object.assign({}, o));
|
|
224
|
+
if (!deepEqual(state, old)) {
|
|
225
|
+
o.notify();
|
|
226
|
+
}
|
|
227
|
+
}, 0), 0);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
let old = o.valueOf(), callbacks = o.callbacks;
|
|
231
|
+
if (val !== old) {
|
|
232
|
+
o = new (getConstructor(val))(val);
|
|
233
|
+
o.callbacks = callbacks;
|
|
234
|
+
o.notify();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
console.warn('IGNORED - cannot change observable types, IS:', typeof o.valueOf(), o, '- CANNOT BECOME:', typeof val);
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
target[key] = val;
|
|
244
|
+
}
|
|
245
|
+
;
|
|
246
|
+
});
|
|
247
|
+
return target;
|
|
248
|
+
};
|
|
249
|
+
//# sourceMappingURL=observables.js.map
|