@dooboostore/simple-web-component 1.0.0 → 1.0.2
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/README.md +70 -78
- package/dist/cjs/decorators/addEventListener.js +42 -0
- package/dist/cjs/decorators/addEventListener.js.map +7 -0
- package/dist/cjs/decorators/attributeChanged.js +24 -4
- package/dist/cjs/decorators/attributeChanged.js.map +2 -2
- package/dist/cjs/decorators/{element.js → elementDefind.js} +91 -13
- package/dist/cjs/decorators/elementDefind.js.map +7 -0
- package/dist/cjs/decorators/query.js +53 -0
- package/dist/cjs/decorators/query.js.map +7 -0
- package/dist/cjs/decorators/queryAll.js +53 -0
- package/dist/cjs/decorators/queryAll.js.map +7 -0
- package/dist/cjs/elements/SwcChoose.js +117 -0
- package/dist/cjs/elements/SwcChoose.js.map +7 -0
- package/dist/cjs/elements/SwcForOf.js +126 -0
- package/dist/cjs/elements/SwcForOf.js.map +7 -0
- package/dist/cjs/elements/SwcHTMLElementBase.js +102 -0
- package/dist/cjs/elements/SwcHTMLElementBase.js.map +7 -0
- package/dist/cjs/elements/SwcIf.js +127 -0
- package/dist/cjs/elements/SwcIf.js.map +7 -0
- package/dist/cjs/elements/SwcObject.js +115 -0
- package/dist/cjs/elements/SwcObject.js.map +7 -0
- package/dist/cjs/elements/SwcOther.js +56 -0
- package/dist/cjs/elements/SwcOther.js.map +7 -0
- package/dist/cjs/elements/SwcWhen.js +56 -0
- package/dist/cjs/elements/SwcWhen.js.map +7 -0
- package/dist/cjs/index.js +11 -1
- package/dist/cjs/index.js.map +2 -2
- package/dist/esm/decorators/addEventListener.js +23 -0
- package/dist/esm/decorators/addEventListener.js.map +7 -0
- package/dist/esm/decorators/attributeChanged.js +24 -4
- package/dist/esm/decorators/attributeChanged.js.map +2 -2
- package/dist/esm/decorators/{element.js → elementDefind.js} +89 -11
- package/dist/esm/decorators/elementDefind.js.map +7 -0
- package/dist/esm/decorators/query.js +34 -0
- package/dist/esm/decorators/query.js.map +7 -0
- package/dist/esm/decorators/queryAll.js +34 -0
- package/dist/esm/decorators/queryAll.js.map +7 -0
- package/dist/esm/elements/SwcChoose.js +98 -0
- package/dist/esm/elements/SwcChoose.js.map +7 -0
- package/dist/esm/elements/SwcForOf.js +107 -0
- package/dist/esm/elements/SwcForOf.js.map +7 -0
- package/dist/esm/elements/SwcHTMLElementBase.js +83 -0
- package/dist/esm/elements/SwcHTMLElementBase.js.map +7 -0
- package/dist/esm/elements/SwcIf.js +108 -0
- package/dist/esm/elements/SwcIf.js.map +7 -0
- package/dist/esm/elements/SwcObject.js +96 -0
- package/dist/esm/elements/SwcObject.js.map +7 -0
- package/dist/esm/elements/SwcOther.js +37 -0
- package/dist/esm/elements/SwcOther.js.map +7 -0
- package/dist/esm/elements/SwcWhen.js +37 -0
- package/dist/esm/elements/SwcWhen.js.map +7 -0
- package/dist/esm/index.js +11 -1
- package/dist/esm/index.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +744 -14
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
- package/dist/types/decorators/addEventListener.d.ts +16 -0
- package/dist/types/decorators/addEventListener.d.ts.map +1 -0
- package/dist/types/decorators/attributeChanged.d.ts +3 -1
- package/dist/types/decorators/attributeChanged.d.ts.map +1 -1
- package/dist/types/decorators/{element.d.ts → elementDefind.d.ts} +2 -2
- package/dist/types/decorators/elementDefind.d.ts.map +1 -0
- package/dist/types/decorators/query.d.ts +13 -0
- package/dist/types/decorators/query.d.ts.map +1 -0
- package/dist/types/decorators/queryAll.d.ts +13 -0
- package/dist/types/decorators/queryAll.d.ts.map +1 -0
- package/dist/types/elements/SwcChoose.d.ts +12 -0
- package/dist/types/elements/SwcChoose.d.ts.map +1 -0
- package/dist/types/elements/SwcForOf.d.ts +14 -0
- package/dist/types/elements/SwcForOf.d.ts.map +1 -0
- package/dist/types/elements/SwcHTMLElementBase.d.ts +14 -0
- package/dist/types/elements/SwcHTMLElementBase.d.ts.map +1 -0
- package/dist/types/elements/SwcIf.d.ts +14 -0
- package/dist/types/elements/SwcIf.d.ts.map +1 -0
- package/dist/types/elements/SwcObject.d.ts +14 -0
- package/dist/types/elements/SwcObject.d.ts.map +1 -0
- package/dist/types/elements/SwcOther.d.ts +5 -0
- package/dist/types/elements/SwcOther.d.ts.map +1 -0
- package/dist/types/elements/SwcWhen.d.ts +5 -0
- package/dist/types/elements/SwcWhen.d.ts.map +1 -0
- package/dist/types/index.d.ts +11 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +744 -14
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
- package/package.json +1 -1
- package/src/decorators/addEventListener.ts +35 -0
- package/src/decorators/attributeChanged.ts +29 -6
- package/src/decorators/{element.ts → elementDefind.ts} +121 -11
- package/src/decorators/query.ts +46 -0
- package/src/decorators/queryAll.ts +46 -0
- package/src/elements/SwcChoose.ts +83 -0
- package/src/elements/SwcForOf.ts +95 -0
- package/src/elements/SwcHTMLElementBase.ts +93 -0
- package/src/elements/SwcIf.ts +92 -0
- package/src/elements/SwcObject.ts +78 -0
- package/src/elements/SwcOther.ts +14 -0
- package/src/elements/SwcWhen.ts +14 -0
- package/src/index.ts +12 -2
- package/dist/cjs/decorators/element.js.map +0 -7
- package/dist/esm/decorators/element.js.map +0 -7
- package/dist/types/decorators/element.d.ts.map +0 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { elementDefind, template, style } from '../index';
|
|
2
|
+
|
|
3
|
+
@elementDefind({ tagName: 'swc-choose', useShadow: true })
|
|
4
|
+
export class SwcChoose extends HTMLElement {
|
|
5
|
+
private _observer: MutationObserver | null = null;
|
|
6
|
+
private _value: any = undefined;
|
|
7
|
+
|
|
8
|
+
set value(val: any) {
|
|
9
|
+
this._value = val;
|
|
10
|
+
this.evaluate();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get value() {
|
|
14
|
+
return this._value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@style
|
|
18
|
+
styles() {
|
|
19
|
+
return `:host { display: contents; }`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@template
|
|
23
|
+
render() {
|
|
24
|
+
return `<slot id="choose-slot"></slot>`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
connectedCallback() {
|
|
28
|
+
this._observer = new MutationObserver(() => this.evaluate());
|
|
29
|
+
this._observer.observe(this, { attributes: true, subtree: true, childList: true });
|
|
30
|
+
this.evaluate();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
disconnectedCallback() {
|
|
34
|
+
this._observer?.disconnect();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private evaluate() {
|
|
38
|
+
const whens = Array.from(this.querySelectorAll('swc-when'));
|
|
39
|
+
const other = this.querySelector('swc-other');
|
|
40
|
+
let matched = false;
|
|
41
|
+
|
|
42
|
+
// 현재 choose에 설정된 value (문자열인 경우 "null", "undefined" 등 처리)
|
|
43
|
+
const chooseValue = this.getAttribute('value') ?? this._value;
|
|
44
|
+
|
|
45
|
+
whens.forEach(when => {
|
|
46
|
+
if (matched) {
|
|
47
|
+
(when as HTMLElement).style.display = 'none';
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const testAttr = when.getAttribute('test');
|
|
52
|
+
if (testAttr === null) return;
|
|
53
|
+
if (testAttr.includes('{{')) return; // 아직 치환 전이면 스킵
|
|
54
|
+
|
|
55
|
+
let isConditionMet = false;
|
|
56
|
+
|
|
57
|
+
if (chooseValue !== undefined && chooseValue !== null) {
|
|
58
|
+
// 1. 매칭 모드: choose의 value와 when의 test값이 같은지 비교
|
|
59
|
+
isConditionMet = String(chooseValue) === String(testAttr);
|
|
60
|
+
} else {
|
|
61
|
+
// 2. 표현식 모드: testAttr 자체가 실행 가능한 코드인 경우
|
|
62
|
+
try {
|
|
63
|
+
if (testAttr === 'true') isConditionMet = true;
|
|
64
|
+
else if (testAttr === 'false') isConditionMet = false;
|
|
65
|
+
else isConditionMet = !!new Function(`return ${testAttr}`)();
|
|
66
|
+
} catch (e) {
|
|
67
|
+
isConditionMet = false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (isConditionMet) {
|
|
72
|
+
(when as HTMLElement).style.display = '';
|
|
73
|
+
matched = true;
|
|
74
|
+
} else {
|
|
75
|
+
(when as HTMLElement).style.display = 'none';
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (other) {
|
|
80
|
+
(other as HTMLElement).style.display = matched ? 'none' : '';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { elementDefind, template, style } from '../index';
|
|
2
|
+
import { SwcHTMLElementBase } from './SwcHTMLElementBase';
|
|
3
|
+
|
|
4
|
+
@elementDefind({ tagName: 'swc-for-of', useShadow: true })
|
|
5
|
+
export class SwcForOf extends SwcHTMLElementBase {
|
|
6
|
+
private _value: any[] = [];
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
set value(val: any[]) {
|
|
13
|
+
if (!Array.isArray(val)) val = [];
|
|
14
|
+
this._value = this.createReactiveProxy(
|
|
15
|
+
val,
|
|
16
|
+
() => this.renderAll(),
|
|
17
|
+
(idx, v) => this.updateSingleRow(idx, v)
|
|
18
|
+
);
|
|
19
|
+
this.renderAll();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get value(): any[] {
|
|
23
|
+
return this._value;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@style
|
|
27
|
+
styles() {
|
|
28
|
+
return `:host { display: contents; }`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@template
|
|
32
|
+
renderTemplate() {
|
|
33
|
+
return `<slot id="tpl-slot" style="display:none;"></slot>`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
connectedCallback() {
|
|
37
|
+
this.initCore();
|
|
38
|
+
this.renderAll();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public updateSingleRow(index: number, newValue: any) {
|
|
42
|
+
const targets = this.querySelectorAll(`[slot="row-${index}"]`);
|
|
43
|
+
if (targets.length > 0) {
|
|
44
|
+
targets.forEach(target => this.applyData(target, newValue, index));
|
|
45
|
+
} else {
|
|
46
|
+
this.renderRow(newValue, index);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private renderRow(item: any, index: number) {
|
|
51
|
+
if (!this.shadowRoot || this._masterTplNodes.length === 0) return;
|
|
52
|
+
|
|
53
|
+
const slotName = `row-${index}`;
|
|
54
|
+
if (!this.shadowRoot.querySelector(`slot[name="${slotName}"]`)) {
|
|
55
|
+
const slot = document.createElement('slot');
|
|
56
|
+
slot.name = slotName;
|
|
57
|
+
this.shadowRoot.appendChild(slot);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this._masterTplNodes.forEach(tplNode => {
|
|
61
|
+
const clone = tplNode.cloneNode(true);
|
|
62
|
+
if (clone.nodeType === Node.ELEMENT_NODE) {
|
|
63
|
+
(clone as HTMLElement).setAttribute('slot', slotName);
|
|
64
|
+
(clone as HTMLElement).style.display = '';
|
|
65
|
+
} else if (clone.nodeType === Node.TEXT_NODE) {
|
|
66
|
+
if (clone.textContent?.trim().length === 0) return;
|
|
67
|
+
const span = document.createElement('span');
|
|
68
|
+
span.setAttribute('slot', slotName);
|
|
69
|
+
span.appendChild(clone);
|
|
70
|
+
this.appendChild(span);
|
|
71
|
+
this.applyData(span, item, index);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this.appendChild(clone);
|
|
75
|
+
this.applyData(clone, item, index);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private renderAll() {
|
|
80
|
+
if (this._masterTplNodes.length === 0 || !this.shadowRoot) return;
|
|
81
|
+
|
|
82
|
+
Array.from(this.children).forEach(c => {
|
|
83
|
+
const slot = c.getAttribute('slot');
|
|
84
|
+
if (slot && slot.startsWith('row-')) {
|
|
85
|
+
c.remove();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
Array.from(this.shadowRoot.querySelectorAll('slot')).forEach(s => {
|
|
90
|
+
if (s.id !== 'tpl-slot') s.remove();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
this._value.forEach((item, index) => this.renderRow(item, index));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { getTemplateMethod } from '../decorators/template';
|
|
2
|
+
import { getStyleMethod } from '../decorators/style';
|
|
3
|
+
|
|
4
|
+
export abstract class SwcHTMLElementBase extends HTMLElement {
|
|
5
|
+
protected _masterTplNodes: Node[] = [];
|
|
6
|
+
protected _asKey: string = 'value';
|
|
7
|
+
protected _asIndexKey: string = 'index';
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
protected initCore() {
|
|
14
|
+
this._asKey = this.getAttribute('as') || 'value';
|
|
15
|
+
this._asIndexKey = this.getAttribute('as-index') || 'index';
|
|
16
|
+
const tplSlot = this.shadowRoot?.getElementById('tpl-slot') as HTMLSlotElement;
|
|
17
|
+
if (tplSlot) {
|
|
18
|
+
this._masterTplNodes = tplSlot.assignedNodes().map(n => n.cloneNode(true));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected getValueByPath(obj: any, path: string) {
|
|
23
|
+
if (path === this._asKey) return obj;
|
|
24
|
+
if (path.startsWith(`${this._asKey}.`)) {
|
|
25
|
+
return path
|
|
26
|
+
.split('.')
|
|
27
|
+
.slice(1)
|
|
28
|
+
.reduce((acc, part) => acc && acc[part], obj);
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
protected applyData(node: Node, data: any, index?: number) {
|
|
34
|
+
const context: Record<string, any> = {};
|
|
35
|
+
if (index !== undefined) {
|
|
36
|
+
context[this._asIndexKey] = index.toString();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const walk = (n: Node) => {
|
|
40
|
+
if (n.nodeType === Node.TEXT_NODE) {
|
|
41
|
+
if (!(n as any)._original) (n as any)._original = n.textContent;
|
|
42
|
+
let text = (n as any)._original;
|
|
43
|
+
|
|
44
|
+
text = text.replace(/{{(.*?)}}/g, (match: string, path: string) => {
|
|
45
|
+
path = path.trim();
|
|
46
|
+
if (context[path] !== undefined) return context[path];
|
|
47
|
+
const val = this.getValueByPath(data, path);
|
|
48
|
+
return val !== undefined ? val : match;
|
|
49
|
+
});
|
|
50
|
+
if (n.textContent !== text) n.textContent = text;
|
|
51
|
+
} else if (n.nodeType === Node.ELEMENT_NODE) {
|
|
52
|
+
const el = n as Element;
|
|
53
|
+
Array.from(el.attributes).forEach(a => {
|
|
54
|
+
if (!(a as any)._original) (a as any)._original = a.value;
|
|
55
|
+
let val = (a as any)._original;
|
|
56
|
+
|
|
57
|
+
val = val.replace(/{{(.*?)}}/g, (match: string, path: string) => {
|
|
58
|
+
path = path.trim();
|
|
59
|
+
if (context[path] !== undefined) return context[path];
|
|
60
|
+
const v = this.getValueByPath(data, path);
|
|
61
|
+
return v !== undefined ? v : match;
|
|
62
|
+
});
|
|
63
|
+
if (a.value !== val) a.value = val;
|
|
64
|
+
});
|
|
65
|
+
el.childNodes.forEach(walk);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
walk(node);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 객체/배열의 변경을 감지하는 Proxy 생성 유틸리티
|
|
73
|
+
*/
|
|
74
|
+
protected createReactiveProxy(target: any, onChange: () => void, onIndexChange?: (index: number, val: any) => void) {
|
|
75
|
+
return new Proxy(target, {
|
|
76
|
+
set: (t, prop, val) => {
|
|
77
|
+
const isIndex = !isNaN(Number(prop));
|
|
78
|
+
t[prop] = val;
|
|
79
|
+
if (isIndex && onIndexChange) {
|
|
80
|
+
onIndexChange(Number(prop), val);
|
|
81
|
+
} else {
|
|
82
|
+
onChange();
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
},
|
|
86
|
+
deleteProperty: (t, prop) => {
|
|
87
|
+
delete t[prop];
|
|
88
|
+
onChange();
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { elementDefind, template, style } from '../index';
|
|
2
|
+
import { SwcHTMLElementBase } from './SwcHTMLElementBase';
|
|
3
|
+
|
|
4
|
+
@elementDefind({ tagName: 'swc-if', useShadow: true })
|
|
5
|
+
export class SwcIf extends SwcHTMLElementBase {
|
|
6
|
+
private _value: any = false;
|
|
7
|
+
private _observer: MutationObserver | null = null;
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
set value(val: any) {
|
|
14
|
+
this._value = val;
|
|
15
|
+
this.render();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get value(): any {
|
|
19
|
+
return this._value;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@style
|
|
23
|
+
styles() {
|
|
24
|
+
return `:host { display: contents; }`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@template
|
|
28
|
+
renderTemplate() {
|
|
29
|
+
return `<slot id="tpl-slot" style="display:none;"></slot>`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
connectedCallback() {
|
|
33
|
+
this.initCore();
|
|
34
|
+
this._observer = new MutationObserver(() => this.render());
|
|
35
|
+
this._observer.observe(this, { attributes: true });
|
|
36
|
+
this.render();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
disconnectedCallback() {
|
|
40
|
+
this._observer?.disconnect();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private render() {
|
|
44
|
+
if (!this.shadowRoot) return;
|
|
45
|
+
|
|
46
|
+
const attrValue = this.getAttribute('value');
|
|
47
|
+
if (attrValue !== null && attrValue.includes('{{')) return;
|
|
48
|
+
|
|
49
|
+
let displayValue = attrValue !== null ? attrValue : this._value;
|
|
50
|
+
let isTruthy = !!displayValue;
|
|
51
|
+
if (typeof displayValue === 'string') {
|
|
52
|
+
if (displayValue === 'false' || displayValue === '0' || displayValue === '') isTruthy = false;
|
|
53
|
+
else {
|
|
54
|
+
try {
|
|
55
|
+
isTruthy = !!new Function(`return ${displayValue}`)();
|
|
56
|
+
} catch (e) {
|
|
57
|
+
isTruthy = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
Array.from(this.children).forEach(c => {
|
|
63
|
+
if (c.getAttribute('slot') === 'if-content') {
|
|
64
|
+
c.remove();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const existingSlot = this.shadowRoot.querySelector('slot[name="if-content"]');
|
|
69
|
+
if (existingSlot) existingSlot.remove();
|
|
70
|
+
|
|
71
|
+
if (isTruthy && this._masterTplNodes.length > 0) {
|
|
72
|
+
const contentSlot = document.createElement('slot');
|
|
73
|
+
contentSlot.name = 'if-content';
|
|
74
|
+
this.shadowRoot.appendChild(contentSlot);
|
|
75
|
+
|
|
76
|
+
this._masterTplNodes.forEach(tplNode => {
|
|
77
|
+
const clone = tplNode.cloneNode(true);
|
|
78
|
+
if (clone.nodeType === Node.ELEMENT_NODE) {
|
|
79
|
+
(clone as HTMLElement).setAttribute('slot', 'if-content');
|
|
80
|
+
} else if (clone.nodeType === Node.TEXT_NODE) {
|
|
81
|
+
if (clone.textContent?.trim().length === 0) return;
|
|
82
|
+
const span = document.createElement('span');
|
|
83
|
+
span.setAttribute('slot', 'if-content');
|
|
84
|
+
span.appendChild(clone);
|
|
85
|
+
this.appendChild(span);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.appendChild(clone);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { elementDefind, template, style } from '../index';
|
|
2
|
+
import { SwcHTMLElementBase } from './SwcHTMLElementBase';
|
|
3
|
+
|
|
4
|
+
@elementDefind({ tagName: 'swc-object', useShadow: true })
|
|
5
|
+
export class SwcObject extends SwcHTMLElementBase {
|
|
6
|
+
private _value: any = {};
|
|
7
|
+
private _renderedNodes: Node[] = [];
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
set value(val: any) {
|
|
14
|
+
if (typeof val !== 'object' || val === null) val = {};
|
|
15
|
+
this._value = this.createReactiveProxy(val, () => this.updateUI());
|
|
16
|
+
this.render();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get value(): any {
|
|
20
|
+
return this._value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@style
|
|
24
|
+
styles() {
|
|
25
|
+
return `:host { display: contents; }`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@template
|
|
29
|
+
renderTemplate() {
|
|
30
|
+
return `<slot id="tpl-slot" style="display:none;"></slot>`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
connectedCallback() {
|
|
34
|
+
this.initCore();
|
|
35
|
+
this.render();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private updateUI() {
|
|
39
|
+
this._renderedNodes.forEach(node => {
|
|
40
|
+
this.applyData(node, this._value);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private render() {
|
|
45
|
+
if (!this.shadowRoot || this._masterTplNodes.length === 0) return;
|
|
46
|
+
|
|
47
|
+
this._renderedNodes.forEach(n => {
|
|
48
|
+
if (n.parentElement === this) this.removeChild(n);
|
|
49
|
+
});
|
|
50
|
+
this._renderedNodes = [];
|
|
51
|
+
|
|
52
|
+
let slot = this.shadowRoot.querySelector('slot[name="obj-content"]');
|
|
53
|
+
if (!slot) {
|
|
54
|
+
slot = document.createElement('slot');
|
|
55
|
+
(slot as HTMLSlotElement).name = 'obj-content';
|
|
56
|
+
this.shadowRoot.appendChild(slot);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
this._masterTplNodes.forEach(tplNode => {
|
|
60
|
+
const clone = tplNode.cloneNode(true);
|
|
61
|
+
if (clone.nodeType === Node.ELEMENT_NODE) {
|
|
62
|
+
(clone as HTMLElement).setAttribute('slot', 'obj-content');
|
|
63
|
+
} else if (clone.nodeType === Node.TEXT_NODE) {
|
|
64
|
+
if (clone.textContent?.trim().length === 0) return;
|
|
65
|
+
const span = document.createElement('span');
|
|
66
|
+
span.setAttribute('slot', 'obj-content');
|
|
67
|
+
span.appendChild(clone);
|
|
68
|
+
this.appendChild(span);
|
|
69
|
+
this._renderedNodes.push(span);
|
|
70
|
+
this.applyData(span, this._value);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
this.appendChild(clone);
|
|
74
|
+
this._renderedNodes.push(clone);
|
|
75
|
+
this.applyData(clone, this._value);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { elementDefind, template, style } from '../index';
|
|
2
|
+
|
|
3
|
+
@elementDefind({ tagName: 'swc-other', useShadow: true })
|
|
4
|
+
export class SwcOther extends HTMLElement {
|
|
5
|
+
@style
|
|
6
|
+
styles() {
|
|
7
|
+
return `:host { display: contents; }`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@template
|
|
11
|
+
render() {
|
|
12
|
+
return `<slot></slot>`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { elementDefind, template, style } from '../index';
|
|
2
|
+
|
|
3
|
+
@elementDefind({ tagName: 'swc-when', useShadow: true })
|
|
4
|
+
export class SwcWhen extends HTMLElement {
|
|
5
|
+
@style
|
|
6
|
+
styles() {
|
|
7
|
+
return `:host { display: contents; }`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@template
|
|
11
|
+
render() {
|
|
12
|
+
return `<slot></slot>`;
|
|
13
|
+
}
|
|
14
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
export * from './decorators/
|
|
1
|
+
export * from './decorators/elementDefind';
|
|
2
2
|
export * from './decorators/template';
|
|
3
3
|
export * from './decorators/style';
|
|
4
|
-
export * from './decorators/attributeChanged';
|
|
4
|
+
export * from './decorators/attributeChanged';
|
|
5
|
+
export * from './decorators/query';
|
|
6
|
+
export * from './decorators/queryAll';
|
|
7
|
+
export * from './decorators/addEventListener';
|
|
8
|
+
export * from './elements/SwcForOf';
|
|
9
|
+
export * from './elements/SwcIf';
|
|
10
|
+
export * from './elements/SwcChoose';
|
|
11
|
+
export * from './elements/SwcWhen';
|
|
12
|
+
export * from './elements/SwcOther';
|
|
13
|
+
export * from './elements/SwcObject';
|
|
14
|
+
export * from './elements/SwcHTMLElementBase';
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/decorators/element.ts"],
|
|
4
|
-
"sourcesContent": ["import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';\nimport { getAttributeChangedMap } from './attributeChanged';\nimport { getTemplateMethod } from './template';\nimport { getStyleMethod } from './style';\n\nexport interface ElementConfig {\n tagName: string;\n useShadow?: boolean;\n extends?: string;\n observedAttributes?: string[];\n customElementRegistry?: CustomElementRegistry;\n}\n\nexport const ELEMENT_CONFIG_KEY = Symbol('simple-web-component:element-config');\n\nconst BUILT_IN_TAG_MAP = new Map<any, string>();\n\nconst registerTag = (className: string, tagName: string) => {\n if (typeof globalThis !== 'undefined' && (globalThis as any)[className]) {\n BUILT_IN_TAG_MAP.set((globalThis as any)[className], tagName);\n }\n};\n\n// Register comprehensive list of supported tags for automatic extends inference\n[\n ['HTMLAnchorElement', 'a'],\n ['HTMLAreaElement', 'area'],\n ['HTMLAudioElement', 'audio'],\n ['HTMLBaseElement', 'base'],\n ['HTMLButtonElement', 'button'],\n ['HTMLCanvasElement', 'canvas'],\n ['HTMLDataElement', 'data'],\n ['HTMLDataListElement', 'datalist'],\n ['HTMLDetailsElement', 'details'],\n ['HTMLDialogElement', 'dialog'],\n ['HTMLDivElement', 'div'],\n ['HTMLDListElement', 'dl'],\n ['HTMLEmbedElement', 'embed'],\n ['HTMLFieldSetElement', 'fieldset'],\n ['HTMLFormElement', 'form'],\n ['HTMLHRElement', 'hr'],\n ['HTMLIFrameElement', 'iframe'],\n ['HTMLImageElement', 'img'],\n ['HTMLInputElement', 'input'],\n ['HTMLLabelElement', 'label'],\n ['HTMLLegendElement', 'legend'],\n ['HTMLLIElement', 'li'],\n ['HTMLLinkElement', 'link'],\n ['HTMLMapElement', 'map'],\n ['HTMLMetaElement', 'meta'],\n ['HTMLMeterElement', 'meter'],\n ['HTMLModElement', 'del'],\n ['HTMLObjectElement', 'object'],\n ['HTMLOListElement', 'ol'],\n ['HTMLOptGroupElement', 'optgroup'],\n ['HTMLOptionElement', 'option'],\n ['HTMLOutputElement', 'output'],\n ['HTMLParagraphElement', 'p'],\n ['HTMLParamElement', 'param'],\n ['HTMLPictureElement', 'picture'],\n ['HTMLPreElement', 'pre'],\n ['HTMLProgressElement', 'progress'],\n ['HTMLQuoteElement', 'blockquote'],\n ['HTMLScriptElement', 'script'],\n ['HTMLSelectElement', 'select'],\n ['HTMLSlotElement', 'slot'],\n ['HTMLSourceElement', 'source'],\n ['HTMLSpanElement', 'span'],\n ['HTMLStyleElement', 'style'],\n ['HTMLTableElement', 'table'],\n ['HTMLTableSectionElement', 'tbody'],\n ['HTMLTableCellElement', 'td'],\n ['HTMLTemplateElement', 'template'],\n ['HTMLTextAreaElement', 'textarea'],\n ['HTMLTimeElement', 'time'],\n ['HTMLTitleElement', 'title'],\n ['HTMLTableRowElement', 'tr'],\n ['HTMLTrackElement', 'track'],\n ['HTMLUListElement', 'ul'],\n ['HTMLVideoElement', 'video'],\n ['HTMLHeadingElement', 'h1']\n].forEach(([cls, tag]) => registerTag(cls, tag));\n\nexport const element =\n (inConfig: ElementConfig | string): ClassDecorator =>\n (constructor: any) => {\n const config: ElementConfig = typeof inConfig === 'string' ? { tagName: inConfig } : inConfig;\n\n // 1. Automatically derive extendsTagName from prototype chain if not provided\n let extendsTagName = config.extends;\n if (!extendsTagName) {\n let proto = Object.getPrototypeOf(constructor);\n while (proto && proto !== HTMLElement && proto !== Function.prototype) {\n extendsTagName = BUILT_IN_TAG_MAP.get(proto);\n if (extendsTagName) break;\n proto = Object.getPrototypeOf(proto);\n }\n }\n\n // 2. Automatically collect observed attributes from @attributeChanged decorators\n const attributeChangedMap = getAttributeChangedMap(constructor);\n const observedFromDecorators = attributeChangedMap ? Array.from(attributeChangedMap.keys()) : [];\n const mergedObservedAttributes = [...new Set([...(config.observedAttributes ?? []), ...observedFromDecorators])];\n\n // 3. Create a new anonymous class that extends the original constructor\n const NewClass = class extends (constructor as any) {\n static get observedAttributes() {\n return mergedObservedAttributes;\n }\n\n constructor(...args: any[]) {\n super(...args);\n if (config.useShadow === true && !this.shadowRoot) {\n this.attachShadow({ mode: 'open' });\n }\n }\n\n disconnectedCallback() {\n if (super.disconnectedCallback) {\n super.disconnectedCallback();\n }\n }\n\n connectedMoveCallback() {\n if (super.connectedMoveCallback) {\n super.connectedMoveCallback();\n }\n }\n\n adoptedCallback() {\n if (super.adoptedCallback) {\n super.adoptedCallback();\n }\n }\n\n async connectedCallback() {\n if (super.connectedCallback) {\n await super.connectedCallback();\n }\n\n const templateMethod = getTemplateMethod(this);\n const styleMethod = getStyleMethod(this);\n\n const template = templateMethod ? await (this as any)[templateMethod]() : undefined;\n const style = styleMethod ? await (this as any)[styleMethod]() : undefined;\n\n // If not using shadow DOM and no decorators are present, do nothing\n if (!this.shadowRoot && template === undefined && style === undefined) {\n return;\n }\n\n let content = '';\n if (style !== undefined && style.trim().length > 0) {\n content += `<style>${style}</style>`;\n }\n\n if (template !== undefined) {\n content += template;\n } else if (!this.shadowRoot) {\n content += this.innerHTML;\n }\n\n if (this.shadowRoot) {\n this.shadowRoot.innerHTML = content;\n } else {\n this.innerHTML = content;\n }\n }\n\n // 4. Handle attribute changes and route to decorated methods\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n // Call the original callback if it exists\n if (super.attributeChangedCallback) {\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n // Call the method associated with @attributeChanged\n const methodKey = attributeChangedMap?.get(name);\n if (methodKey && typeof (this as any)[methodKey] === 'function') {\n (this as any)[methodKey](newValue, oldValue);\n }\n }\n };\n\n // 5. Register Custom Element using specified or default registry\n const registry = config.customElementRegistry || (typeof customElements !== 'undefined' ? customElements : undefined);\n if (registry && !registry.get(config.tagName)) {\n const options = extendsTagName ? { extends: extendsTagName } : undefined;\n registry.define(config.tagName, NewClass as any, options);\n }\n\n // 6. Save metadata\n ReflectUtils.defineMetadata(ELEMENT_CONFIG_KEY, config, NewClass);\n\n return NewClass as any;\n };\n\nexport const getElementConfig = (target: any): ElementConfig | undefined => {\n const constructor = target instanceof Function ? target : target.constructor;\n return ReflectUtils.getMetadata(ELEMENT_CONFIG_KEY, constructor);\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/decorators/element.ts"],
|
|
4
|
-
"sourcesContent": ["import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';\nimport { getAttributeChangedMap } from './attributeChanged';\nimport { getTemplateMethod } from './template';\nimport { getStyleMethod } from './style';\n\nexport interface ElementConfig {\n tagName: string;\n useShadow?: boolean;\n extends?: string;\n observedAttributes?: string[];\n customElementRegistry?: CustomElementRegistry;\n}\n\nexport const ELEMENT_CONFIG_KEY = Symbol('simple-web-component:element-config');\n\nconst BUILT_IN_TAG_MAP = new Map<any, string>();\n\nconst registerTag = (className: string, tagName: string) => {\n if (typeof globalThis !== 'undefined' && (globalThis as any)[className]) {\n BUILT_IN_TAG_MAP.set((globalThis as any)[className], tagName);\n }\n};\n\n// Register comprehensive list of supported tags for automatic extends inference\n[\n ['HTMLAnchorElement', 'a'],\n ['HTMLAreaElement', 'area'],\n ['HTMLAudioElement', 'audio'],\n ['HTMLBaseElement', 'base'],\n ['HTMLButtonElement', 'button'],\n ['HTMLCanvasElement', 'canvas'],\n ['HTMLDataElement', 'data'],\n ['HTMLDataListElement', 'datalist'],\n ['HTMLDetailsElement', 'details'],\n ['HTMLDialogElement', 'dialog'],\n ['HTMLDivElement', 'div'],\n ['HTMLDListElement', 'dl'],\n ['HTMLEmbedElement', 'embed'],\n ['HTMLFieldSetElement', 'fieldset'],\n ['HTMLFormElement', 'form'],\n ['HTMLHRElement', 'hr'],\n ['HTMLIFrameElement', 'iframe'],\n ['HTMLImageElement', 'img'],\n ['HTMLInputElement', 'input'],\n ['HTMLLabelElement', 'label'],\n ['HTMLLegendElement', 'legend'],\n ['HTMLLIElement', 'li'],\n ['HTMLLinkElement', 'link'],\n ['HTMLMapElement', 'map'],\n ['HTMLMetaElement', 'meta'],\n ['HTMLMeterElement', 'meter'],\n ['HTMLModElement', 'del'],\n ['HTMLObjectElement', 'object'],\n ['HTMLOListElement', 'ol'],\n ['HTMLOptGroupElement', 'optgroup'],\n ['HTMLOptionElement', 'option'],\n ['HTMLOutputElement', 'output'],\n ['HTMLParagraphElement', 'p'],\n ['HTMLParamElement', 'param'],\n ['HTMLPictureElement', 'picture'],\n ['HTMLPreElement', 'pre'],\n ['HTMLProgressElement', 'progress'],\n ['HTMLQuoteElement', 'blockquote'],\n ['HTMLScriptElement', 'script'],\n ['HTMLSelectElement', 'select'],\n ['HTMLSlotElement', 'slot'],\n ['HTMLSourceElement', 'source'],\n ['HTMLSpanElement', 'span'],\n ['HTMLStyleElement', 'style'],\n ['HTMLTableElement', 'table'],\n ['HTMLTableSectionElement', 'tbody'],\n ['HTMLTableCellElement', 'td'],\n ['HTMLTemplateElement', 'template'],\n ['HTMLTextAreaElement', 'textarea'],\n ['HTMLTimeElement', 'time'],\n ['HTMLTitleElement', 'title'],\n ['HTMLTableRowElement', 'tr'],\n ['HTMLTrackElement', 'track'],\n ['HTMLUListElement', 'ul'],\n ['HTMLVideoElement', 'video'],\n ['HTMLHeadingElement', 'h1']\n].forEach(([cls, tag]) => registerTag(cls, tag));\n\nexport const element =\n (inConfig: ElementConfig | string): ClassDecorator =>\n (constructor: any) => {\n const config: ElementConfig = typeof inConfig === 'string' ? { tagName: inConfig } : inConfig;\n\n // 1. Automatically derive extendsTagName from prototype chain if not provided\n let extendsTagName = config.extends;\n if (!extendsTagName) {\n let proto = Object.getPrototypeOf(constructor);\n while (proto && proto !== HTMLElement && proto !== Function.prototype) {\n extendsTagName = BUILT_IN_TAG_MAP.get(proto);\n if (extendsTagName) break;\n proto = Object.getPrototypeOf(proto);\n }\n }\n\n // 2. Automatically collect observed attributes from @attributeChanged decorators\n const attributeChangedMap = getAttributeChangedMap(constructor);\n const observedFromDecorators = attributeChangedMap ? Array.from(attributeChangedMap.keys()) : [];\n const mergedObservedAttributes = [...new Set([...(config.observedAttributes ?? []), ...observedFromDecorators])];\n\n // 3. Create a new anonymous class that extends the original constructor\n const NewClass = class extends (constructor as any) {\n static get observedAttributes() {\n return mergedObservedAttributes;\n }\n\n constructor(...args: any[]) {\n super(...args);\n if (config.useShadow === true && !this.shadowRoot) {\n this.attachShadow({ mode: 'open' });\n }\n }\n\n disconnectedCallback() {\n if (super.disconnectedCallback) {\n super.disconnectedCallback();\n }\n }\n\n connectedMoveCallback() {\n if (super.connectedMoveCallback) {\n super.connectedMoveCallback();\n }\n }\n\n adoptedCallback() {\n if (super.adoptedCallback) {\n super.adoptedCallback();\n }\n }\n\n async connectedCallback() {\n if (super.connectedCallback) {\n await super.connectedCallback();\n }\n\n const templateMethod = getTemplateMethod(this);\n const styleMethod = getStyleMethod(this);\n\n const template = templateMethod ? await (this as any)[templateMethod]() : undefined;\n const style = styleMethod ? await (this as any)[styleMethod]() : undefined;\n\n // If not using shadow DOM and no decorators are present, do nothing\n if (!this.shadowRoot && template === undefined && style === undefined) {\n return;\n }\n\n let content = '';\n if (style !== undefined && style.trim().length > 0) {\n content += `<style>${style}</style>`;\n }\n\n if (template !== undefined) {\n content += template;\n } else if (!this.shadowRoot) {\n content += this.innerHTML;\n }\n\n if (this.shadowRoot) {\n this.shadowRoot.innerHTML = content;\n } else {\n this.innerHTML = content;\n }\n }\n\n // 4. Handle attribute changes and route to decorated methods\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n // Call the original callback if it exists\n if (super.attributeChangedCallback) {\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n // Call the method associated with @attributeChanged\n const methodKey = attributeChangedMap?.get(name);\n if (methodKey && typeof (this as any)[methodKey] === 'function') {\n (this as any)[methodKey](newValue, oldValue);\n }\n }\n };\n\n // 5. Register Custom Element using specified or default registry\n const registry = config.customElementRegistry || (typeof customElements !== 'undefined' ? customElements : undefined);\n if (registry && !registry.get(config.tagName)) {\n const options = extendsTagName ? { extends: extendsTagName } : undefined;\n registry.define(config.tagName, NewClass as any, options);\n }\n\n // 6. Save metadata\n ReflectUtils.defineMetadata(ELEMENT_CONFIG_KEY, config, NewClass);\n\n return NewClass as any;\n };\n\nexport const getElementConfig = (target: any): ElementConfig | undefined => {\n const constructor = target instanceof Function ? target : target.constructor;\n return ReflectUtils.getMetadata(ELEMENT_CONFIG_KEY, constructor);\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../../../src/decorators/element.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;CAC/C;AAED,eAAO,MAAM,kBAAkB,eAAgD,CAAC;AAsEhF,eAAO,MAAM,OAAO,GACjB,UAAU,aAAa,GAAG,MAAM,KAAG,cA+GnC,CAAC;AAEJ,eAAO,MAAM,gBAAgB,GAAI,QAAQ,GAAG,KAAG,aAAa,GAAG,SAG9D,CAAC"}
|