@dooboostore/simple-web-component 1.0.30 → 1.0.32

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 (93) hide show
  1. package/README.md +220 -1
  2. package/dist/cjs/decorators/applyStyle.js +1 -1
  3. package/dist/cjs/decorators/applyStyle.js.map +2 -2
  4. package/dist/cjs/decorators/attribute.js +17 -1
  5. package/dist/cjs/decorators/attribute.js.map +2 -2
  6. package/dist/cjs/decorators/elementDefine.js +29 -12
  7. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  8. package/dist/cjs/elements/SwcAppEngine.js +3 -3
  9. package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
  10. package/dist/cjs/elements/SwcAppMixin.js +1 -8
  11. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  12. package/dist/cjs/elements/SwcAsync.js +71 -78
  13. package/dist/cjs/elements/SwcAsync.js.map +2 -2
  14. package/dist/cjs/elements/SwcChoose.js +66 -81
  15. package/dist/cjs/elements/SwcChoose.js.map +2 -2
  16. package/dist/cjs/elements/SwcIf.js +52 -96
  17. package/dist/cjs/elements/SwcIf.js.map +2 -2
  18. package/dist/cjs/elements/SwcLoop.js +60 -103
  19. package/dist/cjs/elements/SwcLoop.js.map +2 -2
  20. package/dist/cjs/elements/SwcSubTemplates.js +0 -27
  21. package/dist/cjs/elements/SwcSubTemplates.js.map +2 -2
  22. package/dist/cjs/elements/register.js +314 -343
  23. package/dist/cjs/elements/register.js.map +2 -2
  24. package/dist/cjs/router/ElementRouter.js +1 -8
  25. package/dist/cjs/router/ElementRouter.js.map +2 -2
  26. package/dist/cjs/types.js.map +1 -1
  27. package/dist/cjs/utils/Utils.js +31 -24
  28. package/dist/cjs/utils/Utils.js.map +2 -2
  29. package/dist/esm/decorators/applyStyle.js +1 -1
  30. package/dist/esm/decorators/applyStyle.js.map +2 -2
  31. package/dist/esm/decorators/attribute.js +18 -2
  32. package/dist/esm/decorators/attribute.js.map +2 -2
  33. package/dist/esm/decorators/elementDefine.js +27 -10
  34. package/dist/esm/decorators/elementDefine.js.map +3 -3
  35. package/dist/esm/elements/SwcAppEngine.js +3 -3
  36. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  37. package/dist/esm/elements/SwcAppMixin.js +1 -8
  38. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  39. package/dist/esm/elements/SwcAsync.js +72 -60
  40. package/dist/esm/elements/SwcAsync.js.map +2 -2
  41. package/dist/esm/elements/SwcChoose.js +67 -63
  42. package/dist/esm/elements/SwcChoose.js.map +2 -2
  43. package/dist/esm/elements/SwcIf.js +53 -78
  44. package/dist/esm/elements/SwcIf.js.map +2 -2
  45. package/dist/esm/elements/SwcLoop.js +61 -85
  46. package/dist/esm/elements/SwcLoop.js.map +2 -2
  47. package/dist/esm/elements/SwcSubTemplates.js +0 -8
  48. package/dist/esm/elements/SwcSubTemplates.js.map +2 -2
  49. package/dist/esm/elements/register.js +246 -275
  50. package/dist/esm/elements/register.js.map +2 -2
  51. package/dist/esm/router/ElementRouter.js +1 -8
  52. package/dist/esm/router/ElementRouter.js.map +2 -2
  53. package/dist/esm/types.js.map +1 -1
  54. package/dist/esm/utils/Utils.js +31 -24
  55. package/dist/esm/utils/Utils.js.map +2 -2
  56. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +2223 -2009
  57. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  58. package/dist/types/decorators/attribute.d.ts.map +1 -1
  59. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  60. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  61. package/dist/types/elements/SwcAsync.d.ts +1 -11
  62. package/dist/types/elements/SwcAsync.d.ts.map +1 -1
  63. package/dist/types/elements/SwcChoose.d.ts +1 -13
  64. package/dist/types/elements/SwcChoose.d.ts.map +1 -1
  65. package/dist/types/elements/SwcIf.d.ts +1 -13
  66. package/dist/types/elements/SwcIf.d.ts.map +1 -1
  67. package/dist/types/elements/SwcLoop.d.ts +1 -13
  68. package/dist/types/elements/SwcLoop.d.ts.map +1 -1
  69. package/dist/types/elements/SwcSubTemplates.d.ts +6 -6
  70. package/dist/types/elements/SwcSubTemplates.d.ts.map +1 -1
  71. package/dist/types/elements/register.d.ts.map +1 -1
  72. package/dist/types/router/ElementRouter.d.ts.map +1 -1
  73. package/dist/types/types.d.ts +11 -1
  74. package/dist/types/types.d.ts.map +1 -1
  75. package/dist/types/utils/Utils.d.ts +10 -0
  76. package/dist/types/utils/Utils.d.ts.map +1 -1
  77. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +2223 -2009
  78. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  79. package/package.json +3 -3
  80. package/src/decorators/applyStyle.ts +1 -1
  81. package/src/decorators/attribute.ts +35 -30
  82. package/src/decorators/elementDefine.ts +32 -10
  83. package/src/elements/SwcAppEngine.ts +3 -3
  84. package/src/elements/SwcAppMixin.ts +6 -27
  85. package/src/elements/SwcAsync.ts +75 -57
  86. package/src/elements/SwcChoose.ts +69 -77
  87. package/src/elements/SwcIf.ts +50 -75
  88. package/src/elements/SwcLoop.ts +56 -82
  89. package/src/elements/SwcSubTemplates.ts +6 -6
  90. package/src/elements/register.ts +234 -285
  91. package/src/router/ElementRouter.ts +1 -12
  92. package/src/types.ts +9 -2
  93. package/src/utils/Utils.ts +48 -37
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.32",
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",
@@ -34,7 +34,7 @@ function createStyleDecorator(action: StyleAction) {
34
34
  if (res !== undefined) {
35
35
  const win = (this as any).ownerDocument?.defaultView || window;
36
36
  const host = this as unknown as HTMLElement;
37
- const hostSet = { ...SwcUtils.getHelperAndHostSet(win, host), $this: this };
37
+ const hostSet = SwcUtils.getHelperAndHostSet(win, host);
38
38
  const r = options.root || 'auto';
39
39
  const targetEls: HTMLElement[] = [];
40
40
 
@@ -1,7 +1,8 @@
1
- import {ReflectUtils} from '@dooboostore/core';
1
+ import {ReflectUtils, FunctionUtils, ActionExpression} from '@dooboostore/core';
2
2
  import {ensureInit, getElementConfig} from './elementDefine';
3
3
  import {SwcUtils} from '../utils/Utils';
4
4
  import {SpecialSelector, SwcQueryOptions} from '../types';
5
+ import { ConvertUtils } from '@dooboostore/core-web';
5
6
  export interface AttributeFieldOptions extends SwcQueryOptions {
6
7
  name?: string;
7
8
  // connectedInitialize?: boolean;
@@ -113,38 +114,42 @@ export function attribute(selector: string, options: AttributeFieldOptions = {})
113
114
 
114
115
  Object.defineProperty(target, propertyKey, {
115
116
  get(this: any) {
116
- // console.log('------>??gettttt', this, propertyKey);
117
- // try {
118
- const attrName = options.name || String(propertyKey);
119
- const conf = getElementConfig(this);
120
- const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
121
- const targetType = options.type || designType;
122
- //
123
- // connectedInitialize: true이면 privateKey 값만 반환 (DOM 무시)
124
- // if (options.connectedInitialize === true && (this as any).__swc_syncing_init) {
125
- // console.log('cccccccc2');
126
- // return this[privateKey];
127
- // // return convertValue(this[privateKey], targetType);
128
- // }
129
-
130
- const targets = resolveTargetEls(this, selector, options, currentWin);
131
- const primaryTarget = targets[0];
132
-
133
- if (primaryTarget && typeof (primaryTarget as any).hasAttribute === 'function') {
134
- if ((primaryTarget as any).hasAttribute(attrName)) {
135
- const domVal = (primaryTarget as any).getAttribute(attrName);
136
- return convertValue(domVal, targetType);
117
+ const attrName = options.name || String(propertyKey);
118
+ const conf = getElementConfig(this);
119
+ const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
120
+ const targetType = options.type || designType;
121
+
122
+ const targets = resolveTargetEls(this, selector, options, currentWin);
123
+ const primaryTarget = targets[0];
124
+
125
+ if (primaryTarget && typeof (primaryTarget as any).hasAttribute === 'function') {
126
+ if ((primaryTarget as any).hasAttribute(attrName)) {
127
+ let domVal = (primaryTarget as any).getAttribute(attrName);
128
+
129
+ // 표현식 체크
130
+ const ae = new ActionExpression(domVal);
131
+ const expr = ae.getFirstExpression('call-return');
132
+ if (expr) {
133
+ try {
134
+ const result = FunctionUtils.executeReturn({
135
+ script: ConvertUtils.decodeHtmlEntity(expr.script, currentWin.document),
136
+ context: this,
137
+ args: SwcUtils.getHelperAndHostSet(currentWin, this)
138
+ });
139
+ return convertValue(result, targetType);
140
+ } catch (e) {
141
+ console.error(`[SWC] Failed to execute directive {{= ${expr.script} }}:`, e);
142
+ return convertValue(domVal, targetType);
143
+ }
137
144
  }
138
- return null;
145
+
146
+ return convertValue(domVal, targetType);
139
147
  }
148
+ return null;
149
+ }
140
150
 
141
- const data = convertValue(this[privateKey], targetType);
142
- // console.log('get rrr', data);
143
- return data;
144
- // } catch (err) {
145
- // console.error('Error in getter:', err);
146
- // throw err;
147
- // }
151
+ const data = convertValue(this[privateKey], targetType);
152
+ return data;
148
153
  },
149
154
  set(this: any, nv: any) {
150
155
  // this[propertyKey] = nv;
@@ -1,5 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core';
2
- import { FunctionUtils } from '@dooboostore/core';
1
+ import { ReflectUtils, FunctionUtils, ActionExpression } from '@dooboostore/core';
3
2
  import { getAddEventListenerMetadata } from './addEventListener';
4
3
  import { ON_INITIALIZE_METADATA_KEY, ON_BEFORE_CONNECTED_METADATA_KEY, ON_AFTER_CONNECTED_METADATA_KEY, ON_BEFORE_DISCONNECTED_METADATA_KEY, ON_AFTER_DISCONNECTED_METADATA_KEY, ON_BEFORE_ADOPTED_METADATA_KEY, ON_AFTER_ADOPTED_METADATA_KEY, findAllLifecycleMetadata, getOnConnectedInnerHtmlMetadata } from './lifecycles';
5
4
  import { getEmitCustomEventMetadataList } from './emitCustomEvent';
@@ -12,6 +11,7 @@ import { SwcUtils } from '../utils/Utils';
12
11
  import { HTML_TAG_ENTRIES, DOM_EVENT_NAMES } from '../config/config';
13
12
  import { SituationTypeContainer, SituationTypeContainers } from '@dooboostore/simple-boot/decorators/inject/Inject';
14
13
  import { InjectSituationType, HostSet } from '../types';
14
+ import { ConvertUtils } from '@dooboostore/core-web';
15
15
 
16
16
  // --- Core Interfaces & Types ---
17
17
 
@@ -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,
@@ -214,8 +214,7 @@ const setupPrototype = (proto: any) => {
214
214
  if (oldHandler) el.removeEventListener(eventName, oldHandler);
215
215
 
216
216
  const handler = async (event: any) => {
217
- const parent = SwcUtils.findNearestSwcHost(el);
218
- const hostSet = SwcUtils.getHostSet(parent || el);
217
+ const hostSet = SwcUtils.getHostSet(el);
219
218
  const conf = getElementConfig(this);
220
219
  const currentWin = (this as any)._resolveWindow(conf);
221
220
  const helpers = SwcUtils.getHelperSet(currentWin);
@@ -237,8 +236,7 @@ const setupPrototype = (proto: any) => {
237
236
  proto.__swc_executeAttributeEvent = async function (el: HTMLElement, attrName: string, script: string, event: Event) {
238
237
  ensureInit(this);
239
238
 
240
- const parent = SwcUtils.findNearestSwcHost(el);
241
- const hostSet = SwcUtils.getHostSet(parent || el);
239
+ const hostSet = SwcUtils.getHostSet(el);
242
240
  const conf = getElementConfig(this);
243
241
  const currentWin = (this as any)._resolveWindow(conf);
244
242
  const currentHelpers = SwcUtils.getHelperSet(currentWin);
@@ -332,7 +330,10 @@ export const elementDefine =
332
330
  let sContent = '',
333
331
  lContent = '';
334
332
  for (const meta of connectedInnerHtmlList) {
335
- const res = (this as any)[meta.propertyKey]();
333
+ // const res = (this as any)[meta.propertyKey]();
334
+ const res = (this as any)._invokeLifecycleMethod(meta.propertyKey, hostSet);
335
+ // console.log('------res0', res);
336
+ // console.log('------res1', res1);
336
337
  if (res !== undefined) {
337
338
  if (meta.options.useShadow) sContent += res;
338
339
  else lContent += res;
@@ -562,6 +563,27 @@ export const elementDefine =
562
563
 
563
564
  const hSet = SwcUtils.getHostSet(this as any);
564
565
 
566
+ // Process expression directive before passing to handlers
567
+ let processedVal = newVal;
568
+ if (newVal !== null) {
569
+ const ae = new ActionExpression(newVal);
570
+ const expr = ae.getFirstExpression('call-return');
571
+ if (expr) {
572
+ const win = (this as any)._resolveWindow?.() || ((typeof window !== 'undefined' ? window : undefined) as any);
573
+ try {
574
+ const result = FunctionUtils.executeReturn({
575
+ script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
576
+ context: this,
577
+ args: SwcUtils.getHelperAndHostSet(win,this as any)
578
+ });
579
+ processedVal = String(result);
580
+ } catch (e) {
581
+ console.error(`[SWC] Failed to execute directive {{= ${expr.script} }} on attribute ${name}:`, e);
582
+ processedVal = newVal;
583
+ }
584
+ }
585
+ }
586
+
565
587
  if (name.startsWith('swc-on-') && !swcLifecycleAttributes.includes(name)) {
566
588
  if (newVal !== null) {
567
589
  const eventName = name.substring(7);
@@ -576,7 +598,7 @@ export const elementDefine =
576
598
 
577
599
  const mKeys = attrChangeMap.get(name);
578
600
  if (mKeys && Array.isArray(mKeys)) {
579
- for (const key of mKeys) (this as any)[key](newVal, old, name, hSet);
601
+ for (const key of mKeys) (this as any)[key](processedVal, old, name, hSet);
580
602
  }
581
603
  };
582
604
 
@@ -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
 
@@ -206,7 +185,7 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
206
185
  const userConfig = FunctionUtils.executeReturn({
207
186
  script: configStr,
208
187
  context: this,
209
- args: SwcUtils.getHelperAndHostSet(win, SwcUtils.findNearestSwcHost(this))
188
+ args: SwcUtils.getHelperAndHostSet(win, this)
210
189
  });
211
190
  this.connect(userConfig);
212
191
  } catch (e) {
@@ -1,60 +1,88 @@
1
1
  import { changedAttributeHost } from '../decorators/changedAttributeHost';
2
2
  import { SwcUtils } from '../utils/Utils';
3
- import { FunctionUtils } from '@dooboostore/core';
3
+ import { FunctionUtils, ActionExpression } from '@dooboostore/core';
4
+ import { ConvertUtils } from '@dooboostore/core-web';
5
+ import { attributeHost } from '../decorators';
4
6
 
5
- export class SwcAsync extends HTMLTemplateElement {
6
- private _nodes: Node[] = [];
7
- private _value: any = null;
7
+ class SwcAsync extends HTMLTemplateElement {
8
+ @attributeHost('value')
9
+ _value: any;
8
10
 
9
- private _resolvePortal(): Element | null {
10
- const portalScript = this.getAttribute('on-get-portal');
11
- if (!portalScript) return this.parentElement;
11
+ @attributeHost('replace-wrap')
12
+ _replaceWrap: string | null;
12
13
 
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;
14
+ resultValue?: any;
15
+
16
+ get value(): boolean {
17
+ return this._value;
23
18
  }
24
19
 
25
- private _executeCloneCallback(attr: string, args: any) {
26
- const script = this.getAttribute(attr);
27
- if (!script) return;
28
- FunctionUtils.execute({ script, context: this, args });
20
+ set value(nv: any) {
21
+ this.executeAsync(nv);
29
22
  }
30
23
 
31
- @changedAttributeHost('on-get-value')
32
- private refresh() {
33
- const script = this.getAttribute('on-get-value');
34
- if (!script) {
35
- this.render('default');
24
+ private _nodes: Node[] = [];
25
+
26
+ @changedAttributeHost('value')
27
+ private setValue(valueAttr?: string | null) {
28
+ this.executeAsync(this._value);
29
+ }
30
+
31
+ @changedAttributeHost('replace-wrap')
32
+ private setReplaceWrap() {
33
+ this.executeAsync(this._value);
34
+ }
35
+
36
+ private executeAsync(result: any = this._value) {
37
+ if (result === undefined || result === null) {
38
+ this.refresh('default');
36
39
  return;
37
40
  }
38
- const win = this.ownerDocument?.defaultView || window;
39
- const result = FunctionUtils.executeReturn({ script, context: this, args: SwcUtils.getHelperAndHostSet(win, this) });
40
41
 
41
42
  if (result instanceof Promise) {
42
- this.render('loading');
43
+ this.refresh('loading');
43
44
  result
44
45
  .then(v => {
45
- this._value = v;
46
- this.render('success');
46
+ this.resultValue = v;
47
+ this.refresh('success');
47
48
  })
48
- .catch(e => this.render('error'));
49
+ .catch(e => {
50
+ console.error('[SWC-ASYNC] Promise rejected:', e);
51
+ this.resultValue = e;
52
+ this.refresh('error');
53
+ });
49
54
  } else {
50
- this._value = result;
51
- this.render('success');
55
+ this.resultValue = result;
56
+ this.refresh('success');
52
57
  }
53
58
  }
54
59
 
55
- private render(state: string) {
60
+ private replaceExpressions(html: string, groupArgs: any, context: any, wrap?: string | null): string {
61
+ const config = wrap ? { wrapExpression: wrap } : undefined;
62
+ const ae = new ActionExpression(html, config);
63
+ const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';
64
+ const win = this.ownerDocument?.defaultView || window;
65
+
66
+ // @ts-ignore
67
+ for (const expr of ae.getExpressions(filterOptions)) {
68
+ try {
69
+ const value = FunctionUtils.executeReturn({
70
+ script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
71
+ context,
72
+ args: groupArgs
73
+ });
74
+ ae.replace(expr, String(value));
75
+ } catch (e) {
76
+ console.error(`[SWC] Failed to execute ${expr.original}:`, e);
77
+ }
78
+ }
79
+ return ae.getUnprocessedTemplate();
80
+ }
81
+
82
+ refresh(state: string = 'default') {
83
+ console.log('rrrrrrrrrrrrrrrrr', state);
56
84
  this.cleanup();
57
- const portal = this._resolvePortal();
85
+ const portal = this.parentElement;
58
86
  if (!portal) return;
59
87
 
60
88
  const win = this.ownerDocument?.defaultView || window;
@@ -62,23 +90,17 @@ export class SwcAsync extends HTMLTemplateElement {
62
90
 
63
91
  const t = this.content.querySelector(`template[is="swc-${state}"]`) as HTMLTemplateElement;
64
92
  if (t) {
65
- const clone = t.content.cloneNode(true) as DocumentFragment;
66
- this._nodes = Array.from(clone.childNodes);
67
- const elements = this._nodes.filter(n => n.nodeType === 1) as HTMLElement[];
68
- const groupArgs = { ...helperSet, $value: this._value, $nodes: this._nodes, $elements: elements, $firstElement: elements[0], $state: state };
69
-
70
- this._nodes.forEach((n, nodeIdx) => {
71
- if (n instanceof HTMLElement) (n as any).__swc_host = this;
72
- this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: n, $nodeIndex: nodeIdx, $isElement: n.nodeType === 1 });
73
- });
74
-
75
- this._executeCloneCallback('on-clone-nodes', groupArgs);
76
-
77
- if (portal === this.parentElement) {
78
- portal.insertBefore(clone, this.nextSibling);
79
- } else {
80
- portal.appendChild(clone);
81
- }
93
+ let htmlString = t.innerHTML;
94
+ const groupArgs = { ...helperSet, $value: this._value, $state: state };
95
+
96
+ htmlString = this.replaceExpressions(htmlString, groupArgs, this, this._replaceWrap);
97
+
98
+ const temp = this.ownerDocument?.createElement('template') || document.createElement('template');
99
+ temp.innerHTML = htmlString;
100
+ const content = temp.content;
101
+
102
+ this._nodes = Array.from(content.childNodes);
103
+ portal.insertBefore(content, this.nextSibling);
82
104
  }
83
105
  }
84
106
 
@@ -87,10 +109,6 @@ export class SwcAsync extends HTMLTemplateElement {
87
109
  this._nodes = [];
88
110
  }
89
111
 
90
- connectedCallback() {
91
- console.log('[SwcAsync] connectedCallback called');
92
- this.refresh();
93
- }
94
112
  disconnectedCallback() {
95
113
  this.cleanup();
96
114
  }