@dooboostore/simple-web-component 1.0.30 → 1.0.31
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 +220 -1
- package/dist/cjs/decorators/elementDefine.js +3 -3
- package/dist/cjs/decorators/elementDefine.js.map +2 -2
- package/dist/cjs/elements/SwcAppEngine.js +3 -3
- package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
- package/dist/cjs/elements/SwcAppMixin.js +0 -7
- package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
- package/dist/cjs/elements/SwcAsync.js +35 -54
- package/dist/cjs/elements/SwcAsync.js.map +2 -2
- package/dist/cjs/elements/SwcChoose.js +2 -23
- package/dist/cjs/elements/SwcChoose.js.map +2 -2
- package/dist/cjs/elements/SwcIf.js +31 -60
- package/dist/cjs/elements/SwcIf.js.map +2 -2
- package/dist/cjs/elements/SwcLoop.js +20 -43
- package/dist/cjs/elements/SwcLoop.js.map +2 -2
- package/dist/cjs/elements/SwcSubTemplates.js +0 -27
- package/dist/cjs/elements/SwcSubTemplates.js.map +2 -2
- package/dist/cjs/elements/register.js +88 -92
- package/dist/cjs/elements/register.js.map +2 -2
- package/dist/cjs/router/ElementRouter.js +1 -8
- package/dist/cjs/router/ElementRouter.js.map +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/utils/Utils.js +24 -11
- package/dist/cjs/utils/Utils.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +3 -3
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/elements/SwcAppEngine.js +3 -3
- package/dist/esm/elements/SwcAppEngine.js.map +2 -2
- package/dist/esm/elements/SwcAppMixin.js +0 -7
- package/dist/esm/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm/elements/SwcAsync.js +35 -35
- package/dist/esm/elements/SwcAsync.js.map +2 -2
- package/dist/esm/elements/SwcChoose.js +2 -4
- package/dist/esm/elements/SwcChoose.js.map +2 -2
- package/dist/esm/elements/SwcIf.js +31 -41
- package/dist/esm/elements/SwcIf.js.map +2 -2
- package/dist/esm/elements/SwcLoop.js +20 -24
- package/dist/esm/elements/SwcLoop.js.map +2 -2
- package/dist/esm/elements/SwcSubTemplates.js +0 -8
- package/dist/esm/elements/SwcSubTemplates.js.map +2 -2
- package/dist/esm/elements/register.js +88 -92
- package/dist/esm/elements/register.js.map +2 -2
- package/dist/esm/router/ElementRouter.js +1 -8
- package/dist/esm/router/ElementRouter.js.map +2 -2
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/Utils.js +24 -11
- package/dist/esm/utils/Utils.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +27 -14
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +2 -2
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
- package/dist/types/elements/SwcAsync.d.ts +1 -11
- package/dist/types/elements/SwcAsync.d.ts.map +1 -1
- package/dist/types/elements/SwcChoose.d.ts +1 -13
- package/dist/types/elements/SwcChoose.d.ts.map +1 -1
- package/dist/types/elements/SwcIf.d.ts +1 -13
- package/dist/types/elements/SwcIf.d.ts.map +1 -1
- package/dist/types/elements/SwcLoop.d.ts +1 -13
- package/dist/types/elements/SwcLoop.d.ts.map +1 -1
- package/dist/types/elements/SwcSubTemplates.d.ts +6 -6
- package/dist/types/elements/SwcSubTemplates.d.ts.map +1 -1
- package/dist/types/elements/register.d.ts.map +1 -1
- package/dist/types/router/ElementRouter.d.ts.map +1 -1
- package/dist/types/types.d.ts +3 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/Utils.d.ts +10 -0
- package/dist/types/utils/Utils.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +27 -14
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +2 -2
- package/package.json +3 -3
- package/src/decorators/elementDefine.ts +6 -3
- package/src/elements/SwcAppEngine.ts +3 -3
- package/src/elements/SwcAppMixin.ts +5 -26
- package/src/elements/SwcAsync.ts +43 -31
- package/src/elements/SwcChoose.ts +8 -3
- package/src/elements/SwcIf.ts +38 -38
- package/src/elements/SwcLoop.ts +24 -19
- package/src/elements/SwcSubTemplates.ts +6 -6
- package/src/elements/register.ts +107 -86
- package/src/router/ElementRouter.ts +1 -12
- package/src/types.ts +3 -1
- package/src/utils/Utils.ts +37 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dooboostore/simple-web-component",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.31",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -93,9 +93,9 @@
|
|
|
93
93
|
"webpack-cli": "^5.1.4",
|
|
94
94
|
"webpack-dev-server": "^5.2.0",
|
|
95
95
|
"@dooboostore/core": "1.0.30",
|
|
96
|
-
"@dooboostore/
|
|
96
|
+
"@dooboostore/core-node": "1.0.12",
|
|
97
97
|
"@dooboostore/core-web": "1.0.10",
|
|
98
|
-
"@dooboostore/
|
|
98
|
+
"@dooboostore/simple-boot": "1.0.54"
|
|
99
99
|
},
|
|
100
100
|
"scripts": {
|
|
101
101
|
"clean": "rm -rf dist",
|
|
@@ -177,14 +177,14 @@ const setupPrototype = (proto: any) => {
|
|
|
177
177
|
ensureInit(this);
|
|
178
178
|
if (typeof (this as any)[methodName] !== 'function') return;
|
|
179
179
|
const useHostSet = hostSet ?? SwcUtils.getHostSet(this);
|
|
180
|
-
const app = useHostSet?.$appHost
|
|
180
|
+
const app = useHostSet?.$appHost?.simpleApplication;
|
|
181
181
|
// console.log('---->hh',app, this, methodName);
|
|
182
182
|
if (app) {
|
|
183
183
|
const otherStorage = new Map<any, any>();
|
|
184
184
|
const situations = new SituationTypeContainers([new SituationTypeContainer({ situationType: InjectSituationType.HOST_SET, data: useHostSet }), new SituationTypeContainer({ situationType: InjectSituationType.APP_HOST, data: useHostSet.$appHost }), new SituationTypeContainer({ situationType: InjectSituationType.APP_HOSTS, data: useHostSet.$appHosts }), new SituationTypeContainer({ situationType: InjectSituationType.HOST, data: useHostSet.$host }), new SituationTypeContainer({ situationType: InjectSituationType.HOSTS, data: useHostSet.$hosts }), new SituationTypeContainer({ situationType: InjectSituationType.FIRST_HOST, data: useHostSet.$firstHost }), new SituationTypeContainer({ situationType: InjectSituationType.LAST_HOST, data: useHostSet.$lastHost }), new SituationTypeContainer({ situationType: InjectSituationType.FIRST_APP_HOST, data: useHostSet.$firstAppHost }), new SituationTypeContainer({ situationType: InjectSituationType.LAST_APP_HOST, data: useHostSet.$lastAppHost })]);
|
|
185
185
|
otherStorage.set(SituationTypeContainers, situations);
|
|
186
186
|
|
|
187
|
-
return app.simstanceManager.
|
|
187
|
+
return app.simstanceManager.executeBindParameterSim(
|
|
188
188
|
{
|
|
189
189
|
target: this,
|
|
190
190
|
targetKey: methodName,
|
|
@@ -332,7 +332,10 @@ export const elementDefine =
|
|
|
332
332
|
let sContent = '',
|
|
333
333
|
lContent = '';
|
|
334
334
|
for (const meta of connectedInnerHtmlList) {
|
|
335
|
-
const res = (this as any)[meta.propertyKey]();
|
|
335
|
+
// const res = (this as any)[meta.propertyKey]();
|
|
336
|
+
const res = (this as any)._invokeLifecycleMethod(meta.propertyKey, hostSet);
|
|
337
|
+
// console.log('------res0', res);
|
|
338
|
+
// console.log('------res1', res1);
|
|
336
339
|
if (res !== undefined) {
|
|
337
340
|
if (meta.options.useShadow) sContent += res;
|
|
338
341
|
else lContent += res;
|
|
@@ -42,11 +42,11 @@ export class SwcAppEngine {
|
|
|
42
42
|
|
|
43
43
|
// Router Selection
|
|
44
44
|
if (this._config.routeType === 'path') {
|
|
45
|
-
this.router = new PathRouter({ window: this._config.window });
|
|
45
|
+
this.router = new PathRouter({ window: this._config.window, firstUrl: this._config.path });
|
|
46
46
|
} else if (this._config.routeType === 'hash') {
|
|
47
|
-
this.router = new HashRouter({ window: this._config.window });
|
|
47
|
+
this.router = new HashRouter({ window: this._config.window, firstUrl: this._config.path });
|
|
48
48
|
} else if (this._config.routeType === 'element') {
|
|
49
|
-
this.router = new ElementRouter({ window: this._config.window });
|
|
49
|
+
this.router = new ElementRouter({ window: this._config.window, firstUrl: this._config.path });
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// console.log('vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv', this.router)
|
|
@@ -28,11 +28,6 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
|
|
|
28
28
|
return this.__swc_engine.router;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
// constructor() {
|
|
32
|
-
// super();
|
|
33
|
-
// console.log('cccccccccccccccccccccc');
|
|
34
|
-
// }
|
|
35
|
-
|
|
36
31
|
_invokeRouteChangeSubscribers(instance: any, re: RouterEventType) {
|
|
37
32
|
const routeChangeSubscribers = getSubscribeSwcAppRouteChangeMetadata(instance);
|
|
38
33
|
if (routeChangeSubscribers && Array.isArray(routeChangeSubscribers)) {
|
|
@@ -153,35 +148,19 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
|
|
|
153
148
|
this._invokeOnConnectedSwcAppStarted(instance);
|
|
154
149
|
});
|
|
155
150
|
|
|
156
|
-
// Safari fix: Manually scan DOM tree and register any SWC components that couldn't find parent
|
|
157
|
-
// This handles the case where is="" elements get upgraded in child-first order
|
|
158
|
-
// const allElements = (this as any).querySelectorAll('*');
|
|
159
|
-
// for (const el of allElements) {
|
|
160
|
-
// const isConnected = (el as any).__swc_connected;
|
|
161
|
-
// if (!isConnected && typeof (el as any)._resolveWindow === 'function') {
|
|
162
|
-
// // Element is an SWC component but hasn't registered with app yet
|
|
163
|
-
// try {
|
|
164
|
-
// this._connected(el);
|
|
165
|
-
// if ((el as any)._invokeOnConnectedSwcAppStarted) {
|
|
166
|
-
// this._invokeOnConnectedSwcAppStarted(el);
|
|
167
|
-
// }
|
|
168
|
-
// } catch (e) {
|
|
169
|
-
// console.warn('[SWC] Error registering discovered element:', el.tagName, e);
|
|
170
|
-
// }
|
|
171
|
-
// }
|
|
172
|
-
// }
|
|
173
151
|
|
|
174
152
|
// Subscribe to router changes after connect
|
|
175
153
|
if (!this._routerSubscription && this.router) {
|
|
176
154
|
this._routerSubscription = this.router.observable.subscribe((route: RouterEventType) => {
|
|
177
|
-
|
|
155
|
+
//@ts-ignore
|
|
156
|
+
// console.log('Route changed:', route, this._swcId);
|
|
178
157
|
this._handleRouteChange(route);
|
|
179
158
|
});
|
|
180
159
|
// Navigate to initial path if specified
|
|
181
160
|
const config = this.__swc_engine.config;
|
|
182
|
-
if (config?.path) {
|
|
183
|
-
|
|
184
|
-
}
|
|
161
|
+
// if (config?.path) {
|
|
162
|
+
// this.router.go(config.path);
|
|
163
|
+
// }
|
|
185
164
|
}
|
|
186
165
|
}
|
|
187
166
|
|
package/src/elements/SwcAsync.ts
CHANGED
|
@@ -2,42 +2,42 @@ import { changedAttributeHost } from '../decorators/changedAttributeHost';
|
|
|
2
2
|
import { SwcUtils } from '../utils/Utils';
|
|
3
3
|
import { FunctionUtils } from '@dooboostore/core';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
class SwcAsync extends HTMLTemplateElement {
|
|
6
6
|
private _nodes: Node[] = [];
|
|
7
7
|
private _value: any = null;
|
|
8
8
|
|
|
9
|
-
private _resolvePortal(): Element | null {
|
|
10
|
-
const portalScript = this.getAttribute('on-get-portal');
|
|
11
|
-
if (!portalScript) return this.parentElement;
|
|
12
|
-
|
|
13
|
-
const win = this.ownerDocument?.defaultView || window;
|
|
14
|
-
const res = FunctionUtils.executeReturn({
|
|
15
|
-
script: portalScript,
|
|
16
|
-
context: this,
|
|
17
|
-
args: SwcUtils.getHelperAndHostSet(win, this)
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
if (res instanceof HTMLElement) return res;
|
|
21
|
-
if (typeof res === 'string') return win.document.querySelector(res);
|
|
22
|
-
return this.parentElement;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
9
|
private _executeCloneCallback(attr: string, args: any) {
|
|
26
10
|
const script = this.getAttribute(attr);
|
|
27
11
|
if (!script) return;
|
|
28
12
|
FunctionUtils.execute({ script, context: this, args });
|
|
29
13
|
}
|
|
30
14
|
|
|
31
|
-
@changedAttributeHost('
|
|
32
|
-
private refresh() {
|
|
33
|
-
|
|
34
|
-
if (!
|
|
15
|
+
@changedAttributeHost('value')
|
|
16
|
+
private refresh(valueAttr?: string | null) {
|
|
17
|
+
valueAttr ??= this.getAttribute('value');
|
|
18
|
+
if (!valueAttr) {
|
|
35
19
|
this.render('default');
|
|
36
20
|
return;
|
|
37
21
|
}
|
|
38
|
-
const win = this.ownerDocument?.defaultView || window;
|
|
39
|
-
const result = FunctionUtils.executeReturn({ script, context: this, args: SwcUtils.getHelperAndHostSet(win, this) });
|
|
40
22
|
|
|
23
|
+
// {{ }} 브레이스로 감싸진 값은 스크립트 실행
|
|
24
|
+
if (valueAttr.startsWith('{{') && valueAttr.endsWith('}}')) {
|
|
25
|
+
const script = valueAttr.slice(2, -2).trim();
|
|
26
|
+
const win = this.ownerDocument?.defaultView || window;
|
|
27
|
+
const result = FunctionUtils.executeReturn({
|
|
28
|
+
script,
|
|
29
|
+
context: this,
|
|
30
|
+
args: SwcUtils.getHelperAndHostSet(win, this)
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
this.executeAsync(result);
|
|
34
|
+
} else {
|
|
35
|
+
// 일반 문자열 값 또는 직접 Promise 속성
|
|
36
|
+
this.executeAsync(valueAttr);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private executeAsync(result: any) {
|
|
41
41
|
if (result instanceof Promise) {
|
|
42
42
|
this.render('loading');
|
|
43
43
|
result
|
|
@@ -54,7 +54,7 @@ export class SwcAsync extends HTMLTemplateElement {
|
|
|
54
54
|
|
|
55
55
|
private render(state: string) {
|
|
56
56
|
this.cleanup();
|
|
57
|
-
const portal = this.
|
|
57
|
+
const portal = this.parentElement;
|
|
58
58
|
if (!portal) return;
|
|
59
59
|
|
|
60
60
|
const win = this.ownerDocument?.defaultView || window;
|
|
@@ -67,18 +67,31 @@ export class SwcAsync extends HTMLTemplateElement {
|
|
|
67
67
|
const elements = this._nodes.filter(n => n.nodeType === 1) as HTMLElement[];
|
|
68
68
|
const groupArgs = { ...helperSet, $value: this._value, $nodes: this._nodes, $elements: elements, $firstElement: elements[0], $state: state };
|
|
69
69
|
|
|
70
|
+
// 부모 체인을 정상적으로 유지하기 위해 __swc_host 할당 제거
|
|
70
71
|
this._nodes.forEach((n, nodeIdx) => {
|
|
71
|
-
if (n instanceof HTMLElement) (n as any).__swc_host = this;
|
|
72
|
+
// if (n instanceof HTMLElement) (n as any).__swc_host = this; // 제거: 부모 체인 유지
|
|
72
73
|
this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: n, $nodeIndex: nodeIdx, $isElement: n.nodeType === 1 });
|
|
74
|
+
|
|
75
|
+
// Attribute {{ }} 치환 - SwcChoose처럼 동적 치환
|
|
76
|
+
if (n instanceof HTMLElement) {
|
|
77
|
+
Array.from(n.attributes).forEach(attr => {
|
|
78
|
+
const value = attr.value || '';
|
|
79
|
+
if (value.startsWith('{{') && value.endsWith('}}')) {
|
|
80
|
+
const script = value.slice(2, -2).trim();
|
|
81
|
+
const result = FunctionUtils.executeReturn({
|
|
82
|
+
script,
|
|
83
|
+
context: n,
|
|
84
|
+
args: groupArgs
|
|
85
|
+
});
|
|
86
|
+
n.setAttribute(attr.name, String(result));
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
73
90
|
});
|
|
74
91
|
|
|
75
92
|
this._executeCloneCallback('on-clone-nodes', groupArgs);
|
|
76
93
|
|
|
77
|
-
|
|
78
|
-
portal.insertBefore(clone, this.nextSibling);
|
|
79
|
-
} else {
|
|
80
|
-
portal.appendChild(clone);
|
|
81
|
-
}
|
|
94
|
+
portal.insertBefore(clone, this.nextSibling);
|
|
82
95
|
}
|
|
83
96
|
}
|
|
84
97
|
|
|
@@ -88,7 +101,6 @@ export class SwcAsync extends HTMLTemplateElement {
|
|
|
88
101
|
}
|
|
89
102
|
|
|
90
103
|
connectedCallback() {
|
|
91
|
-
console.log('[SwcAsync] connectedCallback called');
|
|
92
104
|
this.refresh();
|
|
93
105
|
}
|
|
94
106
|
disconnectedCallback() {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { changedAttributeHost } from '../decorators/changedAttributeHost';
|
|
2
2
|
import { SwcUtils } from '../utils/Utils';
|
|
3
3
|
import { FunctionUtils } from '@dooboostore/core';
|
|
4
|
+
import { SwcChooseInterface } from '../types';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
class SwcChoose extends HTMLTemplateElement implements SwcChooseInterface {
|
|
6
7
|
private _nodes: Node[] = [];
|
|
7
8
|
private _value: any = null;
|
|
8
9
|
private _previousTemplate: HTMLTemplateElement | null = null;
|
|
@@ -22,7 +23,7 @@ export class SwcChoose extends HTMLTemplateElement {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
@changedAttributeHost('value')
|
|
25
|
-
|
|
26
|
+
refresh(valueAttr?: string | null) {
|
|
26
27
|
valueAttr ??= this.getAttribute('value');
|
|
27
28
|
if (valueAttr === null) {
|
|
28
29
|
this.value = null;
|
|
@@ -33,8 +34,11 @@ export class SwcChoose extends HTMLTemplateElement {
|
|
|
33
34
|
if (valueAttr.startsWith('{{') && valueAttr.endsWith('}}')) {
|
|
34
35
|
const script = valueAttr.slice(2, -2).trim();
|
|
35
36
|
const win = this.ownerDocument?.defaultView || window;
|
|
36
|
-
const
|
|
37
|
+
const helperAndHostSet = SwcUtils.getHelperAndHostSet(win, SwcUtils.findNearestSwcHost(this));
|
|
38
|
+
// console.log('vvvvvvvvvvvvvvvvvv323', helperAndHostSet);
|
|
39
|
+
const result = FunctionUtils.executeReturn({ script, context: this, args: helperAndHostSet });
|
|
37
40
|
this.value = result;
|
|
41
|
+
// console.log('----------vv', this.value);
|
|
38
42
|
} else {
|
|
39
43
|
// 일반 문자열 값
|
|
40
44
|
this.value = valueAttr;
|
|
@@ -42,6 +46,7 @@ export class SwcChoose extends HTMLTemplateElement {
|
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
private render() {
|
|
49
|
+
// console.log('-------------', this.value);
|
|
45
50
|
const win = this.ownerDocument?.defaultView || window;
|
|
46
51
|
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
47
52
|
const templates = Array.from(this.content.querySelectorAll('template'));
|
package/src/elements/SwcIf.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { changedAttributeHost } from '../decorators/changedAttributeHost';
|
|
|
2
2
|
import { SwcUtils } from '../utils/Utils';
|
|
3
3
|
import { FunctionUtils } from '@dooboostore/core';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
class SwcIf extends HTMLTemplateElement {
|
|
6
6
|
private _value = false;
|
|
7
7
|
private _nodes: Node[] = [];
|
|
8
8
|
|
|
@@ -14,52 +14,39 @@ export class SwcIf extends HTMLTemplateElement {
|
|
|
14
14
|
this.render();
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
private _resolvePortal(): Element | null {
|
|
18
|
-
const portalScript = this.getAttribute('on-get-portal');
|
|
19
|
-
if (!portalScript) return this.parentElement;
|
|
20
|
-
|
|
21
|
-
const win = this.ownerDocument?.defaultView || window;
|
|
22
|
-
const res = FunctionUtils.executeReturn({
|
|
23
|
-
script: portalScript,
|
|
24
|
-
context: this,
|
|
25
|
-
args: SwcUtils.getHelperAndHostSet(win, this)
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
if (res instanceof HTMLElement) return res;
|
|
29
|
-
if (typeof res === 'string') return win.document.querySelector(res);
|
|
30
|
-
return this.parentElement;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
17
|
private _executeCloneCallback(attr: string, args: any) {
|
|
34
18
|
const script = this.getAttribute(attr);
|
|
35
19
|
if (!script) return;
|
|
36
20
|
FunctionUtils.execute({ script, context: this, args });
|
|
37
21
|
}
|
|
38
22
|
|
|
39
|
-
@changedAttributeHost('
|
|
40
|
-
private refreshValue() {
|
|
41
|
-
|
|
42
|
-
if (
|
|
23
|
+
@changedAttributeHost('value')
|
|
24
|
+
private refreshValue(valueAttr?: string | null) {
|
|
25
|
+
valueAttr ??= this.getAttribute('value');
|
|
26
|
+
if (valueAttr === null) {
|
|
43
27
|
this.value = false;
|
|
44
28
|
return;
|
|
45
29
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
30
|
+
|
|
31
|
+
// {{ }} 브레이스로 감싸진 값은 스크립트 실행
|
|
32
|
+
if (valueAttr.startsWith('{{') && valueAttr.endsWith('}}')) {
|
|
33
|
+
const script = valueAttr.slice(2, -2).trim();
|
|
34
|
+
const win = this.ownerDocument?.defaultView || window;
|
|
35
|
+
const result = FunctionUtils.executeReturn({
|
|
36
|
+
script,
|
|
37
|
+
context: this,
|
|
38
|
+
args: SwcUtils.getHelperAndHostSet(win, this)
|
|
39
|
+
});
|
|
40
|
+
this.value = result;
|
|
55
41
|
} else {
|
|
56
|
-
|
|
42
|
+
// 일반 문자열 값
|
|
43
|
+
this.value = Boolean(valueAttr);
|
|
57
44
|
}
|
|
58
45
|
}
|
|
59
46
|
|
|
60
47
|
private render() {
|
|
61
48
|
this.cleanup();
|
|
62
|
-
const portal = this.
|
|
49
|
+
const portal = this.parentElement;
|
|
63
50
|
if (!portal) return;
|
|
64
51
|
|
|
65
52
|
const win = this.ownerDocument?.defaultView || window;
|
|
@@ -83,18 +70,31 @@ export class SwcIf extends HTMLTemplateElement {
|
|
|
83
70
|
const elements = this._nodes.filter(n => n.nodeType === 1) as HTMLElement[];
|
|
84
71
|
const groupArgs = { ...helperSet, $value: this._value, $nodes: this._nodes, $elements: elements, $firstElement: elements[0] };
|
|
85
72
|
|
|
73
|
+
// 부모 체인을 정상적으로 유지하기 위해 __swc_host 할당 제거
|
|
86
74
|
this._nodes.forEach((node, nodeIdx) => {
|
|
87
|
-
if (node instanceof HTMLElement) (node as any).__swc_host = this;
|
|
75
|
+
// if (node instanceof HTMLElement) (node as any).__swc_host = this; // 제거: 부모 체인 유지
|
|
88
76
|
this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: node, $nodeIndex: nodeIdx, $isElement: node.nodeType === 1 });
|
|
77
|
+
|
|
78
|
+
// Attribute {{ }} 치환 - SwcChoose처럼 동적 치환
|
|
79
|
+
if (node instanceof HTMLElement) {
|
|
80
|
+
Array.from(node.attributes).forEach(attr => {
|
|
81
|
+
const value = attr.value || '';
|
|
82
|
+
if (value.startsWith('{{') && value.endsWith('}}')) {
|
|
83
|
+
const script = value.slice(2, -2).trim();
|
|
84
|
+
const result = FunctionUtils.executeReturn({
|
|
85
|
+
script,
|
|
86
|
+
context: node,
|
|
87
|
+
args: { ...groupArgs, $value: this._value }
|
|
88
|
+
});
|
|
89
|
+
node.setAttribute(attr.name, String(result));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
89
93
|
});
|
|
90
94
|
|
|
91
95
|
this._executeCloneCallback('on-clone-nodes', groupArgs);
|
|
92
96
|
|
|
93
|
-
|
|
94
|
-
portal.insertBefore(clone, this.nextSibling);
|
|
95
|
-
} else {
|
|
96
|
-
portal.appendChild(clone);
|
|
97
|
-
}
|
|
97
|
+
portal.insertBefore(clone, this.nextSibling);
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
package/src/elements/SwcLoop.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { changedAttributeHost } from '../decorators/changedAttributeHost';
|
|
|
2
2
|
import { SwcUtils } from '../utils/Utils';
|
|
3
3
|
import { FunctionUtils } from '@dooboostore/core';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
class SwcLoop extends HTMLTemplateElement {
|
|
6
6
|
private _value: any[] = [];
|
|
7
7
|
private _nodeGroups: Node[][] = [];
|
|
8
8
|
|
|
@@ -14,21 +14,7 @@ export class SwcLoop extends HTMLTemplateElement {
|
|
|
14
14
|
this.render();
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
private _resolvePortal(): Element | null {
|
|
18
|
-
const portalScript = this.getAttribute('on-get-portal');
|
|
19
|
-
if (!portalScript) return this.parentElement;
|
|
20
17
|
|
|
21
|
-
const win = this.ownerDocument?.defaultView || window;
|
|
22
|
-
const res = FunctionUtils.executeReturn({
|
|
23
|
-
script: portalScript,
|
|
24
|
-
context: this,
|
|
25
|
-
args: SwcUtils.getHelperAndHostSet(win, this)
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
if (res instanceof HTMLElement) return res;
|
|
29
|
-
if (typeof res === 'string') return win.document.querySelector(res);
|
|
30
|
-
return this.parentElement;
|
|
31
|
-
}
|
|
32
18
|
|
|
33
19
|
private _executeCloneCallback(attr: string, args: any) {
|
|
34
20
|
const script = this.getAttribute(attr);
|
|
@@ -41,13 +27,17 @@ export class SwcLoop extends HTMLTemplateElement {
|
|
|
41
27
|
this._nodeGroups = [];
|
|
42
28
|
}
|
|
43
29
|
|
|
44
|
-
@changedAttributeHost('
|
|
30
|
+
@changedAttributeHost('value')
|
|
45
31
|
private refreshValue() {
|
|
46
|
-
|
|
32
|
+
let script = this.getAttribute('value');
|
|
47
33
|
if (!script) {
|
|
48
34
|
this.value = [];
|
|
49
35
|
return;
|
|
50
36
|
}
|
|
37
|
+
// Parse {{ }} braces
|
|
38
|
+
if (script.startsWith('{{') && script.endsWith('}}')) {
|
|
39
|
+
script = script.slice(2, -2).trim();
|
|
40
|
+
}
|
|
51
41
|
const win = this.ownerDocument?.defaultView || window;
|
|
52
42
|
const res = FunctionUtils.executeReturn({
|
|
53
43
|
script,
|
|
@@ -64,7 +54,7 @@ export class SwcLoop extends HTMLTemplateElement {
|
|
|
64
54
|
|
|
65
55
|
render() {
|
|
66
56
|
this._cleanup();
|
|
67
|
-
const portal = this.
|
|
57
|
+
const portal = this.parentElement;
|
|
68
58
|
if (!portal) return;
|
|
69
59
|
|
|
70
60
|
const win = this.ownerDocument?.defaultView || window;
|
|
@@ -92,8 +82,23 @@ export class SwcLoop extends HTMLTemplateElement {
|
|
|
92
82
|
const groupArgs = { ...helperSet, $item: item, $index: index, $value: this._value, $nodes: nodes, $elements: elements, $firstElement: elements[0] };
|
|
93
83
|
|
|
94
84
|
nodes.forEach((node, nodeIdx) => {
|
|
95
|
-
if (node instanceof HTMLElement) (node as any).__swc_host = this;
|
|
96
85
|
this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: node, $nodeIndex: nodeIdx, $isElement: node.nodeType === 1 });
|
|
86
|
+
|
|
87
|
+
// Attribute {{ }} 치환 - SwcChoose처럼 동적 치환
|
|
88
|
+
if (node instanceof HTMLElement) {
|
|
89
|
+
Array.from(node.attributes).forEach(attr => {
|
|
90
|
+
const value = attr.value || '';
|
|
91
|
+
if (value.startsWith('{{') && value.endsWith('}}')) {
|
|
92
|
+
const script = value.slice(2, -2).trim();
|
|
93
|
+
const result = FunctionUtils.executeReturn({
|
|
94
|
+
script,
|
|
95
|
+
context: node,
|
|
96
|
+
args: groupArgs
|
|
97
|
+
});
|
|
98
|
+
node.setAttribute(attr.name, String(result));
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
97
102
|
});
|
|
98
103
|
|
|
99
104
|
this._executeCloneCallback('on-clone-nodes', groupArgs);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
class SwcLoading extends HTMLTemplateElement {}
|
|
2
|
+
class SwcError extends HTMLTemplateElement {}
|
|
3
|
+
class SwcSuccess extends HTMLTemplateElement {}
|
|
4
|
+
class SwcWhen extends HTMLTemplateElement {}
|
|
5
|
+
class SwcOtherwise extends HTMLTemplateElement {}
|
|
6
|
+
class SwcDefault extends HTMLTemplateElement {}
|