@dooboostore/simple-web-component 1.0.33 → 1.0.35

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 (150) hide show
  1. package/README.md +23 -30
  2. package/dist/cjs/decorators/addEventListener.js.map +1 -1
  3. package/dist/cjs/decorators/applyAttribute.js +67 -57
  4. package/dist/cjs/decorators/applyAttribute.js.map +2 -2
  5. package/dist/cjs/decorators/applyClass.js +80 -70
  6. package/dist/cjs/decorators/applyClass.js.map +2 -2
  7. package/dist/cjs/decorators/applyNode.js +5 -8
  8. package/dist/cjs/decorators/applyNode.js.map +2 -2
  9. package/dist/cjs/decorators/applyStyle.js +66 -56
  10. package/dist/cjs/decorators/applyStyle.js.map +2 -2
  11. package/dist/cjs/decorators/attribute.js +35 -29
  12. package/dist/cjs/decorators/attribute.js.map +2 -2
  13. package/dist/cjs/decorators/changedAttributeHost.js +32 -12
  14. package/dist/cjs/decorators/changedAttributeHost.js.map +2 -2
  15. package/dist/cjs/decorators/elementDefine.js +238 -180
  16. package/dist/cjs/decorators/elementDefine.js.map +2 -2
  17. package/dist/cjs/decorators/emitCustomEvent.js +67 -48
  18. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  19. package/dist/cjs/decorators/lifecycles.js +15 -17
  20. package/dist/cjs/decorators/lifecycles.js.map +2 -2
  21. package/dist/cjs/decorators/setProperty.js +50 -39
  22. package/dist/cjs/decorators/setProperty.js.map +2 -2
  23. package/dist/cjs/decorators/subscribeSwcAppMessageWhileConnected.js.map +1 -1
  24. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -2
  25. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
  26. package/dist/cjs/elements/SwcAppEngine.js +14 -8
  27. package/dist/cjs/elements/SwcAppEngine.js.map +3 -3
  28. package/dist/cjs/elements/SwcAppMixin.js +154 -81
  29. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  30. package/dist/cjs/elements/SwcAsync.js +28 -18
  31. package/dist/cjs/elements/SwcAsync.js.map +2 -2
  32. package/dist/cjs/elements/SwcChoose.js +68 -45
  33. package/dist/cjs/elements/SwcChoose.js.map +2 -2
  34. package/dist/cjs/elements/SwcIf.js +52 -30
  35. package/dist/cjs/elements/SwcIf.js.map +2 -2
  36. package/dist/cjs/elements/SwcLoop.js +109 -35
  37. package/dist/cjs/elements/SwcLoop.js.map +2 -2
  38. package/dist/cjs/elements/register.js +263 -131
  39. package/dist/cjs/elements/register.js.map +2 -2
  40. package/dist/cjs/router/ElementRouter.js +4 -2
  41. package/dist/cjs/router/ElementRouter.js.map +1 -1
  42. package/dist/cjs/types.js.map +1 -1
  43. package/dist/cjs/utils/Utils.js +25 -7
  44. package/dist/cjs/utils/Utils.js.map +2 -2
  45. package/dist/esm/decorators/addEventListener.js.map +1 -1
  46. package/dist/esm/decorators/applyAttribute.js +67 -57
  47. package/dist/esm/decorators/applyAttribute.js.map +2 -2
  48. package/dist/esm/decorators/applyClass.js +80 -70
  49. package/dist/esm/decorators/applyClass.js.map +2 -2
  50. package/dist/esm/decorators/applyNode.js +5 -8
  51. package/dist/esm/decorators/applyNode.js.map +2 -2
  52. package/dist/esm/decorators/applyStyle.js +66 -56
  53. package/dist/esm/decorators/applyStyle.js.map +2 -2
  54. package/dist/esm/decorators/attribute.js +35 -29
  55. package/dist/esm/decorators/attribute.js.map +2 -2
  56. package/dist/esm/decorators/changedAttributeHost.js +32 -12
  57. package/dist/esm/decorators/changedAttributeHost.js.map +2 -2
  58. package/dist/esm/decorators/elementDefine.js +240 -182
  59. package/dist/esm/decorators/elementDefine.js.map +2 -2
  60. package/dist/esm/decorators/emitCustomEvent.js +67 -48
  61. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  62. package/dist/esm/decorators/lifecycles.js +15 -17
  63. package/dist/esm/decorators/lifecycles.js.map +2 -2
  64. package/dist/esm/decorators/setProperty.js +50 -39
  65. package/dist/esm/decorators/setProperty.js.map +2 -2
  66. package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js.map +1 -1
  67. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -2
  68. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
  69. package/dist/esm/elements/SwcAppEngine.js +14 -7
  70. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  71. package/dist/esm/elements/SwcAppMixin.js +156 -82
  72. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  73. package/dist/esm/elements/SwcAsync.js +28 -18
  74. package/dist/esm/elements/SwcAsync.js.map +2 -2
  75. package/dist/esm/elements/SwcChoose.js +69 -46
  76. package/dist/esm/elements/SwcChoose.js.map +2 -2
  77. package/dist/esm/elements/SwcIf.js +53 -31
  78. package/dist/esm/elements/SwcIf.js.map +2 -2
  79. package/dist/esm/elements/SwcLoop.js +110 -36
  80. package/dist/esm/elements/SwcLoop.js.map +2 -2
  81. package/dist/esm/elements/register.js +264 -132
  82. package/dist/esm/elements/register.js.map +2 -2
  83. package/dist/esm/router/ElementRouter.js +5 -2
  84. package/dist/esm/router/ElementRouter.js.map +1 -1
  85. package/dist/esm/types.js.map +1 -1
  86. package/dist/esm/utils/Utils.js +25 -7
  87. package/dist/esm/utils/Utils.js.map +2 -2
  88. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +728 -595
  89. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  90. package/dist/types/decorators/addEventListener.d.ts +4 -1
  91. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  92. package/dist/types/decorators/applyAttribute.d.ts +5 -1
  93. package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
  94. package/dist/types/decorators/applyClass.d.ts +4 -0
  95. package/dist/types/decorators/applyClass.d.ts.map +1 -1
  96. package/dist/types/decorators/applyNode.d.ts +5 -1
  97. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  98. package/dist/types/decorators/applyStyle.d.ts +5 -1
  99. package/dist/types/decorators/applyStyle.d.ts.map +1 -1
  100. package/dist/types/decorators/attribute.d.ts +5 -0
  101. package/dist/types/decorators/attribute.d.ts.map +1 -1
  102. package/dist/types/decorators/changedAttributeHost.d.ts +14 -3
  103. package/dist/types/decorators/changedAttributeHost.d.ts.map +1 -1
  104. package/dist/types/decorators/elementDefine.d.ts +1 -1
  105. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  106. package/dist/types/decorators/emitCustomEvent.d.ts +15 -7
  107. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  108. package/dist/types/decorators/lifecycles.d.ts +10 -7
  109. package/dist/types/decorators/lifecycles.d.ts.map +1 -1
  110. package/dist/types/decorators/setProperty.d.ts +5 -1
  111. package/dist/types/decorators/setProperty.d.ts.map +1 -1
  112. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts +2 -2
  113. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts.map +1 -1
  114. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts +5 -6
  115. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts.map +1 -1
  116. package/dist/types/elements/SwcAppEngine.d.ts +9 -3
  117. package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
  118. package/dist/types/elements/SwcAppMixin.d.ts +12 -7
  119. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  120. package/dist/types/elements/register.d.ts.map +1 -1
  121. package/dist/types/types.d.ts +1 -0
  122. package/dist/types/types.d.ts.map +1 -1
  123. package/dist/types/utils/Utils.d.ts +4 -1
  124. package/dist/types/utils/Utils.d.ts.map +1 -1
  125. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +728 -595
  126. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  127. package/package.json +5 -5
  128. package/src/decorators/addEventListener.ts +1 -1
  129. package/src/decorators/applyAttribute.ts +74 -61
  130. package/src/decorators/applyClass.ts +91 -77
  131. package/src/decorators/applyNode.ts +16 -13
  132. package/src/decorators/applyStyle.ts +75 -61
  133. package/src/decorators/attribute.ts +55 -43
  134. package/src/decorators/changedAttributeHost.ts +49 -15
  135. package/src/decorators/elementDefine.ts +401 -340
  136. package/src/decorators/emitCustomEvent.ts +92 -62
  137. package/src/decorators/lifecycles.ts +11 -10
  138. package/src/decorators/setProperty.ts +58 -44
  139. package/src/decorators/subscribeSwcAppMessageWhileConnected.ts +2 -2
  140. package/src/decorators/subscribeSwcAppRouteChangeWhileConnected.ts +11 -11
  141. package/src/elements/SwcAppEngine.ts +19 -13
  142. package/src/elements/SwcAppMixin.ts +214 -102
  143. package/src/elements/SwcAsync.ts +28 -17
  144. package/src/elements/SwcChoose.ts +94 -36
  145. package/src/elements/SwcIf.ts +59 -22
  146. package/src/elements/SwcLoop.ts +140 -27
  147. package/src/elements/register.ts +319 -100
  148. package/src/types.ts +1 -0
  149. package/src/utils/Utils.ts +38 -10
  150. package/tsconfig.json +2 -2
@@ -1,17 +1,17 @@
1
- import { ReflectUtils, FunctionUtils, ActionExpression } from '@dooboostore/core';
2
- import { getAddEventListenerMetadata } from './addEventListener';
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';
4
- import { getEmitCustomEventMetadataList } from './emitCustomEvent';
5
- import { findAllAttributeChangedMetadata } from './changedAttributeHost';
6
- import { findAllAttributeApplyMetadata } from './applyAttribute';
7
- import { findAllAttributeMetadata } from './attribute';
8
- import { getQueryMetadata } from './query';
9
- import { getQueryAllMetadata } from './queryAll';
10
- import { SwcUtils } from '../utils/Utils';
11
- import { HTML_TAG_ENTRIES, DOM_EVENT_NAMES } from '../config/config';
12
- import { SituationTypeContainer, SituationTypeContainers } from '@dooboostore/simple-boot/decorators/inject/Inject';
13
- import { InjectSituationType, HostSet } from '../types';
14
- import { ConvertUtils } from '@dooboostore/core-web';
1
+ import {ReflectUtils, FunctionUtils, ActionExpression} from '@dooboostore/core';
2
+ import {getAddEventListenerMetadata} from './addEventListener';
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';
4
+ import {getEmitCustomEventMetadataList} from './emitCustomEvent';
5
+ import {findAllAttributeChangedMetadata, convertAttributeValue} from './changedAttributeHost';
6
+ import {findAllAttributeApplyMetadata} from './applyAttribute';
7
+ import {findAllAttributeMetadata, getAttributeValue} from './attribute';
8
+ import {getQueryMetadata} from './query';
9
+ import {getQueryAllMetadata} from './queryAll';
10
+ import {SwcUtils} from '../utils/Utils';
11
+ import {HTML_TAG_ENTRIES, DOM_EVENT_NAMES} from '../config/config';
12
+ import {SituationTypeContainer, SituationTypeContainers} from '@dooboostore/simple-boot/decorators/inject/Inject';
13
+ import {InjectSituationType, HostSet, HelperHostSet} from '../types';
14
+ import {ConvertUtils} from '@dooboostore/core-web';
15
15
 
16
16
  // --- Core Interfaces & Types ---
17
17
 
@@ -22,7 +22,7 @@ export interface ElementConfig {
22
22
  observedAttributes?: string[];
23
23
  customElementRegistry?: any;
24
24
  window?: Window;
25
- useShadow?: boolean;
25
+ useShadow?: boolean | 'open' | 'closed';
26
26
  }
27
27
 
28
28
  export interface ElementMetadata extends Omit<ElementConfig, 'window'> {
@@ -48,7 +48,7 @@ export const ensureInit = (inst: any) => {
48
48
  // });
49
49
 
50
50
  const target = inst instanceof Function ? inst : inst.constructor;
51
-
51
+
52
52
  // ╔════════════════════════════════════════════════════════════════════════════════╗
53
53
  // ║ decorator 필드의 own property 삭제 ║
54
54
  // ║ ║
@@ -67,13 +67,13 @@ export const ensureInit = (inst: any) => {
67
67
  // ║ 4. own property를 삭제하면 JavaScript가 prototype의 getter를 찾게 됨 ║
68
68
  // ║ → getter 호출됨 → DOM 속성 값 동기화됨 ║
69
69
  // ╚════════════════════════════════════════════════════════════════════════════════╝
70
-
70
+
71
71
  // @attribute 필드의 own property 삭제 → getter/setter 작동
72
72
  const attributeList = findAllAttributeMetadata(target);
73
73
  attributeList.forEach(meta => {
74
74
  delete (inst as any)[meta.propertyKey];
75
75
  });
76
-
76
+
77
77
  // @query 필드의 own property 삭제 → getter 작동
78
78
  const queryList = getQueryMetadata(target);
79
79
  if (queryList) {
@@ -81,7 +81,7 @@ export const ensureInit = (inst: any) => {
81
81
  delete (inst as any)[meta.propertyKey];
82
82
  });
83
83
  }
84
-
84
+
85
85
  // @queryAll 필드의 own property 삭제 → getter 작동
86
86
  const queryAllList = getQueryAllMetadata(target);
87
87
  if (queryAllList) {
@@ -98,7 +98,7 @@ export const ensureInit = (inst: any) => {
98
98
  // Call @onInitialize lifecycle methods
99
99
  const cMethods = findAllLifecycleMetadata(inst, ON_INITIALIZE_METADATA_KEY);
100
100
  if (cMethods) {
101
- for (const m of cMethods) (inst)._invokeLifecycleMethod(m, hostSet);
101
+ for (const m of cMethods) inst._invokeLifecycleMethod(m, hostSet);
102
102
  }
103
103
  }
104
104
  };
@@ -126,16 +126,16 @@ const handleGlobalSwcEvent = async (event: Event) => {
126
126
  }
127
127
  };
128
128
 
129
- function buildEnv(configWindow?: Window) {
130
- const win: Window = configWindow || ((typeof window !== 'undefined' ? window : undefined) as any);
129
+ function buildEnv(configWindow: Window) {
130
+ const win: Window = configWindow;
131
131
  const doc: Document = win?.document;
132
132
  const builtInTagMap = new Map<any, string>();
133
133
  for (const [cls, tag] of HTML_TAG_ENTRIES) {
134
134
  if ((win as any)?.[cls]) builtInTagMap.set((win as any)[cls], tag);
135
135
  }
136
136
  const domHelpers = SwcUtils.getHelperSet(win);
137
-
138
- return { win, doc, builtInTagMap, domHelpers };
137
+
138
+ return {win, doc, builtInTagMap, domHelpers};
139
139
  }
140
140
 
141
141
  const getHandlers = (inst: any) => {
@@ -155,8 +155,8 @@ const setupPrototype = (proto: any) => {
155
155
  const conf = getElementConfig(this);
156
156
  const currentWin = (this as any)._resolveWindow(conf);
157
157
  const helpers = SwcUtils.getHelperSet(currentWin);
158
- const args = { ...hostSet, ...helpers, ...extraArgs, $el: this, $root: this.getRootNode() };
159
- FunctionUtils.execute({ script, context: this, args });
158
+ const args = {...hostSet, ...helpers, ...extraArgs, $el: this, $root: this.getRootNode()};
159
+ FunctionUtils.execute({script, context: this, args});
160
160
  } catch (e) {
161
161
  console.error(`[SWC] Failed to execute ${attrName}:`, e);
162
162
  }
@@ -171,7 +171,7 @@ const setupPrototype = (proto: any) => {
171
171
  const aConf = getElementConfig(ancestors[i]);
172
172
  if (aConf?.window) return aConf.window;
173
173
  }
174
- return (typeof window !== 'undefined' ? window : undefined) as Window;
174
+ return getElementConfig(this).window ?? ((typeof window !== 'undefined' ? window : undefined) as Window);
175
175
  };
176
176
 
177
177
  proto._invokeLifecycleMethod = function (methodName: string | symbol, hostSet?: HostSet, extraArgs: any[] = []) {
@@ -182,7 +182,13 @@ const setupPrototype = (proto: any) => {
182
182
  // console.log('---->hh',app, this, methodName);
183
183
  if (app) {
184
184
  const otherStorage = new Map<any, any>();
185
- 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
+ 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({
186
+ situationType: InjectSituationType.HOST,
187
+ data: useHostSet.$host
188
+ }), 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({
189
+ situationType: InjectSituationType.FIRST_APP_HOST,
190
+ data: useHostSet.$firstAppHost
191
+ }), new SituationTypeContainer({situationType: InjectSituationType.LAST_APP_HOST, data: useHostSet.$lastAppHost})]);
186
192
  otherStorage.set(SituationTypeContainers, situations);
187
193
 
188
194
  return app.simstanceManager.executeBindParameterSim(
@@ -227,7 +233,7 @@ const setupPrototype = (proto: any) => {
227
233
  $el: el,
228
234
  $root: this.getRootNode()
229
235
  };
230
- await FunctionUtils.execute({ script, context: el, args });
236
+ await FunctionUtils.execute({script, context: el, args});
231
237
  };
232
238
 
233
239
  el.addEventListener(eventName, handler);
@@ -252,366 +258,421 @@ const setupPrototype = (proto: any) => {
252
258
  $el: el,
253
259
  $root: this.getRootNode()
254
260
  };
255
- await FunctionUtils.execute({ script, context: el, args });
261
+ await FunctionUtils.execute({script, context: el, args});
256
262
  };
257
263
  };
258
264
 
259
265
  export const elementDefine =
260
266
  (name: string, config: Partial<ElementConfig> = {}): ClassDecorator =>
261
- (constructor: any) => {
262
- const { win, doc, builtInTagMap: BUILT_IN_TAG_MAP, domHelpers: SWC_DOM_HELPERS } = buildEnv(config.window);
263
- const metadata: ElementMetadata = { ...config, name, window: win };
267
+ (constructor: any) => {
268
+ const {win, doc, builtInTagMap: BUILT_IN_TAG_MAP, domHelpers: SWC_DOM_HELPERS} = buildEnv(config.window);
269
+ const metadata: ElementMetadata = {...config, name, window: win};
264
270
 
265
- if (!metadata.window) {
266
- throw new Error('window is required');
267
- }
271
+ if (!metadata.window) {
272
+ throw new Error('window is required');
273
+ }
268
274
 
269
- let extendsTagName = metadata.extends;
270
- if (!extendsTagName) {
271
- let proto = constructor;
272
- const BaseHTMLElement = (win as any).HTMLElement;
273
- while (proto && proto !== BaseHTMLElement && proto !== Function.prototype) {
274
- extendsTagName = BUILT_IN_TAG_MAP.get(proto);
275
- if (extendsTagName) break;
276
- proto = Object.getPrototypeOf(proto);
275
+ let extendsTagName = metadata.extends;
276
+ if (!extendsTagName) {
277
+ let proto = constructor;
278
+ const BaseHTMLElement = (win as any).HTMLElement;
279
+ while (proto && proto !== BaseHTMLElement && proto !== Function.prototype) {
280
+ extendsTagName = BUILT_IN_TAG_MAP.get(proto);
281
+ if (extendsTagName) break;
282
+ proto = Object.getPrototypeOf(proto);
283
+ }
284
+ metadata.extends = extendsTagName;
277
285
  }
278
- metadata.extends = extendsTagName;
279
- }
280
286
 
281
- const emitCustomEventList = getEmitCustomEventMetadataList(constructor) || [];
282
- const emitHostCustomEventList = emitCustomEventList.filter(meta => meta.selector === ':host' || meta.selector === '');
283
- const addEventListenerList = getAddEventListenerMetadata(constructor) || [];
284
- const attrChangeMap = findAllAttributeChangedMetadata(constructor);
285
- const attributeList = findAllAttributeMetadata(constructor);
286
- const applyAttributeMap = findAllAttributeApplyMetadata(constructor);
287
-
288
- const swcLifecycleAttributes = ['swc-on-constructor', 'swc-on-connected', 'swc-on-disconnected', 'swc-on-before-connected', 'swc-on-after-connected', 'swc-on-before-disconnected', 'swc-on-after-disconnected', 'swc-on-before-adopted', 'swc-on-after-adopted', 'swc-on-attribute-changed'];
289
- const swcOnEvents = DOM_EVENT_NAMES.map(e => `swc-on-${e}`);
290
-
291
- // Collect all observed attributes from all decorators
292
- const attributeApplyNames = Array.from(applyAttributeMap.values()).map(it => it.options.name).filter(Boolean) as string[];
293
- // const attributeListNames = attributeList.map(it => it.options.name || String(it.propertyKey));
294
- const hostAttributes = attributeList.filter(it => it.selector === ':host').map(it=>it.options.name || String(it.propertyKey));
295
-
296
- const mergedObservedAttributes = [...new Set([
297
- ...(metadata.observedAttributes ?? []),
298
- ...attrChangeMap.keys(),
299
- ...attributeApplyNames,
300
- ...hostAttributes,
301
- ...emitHostCustomEventList.map(it => (it.options as any).attributeName).filter(Boolean),
302
- ...swcLifecycleAttributes,
303
- ...swcOnEvents
304
- ])];
305
-
306
- const connectedInnerHtmlList = getOnConnectedInnerHtmlMetadata(constructor) || [];
307
-
308
- const proto = constructor.prototype;
309
- setupPrototype(proto);
310
-
311
- const originalConnected = proto.connectedCallback;
312
- proto.connectedCallback = function () {
313
- ensureInit(this);
314
-
315
- const hostSet = SwcUtils.getHostSet(this as any);
316
- const appHost = hostSet.$appHost;
317
- const conf = getElementConfig(this);
318
- const currentWin = (this as any)._resolveWindow(conf);
287
+ const emitCustomEventList = getEmitCustomEventMetadataList(constructor) || [];
288
+ const emitHostCustomEventList = emitCustomEventList.filter(meta => meta.selector === ':host' || meta.selector === '');
289
+ const addEventListenerList = getAddEventListenerMetadata(constructor) || [];
290
+ const attrChangeMap = findAllAttributeChangedMetadata(constructor);
291
+ const attributeList = findAllAttributeMetadata(constructor);
292
+ const applyAttributeMap = findAllAttributeApplyMetadata(constructor);
293
+
294
+ const swcLifecycleAttributes = ['swc-on-constructor', 'swc-on-connected', 'swc-on-disconnected', 'swc-on-before-connected', 'swc-on-after-connected', 'swc-on-before-disconnected', 'swc-on-after-disconnected', 'swc-on-before-adopted', 'swc-on-after-adopted', 'swc-on-attribute-changed'];
295
+ const swcOnEvents = DOM_EVENT_NAMES.map(e => `swc-on-${e}`);
296
+
297
+ const attributeApplyNames = Array.from(applyAttributeMap.values())
298
+ .map(it => it.options.name)
299
+ .filter(Boolean) as string[];
300
+ const hostAttributes = attributeList.filter(it => it.selector === ':host').map(it => it.options.name || String(it.propertyKey));
301
+ // Get original static observedAttributes before they're overwritten by Object.defineProperty
302
+ const originalStaticObservedAttributes = (constructor.observedAttributes ?? []) as string[];
303
+ const mergedObservedAttributes = [...new Set([...(metadata.observedAttributes ?? []), ...originalStaticObservedAttributes, ...attrChangeMap.keys(), ...attributeApplyNames, ...hostAttributes, ...emitHostCustomEventList.map(it => (it.options as any).attributeName).filter(Boolean), ...swcLifecycleAttributes, ...swcOnEvents])];
304
+ const connectedInnerHtmlList = getOnConnectedInnerHtmlMetadata(constructor) || [];
305
+
306
+ const proto = constructor.prototype;
307
+ setupPrototype(proto);
308
+
309
+ // 값을 기대하지않는다.
310
+ let helperHostSet: HelperHostSet | null = null;
311
+ const originalConnected = proto.connectedCallback;
312
+ proto.connectedCallback = async function () {
313
+ ensureInit(this);
314
+ // connected 됐을시 최신화
315
+ helperHostSet = SwcUtils.getHelperAndHostSet(win, this as any);
316
+ const appHost = helperHostSet.$appHost;
317
+ try {
318
+ if (appHost && typeof (appHost as any)._connected === 'function') {
319
+ await (appHost as any)._connected(this);
320
+ } else if (appHost && typeof (appHost as any)) {
321
+ (appHost as any)._connected_safari ??= [];
322
+ (appHost as any)._connected_safari.push(this);
323
+ }
319
324
 
320
- if ((connectedInnerHtmlList.some(it => it.options.useShadow === true) || conf?.useShadow === true) && !this.shadowRoot) {
321
- this.attachShadow({ mode: 'open' });
322
- }
325
+ // const hostSet = SwcUtils.getHostSet(this as any);
326
+ const conf = getElementConfig(this);
327
+ const currentWin = (this as any)._resolveWindow(conf);
323
328
 
324
- (this as any)._executeSwcScript('swc-on-before-connected', hostSet);
325
- const bMethods = findAllLifecycleMetadata(this, ON_BEFORE_CONNECTED_METADATA_KEY);
326
- if (bMethods) {
327
- for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
328
- }
329
+ const shadowMode = conf?.useShadow || connectedInnerHtmlList.find(it => it.options.useShadow)?.options.useShadow;
330
+ if (shadowMode && !this.shadowRoot) {
331
+ const mode = shadowMode === true ? 'open' : shadowMode;
332
+ this.attachShadow({mode: mode as ShadowRootMode});
333
+ }
329
334
 
330
- if (connectedInnerHtmlList.length > 0) {
331
- let sContent = '',
332
- lContent = '';
333
- for (const meta of connectedInnerHtmlList) {
334
- // const res = (this as any)[meta.propertyKey]();
335
- const res = (this as any)._invokeLifecycleMethod(meta.propertyKey, hostSet);
336
- // console.log('------res0', res);
337
- // console.log('------res1', res1);
338
- if (res !== undefined) {
339
- if (meta.options.useShadow) sContent += res;
340
- else lContent += res;
335
+ const bMethods = findAllLifecycleMetadata(this, ON_BEFORE_CONNECTED_METADATA_KEY);
336
+ if (bMethods) {
337
+ for (const m of bMethods) await (this as any)._invokeLifecycleMethod(m, helperHostSet);
341
338
  }
342
- }
343
- if (this.shadowRoot) this.shadowRoot.innerHTML = sContent;
344
- if (lContent) this.innerHTML = lContent;
345
- }
339
+ (this as any)._executeSwcScript('swc-on-before-connected', helperHostSet);
340
+
341
+ if (connectedInnerHtmlList.length > 0) {
342
+ let sContent = '',
343
+ lContent = '';
344
+ for (const meta of connectedInnerHtmlList) {
345
+ // const res = (this as any)[meta.propertyKey]();
346
+ let res = await (this as any)._invokeLifecycleMethod(meta.propertyKey, helperHostSet);
347
+ const actionExpression = new ActionExpression(res, {
348
+ expression: {
349
+ replace: {
350
+ start: meta.options.replaceWrap?.start || '{%{',
351
+ end: meta.options.replaceWrap?.end || '}%}'
352
+ },
353
+ callReturn: {
354
+ start: meta.options.replaceWrap?.start || '{%{=',
355
+ end: meta.options.replaceWrap?.end || '}%}'
356
+ },
357
+ call: {
358
+ start: meta.options.replaceWrap?.start || '{%{@',
359
+ end: meta.options.replaceWrap?.end || '}%}'
360
+ }
361
+ }
362
+ });
363
+
364
+ actionExpression.getExpressions().filter(it => it.type === 'replace').forEach(it => {
365
+ try {
366
+ // const helperHostSet22 = SwcUtils.getHelperAndHostSet(win, this as any);
367
+ const sr = FunctionUtils.executeReturn({script: it.script, context: this, args: helperHostSet});
368
+ actionExpression.replace(it, sr);
369
+ } catch (e) {
370
+ console.error(`[SWC] Failed to execute connectedInnerHTML:`, e);
371
+ }
372
+ });
373
+ res = actionExpression.getUnprocessedTemplate();
346
374
 
347
- const root = this.getRootNode();
348
- if (!globalDelegatedRoots.has(root)) {
349
- DOM_EVENT_NAMES.forEach(type => {
350
- root.addEventListener(type, handleGlobalSwcEvent);
351
- });
352
- globalDelegatedRoots.add(root);
353
- }
375
+ if (res !== undefined) {
376
+ if (meta.options.useShadow || conf?.useShadow) sContent += res;
377
+ else lContent += res;
378
+ }
379
+ }
380
+ try {
381
+ if (this.shadowRoot) {
382
+ this.shadowRoot.innerHTML = sContent;
383
+ }
384
+ if (lContent) {
385
+ this.innerHTML = lContent;
386
+ }
387
+ } catch (e) {
388
+ console.error('[ElementDefine] innerHTML setting error:', e);
389
+ }
390
+ }
354
391
 
355
- // Separate delegate and non-delegate listeners
356
- const delegateListeners: typeof addEventListenerList = [];
357
- const nonDelegateListeners: typeof addEventListenerList = [];
358
-
359
- addEventListenerList.forEach(meta => {
360
- if (meta.options.delegate && meta.selector !== ':window' && meta.selector !== ':document' && meta.selector !== ':parentHost' && meta.selector !== ':appHost' && meta.selector !== ':firstHost' && meta.selector !== ':lastHost' && meta.selector !== ':firstAppHost' && meta.selector !== ':lastAppHost' && meta.selector !== ':hosts' && meta.selector !== ':appHosts' && meta.selector !== ':host' && meta.selector !== '') {
361
- delegateListeners.push(meta);
362
- } else {
363
- nonDelegateListeners.push(meta);
364
- }
365
- });
392
+ const root = this.getRootNode();
393
+ if (!globalDelegatedRoots.has(root)) {
394
+ DOM_EVENT_NAMES.forEach(type => {
395
+ root.addEventListener(type, handleGlobalSwcEvent);
396
+ });
397
+ globalDelegatedRoots.add(root);
398
+ }
366
399
 
367
- const delegatesByTypeAndRoot = new Map<string, any[]>();
368
- delegateListeners.forEach(meta => {
369
- const r = meta.options.root || 'auto';
370
- const rootKey = `${meta.type}:${r}`;
371
- if (!delegatesByTypeAndRoot.has(rootKey)) {
372
- delegatesByTypeAndRoot.set(rootKey, []);
373
- }
374
- delegatesByTypeAndRoot.get(rootKey)!.push(meta);
375
- });
400
+ // Separate delegate and non-delegate listeners
401
+ const delegateListeners: typeof addEventListenerList = [];
402
+ const nonDelegateListeners: typeof addEventListenerList = [];
376
403
 
377
- delegatesByTypeAndRoot.forEach((metaList, typeRootKey) => {
378
- const [type, rStr] = typeRootKey.split(':');
379
- const r = rStr === 'auto' ? 'auto' : rStr;
380
- const opts = { capture: metaList[0].options.capture, once: metaList[0].options.once, passive: metaList[0].options.passive };
381
-
382
- const bindRoots: (HTMLElement | ShadowRoot)[] = [];
383
- if (r === 'auto') bindRoots.push(this.shadowRoot || (this as any));
384
- else if (r === 'light') bindRoots.push(this as any);
385
- else if (r === 'shadow' && this.shadowRoot) bindRoots.push(this.shadowRoot);
386
- else if (r === 'all') {
387
- bindRoots.push(this as any);
388
- if (this.shadowRoot) bindRoots.push(this.shadowRoot);
389
- }
404
+ addEventListenerList.forEach(meta => {
405
+ if (meta.options.delegate && meta.selector !== ':window' && meta.selector !== ':document' && meta.selector !== ':parentHost' && meta.selector !== ':appHost' && meta.selector !== ':firstHost' && meta.selector !== ':lastHost' && meta.selector !== ':firstAppHost' && meta.selector !== ':lastAppHost' && meta.selector !== ':hosts' && meta.selector !== ':appHosts' && meta.selector !== ':host' && meta.selector !== '') {
406
+ delegateListeners.push(meta);
407
+ } else {
408
+ nonDelegateListeners.push(meta);
409
+ }
410
+ });
411
+
412
+ const delegatesByTypeAndRoot = new Map<string, any[]>();
413
+ delegateListeners.forEach(meta => {
414
+ const r = meta.options.root || 'auto';
415
+ const rootKey = `${meta.type}:${r}`;
416
+ if (!delegatesByTypeAndRoot.has(rootKey)) {
417
+ delegatesByTypeAndRoot.set(rootKey, []);
418
+ }
419
+ delegatesByTypeAndRoot.get(rootKey)!.push(meta);
420
+ });
390
421
 
391
- bindRoots.forEach(br => {
392
- const sortedMetaList = [...metaList].sort((a, b) => {
393
- const aStop = a.options.stopPropagation ? 1 : 0;
394
- const bStop = b.options.stopPropagation ? 1 : 0;
395
- return bStop - aStop;
422
+ delegatesByTypeAndRoot.forEach((metaList, typeRootKey) => {
423
+ const [type, rStr] = typeRootKey.split(':');
424
+ const r = rStr === 'auto' ? 'auto' : rStr;
425
+ const opts = {capture: metaList[0].options.capture, once: metaList[0].options.once, passive: metaList[0].options.passive};
426
+
427
+ const bindRoots: (HTMLElement | ShadowRoot)[] = [];
428
+ if (r === 'auto') bindRoots.push(this.shadowRoot || (this as any));
429
+ else if (r === 'light') bindRoots.push(this as any);
430
+ else if (r === 'shadow' && this.shadowRoot) bindRoots.push(this.shadowRoot);
431
+ else if (r === 'all') {
432
+ bindRoots.push(this as any);
433
+ if (this.shadowRoot) bindRoots.push(this.shadowRoot);
434
+ }
435
+
436
+ bindRoots.forEach(br => {
437
+ const sortedMetaList = [...metaList].sort((a, b) => {
438
+ const aStop = a.options.stopPropagation ? 1 : 0;
439
+ const bStop = b.options.stopPropagation ? 1 : 0;
440
+ return bStop - aStop;
441
+ });
442
+
443
+ const unifiedHandler = async (event: Event) => {
444
+ for (const meta of sortedMetaList) {
445
+ const {selector, options} = meta;
446
+ const matchedEl = (event.target as HTMLElement).closest(selector);
447
+ if (matchedEl && (br as any).contains(matchedEl)) {
448
+ // Apply filter if specified
449
+ if (options.filter) {
450
+ const helper = SwcUtils.getHelperAndHostSet(currentWin, matchedEl);
451
+ if (!options.filter(event, helper)) {
452
+ continue; // Skip this listener if filter returns false
453
+ }
454
+ }
455
+ if (options.stopPropagation) event.stopPropagation();
456
+ if (options.stopImmediatePropagation) event.stopImmediatePropagation();
457
+ if (options.preventDefault) event.preventDefault();
458
+ const currentHostSet = SwcUtils.getHostSet(this as any);
459
+ const args = {event, ...currentHostSet, $el: matchedEl, $root: br};
460
+ await (this as any)[meta.propertyKey](event, {...currentHostSet, $matchedElement: matchedEl}, args);
461
+ if ((event as any).cancelBubble) break;
462
+ }
463
+ }
464
+ };
465
+ br.addEventListener(type, unifiedHandler, opts);
466
+ (this as any)._boundListeners.push({target: br, type, handler: unifiedHandler, options: opts});
467
+ });
396
468
  });
397
-
398
- const unifiedHandler = async (event: Event) => {
399
- for (const meta of sortedMetaList) {
400
- const { selector, options } = meta;
401
- const matchedEl = (event.target as HTMLElement).closest(selector);
402
- if (matchedEl && (br as any).contains(matchedEl)) {
469
+
470
+ nonDelegateListeners.forEach(meta => {
471
+ const {selector, type, options} = meta;
472
+ const opts = {capture: options.capture, once: options.once, passive: options.passive};
473
+ const bindTargets: EventTarget[] = [];
474
+ const r = options.root || 'auto';
475
+ const applyRootOption = (target: any) => {
476
+ if (!target) return;
477
+ if (r === 'auto') {
478
+ bindTargets.push(target.shadowRoot || target);
479
+ } else {
480
+ if (r === 'light' || r === 'all') bindTargets.push(target);
481
+ if ((r === 'shadow' || r === 'all') && target.shadowRoot) bindTargets.push(target.shadowRoot);
482
+ }
483
+ };
484
+
485
+ if (selector === ':window') bindTargets.push(currentWin);
486
+ else if (selector === ':document') bindTargets.push(currentWin.document);
487
+ else if (selector === ':parentHost') applyRootOption(helperHostSet.$parentHost);
488
+ else if (selector === ':appHost') applyRootOption(helperHostSet.$appHost);
489
+ else if (selector === ':firstHost') applyRootOption(helperHostSet.$firstHost);
490
+ else if (selector === ':lastHost') applyRootOption(helperHostSet.$lastHost);
491
+ else if (selector === ':firstAppHost') applyRootOption(helperHostSet.$firstAppHost);
492
+ else if (selector === ':lastAppHost') applyRootOption(helperHostSet.$lastAppHost);
493
+ else if (selector === ':hosts') helperHostSet.$hosts.forEach(applyRootOption);
494
+ else if (selector === ':appHosts') helperHostSet.$appHosts.forEach(applyRootOption);
495
+ else if (selector === ':host' || !selector) applyRootOption(this);
496
+ else {
497
+ const searchRoots: (HTMLElement | ShadowRoot)[] = [];
498
+ if (r === 'auto') searchRoots.push(this.shadowRoot || (this as any));
499
+ else if (r === 'light') searchRoots.push(this as any);
500
+ else if (r === 'shadow' && this.shadowRoot) searchRoots.push(this.shadowRoot);
501
+ else if (r === 'all') {
502
+ searchRoots.push(this as any);
503
+ if (this.shadowRoot) searchRoots.push(this.shadowRoot);
504
+ }
505
+
506
+ searchRoots.forEach(sr => {
507
+ sr.querySelectorAll(selector).forEach(el => bindTargets.push(el));
508
+ });
509
+ }
510
+
511
+ bindTargets.forEach(t => {
512
+ const handler = async (event: Event) => {
403
513
  // Apply filter if specified
404
514
  if (options.filter) {
405
- const helper = SwcUtils.getHelperAndHostSet(currentWin, matchedEl);
406
- if (!options.filter(event, helper)) {
407
- continue; // Skip this listener if filter returns false
515
+ const helper = SwcUtils.getHelperAndHostSet(currentWin, t as HTMLElement);
516
+ if (!options.filter(event, {currentThis: this, helper})) {
517
+ return; // Skip if filter returns false
408
518
  }
409
519
  }
410
520
  if (options.stopPropagation) event.stopPropagation();
411
521
  if (options.stopImmediatePropagation) event.stopImmediatePropagation();
412
522
  if (options.preventDefault) event.preventDefault();
413
523
  const currentHostSet = SwcUtils.getHostSet(this as any);
414
- const args = { event, ...currentHostSet, $el: matchedEl, $root: br };
415
- await (this as any)[meta.propertyKey](event, currentHostSet, matchedEl, args);
416
- if ((event as any).cancelBubble) break;
524
+ const args = {event, ...currentHostSet, $el: t, $root: t};
525
+ await (this as any)[meta.propertyKey](event, {currentHostSet, $$matchedElement: event.currentTarget}, args);
526
+ };
527
+ t.addEventListener(type, handler, opts);
528
+ if (options.removeOnDisconnected === true || t === currentWin || t === currentWin.document) {
529
+ (this as any)._boundListeners.push({target: t, type, handler, options: opts});
417
530
  }
418
- }
419
- };
420
- br.addEventListener(type, unifiedHandler, opts);
421
- (this as any)._boundListeners.push({ target: br, type, handler: unifiedHandler, options: opts });
422
- });
423
- });
531
+ });
532
+ });
424
533
 
425
- nonDelegateListeners.forEach(meta => {
426
- const { selector, type, options } = meta;
427
- const opts = { capture: options.capture, once: options.once, passive: options.passive };
428
- const bindTargets: EventTarget[] = [];
429
- const r = options.root || 'auto';
430
- const applyRootOption = (target: any) => {
431
- if (!target) return;
432
- if (r === 'auto') {
433
- bindTargets.push(target.shadowRoot || target);
434
- } else {
435
- if (r === 'light' || r === 'all') bindTargets.push(target);
436
- if ((r === 'shadow' || r === 'all') && target.shadowRoot) bindTargets.push(target.shadowRoot);
534
+ if (originalConnected) await (originalConnected.apply(this));
535
+
536
+ const aMethods = findAllLifecycleMetadata(this, ON_AFTER_CONNECTED_METADATA_KEY);
537
+ if (aMethods) {
538
+ for (const m of aMethods) await (this as any)._invokeLifecycleMethod(m, helperHostSet);
539
+ }
540
+ (this as any)._executeSwcScript('swc-on-connected', helperHostSet);
541
+ (this as any)._executeSwcScript('swc-on-after-connected', helperHostSet);
542
+ (this as any).__swc_connected = true;
543
+
544
+ // Trigger @changedAttributeHost with while: 'connected'
545
+ for (let [name, metaList] of Array.from(attrChangeMap)) {
546
+ for (const meta of metaList) {
547
+ if (meta.options.while === 'connected') {
548
+ const val = getAttributeValue(this, name, {type: meta.options.type});
549
+ if (val !== null) {
550
+ await ((this as any)[meta.propertyKey](val, null, name, helperHostSet));
551
+ }
552
+ }
553
+ }
437
554
  }
438
- };
439
-
440
- if (selector === ':window') bindTargets.push(currentWin);
441
- else if (selector === ':document') bindTargets.push(currentWin.document);
442
- else if (selector === ':parentHost') applyRootOption(hostSet.$parentHost);
443
- else if (selector === ':appHost') applyRootOption(hostSet.$appHost);
444
- else if (selector === ':firstHost') applyRootOption(hostSet.$firstHost);
445
- else if (selector === ':lastHost') applyRootOption(hostSet.$lastHost);
446
- else if (selector === ':firstAppHost') applyRootOption(hostSet.$firstAppHost);
447
- else if (selector === ':lastAppHost') applyRootOption(hostSet.$lastAppHost);
448
- else if (selector === ':hosts') hostSet.$hosts.forEach(applyRootOption);
449
- else if (selector === ':appHosts') hostSet.$appHosts.forEach(applyRootOption);
450
- else if (selector === ':host' || !selector) applyRootOption(this);
451
- else {
452
- const searchRoots: (HTMLElement | ShadowRoot)[] = [];
453
- if (r === 'auto') searchRoots.push(this.shadowRoot || (this as any));
454
- else if (r === 'light') searchRoots.push(this as any);
455
- else if (r === 'shadow' && this.shadowRoot) searchRoots.push(this.shadowRoot);
456
- else if (r === 'all') {
457
- searchRoots.push(this as any);
458
- if (this.shadowRoot) searchRoots.push(this.shadowRoot);
555
+ } finally {
556
+ if (appHost && typeof (appHost as any)._connectedDone === 'function') {
557
+ await (appHost as any)._connectedDone(this);
459
558
  }
559
+ }
560
+ };
460
561
 
461
- searchRoots.forEach(sr => {
462
- sr.querySelectorAll(selector).forEach(el => bindTargets.push(el));
463
- });
562
+ const originalDisconnected = proto.disconnectedCallback;
563
+ proto.disconnectedCallback = function () {
564
+ // const helperHostSet = SwcUtils.getHelperAndHostSet(win, this as any);
565
+ // Remove from appHost LAST when disconnected
566
+ console.log('disconnnnnnnnnnnnnnnnnnn', helperHostSet, this)
567
+ const appHost = helperHostSet.$appHost;
568
+ if (appHost && typeof (appHost as any)._disconnected === 'function') {
569
+ (appHost as any)._disconnected(this);
464
570
  }
465
571
 
466
- bindTargets.forEach(t => {
467
- const handler = async (event: Event) => {
468
- // Apply filter if specified
469
- if (options.filter) {
470
- const helper = SwcUtils.getHelperAndHostSet(currentWin, t as HTMLElement);
471
- if (!options.filter(event, helper)) {
472
- return; // Skip if filter returns false
473
- }
474
- }
475
- if (options.stopPropagation) event.stopPropagation();
476
- if (options.stopImmediatePropagation) event.stopImmediatePropagation();
477
- if (options.preventDefault) event.preventDefault();
478
- const currentHostSet = SwcUtils.getHostSet(this as any);
479
- const args = { event, ...currentHostSet, $el: t, $root: t };
480
- await (this as any)[meta.propertyKey](event, currentHostSet, args);
481
- };
482
- t.addEventListener(type, handler, opts);
483
- if (options.removeOnDisconnected === true || t === currentWin || t === currentWin.document) {
484
- (this as any)._boundListeners.push({ target: t, type, handler, options: opts });
485
- }
486
- });
487
- });
572
+ (this as any)._executeSwcScript('swc-on-before-disconnected', helperHostSet);
573
+ const bMethods = findAllLifecycleMetadata(this, ON_BEFORE_DISCONNECTED_METADATA_KEY);
574
+ if (bMethods) {
575
+ for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, helperHostSet);
576
+ }
488
577
 
489
- if (originalConnected) originalConnected.apply(this);
578
+ if ((this as any)._boundListeners) {
579
+ (this as any)._boundListeners.forEach((l: any) => l.target.removeEventListener(l.type, l.handler, l.options));
580
+ (this as any)._boundListeners = [];
581
+ }
490
582
 
491
- const aMethods = findAllLifecycleMetadata(this, ON_AFTER_CONNECTED_METADATA_KEY);
492
- if (aMethods) {
493
- for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
494
- }
495
- (this as any)._executeSwcScript('swc-on-connected', hostSet);
496
- (this as any)._executeSwcScript('swc-on-after-connected', hostSet);
497
- (this as any).__swc_connected = true;
498
-
499
- // Register to appHost LAST when all lifecycle completed
500
- // console.log('!!!!!!!!!!!!!!', this, appHost)
501
- const appHostss = SwcUtils.findAllParentAppHostsDirect(this)
502
- // const nAppHostSet = SwcUtils.getHostSet(this as any);
503
- if (appHost && typeof (appHost as any)._connected === 'function') {
504
- (appHost as any)._connected(this);
505
- } else if (appHost && typeof (appHost as any)) {
506
- (appHost as any)._connected_safari ??= [];
507
- (appHost as any)._connected_safari.push(this);
508
- }
509
- };
583
+ if (originalDisconnected) originalDisconnected.apply(this);
510
584
 
511
- const originalDisconnected = proto.disconnectedCallback;
512
- proto.disconnectedCallback = function () {
513
- const hostSet = SwcUtils.getHostSet(this as any);
514
- (this as any)._executeSwcScript('swc-on-before-disconnected', hostSet);
515
- const bMethods = findAllLifecycleMetadata(this, ON_BEFORE_DISCONNECTED_METADATA_KEY);
516
- if (bMethods) {
517
- for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
518
- }
585
+ const aMethods = findAllLifecycleMetadata(this, ON_AFTER_DISCONNECTED_METADATA_KEY);
586
+ if (aMethods) {
587
+ for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, helperHostSet);
588
+ }
589
+ (this as any)._executeSwcScript('swc-on-disconnected', helperHostSet);
590
+ (this as any)._executeSwcScript('swc-on-after-disconnected', helperHostSet);
591
+ (this as any).__swc_connected = false;
592
+ };
519
593
 
520
- if ((this as any)._boundListeners) {
521
- (this as any)._boundListeners.forEach((l: any) => l.target.removeEventListener(l.type, l.handler, l.options));
522
- (this as any)._boundListeners = [];
523
- }
594
+ const originalAdopted = proto.adoptedCallback;
595
+ proto.adoptedCallback = function () {
596
+ const hostSet = SwcUtils.getHostSet(this as any);
597
+ (this as any)._executeSwcScript('swc-on-before-adopted', hostSet);
598
+ const bMethods = findAllLifecycleMetadata(this, ON_BEFORE_ADOPTED_METADATA_KEY);
599
+ if (bMethods) {
600
+ for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
601
+ }
524
602
 
525
- if (originalDisconnected) originalDisconnected.apply(this);
603
+ if (originalAdopted) originalAdopted.apply(this);
526
604
 
527
- const aMethods = findAllLifecycleMetadata(this, ON_AFTER_DISCONNECTED_METADATA_KEY);
528
- if (aMethods) {
529
- for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
530
- }
531
- (this as any)._executeSwcScript('swc-on-disconnected', hostSet);
532
- (this as any)._executeSwcScript('swc-on-after-disconnected', hostSet);
533
- (this as any).__swc_connected = false;
534
-
535
- // Remove from appHost LAST when disconnected
536
- const appHost = hostSet.$appHost;
537
- if (appHost && typeof (appHost as any)._disconnected === 'function') {
538
- (appHost as any)._disconnected(this);
539
- }
540
- };
605
+ const aMethods = findAllLifecycleMetadata(this, ON_AFTER_ADOPTED_METADATA_KEY);
606
+ if (aMethods) {
607
+ for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
608
+ }
609
+ (this as any)._executeSwcScript('swc-on-adopted', hostSet);
610
+ (this as any)._executeSwcScript('swc-on-after-adopted', hostSet);
611
+ };
541
612
 
542
- const originalAdopted = proto.adoptedCallback;
543
- proto.adoptedCallback = function () {
544
- const hostSet = SwcUtils.getHostSet(this as any);
545
- (this as any)._executeSwcScript('swc-on-before-adopted', hostSet);
546
- const bMethods = findAllLifecycleMetadata(this, ON_BEFORE_ADOPTED_METADATA_KEY);
547
- if (bMethods) {
548
- for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
549
- }
613
+ const originalAttributeChanged = proto.attributeChangedCallback;
614
+ proto.attributeChangedCallback = function (name: string, old: string | null, newVal: string | null) {
615
+ if (originalAttributeChanged) originalAttributeChanged.apply(this, [name, old, newVal]);
550
616
 
551
- if (originalAdopted) originalAdopted.apply(this);
617
+ const hSet = SwcUtils.getHostSet(this as any);
552
618
 
553
- const aMethods = findAllLifecycleMetadata(this, ON_AFTER_ADOPTED_METADATA_KEY);
554
- if (aMethods) {
555
- for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
556
- }
557
- (this as any)._executeSwcScript('swc-on-adopted', hostSet);
558
- (this as any)._executeSwcScript('swc-on-after-adopted', hostSet);
559
- };
619
+ // Process expression directive before passing to handlers
620
+ let processedVal: any = newVal;
621
+ if (newVal !== null) {
622
+ const ae = new ActionExpression(newVal);
623
+ const expr = ae.getFirstExpression('callReturn');
624
+ if (expr) {
625
+ const win = (this as any)._resolveWindow?.() || ((typeof window !== 'undefined' ? window : undefined) as any);
626
+ const helperAndHostSet = SwcUtils.getHelperAndHostSet(win, this as any);
627
+ const script = ConvertUtils.decodeHtmlEntity(expr.script, win.document);
628
+ try {
629
+ const result = FunctionUtils.executeReturn({
630
+ script: script,
631
+ context: this,
632
+ args: helperAndHostSet
633
+ });
634
+ // Pass the result object directly without serialization
635
+ processedVal = result;
636
+ } catch (e) {
637
+ console.error(`[SWC] Failed to execute directive {{= ${expr.script} }} on attribute ${name}: ${helperAndHostSet}`, e);
638
+ processedVal = newVal;
639
+ }
640
+ }
641
+ }
560
642
 
561
- const originalAttributeChanged = proto.attributeChangedCallback;
562
- proto.attributeChangedCallback = function (name: string, old: string | null, newVal: string | null) {
563
- if (originalAttributeChanged) originalAttributeChanged.apply(this, [name, old, newVal]);
564
-
565
- const hSet = SwcUtils.getHostSet(this as any);
566
-
567
- // Process expression directive before passing to handlers
568
- let processedVal = newVal;
569
- if (newVal !== null) {
570
- const ae = new ActionExpression(newVal);
571
- const expr = ae.getFirstExpression('call-return');
572
- if (expr) {
573
- const win = (this as any)._resolveWindow?.() || ((typeof window !== 'undefined' ? window : undefined) as any);
574
- try {
575
- const result = FunctionUtils.executeReturn({
576
- script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
577
- context: this,
578
- args: SwcUtils.getHelperAndHostSet(win,this as any)
579
- });
580
- processedVal = String(result);
581
- } catch (e) {
582
- console.error(`[SWC] Failed to execute directive {{= ${expr.script} }} on attribute ${name}:`, e);
583
- processedVal = newVal;
643
+ if (name.startsWith('swc-on-') && !swcLifecycleAttributes.includes(name)) {
644
+ if (newVal !== null) {
645
+ const eventName = name.substring(7);
646
+ (this as any)._bindAttributeEvent(this as any, name, newVal, eventName);
584
647
  }
585
648
  }
586
- }
587
649
 
588
- if (name.startsWith('swc-on-') && !swcLifecycleAttributes.includes(name)) {
589
- if (newVal !== null) {
590
- const eventName = name.substring(7);
591
- (this as any)._bindAttributeEvent(this as any, name, newVal, eventName);
650
+ const hostCustomEventMeta = emitHostCustomEventList.find(it => (it.options as any).attributeName === name);
651
+ if (hostCustomEventMeta && newVal !== null) {
652
+ (this as any)._bindAttributeEvent(this as any, name, newVal, hostCustomEventMeta.type);
592
653
  }
593
- }
594
654
 
595
- const hostCustomEventMeta = emitHostCustomEventList.find(it => (it.options as any).attributeName === name);
596
- if (hostCustomEventMeta && newVal !== null) {
597
- (this as any)._bindAttributeEvent(this as any, name, newVal, hostCustomEventMeta.type);
598
- }
655
+ const metaList = attrChangeMap.get(name);
656
+ if (metaList && Array.isArray(metaList)) {
657
+ for (const meta of metaList) {
658
+ if (meta.options.while === 'connected' && !(this as any).__swc_connected) {
659
+ continue;
660
+ }
661
+ const convertedVal = convertAttributeValue(processedVal, meta.options.type);
662
+ (this as any)[meta.propertyKey](convertedVal, old, name, hSet);
663
+ }
664
+ }
665
+ };
599
666
 
600
- const mKeys = attrChangeMap.get(name);
601
- if (mKeys && Array.isArray(mKeys)) {
602
- for (const key of mKeys) (this as any)[key](processedVal, old, name, hSet);
667
+ Object.defineProperty(constructor, 'observedAttributes', {
668
+ get: () => mergedObservedAttributes,
669
+ configurable: true
670
+ });
671
+
672
+ ReflectUtils.defineMetadata(ELEMENT_CONFIG_KEY, metadata, constructor);
673
+ const registry = metadata.customElementRegistry || (win as any)?.customElements;
674
+ if (registry && !registry.get(metadata.name)) {
675
+ registry.define(metadata.name, constructor as any, metadata.extends ? {extends: metadata.extends} : undefined);
603
676
  }
677
+ return constructor;
604
678
  };
605
-
606
- Object.defineProperty(constructor, 'observedAttributes', {
607
- get: () => mergedObservedAttributes,
608
- configurable: true
609
- });
610
-
611
- ReflectUtils.defineMetadata(ELEMENT_CONFIG_KEY, metadata, constructor);
612
- const registry = metadata.customElementRegistry || (win as any)?.customElements;
613
- if (registry && !registry.get(metadata.name)) {
614
- registry.define(metadata.name, constructor as any, metadata.extends ? { extends: metadata.extends } : undefined);
615
- }
616
- return constructor;
617
- };