@dooboostore/simple-web-component 1.0.34 → 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 (107) hide show
  1. package/README.md +23 -30
  2. package/dist/cjs/decorators/applyNode.js +4 -0
  3. package/dist/cjs/decorators/applyNode.js.map +2 -2
  4. package/dist/cjs/decorators/attribute.js +1 -1
  5. package/dist/cjs/decorators/attribute.js.map +2 -2
  6. package/dist/cjs/decorators/changedAttributeHost.js.map +2 -2
  7. package/dist/cjs/decorators/elementDefine.js +225 -180
  8. package/dist/cjs/decorators/elementDefine.js.map +2 -2
  9. package/dist/cjs/decorators/emitCustomEvent.js +10 -4
  10. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  11. package/dist/cjs/decorators/lifecycles.js +15 -17
  12. package/dist/cjs/decorators/lifecycles.js.map +2 -2
  13. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -2
  14. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
  15. package/dist/cjs/elements/SwcAppEngine.js +8 -2
  16. package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
  17. package/dist/cjs/elements/SwcAppMixin.js +120 -65
  18. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  19. package/dist/cjs/elements/SwcAsync.js +28 -18
  20. package/dist/cjs/elements/SwcAsync.js.map +2 -2
  21. package/dist/cjs/elements/SwcChoose.js +51 -32
  22. package/dist/cjs/elements/SwcChoose.js.map +2 -2
  23. package/dist/cjs/elements/SwcIf.js +52 -30
  24. package/dist/cjs/elements/SwcIf.js.map +2 -2
  25. package/dist/cjs/elements/SwcLoop.js +109 -35
  26. package/dist/cjs/elements/SwcLoop.js.map +2 -2
  27. package/dist/cjs/elements/register.js +244 -117
  28. package/dist/cjs/elements/register.js.map +2 -2
  29. package/dist/cjs/router/ElementRouter.js +4 -2
  30. package/dist/cjs/router/ElementRouter.js.map +1 -1
  31. package/dist/cjs/types.js.map +1 -1
  32. package/dist/cjs/utils/Utils.js +18 -4
  33. package/dist/cjs/utils/Utils.js.map +2 -2
  34. package/dist/esm/decorators/applyNode.js +4 -0
  35. package/dist/esm/decorators/applyNode.js.map +2 -2
  36. package/dist/esm/decorators/attribute.js +1 -1
  37. package/dist/esm/decorators/attribute.js.map +2 -2
  38. package/dist/esm/decorators/changedAttributeHost.js.map +2 -2
  39. package/dist/esm/decorators/elementDefine.js +226 -181
  40. package/dist/esm/decorators/elementDefine.js.map +2 -2
  41. package/dist/esm/decorators/emitCustomEvent.js +10 -4
  42. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  43. package/dist/esm/decorators/lifecycles.js +15 -17
  44. package/dist/esm/decorators/lifecycles.js.map +2 -2
  45. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -2
  46. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
  47. package/dist/esm/elements/SwcAppEngine.js +9 -2
  48. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  49. package/dist/esm/elements/SwcAppMixin.js +122 -66
  50. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  51. package/dist/esm/elements/SwcAsync.js +28 -18
  52. package/dist/esm/elements/SwcAsync.js.map +2 -2
  53. package/dist/esm/elements/SwcChoose.js +51 -32
  54. package/dist/esm/elements/SwcChoose.js.map +2 -2
  55. package/dist/esm/elements/SwcIf.js +53 -31
  56. package/dist/esm/elements/SwcIf.js.map +2 -2
  57. package/dist/esm/elements/SwcLoop.js +110 -36
  58. package/dist/esm/elements/SwcLoop.js.map +2 -2
  59. package/dist/esm/elements/register.js +244 -117
  60. package/dist/esm/elements/register.js.map +2 -2
  61. package/dist/esm/router/ElementRouter.js +5 -2
  62. package/dist/esm/router/ElementRouter.js.map +1 -1
  63. package/dist/esm/types.js.map +1 -1
  64. package/dist/esm/utils/Utils.js +18 -4
  65. package/dist/esm/utils/Utils.js.map +2 -2
  66. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +319 -276
  67. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  68. package/dist/types/decorators/applyNode.d.ts +1 -0
  69. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  70. package/dist/types/decorators/changedAttributeHost.d.ts +1 -0
  71. package/dist/types/decorators/changedAttributeHost.d.ts.map +1 -1
  72. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  73. package/dist/types/decorators/emitCustomEvent.d.ts +10 -6
  74. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  75. package/dist/types/decorators/lifecycles.d.ts +10 -7
  76. package/dist/types/decorators/lifecycles.d.ts.map +1 -1
  77. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts +4 -5
  78. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts.map +1 -1
  79. package/dist/types/elements/SwcAppEngine.d.ts +4 -1
  80. package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
  81. package/dist/types/elements/SwcAppMixin.d.ts +11 -8
  82. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  83. package/dist/types/elements/register.d.ts.map +1 -1
  84. package/dist/types/types.d.ts +1 -0
  85. package/dist/types/types.d.ts.map +1 -1
  86. package/dist/types/utils/Utils.d.ts +4 -1
  87. package/dist/types/utils/Utils.d.ts.map +1 -1
  88. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +319 -276
  89. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  90. package/package.json +4 -4
  91. package/src/decorators/applyNode.ts +13 -1
  92. package/src/decorators/attribute.ts +1 -1
  93. package/src/decorators/changedAttributeHost.ts +3 -2
  94. package/src/decorators/elementDefine.ts +397 -354
  95. package/src/decorators/emitCustomEvent.ts +29 -15
  96. package/src/decorators/lifecycles.ts +11 -10
  97. package/src/decorators/subscribeSwcAppRouteChangeWhileConnected.ts +10 -10
  98. package/src/elements/SwcAppEngine.ts +10 -3
  99. package/src/elements/SwcAppMixin.ts +177 -97
  100. package/src/elements/SwcAsync.ts +28 -17
  101. package/src/elements/SwcChoose.ts +71 -34
  102. package/src/elements/SwcIf.ts +59 -22
  103. package/src/elements/SwcLoop.ts +140 -27
  104. package/src/elements/register.ts +296 -98
  105. package/src/types.ts +1 -0
  106. package/src/utils/Utils.ts +23 -5
  107. 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, convertAttributeValue } 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
 
@@ -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
  };
@@ -134,8 +134,8 @@ function buildEnv(configWindow: Window) {
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 getElementConfig(this).window ?? (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,384 +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 proto = constructor.prototype;
297
-
298
- // Get original static observedAttributes before they're overwritten by Object.defineProperty
299
- const originalStaticObservedAttributes = (constructor.observedAttributes ?? []) as string[];
300
-
301
- // proto.observedAttributes??[];
302
- const mergedObservedAttributes = [...new Set([
303
- ...(metadata.observedAttributes ?? []),
304
- ...originalStaticObservedAttributes,
305
- ...attrChangeMap.keys(),
306
- ...attributeApplyNames,
307
- ...hostAttributes,
308
- ...emitHostCustomEventList.map(it => (it.options as any).attributeName).filter(Boolean),
309
- ...swcLifecycleAttributes,
310
- ...swcOnEvents
311
- ])];
312
-
313
- const connectedInnerHtmlList = getOnConnectedInnerHtmlMetadata(constructor) || [];
314
-
315
- setupPrototype(proto);
316
-
317
- const originalConnected = proto.connectedCallback;
318
- proto.connectedCallback = function () {
319
- ensureInit(this);
320
-
321
- const hostSet = SwcUtils.getHostSet(this as any);
322
- const appHost = hostSet.$appHost;
323
- const conf = getElementConfig(this);
324
- 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
+ }
325
324
 
326
- const shadowMode = conf?.useShadow || connectedInnerHtmlList.find(it => it.options.useShadow)?.options.useShadow;
327
- if (shadowMode && !this.shadowRoot) {
328
- const mode = shadowMode === true ? 'open' : shadowMode;
329
- this.attachShadow({ mode: mode as ShadowRootMode });
330
- }
325
+ // const hostSet = SwcUtils.getHostSet(this as any);
326
+ const conf = getElementConfig(this);
327
+ const currentWin = (this as any)._resolveWindow(conf);
331
328
 
332
- (this as any)._executeSwcScript('swc-on-before-connected', hostSet);
333
- const bMethods = findAllLifecycleMetadata(this, ON_BEFORE_CONNECTED_METADATA_KEY);
334
- if (bMethods) {
335
- for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
336
- }
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
+ }
337
334
 
338
- if (connectedInnerHtmlList.length > 0) {
339
- let sContent = '',
340
- lContent = '';
341
- for (const meta of connectedInnerHtmlList) {
342
- // const res = (this as any)[meta.propertyKey]();
343
- const res = (this as any)._invokeLifecycleMethod(meta.propertyKey, hostSet);
344
- // console.log('------res0', res);
345
- // console.log('------res1', res1);
346
- if (res !== undefined) {
347
- if (meta.options.useShadow || conf?.useShadow) sContent += res;
348
- 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);
349
338
  }
350
- }
351
- try {
352
- if (this.shadowRoot) this.shadowRoot.innerHTML = sContent;
353
- if (lContent) this.innerHTML = lContent;
354
- } catch (e) {
355
- console.error('[ElementDefine] innerHTML setting error:', e);
356
- }
357
- }
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();
358
374
 
359
- const root = this.getRootNode();
360
- if (!globalDelegatedRoots.has(root)) {
361
- DOM_EVENT_NAMES.forEach(type => {
362
- root.addEventListener(type, handleGlobalSwcEvent);
363
- });
364
- globalDelegatedRoots.add(root);
365
- }
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
+ }
366
391
 
367
- // Separate delegate and non-delegate listeners
368
- const delegateListeners: typeof addEventListenerList = [];
369
- const nonDelegateListeners: typeof addEventListenerList = [];
370
-
371
- addEventListenerList.forEach(meta => {
372
- 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 !== '') {
373
- delegateListeners.push(meta);
374
- } else {
375
- nonDelegateListeners.push(meta);
376
- }
377
- });
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
+ }
378
399
 
379
- const delegatesByTypeAndRoot = new Map<string, any[]>();
380
- delegateListeners.forEach(meta => {
381
- const r = meta.options.root || 'auto';
382
- const rootKey = `${meta.type}:${r}`;
383
- if (!delegatesByTypeAndRoot.has(rootKey)) {
384
- delegatesByTypeAndRoot.set(rootKey, []);
385
- }
386
- delegatesByTypeAndRoot.get(rootKey)!.push(meta);
387
- });
400
+ // Separate delegate and non-delegate listeners
401
+ const delegateListeners: typeof addEventListenerList = [];
402
+ const nonDelegateListeners: typeof addEventListenerList = [];
388
403
 
389
- delegatesByTypeAndRoot.forEach((metaList, typeRootKey) => {
390
- const [type, rStr] = typeRootKey.split(':');
391
- const r = rStr === 'auto' ? 'auto' : rStr;
392
- const opts = { capture: metaList[0].options.capture, once: metaList[0].options.once, passive: metaList[0].options.passive };
393
-
394
- const bindRoots: (HTMLElement | ShadowRoot)[] = [];
395
- if (r === 'auto') bindRoots.push(this.shadowRoot || (this as any));
396
- else if (r === 'light') bindRoots.push(this as any);
397
- else if (r === 'shadow' && this.shadowRoot) bindRoots.push(this.shadowRoot);
398
- else if (r === 'all') {
399
- bindRoots.push(this as any);
400
- if (this.shadowRoot) bindRoots.push(this.shadowRoot);
401
- }
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
+ });
402
411
 
403
- bindRoots.forEach(br => {
404
- const sortedMetaList = [...metaList].sort((a, b) => {
405
- const aStop = a.options.stopPropagation ? 1 : 0;
406
- const bStop = b.options.stopPropagation ? 1 : 0;
407
- return bStop - aStop;
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);
408
420
  });
409
-
410
- const unifiedHandler = async (event: Event) => {
411
- for (const meta of sortedMetaList) {
412
- const { selector, options } = meta;
413
- const matchedEl = (event.target as HTMLElement).closest(selector);
414
- if (matchedEl && (br as any).contains(matchedEl)) {
421
+
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
+ });
468
+ });
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) => {
415
513
  // Apply filter if specified
416
514
  if (options.filter) {
417
- const helper = SwcUtils.getHelperAndHostSet(currentWin, matchedEl);
418
- if (!options.filter(event, helper)) {
419
- 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
420
518
  }
421
519
  }
422
520
  if (options.stopPropagation) event.stopPropagation();
423
521
  if (options.stopImmediatePropagation) event.stopImmediatePropagation();
424
522
  if (options.preventDefault) event.preventDefault();
425
523
  const currentHostSet = SwcUtils.getHostSet(this as any);
426
- const args = { event, ...currentHostSet, $el: matchedEl, $root: br };
427
- await (this as any)[meta.propertyKey](event, currentHostSet, matchedEl, args);
428
- 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});
429
530
  }
430
- }
431
- };
432
- br.addEventListener(type, unifiedHandler, opts);
433
- (this as any)._boundListeners.push({ target: br, type, handler: unifiedHandler, options: opts });
434
- });
435
- });
436
-
437
- nonDelegateListeners.forEach(meta => {
438
- const { selector, type, options } = meta;
439
- const opts = { capture: options.capture, once: options.once, passive: options.passive };
440
- const bindTargets: EventTarget[] = [];
441
- const r = options.root || 'auto';
442
- const applyRootOption = (target: any) => {
443
- if (!target) return;
444
- if (r === 'auto') {
445
- bindTargets.push(target.shadowRoot || target);
446
- } else {
447
- if (r === 'light' || r === 'all') bindTargets.push(target);
448
- if ((r === 'shadow' || r === 'all') && target.shadowRoot) bindTargets.push(target.shadowRoot);
449
- }
450
- };
451
-
452
- if (selector === ':window') bindTargets.push(currentWin);
453
- else if (selector === ':document') bindTargets.push(currentWin.document);
454
- else if (selector === ':parentHost') applyRootOption(hostSet.$parentHost);
455
- else if (selector === ':appHost') applyRootOption(hostSet.$appHost);
456
- else if (selector === ':firstHost') applyRootOption(hostSet.$firstHost);
457
- else if (selector === ':lastHost') applyRootOption(hostSet.$lastHost);
458
- else if (selector === ':firstAppHost') applyRootOption(hostSet.$firstAppHost);
459
- else if (selector === ':lastAppHost') applyRootOption(hostSet.$lastAppHost);
460
- else if (selector === ':hosts') hostSet.$hosts.forEach(applyRootOption);
461
- else if (selector === ':appHosts') hostSet.$appHosts.forEach(applyRootOption);
462
- else if (selector === ':host' || !selector) applyRootOption(this);
463
- else {
464
- const searchRoots: (HTMLElement | ShadowRoot)[] = [];
465
- if (r === 'auto') searchRoots.push(this.shadowRoot || (this as any));
466
- else if (r === 'light') searchRoots.push(this as any);
467
- else if (r === 'shadow' && this.shadowRoot) searchRoots.push(this.shadowRoot);
468
- else if (r === 'all') {
469
- searchRoots.push(this as any);
470
- if (this.shadowRoot) searchRoots.push(this.shadowRoot);
471
- }
472
-
473
- searchRoots.forEach(sr => {
474
- sr.querySelectorAll(selector).forEach(el => bindTargets.push(el));
531
+ });
475
532
  });
476
- }
477
533
 
478
- bindTargets.forEach(t => {
479
- const handler = async (event: Event) => {
480
- // Apply filter if specified
481
- if (options.filter) {
482
- const helper = SwcUtils.getHelperAndHostSet(currentWin, t as HTMLElement);
483
- if (!options.filter(event, {currentThis: this,helper})) {
484
- return; // Skip if filter returns false
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
+ }
485
552
  }
486
553
  }
487
- if (options.stopPropagation) event.stopPropagation();
488
- if (options.stopImmediatePropagation) event.stopImmediatePropagation();
489
- if (options.preventDefault) event.preventDefault();
490
- const currentHostSet = SwcUtils.getHostSet(this as any);
491
- const args = { event, ...currentHostSet, $el: t, $root: t };
492
- await (this as any)[meta.propertyKey](event, currentHostSet, args);
493
- };
494
- t.addEventListener(type, handler, opts);
495
- if (options.removeOnDisconnected === true || t === currentWin || t === currentWin.document) {
496
- (this as any)._boundListeners.push({ target: t, type, handler, options: opts });
497
554
  }
498
- });
499
- });
555
+ } finally {
556
+ if (appHost && typeof (appHost as any)._connectedDone === 'function') {
557
+ await (appHost as any)._connectedDone(this);
558
+ }
559
+ }
560
+ };
500
561
 
501
- if (originalConnected) originalConnected.apply(this);
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);
570
+ }
502
571
 
503
- const aMethods = findAllLifecycleMetadata(this, ON_AFTER_CONNECTED_METADATA_KEY);
504
- if (aMethods) {
505
- for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
506
- }
507
- (this as any)._executeSwcScript('swc-on-connected', hostSet);
508
- (this as any)._executeSwcScript('swc-on-after-connected', hostSet);
509
- (this as any).__swc_connected = true;
510
-
511
- // Register to appHost LAST when all lifecycle completed
512
- // console.log('!!!!!!!!!!!!!!', this, appHost)
513
- const appHostss = SwcUtils.findAllParentAppHostsDirect(this)
514
- // const nAppHostSet = SwcUtils.getHostSet(this as any);
515
- if (appHost && typeof (appHost as any)._connected === 'function') {
516
- (appHost as any)._connected(this);
517
- } else if (appHost && typeof (appHost as any)) {
518
- (appHost as any)._connected_safari ??= [];
519
- (appHost as any)._connected_safari.push(this);
520
- }
521
- };
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
+ }
522
577
 
523
- const originalDisconnected = proto.disconnectedCallback;
524
- proto.disconnectedCallback = function () {
525
- const hostSet = SwcUtils.getHostSet(this as any);
526
- (this as any)._executeSwcScript('swc-on-before-disconnected', hostSet);
527
- const bMethods = findAllLifecycleMetadata(this, ON_BEFORE_DISCONNECTED_METADATA_KEY);
528
- if (bMethods) {
529
- for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
530
- }
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
+ }
531
582
 
532
- if ((this as any)._boundListeners) {
533
- (this as any)._boundListeners.forEach((l: any) => l.target.removeEventListener(l.type, l.handler, l.options));
534
- (this as any)._boundListeners = [];
535
- }
583
+ if (originalDisconnected) originalDisconnected.apply(this);
536
584
 
537
- if (originalDisconnected) originalDisconnected.apply(this);
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
+ };
538
593
 
539
- const aMethods = findAllLifecycleMetadata(this, ON_AFTER_DISCONNECTED_METADATA_KEY);
540
- if (aMethods) {
541
- for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
542
- }
543
- (this as any)._executeSwcScript('swc-on-disconnected', hostSet);
544
- (this as any)._executeSwcScript('swc-on-after-disconnected', hostSet);
545
- (this as any).__swc_connected = false;
546
-
547
- // Remove from appHost LAST when disconnected
548
- const appHost = hostSet.$appHost;
549
- if (appHost && typeof (appHost as any)._disconnected === 'function') {
550
- (appHost as any)._disconnected(this);
551
- }
552
- };
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
+ }
553
602
 
554
- const originalAdopted = proto.adoptedCallback;
555
- proto.adoptedCallback = function () {
556
- const hostSet = SwcUtils.getHostSet(this as any);
557
- (this as any)._executeSwcScript('swc-on-before-adopted', hostSet);
558
- const bMethods = findAllLifecycleMetadata(this, ON_BEFORE_ADOPTED_METADATA_KEY);
559
- if (bMethods) {
560
- for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
561
- }
603
+ if (originalAdopted) originalAdopted.apply(this);
562
604
 
563
- if (originalAdopted) originalAdopted.apply(this);
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
+ };
564
612
 
565
- const aMethods = findAllLifecycleMetadata(this, ON_AFTER_ADOPTED_METADATA_KEY);
566
- if (aMethods) {
567
- for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
568
- }
569
- (this as any)._executeSwcScript('swc-on-adopted', hostSet);
570
- (this as any)._executeSwcScript('swc-on-after-adopted', hostSet);
571
- };
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]);
616
+
617
+ const hSet = SwcUtils.getHostSet(this as any);
572
618
 
573
- const originalAttributeChanged = proto.attributeChangedCallback;
574
- proto.attributeChangedCallback = function (name: string, old: string | null, newVal: string | null) {
575
- if (originalAttributeChanged) originalAttributeChanged.apply(this, [name, old, newVal]);
576
-
577
- const hSet = SwcUtils.getHostSet(this as any);
578
-
579
- // Process expression directive before passing to handlers
580
- let processedVal: any = newVal;
581
- if (newVal !== null) {
582
- const ae = new ActionExpression(newVal);
583
- const expr = ae.getFirstExpression('call-return');
584
- if (expr) {
585
- const win = (this as any)._resolveWindow?.() || ((typeof window !== 'undefined' ? window : undefined) as any);
586
- const helperAndHostSet = SwcUtils.getHelperAndHostSet(win,this as any);
587
- try {
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);
588
627
  const script = ConvertUtils.decodeHtmlEntity(expr.script, win.document);
589
- const result = FunctionUtils.executeReturn({
590
- script: script,
591
- context: this,
592
- args: helperAndHostSet
593
- });
594
- // Pass the result object directly without serialization
595
- processedVal = result;
596
- } catch (e) {
597
- console.error(`[SWC] Failed to execute directive {{= ${expr.script} }} on attribute ${name}: ${helperAndHostSet}`, e);
598
- processedVal = newVal;
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
+ }
599
640
  }
600
641
  }
601
- }
602
642
 
603
- if (name.startsWith('swc-on-') && !swcLifecycleAttributes.includes(name)) {
604
- if (newVal !== null) {
605
- const eventName = name.substring(7);
606
- (this as any)._bindAttributeEvent(this as any, name, newVal, eventName);
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);
647
+ }
607
648
  }
608
- }
609
649
 
610
- const hostCustomEventMeta = emitHostCustomEventList.find(it => (it.options as any).attributeName === name);
611
- if (hostCustomEventMeta && newVal !== null) {
612
- (this as any)._bindAttributeEvent(this as any, name, newVal, hostCustomEventMeta.type);
613
- }
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);
653
+ }
614
654
 
615
- const metaList = attrChangeMap.get(name);
616
- if (metaList && Array.isArray(metaList)) {
617
- for (const meta of metaList) {
618
- const convertedVal = convertAttributeValue(processedVal, meta.options.type);
619
- (this as any)[meta.propertyKey](convertedVal, old, name, hSet);
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
+ }
620
664
  }
621
- }
622
- };
665
+ };
623
666
 
624
- Object.defineProperty(constructor, 'observedAttributes', {
625
- get: () => mergedObservedAttributes,
626
- configurable: true
627
- });
667
+ Object.defineProperty(constructor, 'observedAttributes', {
668
+ get: () => mergedObservedAttributes,
669
+ configurable: true
670
+ });
628
671
 
629
- ReflectUtils.defineMetadata(ELEMENT_CONFIG_KEY, metadata, constructor);
630
- const registry = metadata.customElementRegistry || (win as any)?.customElements;
631
- if (registry && !registry.get(metadata.name)) {
632
- registry.define(metadata.name, constructor as any, metadata.extends ? { extends: metadata.extends } : undefined);
633
- }
634
- return constructor;
635
- };
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);
676
+ }
677
+ return constructor;
678
+ };