@alexgyver/component 1.5.0 → 2.0.0

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/Component.js DELETED
@@ -1,388 +0,0 @@
1
- //#region EL
2
- export class EL {
3
- static context;
4
-
5
- /**
6
- * Создать элемент и поместить его в переменную $root
7
- * @param {string} tag html tag элемента
8
- * @param {object} data параметры
9
- * @param {Boolean} svg SVG
10
- */
11
- constructor(tag, data = {}, svg = false) {
12
- this.$root = EL.makeIn(this, tag, data, svg);
13
- }
14
- make(tag, data = {}, svg = false) {
15
- return EL.makeIn(this, tag, data, svg);
16
- }
17
- makeArray(arr, svg = false) {
18
- return EL.makeArrayIn(this, arr, svg);
19
- }
20
- config(el, data, svg = false) {
21
- return EL.configIn(this, el, data, svg);
22
- }
23
- makeShadow(host, data = {}, sheet = null) {
24
- return EL.makeShadowIn(this, host, data, sheet);
25
- }
26
-
27
- /**
28
- * Создать элемент
29
- * @param {string} tag html tag элемента
30
- * @param {object} data параметры
31
- * @param {Boolean} svg SVG
32
- * @returns {Node}
33
- */
34
- static make(tag, data = {}, svg = false) {
35
- if (data instanceof Node) return data;
36
- if (tag == 'svg') svg = true;
37
- return EL.config(svg ? document.createElementNS("http://www.w3.org/2000/svg", tag ?? 'svg') : document.createElement(tag ?? 'div'), data, svg);
38
- }
39
- static makeIn(ctx, tag, data = {}, svg = false) {
40
- return EL.make(tag, { ...data, context: ctx }, svg);
41
- }
42
-
43
- /**
44
- * Настроить элемент
45
- * @param {Node | Array} el элемент или массив элементов
46
- * @param {object} data параметры
47
- * @param {Boolean} svg SVG
48
- * @returns {Node | Array}
49
- */
50
- static config(el, data, svg = false) {
51
- if (!(el instanceof Node) || (typeof data !== 'object')) {
52
- return el;
53
- }
54
- if (Array.isArray(el)) {
55
- return el.map(e => EL.config(e, data, svg));
56
- }
57
-
58
- const ctx = ('context' in data) ? (EL.context = data.context) : EL.context;
59
-
60
- const addChild = obj => {
61
- if (obj) {
62
- if (obj instanceof Node) el.appendChild(obj);
63
- else if (obj instanceof EL) el.appendChild(obj.$root);
64
- else if (typeof obj === 'string') el.insertAdjacentHTML('beforeend', obj);
65
- else if (typeof obj === 'object') EL.make(obj.tag, { ...obj, parent: el }, (svg || obj.tag == 'svg'));
66
- }
67
- }
68
-
69
- const call = fn => { if (fn) fn.call(ctx, el, ctx) }
70
-
71
- for (const [key, val] of Object.entries(data)) {
72
- switch (key) {
73
- case 'text':
74
- el.textContent = (val == null) ? '' : String(val); // == - null + undef
75
- continue;
76
-
77
- case 'html':
78
- el.innerHTML = (val == null) ? '' : String(val);
79
- continue;
80
-
81
- case 'tag':
82
- case 'get':
83
- case 'also':
84
- case 'parent':
85
- case 'context':
86
- case 'onMount':
87
- case 'onUpdate':
88
- case 'onDestroy':
89
- continue;
90
- }
91
-
92
- if (val === undefined || val === null) continue;
93
-
94
- switch (key) {
95
- case 'push':
96
- val.push(el);
97
- break;
98
-
99
- case '$':
100
- case 'var':
101
- if (ctx) ctx['$' + val] = el;
102
- break;
103
-
104
- case 'events':
105
- for (let ev in val) el.addEventListener(ev, e => val[ev].call(ctx, e, el, ctx));
106
- break;
107
-
108
- case 'click':
109
- case 'input':
110
- case 'change':
111
- case 'mousewheel':
112
- el.addEventListener(key, e => val.call(ctx, e, el, ctx));
113
- break;
114
-
115
- case 'attrs':
116
- for (let attr in val) el.setAttribute(attr, val[attr]);
117
- break;
118
-
119
- case 'props':
120
- for (let prop in val) el[prop] = val[prop];
121
- break;
122
-
123
- case 'data':
124
- for (let key in val) el.dataset[key] = val[key];
125
- break;
126
-
127
- case 'child_r':
128
- EL.clear(el);
129
- // fall
130
- case 'child':
131
- addChild(val);
132
- break;
133
-
134
- case 'children_r':
135
- EL.clear(el);
136
- // fall
137
- case 'children':
138
- for (let obj of val) addChild(obj);
139
- break;
140
-
141
- case 'style_r':
142
- el.style.cssText = '';
143
- // fall
144
- case 'style':
145
- if (typeof val === 'string') {
146
- el.style.cssText += val + ';';
147
- } else {
148
- for (let st in val) if (val[st]) el.style[st] = val[st];
149
- }
150
- break;
151
-
152
- case 'class_r':
153
- el.className = '';
154
- // fall
155
- case 'class': {
156
- const getClasses = (cls) => {
157
- if (Array.isArray(cls)) return Object.fromEntries(cls.filter(Boolean).map(c => [c, true]));
158
- if (typeof cls === 'string') return getClasses(cls.split(/\s+/));
159
- return cls;
160
- }
161
- for (const [cls, state] of Object.entries(getClasses(val))) {
162
- state ? el.classList.add(cls) : el.classList.remove(cls);
163
- }
164
- } break;
165
-
166
- case 'animate': {
167
- const { duration = 300, easing = 'ease', onEnd = null, ...styles } = val;
168
- el.style.transition = Object.keys(styles).map(st => `${st} ${duration}ms ${easing}`).join(', ');
169
- requestAnimationFrame(() => { for (let st in styles) el.style[st] = styles[st]; });
170
-
171
- const onEndHandler = () => {
172
- el.removeEventListener('transitionend', onEndHandler);
173
- call(onEnd);
174
- };
175
- el.addEventListener('transitionend', onEndHandler);
176
- } break;
177
-
178
- default: el[key] = val;
179
- break;
180
- }
181
- }
182
-
183
- if (data.parent) data.parent.appendChild(el);
184
-
185
- let tries = 50;
186
- const mount = () => {
187
- if (!el._mounted) {
188
- if (el.isConnected) {
189
- el._mounted = true;
190
- call(data.onMount);
191
- } else if (--tries) {
192
- requestAnimationFrame(mount);
193
- }
194
- }
195
- }
196
- mount();
197
-
198
- if (data.onDestroy) el._onDestroy = data.onDestroy.bind(ctx, el, ctx);
199
- if (data.onUpdate) el._onUpdate = data.onUpdate.bind(ctx, el, ctx);
200
- if (el._onUpdate) el._onUpdate();
201
- call(data.also);
202
-
203
- return el;
204
- }
205
- static configIn(ctx, el, data, svg = false) {
206
- return EL.config(el, { ...data, context: ctx }, svg);
207
- }
208
-
209
- /**
210
- * Удалить все child ноды
211
- * @param {HTMLElement} el
212
- */
213
- static clear(el, recursive = true) {
214
- while (el.firstChild) {
215
- if (recursive) EL.clear(el.firstChild, true);
216
- EL.remove(el.firstChild, false);
217
- }
218
- }
219
-
220
- /**
221
- * Удалить элемент
222
- * @param {HTMLElement} el
223
- */
224
- static remove(el, recursive = true) {
225
- if (recursive) EL.clear(el);
226
- if (el._onDestroy) el._onDestroy();
227
- el.remove();
228
- }
229
-
230
- /**
231
- * Создать массив элементов из массива объектов конфигурации
232
- * @param {array} arr массив объектов конфигурации
233
- * @param {Boolean} svg SVG
234
- * @returns {array} of Elements
235
- */
236
- static makeArray(arr, svg = false) {
237
- if (!arr || !Array.isArray(arr)) return [];
238
- return arr.map(data => EL.make(data.tag, data, svg));
239
- }
240
- static makeArrayIn(ctx, arr, svg) {
241
- return EL.makeArray(arr.map(data => ({ ...data, context: ctx })), svg);
242
- }
243
-
244
- /**
245
- * Создать теневой элемент от указанного tag, дети подключатся к нему в shadowRoot
246
- * @param {string|Node} host html tag теневого элемента или Node
247
- * @param {object} data параметры внешнего элемента
248
- * @param {string} sheet css стили
249
- * @returns {Node} host
250
- */
251
- static makeShadow(host, data = {}, sheet = null) {
252
- if (!host || typeof data !== 'object') return null;
253
-
254
- let $host = (host instanceof Node) ? host : document.createElement(host);
255
- $host.attachShadow({ mode: 'open' });
256
-
257
- EL.config($host.shadowRoot, {
258
- context: data.context,
259
- children: [
260
- {
261
- tag: 'style',
262
- textContent: sheet ?? '',
263
- },
264
- data.child ?? {},
265
- ...(data.children ?? []),
266
- ]
267
- });
268
- delete data.children;
269
- delete data.child;
270
- EL.config($host, data);
271
- return $host;
272
- }
273
- static makeShadowIn(ctx, host, data = {}, sheet = null) {
274
- return EL.makeShadow(host, { ...data, context: ctx }, sheet);
275
- }
276
- }
277
-
278
- // legacy
279
- export const Component = EL;
280
-
281
- //#region State
282
- export class State {
283
- constructor(init = {}) {
284
- this.data = init;
285
- this.subs = new Set();
286
- }
287
- set(key, value) {
288
- this.data[key] = value;
289
- this.subs.forEach(fn => fn(this.data));
290
- }
291
- get(key) {
292
- return this.data[key];
293
- }
294
- subscribe(fn) {
295
- this.subs.add(fn);
296
- return () => this.subs.delete(fn);
297
- }
298
- }
299
-
300
- //#region SVG
301
- export class SVG {
302
- static make = (tag, data) => EL.make(tag, data, true);
303
- static config = (el, data) => EL.config(el, data, true);
304
- static makeArray = (arr) => EL.makeArray(arr, true);
305
-
306
- static svg = (attrs = {}, props = {}) => SVG._make('svg', attrs, props);
307
- static rect = (x, y, w, h, rx, ry, attrs = {}, props = {}) => SVG._make('rect', { ...attrs, x: x, y: y, width: w, height: h, rx: rx, ry: ry }, props);
308
- static circle = (x, y, r, attrs = {}, props = {}) => SVG._make('circle', { ...attrs, cx: x, cy: y, r: r }, props);
309
- static line = (x1, y1, x2, y2, attrs = {}, props = {}) => SVG._make('line', { ...attrs, x1: x1, y1: y1, x2: x2, y2: y2 }, props);
310
- static polyline = (points, attrs = {}, props = {}) => SVG._make('polyline', { ...attrs, points: points }, props);
311
- static polygon = (points, attrs = {}, props = {}) => SVG._make('polygon', { ...attrs, points: points }, props);
312
- static path = (d, attrs = {}, props = {}) => SVG._make('path', { ...attrs, d: d }, props);
313
- static text = (text, x, y, attrs = {}, props = {}) => SVG._make('text', { ...attrs, x: x, y: y }, { ...props, text: text });
314
-
315
- static _make = (tag, attrs = {}, props = {}) => SVG.make(tag, { attrs: { ...attrs }, ...props });
316
- }
317
-
318
- //#region Sheet
319
- export class Sheet {
320
- /**
321
- * Добавить стиль с уникальным id в head. ext - стиль можно будет удалить по id
322
- * @param {string|array} style стили в виде css строки
323
- * @param {string|this} id уникальный id стиля. При передаче this будет именем класса
324
- * @param {boolean} ext внешний стиль - может быть удалён по id
325
- */
326
- static addStyle(style, id, ext = false) {
327
- if (!style || !id) return;
328
- if (typeof id === 'object') id = id.constructor.name;
329
-
330
- if (!Sheet.#int.has(id) && !Sheet.#ext.has(id)) {
331
- if (ext) {
332
- let sheet = document.createElement('style');
333
- document.head.appendChild(sheet);
334
- sheet.textContent = style;
335
- Sheet.#ext.set(id, sheet);
336
- } else {
337
- if (!Sheet.#sheet) Sheet.#sheet = document.head.appendChild(document.createElement('style'));
338
- Sheet.#sheet.textContent += style + '\r\n';
339
- Sheet.#int.add(id);
340
- }
341
- }
342
- }
343
-
344
- /**
345
- * Удалить ext стиль по его id
346
- * @param {string} id id стиля. При передаче this будет именем класса
347
- */
348
- static removeStyle(id) {
349
- if (typeof id === 'object') id = id.constructor.name;
350
- if (Sheet.#ext.has(id)) {
351
- Sheet.#ext.get(id).remove();
352
- Sheet.#ext.delete(id);
353
- }
354
- }
355
-
356
- static #sheet = null;
357
- static #int = new Set();
358
- static #ext = new Map();
359
- }
360
-
361
- //#region StyledComponent
362
- export class StyledComponent extends EL {
363
- /**
364
- * Создать элемент и поместить его в переменную $root
365
- * @param {string} tag html tag элемента
366
- * @param {object} data параметры
367
- * @param {string|array} style стили в виде css строки
368
- * @param {string|this} id уникальный id стиля. При передаче this будет именем класса
369
- * @param {boolean} ext внешний стиль - может быть удалён по id
370
- */
371
- constructor(tag, data = {}, style = null, id = null, ext = false) {
372
- super(tag, data);
373
- Sheet.addStyle(style, id, ext);
374
- }
375
-
376
- /**
377
- * Создать элемент
378
- * @param {string} tag html tag элемента
379
- * @param {object} data параметры
380
- * @param {string|array} style стили в виде css строки
381
- * @param {string|this} id уникальный id стиля. При передаче this будет именем класса
382
- * @param {boolean} ext внешний стиль - может быть удалён по id
383
- */
384
- static make(tag, data = {}, style = null, id = null, ext = false) {
385
- Sheet.addStyle(style, id, ext);
386
- return EL.make(tag, data);
387
- }
388
- }
package/test/example.html DELETED
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Document</title>
8
- <script type="module" src="script.js"></script>
9
- </head>
10
-
11
- <body>
12
-
13
- </body>
14
-
15
- </html>