@dooboostore/simple-web-component 1.0.23 → 1.0.25
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 +64 -3212
- package/dist/cjs/decorators/addEventListener.js +1 -1
- package/dist/cjs/decorators/addEventListener.js.map +2 -2
- package/dist/cjs/decorators/applyAttribute.js +148 -0
- package/dist/cjs/decorators/applyAttribute.js.map +7 -0
- package/dist/cjs/decorators/applyClass.js +164 -0
- package/dist/cjs/decorators/applyClass.js.map +7 -0
- package/dist/cjs/decorators/applyNode.js +97 -109
- package/dist/cjs/decorators/applyNode.js.map +2 -2
- package/dist/cjs/decorators/applyStyle.js +135 -0
- package/dist/cjs/decorators/applyStyle.js.map +7 -0
- package/dist/cjs/decorators/attribute.js +24 -11
- package/dist/cjs/decorators/attribute.js.map +2 -2
- package/dist/cjs/decorators/changedAttributeHost.js +1 -1
- package/dist/cjs/decorators/changedAttributeHost.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +14 -23
- package/dist/cjs/decorators/elementDefine.js.map +2 -2
- package/dist/cjs/decorators/emitCustomEvent.js +5 -2
- package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
- package/dist/cjs/decorators/index.js +3 -3
- package/dist/cjs/decorators/index.js.map +2 -2
- package/dist/cjs/decorators/lifecycles.js +9 -9
- package/dist/cjs/decorators/lifecycles.js.map +2 -2
- package/dist/cjs/decorators/query.js +78 -3
- package/dist/cjs/decorators/query.js.map +2 -2
- package/dist/cjs/decorators/queryAll.js +78 -3
- package/dist/cjs/decorators/queryAll.js.map +2 -2
- package/dist/cjs/elements/SwcAppEngine.js +19 -4
- package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
- package/dist/cjs/elements/SwcAppMixin.js +2 -0
- package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
- package/dist/cjs/index.js +4 -4
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/utils/Utils.js +141 -2
- package/dist/cjs/utils/Utils.js.map +2 -2
- package/dist/esm/decorators/addEventListener.js +1 -1
- package/dist/esm/decorators/addEventListener.js.map +2 -2
- package/dist/esm/decorators/applyAttribute.js +129 -0
- package/dist/esm/decorators/applyAttribute.js.map +7 -0
- package/dist/esm/decorators/applyClass.js +145 -0
- package/dist/esm/decorators/applyClass.js.map +7 -0
- package/dist/esm/decorators/applyNode.js +97 -109
- package/dist/esm/decorators/applyNode.js.map +2 -2
- package/dist/esm/decorators/applyStyle.js +116 -0
- package/dist/esm/decorators/applyStyle.js.map +7 -0
- package/dist/esm/decorators/attribute.js +24 -11
- package/dist/esm/decorators/attribute.js.map +2 -2
- package/dist/esm/decorators/changedAttributeHost.js +1 -1
- package/dist/esm/decorators/changedAttributeHost.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +14 -23
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/emitCustomEvent.js +5 -2
- package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
- package/dist/esm/decorators/index.js +3 -3
- package/dist/esm/decorators/index.js.map +1 -1
- package/dist/esm/decorators/lifecycles.js +9 -9
- package/dist/esm/decorators/lifecycles.js.map +2 -2
- package/dist/esm/decorators/query.js +78 -3
- package/dist/esm/decorators/query.js.map +2 -2
- package/dist/esm/decorators/queryAll.js +78 -3
- package/dist/esm/decorators/queryAll.js.map +2 -2
- package/dist/esm/elements/SwcAppEngine.js +19 -4
- package/dist/esm/elements/SwcAppEngine.js.map +2 -2
- package/dist/esm/elements/SwcAppMixin.js +2 -0
- package/dist/esm/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm/index.js +4 -4
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/utils/Utils.js +141 -2
- package/dist/esm/utils/Utils.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +3191 -506
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
- package/dist/types/decorators/addEventListener.d.ts.map +1 -1
- package/dist/types/decorators/applyAttribute.d.ts +22 -0
- package/dist/types/decorators/applyAttribute.d.ts.map +1 -0
- package/dist/types/decorators/applyClass.d.ts +65 -0
- package/dist/types/decorators/applyClass.d.ts.map +1 -0
- package/dist/types/decorators/applyNode.d.ts +18 -104
- package/dist/types/decorators/applyNode.d.ts.map +1 -1
- package/dist/types/decorators/applyStyle.d.ts +21 -0
- package/dist/types/decorators/applyStyle.d.ts.map +1 -0
- package/dist/types/decorators/attribute.d.ts +12 -14
- package/dist/types/decorators/attribute.d.ts.map +1 -1
- package/dist/types/decorators/changedAttributeHost.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/emitCustomEvent.d.ts +1 -1
- package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
- package/dist/types/decorators/index.d.ts +3 -3
- package/dist/types/decorators/index.d.ts.map +1 -1
- package/dist/types/decorators/lifecycles.d.ts.map +1 -1
- package/dist/types/decorators/query.d.ts +68 -4
- package/dist/types/decorators/query.d.ts.map +1 -1
- package/dist/types/decorators/queryAll.d.ts +70 -1
- package/dist/types/decorators/queryAll.d.ts.map +1 -1
- package/dist/types/elements/SwcAppEngine.d.ts +7 -0
- package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/utils/Utils.d.ts +49 -0
- package/dist/types/utils/Utils.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +3191 -506
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
- package/package.json +3 -3
- package/src/decorators/addEventListener.ts +1 -1
- package/src/decorators/applyAttribute.ts +147 -0
- package/src/decorators/applyClass.ts +158 -0
- package/src/decorators/applyNode.ts +126 -225
- package/src/decorators/applyStyle.ts +128 -0
- package/src/decorators/attribute.ts +42 -43
- package/src/decorators/changedAttributeHost.ts +2 -2
- package/src/decorators/elementDefine.ts +18 -39
- package/src/decorators/emitCustomEvent.ts +6 -3
- package/src/decorators/index.ts +3 -3
- package/src/decorators/lifecycles.ts +9 -11
- package/src/decorators/query.ts +148 -6
- package/src/decorators/queryAll.ts +149 -3
- package/src/elements/SwcAppEngine.ts +32 -4
- package/src/elements/SwcAppMixin.ts +2 -0
- package/src/index.ts +6 -6
- package/src/utils/Utils.ts +146 -1
- package/dist/cjs/decorators/classList.js +0 -134
- package/dist/cjs/decorators/classList.js.map +0 -7
- package/dist/cjs/decorators/setAttribute.js +0 -111
- package/dist/cjs/decorators/setAttribute.js.map +0 -7
- package/dist/cjs/decorators/style.js +0 -114
- package/dist/cjs/decorators/style.js.map +0 -7
- package/dist/cjs/utils/TemplateUtils.js +0 -109
- package/dist/cjs/utils/TemplateUtils.js.map +0 -7
- package/dist/esm/decorators/classList.js +0 -115
- package/dist/esm/decorators/classList.js.map +0 -7
- package/dist/esm/decorators/setAttribute.js +0 -92
- package/dist/esm/decorators/setAttribute.js.map +0 -7
- package/dist/esm/decorators/style.js +0 -95
- package/dist/esm/decorators/style.js.map +0 -7
- package/dist/esm/utils/TemplateUtils.js +0 -90
- package/dist/esm/utils/TemplateUtils.js.map +0 -7
- package/dist/types/decorators/classList.d.ts +0 -61
- package/dist/types/decorators/classList.d.ts.map +0 -1
- package/dist/types/decorators/setAttribute.d.ts +0 -23
- package/dist/types/decorators/setAttribute.d.ts.map +0 -1
- package/dist/types/decorators/style.d.ts +0 -49
- package/dist/types/decorators/style.d.ts.map +0 -1
- package/dist/types/utils/TemplateUtils.d.ts +0 -59
- package/dist/types/utils/TemplateUtils.d.ts.map +0 -1
- package/src/decorators/classList.ts +0 -172
- package/src/decorators/setAttribute.ts +0 -113
- package/src/decorators/style.ts +0 -140
- package/src/utils/TemplateUtils.ts +0 -92
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { ReflectUtils } from '@dooboostore/core';
|
|
2
2
|
import { ensureInit, getElementConfig } from './elementDefine';
|
|
3
|
-
import { SwcRootType } from '../types';
|
|
3
|
+
import { HelperHostSet, SwcRootType } from '../types';
|
|
4
|
+
import { SwcUtils } from "../utils/Utils";
|
|
4
5
|
|
|
5
6
|
export type ApplyNodePosition = 'beforeBegin' | 'afterBegin' | 'beforeEnd' | 'afterEnd' | 'replace' | 'replaceChildren' | 'innerHtml' | 'innerText' | 'remove';
|
|
6
7
|
|
|
7
8
|
export interface ApplyNodeOptions {
|
|
8
9
|
position?: ApplyNodePosition;
|
|
9
10
|
root?: SwcRootType;
|
|
11
|
+
/**
|
|
12
|
+
* Filter function to determine whether to perform DOM operation.
|
|
13
|
+
* If it returns false, the operation is skipped.
|
|
14
|
+
*/
|
|
15
|
+
filter?: (target: HTMLElement | ShadowRoot, newValue: any, helper: HelperHostSet) => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Optional loading content to display while an async method is executing.
|
|
18
|
+
*/
|
|
19
|
+
loading?: (helper: HelperHostSet) => any;
|
|
10
20
|
}
|
|
11
21
|
|
|
12
22
|
export interface ApplyNodeMetadata {
|
|
@@ -15,7 +25,7 @@ export interface ApplyNodeMetadata {
|
|
|
15
25
|
options: ApplyNodeOptions;
|
|
16
26
|
}
|
|
17
27
|
|
|
18
|
-
export const APPLY_NODE_METADATA_KEY = Symbol('simple-web-component:apply-node');
|
|
28
|
+
export const APPLY_NODE_METADATA_KEY = Symbol.for('simple-web-component:apply-node');
|
|
19
29
|
|
|
20
30
|
const normalizeNodes = (res: any, doc: Document): Node[] => {
|
|
21
31
|
const items = Array.isArray(res) ? res : [res];
|
|
@@ -25,37 +35,41 @@ const normalizeNodes = (res: any, doc: Document): Node[] => {
|
|
|
25
35
|
});
|
|
26
36
|
};
|
|
27
37
|
|
|
38
|
+
const applyToDom = (targetEl: any, res: any, pos: ApplyNodePosition, doc: Document) => {
|
|
39
|
+
if (!targetEl) return;
|
|
40
|
+
|
|
41
|
+
if (pos === 'innerHtml') {
|
|
42
|
+
targetEl.innerHTML = res !== undefined && res !== null ? String(res) : '';
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (pos === 'innerText') {
|
|
47
|
+
if (targetEl.innerText !== undefined) {
|
|
48
|
+
targetEl.innerText = res !== undefined && res !== null ? String(res) : '';
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const isShadowRoot = targetEl instanceof ShadowRoot;
|
|
54
|
+
const nodes = normalizeNodes(res, doc);
|
|
55
|
+
if (pos === 'replace') {
|
|
56
|
+
if (!isShadowRoot) targetEl.replaceWith(...nodes);
|
|
57
|
+
} else if (pos === 'replaceChildren') {
|
|
58
|
+
targetEl.replaceChildren(...nodes);
|
|
59
|
+
} else {
|
|
60
|
+
if (pos === 'beforeEnd') targetEl.append(...nodes);
|
|
61
|
+
else if (pos === 'afterBegin') targetEl.prepend(...nodes);
|
|
62
|
+
else if (pos === 'beforeBegin' && !isShadowRoot) targetEl.before(...nodes);
|
|
63
|
+
else if (pos === 'afterEnd' && !isShadowRoot) targetEl.after(...nodes);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
28
67
|
/**
|
|
29
68
|
* @applyNode decorator to surgically add/replace nodes to a target element.
|
|
30
|
-
*
|
|
31
|
-
* Usage examples:
|
|
32
|
-
* @applyNode('#list') addItem() { return '<li>New Item</li>'; } // append at end
|
|
33
|
-
* @applyNode('#header', { position: 'afterBegin' }) prependItem() { return '<h1>Title</h1>'; } // prepend at start
|
|
34
|
-
* @applyNode('#item', { position: 'replace' }) replaceItem() { return '<div>Replaced</div>'; } // replace element
|
|
35
|
-
* @applyNode('#list', { position: 'replaceChildren' }) updateList() { return [item1, item2]; } // replace all children
|
|
36
|
-
* @applyNode('#notification', { position: 'remove' }) dismissNotification() { return shouldDismiss; } // remove if truthy
|
|
37
|
-
* @applyNode('.items', { position: 'remove', root: 'shadow' }) clearItems() { return true; } // remove shadow DOM elements
|
|
38
|
-
*
|
|
39
|
-
* Positions:
|
|
40
|
-
* - 'beforeEnd' (default): Append at end of target
|
|
41
|
-
* - 'afterBegin': Prepend at start of target
|
|
42
|
-
* - 'beforeBegin': Insert before target
|
|
43
|
-
* - 'afterEnd': Insert after target
|
|
44
|
-
* - 'replace': Replace the entire target element
|
|
45
|
-
* - 'replaceChildren': Replace all children of target element
|
|
46
|
-
* - 'innerHtml': Set target's innerHTML
|
|
47
|
-
* - 'innerText': Set target's innerText
|
|
48
|
-
* - 'remove': Remove target element if returned value is truthy
|
|
49
|
-
*
|
|
50
|
-
* Root Options:
|
|
51
|
-
* - 'auto' (default): Search shadow DOM first, then light DOM
|
|
52
|
-
* - 'shadow': Search only in shadow DOM
|
|
53
|
-
* - 'light': Search only in light DOM
|
|
54
|
-
* - 'all': Use both (shadow preferred for query, both for remove)
|
|
55
69
|
*/
|
|
56
70
|
export function applyNode(selector: string, options: ApplyNodeOptions = { position: 'beforeEnd' }): MethodDecorator {
|
|
57
|
-
return (
|
|
58
|
-
const constructor =
|
|
71
|
+
return (targetObj: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
|
|
72
|
+
const constructor = targetObj.constructor;
|
|
59
73
|
let metaList = ReflectUtils.getOwnMetadata(APPLY_NODE_METADATA_KEY, constructor) as Map<string | symbol, ApplyNodeMetadata>;
|
|
60
74
|
if (!metaList) {
|
|
61
75
|
metaList = new Map<string | symbol, ApplyNodeMetadata>();
|
|
@@ -64,95 +78,71 @@ export function applyNode(selector: string, options: ApplyNodeOptions = { positi
|
|
|
64
78
|
metaList.set(propertyKey, { propertyKey, selector, options });
|
|
65
79
|
|
|
66
80
|
const original = descriptor.value;
|
|
67
|
-
descriptor.value =
|
|
81
|
+
descriptor.value = function (...args: any[]) {
|
|
68
82
|
ensureInit(this);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
83
|
+
|
|
84
|
+
const conf = getElementConfig(this);
|
|
85
|
+
const currentWin = (this as any)._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as Window);
|
|
86
|
+
const currentDoc = currentWin.document;
|
|
87
|
+
const hostSet = SwcUtils.getHelperAndHostSet(currentWin, this);
|
|
88
|
+
|
|
89
|
+
const getTarget = () => {
|
|
76
90
|
const r = options.root || 'auto';
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (r === '
|
|
80
|
-
if (r === '
|
|
81
|
-
if (r === '
|
|
82
|
-
return
|
|
91
|
+
const applyRoot = (t: any) => {
|
|
92
|
+
if (!t) return t;
|
|
93
|
+
if (r === 'auto') return t.shadowRoot || t;
|
|
94
|
+
if (r === 'shadow') return t.shadowRoot;
|
|
95
|
+
if (r === 'light') return t;
|
|
96
|
+
if (r === 'all') return t.shadowRoot || t;
|
|
97
|
+
return t;
|
|
83
98
|
};
|
|
84
99
|
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
(this as any).remove();
|
|
95
|
-
}
|
|
96
|
-
} else {
|
|
97
|
-
const targetRoot = getTargetRoot();
|
|
98
|
-
if (targetRoot) {
|
|
99
|
-
const targets = targetRoot.querySelectorAll(selector);
|
|
100
|
-
targets.forEach((el: Element) => el.remove());
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
} else {
|
|
105
|
-
let targetEl: any = null;
|
|
106
|
-
if (selector === ':host' || !selector) {
|
|
107
|
-
if (r === 'shadow') {
|
|
108
|
-
targetEl = this.shadowRoot; // Target shadow DOM root
|
|
109
|
-
} else {
|
|
110
|
-
targetEl = this as any; // Target the component itself
|
|
111
|
-
}
|
|
112
|
-
} else {
|
|
113
|
-
const targetRoot = getTargetRoot();
|
|
114
|
-
targetEl = targetRoot ? targetRoot.querySelector(selector) : null;
|
|
115
|
-
}
|
|
100
|
+
if (selector === ':host') return applyRoot(this);
|
|
101
|
+
if (selector === ':parentHost') return applyRoot(hostSet.$parentHost);
|
|
102
|
+
if (selector === ':appHost') return applyRoot(hostSet.$appHost);
|
|
103
|
+
if (selector === ':firstHost') return applyRoot(hostSet.$firstHost);
|
|
104
|
+
if (selector === ':lastHost') return applyRoot(hostSet.$lastHost);
|
|
105
|
+
|
|
106
|
+
const targetRoot = applyRoot(this);
|
|
107
|
+
return targetRoot ? targetRoot.querySelector(selector) : null;
|
|
108
|
+
};
|
|
116
109
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const nodes = normalizeNodes(res, currentDoc);
|
|
110
|
+
const targetEl = getTarget();
|
|
111
|
+
const res = original.apply(this, args);
|
|
120
112
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
} else {
|
|
138
|
-
/*
|
|
139
|
-
<!-- beforebegin -->
|
|
140
|
-
<p>
|
|
141
|
-
<!-- afterbegin -->
|
|
142
|
-
foo
|
|
143
|
-
<!-- beforeend -->
|
|
144
|
-
</p>
|
|
145
|
-
<!-- afterend -->
|
|
146
|
-
*/
|
|
147
|
-
if (pos === 'beforeEnd') targetEl.append(...nodes);
|
|
148
|
-
else if (pos === 'afterBegin') targetEl.prepend(...nodes);
|
|
149
|
-
else if (pos === 'beforeBegin' && !isShadowRoot) targetEl.before(...nodes);
|
|
150
|
-
else if (pos === 'afterEnd' && !isShadowRoot) targetEl.after(...nodes);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
113
|
+
const runApply = (target: any, val: any) => {
|
|
114
|
+
const pos = options.position || 'beforeEnd';
|
|
115
|
+
|
|
116
|
+
// Intelligent Default Filter
|
|
117
|
+
const defaultFilter = (t: any, v: any) => {
|
|
118
|
+
if (v instanceof Node) return !t.contains(v);
|
|
119
|
+
if (pos === 'innerHtml' && typeof v === 'string') return t.innerHTML !== v;
|
|
120
|
+
if (pos === 'replaceChildren' && v instanceof Node) return !t.contains(v);
|
|
121
|
+
return true;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const activeFilter = options.filter || defaultFilter;
|
|
125
|
+
|
|
126
|
+
if (activeFilter(target, val, hostSet)) {
|
|
127
|
+
applyToDom(target, val, pos, currentDoc);
|
|
153
128
|
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
if (res instanceof Promise) {
|
|
132
|
+
// 비동기일 때만 로딩 표시
|
|
133
|
+
if (targetEl && options.loading) {
|
|
134
|
+
const loadingRes = options.loading.call(this, hostSet);
|
|
135
|
+
applyToDom(targetEl, loadingRes, options.position || 'beforeEnd', currentDoc);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return res.then(finalRes => {
|
|
139
|
+
if (finalRes !== undefined && targetEl) runApply(targetEl, finalRes);
|
|
140
|
+
return finalRes;
|
|
141
|
+
});
|
|
142
|
+
} else {
|
|
143
|
+
if (res !== undefined && targetEl) runApply(targetEl, res);
|
|
144
|
+
return res;
|
|
154
145
|
}
|
|
155
|
-
return res;
|
|
156
146
|
};
|
|
157
147
|
};
|
|
158
148
|
}
|
|
@@ -168,123 +158,34 @@ export const findAllApplyNodeMetadata = (target: any): Map<string | symbol, Appl
|
|
|
168
158
|
return result;
|
|
169
159
|
};
|
|
170
160
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return applyNode(':host', options);
|
|
161
|
+
export function applyNodeHost(options: ApplyNodeOptions): MethodDecorator;
|
|
162
|
+
export function applyNodeHost(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void;
|
|
163
|
+
export function applyNodeHost(targetOrOptions?: any, propertyKey?: string | symbol, descriptor?: PropertyDescriptor): any {
|
|
164
|
+
if (propertyKey !== undefined) return applyNode(':host', { position: 'beforeEnd' })(targetOrOptions, propertyKey, descriptor);
|
|
165
|
+
const opt = targetOrOptions || {};
|
|
166
|
+
return applyNode(':host', { position: 'beforeEnd', ...opt });
|
|
178
167
|
}
|
|
179
168
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* @applyAfterBeginNode - Prepend to target element
|
|
190
|
-
*/
|
|
191
|
-
export const applyAfterBeginNode = (selector: string, options: ApplyNodeOptions = {}) =>
|
|
192
|
-
applyNode(selector, { ...options, position: 'afterBegin' });
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* @applyBeforeEndNode - Append to target element (default)
|
|
196
|
-
*/
|
|
197
|
-
export const applyBeforeEndNode = (selector: string, options: ApplyNodeOptions = {}) =>
|
|
198
|
-
applyNode(selector, { ...options, position: 'beforeEnd' });
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* @applyAfterEndNode - Insert after target element
|
|
202
|
-
*/
|
|
203
|
-
export const applyAfterEndNode = (selector: string, options: ApplyNodeOptions = {}) =>
|
|
204
|
-
applyNode(selector, { ...options, position: 'afterEnd' });
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* @applyReplaceNode - Replace entire target element
|
|
208
|
-
*/
|
|
209
|
-
export const applyReplaceNode = (selector: string, options: ApplyNodeOptions = {}) =>
|
|
210
|
-
applyNode(selector, { ...options, position: 'replace' });
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* @applyReplaceChildrenNode - Replace all children of target element
|
|
214
|
-
*/
|
|
215
|
-
export const applyReplaceChildrenNode = (selector: string, options: ApplyNodeOptions = {}) =>
|
|
216
|
-
applyNode(selector, { ...options, position: 'replaceChildren' });
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* @applyInnerHtmlNode - Set target's innerHTML
|
|
220
|
-
*/
|
|
221
|
-
export const applyInnerHtmlNode = (selector: string, options: ApplyNodeOptions = {}) =>
|
|
222
|
-
applyNode(selector, { ...options, position: 'innerHtml' });
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* @applyInnerTextNode - Set target's innerText
|
|
226
|
-
*/
|
|
227
|
-
export const applyInnerTextNode = (selector: string, options: ApplyNodeOptions = {}) =>
|
|
228
|
-
applyNode(selector, { ...options, position: 'innerText' });
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* @applyRemoveNode - Remove target element if truthy
|
|
232
|
-
*/
|
|
233
|
-
export const applyRemoveNode = (selector: string, options: ApplyNodeOptions = {}) =>
|
|
234
|
-
applyNode(selector, { ...options, position: 'remove' });
|
|
235
|
-
|
|
236
|
-
// Host versions
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* @applyBeforeBeginNodeHost - Insert before :host
|
|
240
|
-
*/
|
|
241
|
-
export const applyBeforeBeginNodeHost = (options: ApplyNodeOptions = {}) =>
|
|
242
|
-
applyNode(':host', { ...options, position: 'beforeBegin' });
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* @applyAfterBeginNodeHost - Prepend to :host
|
|
246
|
-
*/
|
|
247
|
-
export const applyAfterBeginNodeHost = (options: ApplyNodeOptions = {}) =>
|
|
248
|
-
applyNode(':host', { ...options, position: 'afterBegin' });
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* @applyBeforeEndNodeHost - Append to :host
|
|
252
|
-
*/
|
|
253
|
-
export const applyBeforeEndNodeHost = (options: ApplyNodeOptions = {}) =>
|
|
254
|
-
applyNode(':host', { ...options, position: 'beforeEnd' });
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* @applyAfterEndNodeHost - Insert after :host
|
|
258
|
-
*/
|
|
259
|
-
export const applyAfterEndNodeHost = (options: ApplyNodeOptions = {}) =>
|
|
260
|
-
applyNode(':host', { ...options, position: 'afterEnd' });
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* @applyReplaceNodeHost - Replace :host
|
|
264
|
-
*/
|
|
265
|
-
export const applyReplaceNodeHost = (options: ApplyNodeOptions = {}) =>
|
|
266
|
-
applyNode(':host', { ...options, position: 'replace' });
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* @applyReplaceChildrenNodeHost - Replace children of :host
|
|
270
|
-
*/
|
|
271
|
-
export const applyReplaceChildrenNodeHost = (options: ApplyNodeOptions = {}) =>
|
|
272
|
-
applyNode(':host', { ...options, position: 'replaceChildren' });
|
|
169
|
+
export function applyReplaceChildrenNodeHost(options: ApplyNodeOptions): MethodDecorator;
|
|
170
|
+
export function applyReplaceChildrenNodeHost(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void;
|
|
171
|
+
export function applyReplaceChildrenNodeHost(targetOrOptions?: any, propertyKey?: string | symbol, descriptor?: PropertyDescriptor): any {
|
|
172
|
+
if (propertyKey !== undefined) return applyNode(':host', { position: 'replaceChildren' })(targetOrOptions, propertyKey, descriptor);
|
|
173
|
+
const opt = targetOrOptions || {};
|
|
174
|
+
return applyNode(':host', { position: 'replaceChildren', ...opt });
|
|
175
|
+
}
|
|
273
176
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
177
|
+
export function applyInnerHtmlNodeHost(options: ApplyNodeOptions): MethodDecorator;
|
|
178
|
+
export function applyInnerHtmlNodeHost(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void;
|
|
179
|
+
export function applyInnerHtmlNodeHost(targetOrOptions?: any, propertyKey?: string | symbol, descriptor?: PropertyDescriptor): any {
|
|
180
|
+
if (propertyKey !== undefined) return applyNode(':host', { position: 'innerHtml' })(targetOrOptions, propertyKey, descriptor);
|
|
181
|
+
const opt = targetOrOptions || {};
|
|
182
|
+
return applyNode(':host', { position: 'innerHtml', ...opt });
|
|
183
|
+
}
|
|
279
184
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
export const applyInnerTextNodeHost = (options: ApplyNodeOptions = {}) =>
|
|
284
|
-
applyNode(':host', { ...options, position: 'innerText' });
|
|
185
|
+
export function applyReplaceChildrenNode(selector: string, options: ApplyNodeOptions = {}): MethodDecorator {
|
|
186
|
+
return applyNode(selector, { ...options, position: 'replaceChildren' });
|
|
187
|
+
}
|
|
285
188
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
export const applyRemoveNodeHost = (options: ApplyNodeOptions = {}) =>
|
|
290
|
-
applyNode(':host', { ...options, position: 'remove' });
|
|
189
|
+
export function applyInnerHtmlNode(selector: string, options: ApplyNodeOptions = {}): MethodDecorator {
|
|
190
|
+
return applyNode(selector, { ...options, position: 'innerHtml' });
|
|
191
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
|
+
import { ensureInit } from './elementDefine';
|
|
3
|
+
import { SwcUtils } from '../utils/Utils';
|
|
4
|
+
import { SwcQueryOptions, HelperHostSet } from '../types';
|
|
5
|
+
|
|
6
|
+
export type StyleAction = 'set' | 'update' | 'remove';
|
|
7
|
+
|
|
8
|
+
export interface StyleApplyOptions extends SwcQueryOptions {}
|
|
9
|
+
|
|
10
|
+
export interface StyleApplyMetadata {
|
|
11
|
+
propertyKey: string | symbol;
|
|
12
|
+
selector: string;
|
|
13
|
+
action: StyleAction;
|
|
14
|
+
options: StyleApplyOptions;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const STYLE_METADATA_KEY = Symbol.for('simple-web-component:style');
|
|
18
|
+
|
|
19
|
+
function createStyleDecorator(action: StyleAction) {
|
|
20
|
+
return (selector: string, options: StyleApplyOptions = {}): MethodDecorator => {
|
|
21
|
+
return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
|
|
22
|
+
const constructor = target.constructor;
|
|
23
|
+
let metaList = ReflectUtils.getOwnMetadata(STYLE_METADATA_KEY, constructor) as Map<string | symbol, StyleApplyMetadata>;
|
|
24
|
+
if (!metaList) {
|
|
25
|
+
metaList = new Map<string | symbol, StyleApplyMetadata>();
|
|
26
|
+
ReflectUtils.defineMetadata(STYLE_METADATA_KEY, metaList, constructor);
|
|
27
|
+
}
|
|
28
|
+
metaList.set(propertyKey, { propertyKey, selector, action, options });
|
|
29
|
+
|
|
30
|
+
const original = descriptor.value;
|
|
31
|
+
descriptor.value = async function (...args: any[]) {
|
|
32
|
+
ensureInit(this);
|
|
33
|
+
const res = await (original as any).apply(this, args);
|
|
34
|
+
if (res !== undefined) {
|
|
35
|
+
const win = (this as any).ownerDocument?.defaultView || window;
|
|
36
|
+
const host = this as unknown as HTMLElement;
|
|
37
|
+
const hostSet = { ...SwcUtils.getHelperAndHostSet(win, host), $this: this };
|
|
38
|
+
const r = options.root || 'auto';
|
|
39
|
+
const targetEls: HTMLElement[] = [];
|
|
40
|
+
|
|
41
|
+
const applyRoot = (t: any) => {
|
|
42
|
+
if (!t || !(t instanceof win.HTMLElement)) return;
|
|
43
|
+
targetEls.push(t);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
if (selector === ':parentHost') applyRoot(hostSet.$parentHost);
|
|
47
|
+
else if (selector === ':appHost') applyRoot(hostSet.$appHost);
|
|
48
|
+
else if (selector === ':firstHost') applyRoot(hostSet.$firstHost);
|
|
49
|
+
else if (selector === ':lastHost') applyRoot(hostSet.$lastHost);
|
|
50
|
+
else if (selector === ':firstAppHost') applyRoot(hostSet.$firstAppHost);
|
|
51
|
+
else if (selector === ':lastAppHost') applyRoot(hostSet.$lastAppHost);
|
|
52
|
+
else if (selector === ':hosts') hostSet.$hosts.forEach(applyRoot);
|
|
53
|
+
else if (selector === ':appHosts') hostSet.$appHosts.forEach(applyRoot);
|
|
54
|
+
else if (selector === ':host' || !selector) applyRoot(host);
|
|
55
|
+
else {
|
|
56
|
+
const targetRoot = r === 'auto' ? (host.shadowRoot || host) : (r === 'shadow' ? host.shadowRoot : host);
|
|
57
|
+
if (targetRoot) {
|
|
58
|
+
const found = targetRoot.querySelectorAll(selector);
|
|
59
|
+
if (found) targetEls.push(...(Array.from(found) as HTMLElement[]));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
targetEls.forEach(targetEl => {
|
|
64
|
+
const resolvedRes = typeof res === 'function' ? (res as any)(targetEl, hostSet) : res;
|
|
65
|
+
|
|
66
|
+
if (action === 'set' || action === 'update') {
|
|
67
|
+
if (action === 'set') targetEl.style.cssText = '';
|
|
68
|
+
|
|
69
|
+
if (typeof resolvedRes === 'object' && resolvedRes !== null && !Array.isArray(resolvedRes)) {
|
|
70
|
+
Object.entries(resolvedRes as any).forEach(([prop, val]) => {
|
|
71
|
+
const finalVal = typeof val === 'function' ? val(targetEl, hostSet) : val;
|
|
72
|
+
if (finalVal === null || finalVal === undefined) {
|
|
73
|
+
targetEl.style.removeProperty(prop);
|
|
74
|
+
} else {
|
|
75
|
+
targetEl.style[prop as any] = String(finalVal);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
} else if (typeof resolvedRes === 'string') {
|
|
79
|
+
targetEl.style.cssText = resolvedRes;
|
|
80
|
+
}
|
|
81
|
+
} else if (action === 'remove') {
|
|
82
|
+
if (typeof resolvedRes === 'object' && resolvedRes !== null && !Array.isArray(resolvedRes)) {
|
|
83
|
+
Object.entries(resolvedRes as any).forEach(([prop, val]) => {
|
|
84
|
+
const shouldRemove = typeof val === 'function' ? val(targetEl, hostSet) : !!val;
|
|
85
|
+
if (shouldRemove) {
|
|
86
|
+
targetEl.style.removeProperty(prop);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
const props = Array.isArray(resolvedRes) ? resolvedRes : [resolvedRes];
|
|
91
|
+
props.forEach(p => targetEl.style.removeProperty(String(p)));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return res;
|
|
97
|
+
};
|
|
98
|
+
return descriptor;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function applyStyle(selector: string, action: StyleAction = 'update', options: StyleApplyOptions = {}): MethodDecorator {
|
|
104
|
+
return createStyleDecorator(action)(selector, options);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const setStyle = (selector: string, options: StyleApplyOptions = {}) => createStyleDecorator('set')(selector, options);
|
|
108
|
+
export const updateStyle = (selector: string, options: StyleApplyOptions = {}) => createStyleDecorator('update')(selector, options);
|
|
109
|
+
export const removeStyle = (selector: string, options: StyleApplyOptions = {}) => createStyleDecorator('remove')(selector, options);
|
|
110
|
+
|
|
111
|
+
// Host versions
|
|
112
|
+
export function applyStyleHost(action: StyleAction = 'update', options: StyleApplyOptions = {}): MethodDecorator {
|
|
113
|
+
return createStyleDecorator(action)(':host', options);
|
|
114
|
+
}
|
|
115
|
+
export const setStyleHost = (options: StyleApplyOptions = {}) => createStyleDecorator('set')(':host', options);
|
|
116
|
+
export const updateStyleHost = (options: StyleApplyOptions = {}) => createStyleDecorator('update')(':host', options);
|
|
117
|
+
export const removeStyleHost = (options: StyleApplyOptions = {}) => createStyleDecorator('remove')(':host', options);
|
|
118
|
+
|
|
119
|
+
export const findAllStyleMetadata = (target: any): Map<string | symbol, StyleApplyMetadata> => {
|
|
120
|
+
const result = new Map<string | symbol, StyleApplyMetadata>();
|
|
121
|
+
const maps = ReflectUtils.findAllMetadata<Map<string | symbol, StyleApplyMetadata>>(STYLE_METADATA_KEY, target);
|
|
122
|
+
maps.forEach(map => {
|
|
123
|
+
if (map instanceof Map) {
|
|
124
|
+
map.forEach((v, k) => result.set(k, v));
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
return result;
|
|
128
|
+
};
|