@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.
Files changed (82) hide show
  1. package/README.md +220 -1
  2. package/dist/cjs/decorators/elementDefine.js +3 -3
  3. package/dist/cjs/decorators/elementDefine.js.map +2 -2
  4. package/dist/cjs/elements/SwcAppEngine.js +3 -3
  5. package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
  6. package/dist/cjs/elements/SwcAppMixin.js +0 -7
  7. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  8. package/dist/cjs/elements/SwcAsync.js +35 -54
  9. package/dist/cjs/elements/SwcAsync.js.map +2 -2
  10. package/dist/cjs/elements/SwcChoose.js +2 -23
  11. package/dist/cjs/elements/SwcChoose.js.map +2 -2
  12. package/dist/cjs/elements/SwcIf.js +31 -60
  13. package/dist/cjs/elements/SwcIf.js.map +2 -2
  14. package/dist/cjs/elements/SwcLoop.js +20 -43
  15. package/dist/cjs/elements/SwcLoop.js.map +2 -2
  16. package/dist/cjs/elements/SwcSubTemplates.js +0 -27
  17. package/dist/cjs/elements/SwcSubTemplates.js.map +2 -2
  18. package/dist/cjs/elements/register.js +88 -92
  19. package/dist/cjs/elements/register.js.map +2 -2
  20. package/dist/cjs/router/ElementRouter.js +1 -8
  21. package/dist/cjs/router/ElementRouter.js.map +2 -2
  22. package/dist/cjs/types.js.map +1 -1
  23. package/dist/cjs/utils/Utils.js +24 -11
  24. package/dist/cjs/utils/Utils.js.map +2 -2
  25. package/dist/esm/decorators/elementDefine.js +3 -3
  26. package/dist/esm/decorators/elementDefine.js.map +2 -2
  27. package/dist/esm/elements/SwcAppEngine.js +3 -3
  28. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  29. package/dist/esm/elements/SwcAppMixin.js +0 -7
  30. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  31. package/dist/esm/elements/SwcAsync.js +35 -35
  32. package/dist/esm/elements/SwcAsync.js.map +2 -2
  33. package/dist/esm/elements/SwcChoose.js +2 -4
  34. package/dist/esm/elements/SwcChoose.js.map +2 -2
  35. package/dist/esm/elements/SwcIf.js +31 -41
  36. package/dist/esm/elements/SwcIf.js.map +2 -2
  37. package/dist/esm/elements/SwcLoop.js +20 -24
  38. package/dist/esm/elements/SwcLoop.js.map +2 -2
  39. package/dist/esm/elements/SwcSubTemplates.js +0 -8
  40. package/dist/esm/elements/SwcSubTemplates.js.map +2 -2
  41. package/dist/esm/elements/register.js +88 -92
  42. package/dist/esm/elements/register.js.map +2 -2
  43. package/dist/esm/router/ElementRouter.js +1 -8
  44. package/dist/esm/router/ElementRouter.js.map +2 -2
  45. package/dist/esm/types.js.map +1 -1
  46. package/dist/esm/utils/Utils.js +24 -11
  47. package/dist/esm/utils/Utils.js.map +2 -2
  48. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +27 -14
  49. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +2 -2
  50. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  51. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  52. package/dist/types/elements/SwcAsync.d.ts +1 -11
  53. package/dist/types/elements/SwcAsync.d.ts.map +1 -1
  54. package/dist/types/elements/SwcChoose.d.ts +1 -13
  55. package/dist/types/elements/SwcChoose.d.ts.map +1 -1
  56. package/dist/types/elements/SwcIf.d.ts +1 -13
  57. package/dist/types/elements/SwcIf.d.ts.map +1 -1
  58. package/dist/types/elements/SwcLoop.d.ts +1 -13
  59. package/dist/types/elements/SwcLoop.d.ts.map +1 -1
  60. package/dist/types/elements/SwcSubTemplates.d.ts +6 -6
  61. package/dist/types/elements/SwcSubTemplates.d.ts.map +1 -1
  62. package/dist/types/elements/register.d.ts.map +1 -1
  63. package/dist/types/router/ElementRouter.d.ts.map +1 -1
  64. package/dist/types/types.d.ts +3 -0
  65. package/dist/types/types.d.ts.map +1 -1
  66. package/dist/types/utils/Utils.d.ts +10 -0
  67. package/dist/types/utils/Utils.d.ts.map +1 -1
  68. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +27 -14
  69. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +2 -2
  70. package/package.json +3 -3
  71. package/src/decorators/elementDefine.ts +6 -3
  72. package/src/elements/SwcAppEngine.ts +3 -3
  73. package/src/elements/SwcAppMixin.ts +5 -26
  74. package/src/elements/SwcAsync.ts +43 -31
  75. package/src/elements/SwcChoose.ts +8 -3
  76. package/src/elements/SwcIf.ts +38 -38
  77. package/src/elements/SwcLoop.ts +24 -19
  78. package/src/elements/SwcSubTemplates.ts +6 -6
  79. package/src/elements/register.ts +107 -86
  80. package/src/router/ElementRouter.ts +1 -12
  81. package/src/types.ts +3 -1
  82. 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.30",
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/simple-boot": "1.0.54",
96
+ "@dooboostore/core-node": "1.0.12",
97
97
  "@dooboostore/core-web": "1.0.10",
98
- "@dooboostore/core-node": "1.0.12"
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.simpleApplication;
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.executeBindParameterSimPromise(
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
- // console.log('Route changed:', route);
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
- this.router.go(config.path);
184
- }
161
+ // if (config?.path) {
162
+ // this.router.go(config.path);
163
+ // }
185
164
  }
186
165
  }
187
166
 
@@ -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
- export class SwcAsync extends HTMLTemplateElement {
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('on-get-value')
32
- private refresh() {
33
- const script = this.getAttribute('on-get-value');
34
- if (!script) {
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._resolvePortal();
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
- if (portal === this.parentElement) {
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
- export class SwcChoose extends HTMLTemplateElement {
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
- private refresh(valueAttr?: string | null) {
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 result = FunctionUtils.executeReturn({ script, context: this, args: SwcUtils.getHelperAndHostSet(win, this) });
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'));
@@ -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
- export class SwcIf extends HTMLTemplateElement {
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('on-get-value')
40
- private refreshValue() {
41
- const script = this.getAttribute('on-get-value');
42
- if (!script) {
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
- const win = this.ownerDocument?.defaultView || window;
47
- const res = FunctionUtils.executeReturn({
48
- script,
49
- context: this,
50
- args: SwcUtils.getHelperAndHostSet(win, this)
51
- });
52
-
53
- if (res instanceof Promise) {
54
- res.then(v => (this.value = v)).catch(() => (this.value = false));
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
- this.value = res;
42
+ // 일반 문자열 값
43
+ this.value = Boolean(valueAttr);
57
44
  }
58
45
  }
59
46
 
60
47
  private render() {
61
48
  this.cleanup();
62
- const portal = this._resolvePortal();
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
- if (portal === this.parentElement) {
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
 
@@ -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
- export class SwcLoop extends HTMLTemplateElement {
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('on-get-value')
30
+ @changedAttributeHost('value')
45
31
  private refreshValue() {
46
- const script = this.getAttribute('on-get-value');
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._resolvePortal();
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
- export class SwcLoading extends HTMLTemplateElement {}
2
- export class SwcError extends HTMLTemplateElement {}
3
- export class SwcSuccess extends HTMLTemplateElement {}
4
- export class SwcWhen extends HTMLTemplateElement {}
5
- export class SwcOtherwise extends HTMLTemplateElement {}
6
- export class SwcDefault extends HTMLTemplateElement {}
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 {}