@dooboostore/simple-web-component 1.0.15 → 1.0.16
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 +183 -92
- package/dist/cjs/decorators/addEventListener.js +2 -3
- package/dist/cjs/decorators/addEventListener.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +89 -33
- package/dist/cjs/decorators/elementDefine.js.map +2 -2
- package/dist/cjs/decorators/emitCustomEvent.js +2 -14
- package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
- package/dist/cjs/decorators/query.js +25 -36
- package/dist/cjs/decorators/query.js.map +2 -2
- package/dist/cjs/decorators/queryAll.js +28 -36
- package/dist/cjs/decorators/queryAll.js.map +2 -2
- package/dist/cjs/types.js +1 -0
- package/dist/cjs/types.js.map +2 -2
- package/dist/cjs/utils/Utils.js +36 -143
- package/dist/cjs/utils/Utils.js.map +2 -2
- package/dist/esm/decorators/addEventListener.js +2 -3
- package/dist/esm/decorators/addEventListener.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +89 -33
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/emitCustomEvent.js +2 -14
- package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
- package/dist/esm/decorators/query.js +25 -36
- package/dist/esm/decorators/query.js.map +2 -2
- package/dist/esm/decorators/queryAll.js +28 -36
- package/dist/esm/decorators/queryAll.js.map +2 -2
- package/dist/esm/types.js +1 -0
- package/dist/esm/types.js.map +2 -2
- package/dist/esm/utils/Utils.js +36 -143
- package/dist/esm/utils/Utils.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +183 -266
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +3 -3
- package/dist/types/decorators/addEventListener.d.ts +9 -4
- package/dist/types/decorators/addEventListener.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
- package/dist/types/decorators/query.d.ts +6 -5
- package/dist/types/decorators/query.d.ts.map +1 -1
- package/dist/types/decorators/queryAll.d.ts +6 -5
- package/dist/types/decorators/queryAll.d.ts.map +1 -1
- package/dist/types/types.d.ts +3 -1
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/Utils.d.ts +6 -14
- package/dist/types/utils/Utils.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +183 -266
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +3 -3
- package/package.json +3 -3
- package/src/decorators/addEventListener.ts +10 -7
- package/src/decorators/elementDefine.ts +86 -31
- package/src/decorators/emitCustomEvent.ts +5 -21
- package/src/decorators/query.ts +33 -46
- package/src/decorators/queryAll.ts +36 -46
- package/src/types.ts +6 -4
- package/src/utils/Utils.ts +40 -176
package/src/utils/Utils.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SwcAppInterface, HostSet } from '../types';
|
|
2
|
+
import { getElementConfig } from '../decorators/elementDefine';
|
|
2
3
|
|
|
3
4
|
export const SWC_NOT_FOUND = Symbol('SWC_NOT_FOUND');
|
|
4
5
|
|
|
@@ -7,177 +8,45 @@ export class SwcUtils {
|
|
|
7
8
|
if (!obj || !path) return SWC_NOT_FOUND;
|
|
8
9
|
|
|
9
10
|
const parts = path.split('.');
|
|
11
|
+
let current = obj;
|
|
10
12
|
|
|
11
|
-
// 1. If the path starts with the rootName (alias), strip it and resolve within obj
|
|
12
|
-
if (parts[0] === rootName && parts.length > 1) {
|
|
13
|
-
const subParts = parts.slice(1);
|
|
14
|
-
let subResult = obj;
|
|
15
|
-
for (const part of subParts) {
|
|
16
|
-
if (subResult === null || typeof subResult !== 'object' || !(part in subResult)) return SWC_NOT_FOUND;
|
|
17
|
-
subResult = subResult[part];
|
|
18
|
-
}
|
|
19
|
-
return subResult;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// 2. Fallback: resolve directly on obj (standard behavior)
|
|
23
|
-
let result = obj;
|
|
24
13
|
for (const part of parts) {
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
result = result[part];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Safety: don't return the instance itself or a DOM element as a template value
|
|
32
|
-
if (result !== obj && !(result instanceof HTMLElement)) {
|
|
33
|
-
return result;
|
|
14
|
+
if (current === null || current === undefined) return SWC_NOT_FOUND;
|
|
15
|
+
current = current[part];
|
|
34
16
|
}
|
|
35
|
-
|
|
36
|
-
return SWC_NOT_FOUND;
|
|
17
|
+
return current;
|
|
37
18
|
}
|
|
38
19
|
|
|
39
|
-
static
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const values = Object.values(context);
|
|
43
|
-
// eslint-disable-next-line no-new-func
|
|
44
|
-
return new Function(...keys, `return (${expr})`).apply(null, values);
|
|
45
|
-
} catch {
|
|
46
|
-
return SWC_NOT_FOUND;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
20
|
+
static findNearestSwcHost(el: HTMLElement | Node): HTMLElement | undefined {
|
|
21
|
+
let current: any = el instanceof Node && !(el instanceof HTMLElement) ? (el as any).host : el;
|
|
22
|
+
current = current?.parentElement || (current?.getRootNode() as any)?.host;
|
|
49
23
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
options: {
|
|
54
|
-
asKey: string;
|
|
55
|
-
asIndexKey: string;
|
|
56
|
-
index?: number;
|
|
57
|
-
hostContext?: Record<string, any>;
|
|
58
|
-
}
|
|
59
|
-
) {
|
|
60
|
-
const { asKey, asIndexKey, index, hostContext } = options;
|
|
61
|
-
const context: Record<string, any> = {};
|
|
62
|
-
if (index !== undefined) {
|
|
63
|
-
context[asIndexKey] = index;
|
|
24
|
+
while (current) {
|
|
25
|
+
if (getElementConfig(current)) return current as HTMLElement;
|
|
26
|
+
current = current.parentElement || (current?.getRootNode() as any)?.host;
|
|
64
27
|
}
|
|
65
|
-
|
|
66
|
-
context[asKey] = data;
|
|
67
|
-
context['value'] = data; // Always provide 'value' as well
|
|
68
|
-
}
|
|
69
|
-
const fullContext: Record<string, any> = { ...(hostContext || {}), ...context };
|
|
70
|
-
|
|
71
|
-
const resolveExpr = (expr: string, match: string): string => {
|
|
72
|
-
expr = expr.trim();
|
|
73
|
-
// 1. Local path resolve
|
|
74
|
-
const simpleVal = SwcUtils.getValueByPath(data, expr, asKey);
|
|
75
|
-
if (simpleVal !== SWC_NOT_FOUND && typeof simpleVal !== 'symbol') {
|
|
76
|
-
return simpleVal === null || simpleVal === undefined ? '' : String(simpleVal);
|
|
77
|
-
}
|
|
78
|
-
// 2. Full context eval (alias, host states, etc.)
|
|
79
|
-
const exprVal = SwcUtils.evalExpression(expr, fullContext);
|
|
80
|
-
if (exprVal !== SWC_NOT_FOUND && typeof exprVal !== 'symbol') {
|
|
81
|
-
return exprVal === null || exprVal === undefined ? '' : String(exprVal);
|
|
82
|
-
}
|
|
83
|
-
return match;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const walk = (n: Node) => {
|
|
87
|
-
if (n.nodeType === Node.TEXT_NODE) {
|
|
88
|
-
if (!(n as any)._original) (n as any)._original = n.textContent;
|
|
89
|
-
let text = (n as any)._original;
|
|
90
|
-
text = text.replace(/{{(.*?)}}/g, (match: string, path: string) => {
|
|
91
|
-
return resolveExpr(path, match);
|
|
92
|
-
});
|
|
93
|
-
if (n.textContent !== text) n.textContent = text;
|
|
94
|
-
} else if (n.nodeType === Node.ELEMENT_NODE) {
|
|
95
|
-
const el = n as HTMLElement;
|
|
96
|
-
Array.from(el.attributes).forEach(a => {
|
|
97
|
-
if (!(a as any)._original) (a as any)._original = a.value;
|
|
98
|
-
let val = (a as any)._original;
|
|
99
|
-
val = val.replace(/{{(.*?)}}/g, (match: string, path: string) => {
|
|
100
|
-
return resolveExpr(path, match);
|
|
101
|
-
});
|
|
102
|
-
if (a.value !== val) a.value = val;
|
|
103
|
-
});
|
|
104
|
-
el.childNodes.forEach(walk);
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
walk(node);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
static createReactiveProxy(target: any, onChange: () => void, onIndexChange?: (index: number, val: any) => void) {
|
|
111
|
-
const makeRecursiveProxy = (obj: any): any => {
|
|
112
|
-
if (typeof obj !== 'object' || obj === null || obj instanceof Node) return obj;
|
|
113
|
-
if ((obj as any).__swc_is_proxy) return obj;
|
|
114
|
-
|
|
115
|
-
const IS_PROXY_KEY = '__swc_is_proxy';
|
|
116
|
-
|
|
117
|
-
const proxy = new Proxy(obj, {
|
|
118
|
-
get: (t, prop) => {
|
|
119
|
-
if (prop === IS_PROXY_KEY) return true;
|
|
120
|
-
if (typeof prop === 'symbol') return t[prop];
|
|
121
|
-
return t[prop];
|
|
122
|
-
},
|
|
123
|
-
set: (t, prop, val) => {
|
|
124
|
-
if (prop === IS_PROXY_KEY) return true;
|
|
125
|
-
if (typeof prop === 'symbol') {
|
|
126
|
-
t[prop] = val;
|
|
127
|
-
return true;
|
|
128
|
-
}
|
|
129
|
-
const oldVal = t[prop];
|
|
130
|
-
if (oldVal === val) return true;
|
|
131
|
-
t[prop] = makeRecursiveProxy(val);
|
|
132
|
-
const isIndex = !isNaN(Number(prop)) && Array.isArray(t);
|
|
133
|
-
if (isIndex && onIndexChange) {
|
|
134
|
-
onIndexChange(Number(prop), val);
|
|
135
|
-
} else {
|
|
136
|
-
onChange();
|
|
137
|
-
}
|
|
138
|
-
return true;
|
|
139
|
-
},
|
|
140
|
-
deleteProperty: (t, prop) => {
|
|
141
|
-
delete t[prop];
|
|
142
|
-
onChange();
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
return proxy;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
return makeRecursiveProxy(target);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
static findNearestSwcHost(el: HTMLElement | Node): any {
|
|
153
|
-
const hosts = this.findAllSwcHosts(el);
|
|
154
|
-
return hosts.length > 0 ? hosts[hosts.length - 1] : null;
|
|
28
|
+
return undefined;
|
|
155
29
|
}
|
|
156
30
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Returns all SWC ancestors (excluding self) in [root, ..., parent] order.
|
|
33
|
+
*/
|
|
34
|
+
static findAllSwcHosts(el: HTMLElement | Node): HTMLElement[] {
|
|
35
|
+
const hosts: HTMLElement[] = [];
|
|
36
|
+
let current = this.findNearestSwcHost(el);
|
|
37
|
+
while (current) {
|
|
38
|
+
hosts.push(current);
|
|
39
|
+
current = this.findNearestSwcHost(current);
|
|
165
40
|
}
|
|
166
41
|
return hosts.reverse();
|
|
167
42
|
}
|
|
168
43
|
|
|
169
44
|
static getHosts(el: HTMLElement): HTMLElement[] {
|
|
170
|
-
return this.findAllSwcHosts(el);
|
|
45
|
+
return [...this.findAllSwcHosts(el), el];
|
|
171
46
|
}
|
|
172
47
|
|
|
173
48
|
static getHost(el: HTMLElement): HTMLElement | undefined {
|
|
174
|
-
|
|
175
|
-
return hosts.length > 0 ? hosts[hosts.length - 1] : undefined;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
static getFirstHost(el: HTMLElement): HTMLElement | undefined {
|
|
179
|
-
const hosts = this.getHosts(el);
|
|
180
|
-
return hosts.length > 0 ? hosts[0] : undefined;
|
|
49
|
+
return el;
|
|
181
50
|
}
|
|
182
51
|
|
|
183
52
|
static getAppHosts(el: HTMLElement): SwcAppInterface[] {
|
|
@@ -187,37 +56,32 @@ export class SwcUtils {
|
|
|
187
56
|
|
|
188
57
|
static getAppHost(el: HTMLElement): SwcAppInterface | undefined {
|
|
189
58
|
const appHosts = this.getAppHosts(el);
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
static getFirstAppHost(el: HTMLElement): SwcAppInterface | undefined {
|
|
194
|
-
const appHosts = this.getAppHosts(el);
|
|
195
|
-
return appHosts.length > 0 ? appHosts[0] : undefined;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
static getLastAppHost(el: HTMLElement): SwcAppInterface | undefined {
|
|
199
|
-
return this.getAppHost(el);
|
|
59
|
+
const appHostsWithoutSelf = appHosts.filter(h => h !== el);
|
|
60
|
+
// Nearest app host is the last one in [root, ..., parent]
|
|
61
|
+
return appHostsWithoutSelf.length > 0 ? appHostsWithoutSelf[appHostsWithoutSelf.length - 1] : undefined;
|
|
200
62
|
}
|
|
201
63
|
|
|
202
64
|
static getHostSet(el: HTMLElement): HostSet {
|
|
203
|
-
const
|
|
204
|
-
const $
|
|
205
|
-
|
|
206
|
-
const $
|
|
207
|
-
const $
|
|
65
|
+
const ancestors = this.findAllSwcHosts(el); // [root, ..., parent]
|
|
66
|
+
const $host = el;
|
|
67
|
+
const $hosts = [...ancestors, $host]; // [root, ..., parent, self]
|
|
68
|
+
const $parentHost = ancestors.length > 0 ? ancestors[ancestors.length - 1] : null;
|
|
69
|
+
const $firstHost = ancestors.length > 0 ? ancestors[0] : null;
|
|
208
70
|
|
|
209
|
-
const $
|
|
210
|
-
const $
|
|
71
|
+
const $appHosts = $hosts.filter(h => h.tagName.toLowerCase() === 'swc-app' || h.getAttribute('is')?.startsWith('swc-app-')) as SwcAppInterface[];
|
|
72
|
+
const $appHost = $appHosts.length > 0 ? ($appHosts[$appHosts.length - 1] === el ? ($appHosts.length > 1 ? $appHosts[$appHosts.length - 2] : null) : $appHosts[$appHosts.length - 1]) : null;
|
|
73
|
+
const $firstAppHost = $appHosts.length > 0 ? $appHosts[0] : null;
|
|
211
74
|
|
|
212
75
|
return {
|
|
213
|
-
$host
|
|
76
|
+
$host,
|
|
77
|
+
$parentHost,
|
|
214
78
|
$hosts,
|
|
215
79
|
$firstHost,
|
|
216
|
-
$lastHost,
|
|
217
|
-
$appHost
|
|
80
|
+
$lastHost: $parentHost,
|
|
81
|
+
$appHost,
|
|
218
82
|
$appHosts,
|
|
219
83
|
$firstAppHost,
|
|
220
|
-
$lastAppHost
|
|
84
|
+
$lastAppHost: $appHost
|
|
221
85
|
};
|
|
222
86
|
}
|
|
223
87
|
}
|