@dooboostore/simple-web-component 1.0.27 → 1.0.29

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 (56) hide show
  1. package/README.md +55 -1
  2. package/dist/cjs/decorators/addEventListener.js +4 -0
  3. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  4. package/dist/cjs/decorators/attribute.js +2 -1
  5. package/dist/cjs/decorators/attribute.js.map +2 -2
  6. package/dist/cjs/decorators/elementDefine.js +18 -2
  7. package/dist/cjs/decorators/elementDefine.js.map +2 -2
  8. package/dist/cjs/decorators/lifecycles.js +4 -0
  9. package/dist/cjs/decorators/lifecycles.js.map +2 -2
  10. package/dist/cjs/elements/SwcAppEngine.js +3 -3
  11. package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
  12. package/dist/cjs/elements/SwcAppMixin.js +43 -5
  13. package/dist/cjs/elements/SwcAppMixin.js.map +3 -3
  14. package/dist/cjs/types.js.map +1 -1
  15. package/dist/cjs/utils/Utils.js +27 -1
  16. package/dist/cjs/utils/Utils.js.map +2 -2
  17. package/dist/esm/decorators/addEventListener.js +4 -0
  18. package/dist/esm/decorators/addEventListener.js.map +2 -2
  19. package/dist/esm/decorators/attribute.js +2 -1
  20. package/dist/esm/decorators/attribute.js.map +2 -2
  21. package/dist/esm/decorators/elementDefine.js +18 -2
  22. package/dist/esm/decorators/elementDefine.js.map +2 -2
  23. package/dist/esm/decorators/lifecycles.js +4 -0
  24. package/dist/esm/decorators/lifecycles.js.map +2 -2
  25. package/dist/esm/elements/SwcAppEngine.js +3 -3
  26. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  27. package/dist/esm/elements/SwcAppMixin.js +43 -5
  28. package/dist/esm/elements/SwcAppMixin.js.map +3 -3
  29. package/dist/esm/types.js.map +1 -1
  30. package/dist/esm/utils/Utils.js +27 -1
  31. package/dist/esm/utils/Utils.js.map +2 -2
  32. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +55 -4
  33. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +2 -2
  34. package/dist/types/decorators/addEventListener.d.ts +8 -1
  35. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  36. package/dist/types/decorators/attribute.d.ts.map +1 -1
  37. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  38. package/dist/types/decorators/lifecycles.d.ts +2 -0
  39. package/dist/types/decorators/lifecycles.d.ts.map +1 -1
  40. package/dist/types/elements/SwcAppMixin.d.ts +7 -2
  41. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  42. package/dist/types/types.d.ts +3 -0
  43. package/dist/types/types.d.ts.map +1 -1
  44. package/dist/types/utils/Utils.d.ts +13 -0
  45. package/dist/types/utils/Utils.d.ts.map +1 -1
  46. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +55 -4
  47. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +2 -2
  48. package/package.json +3 -3
  49. package/src/decorators/addEventListener.ts +11 -1
  50. package/src/decorators/attribute.ts +6 -1
  51. package/src/decorators/elementDefine.ts +22 -4
  52. package/src/decorators/lifecycles.ts +3 -0
  53. package/src/elements/SwcAppEngine.ts +3 -3
  54. package/src/elements/SwcAppMixin.ts +76 -13
  55. package/src/types.ts +3 -0
  56. package/src/utils/Utils.ts +51 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dooboostore/simple-web-component",
3
- "version": "1.0.27",
3
+ "version": "1.0.29",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -93,9 +93,9 @@
93
93
  "webpack-cli": "^5.1.4",
94
94
  "webpack-dev-server": "^5.2.0",
95
95
  "@dooboostore/core": "1.0.30",
96
+ "@dooboostore/simple-boot": "1.0.54",
96
97
  "@dooboostore/core-web": "1.0.10",
97
- "@dooboostore/core-node": "1.0.12",
98
- "@dooboostore/simple-boot": "1.0.54"
98
+ "@dooboostore/core-node": "1.0.12"
99
99
  },
100
100
  "scripts": {
101
101
  "clean": "rm -rf dist",
@@ -1,5 +1,5 @@
1
1
  import { ReflectUtils } from '@dooboostore/core';
2
- import { SpecialSelector, SwcQueryOptions } from '../types';
2
+ import { SpecialSelector, SwcQueryOptions, HelperHostSet } from '../types';
3
3
 
4
4
  export interface AddEventListenerBaseOptions extends EventListenerOptions {
5
5
  capture?: boolean;
@@ -10,6 +10,7 @@ export interface AddEventListenerBaseOptions extends EventListenerOptions {
10
10
  preventDefault?: boolean;
11
11
  removeOnDisconnected?: boolean;
12
12
  delegate?: boolean;
13
+ filter?: (target: Event | CustomEvent, helper: HelperHostSet) => boolean;
13
14
  }
14
15
 
15
16
  export interface AddEventListenerMetadata {
@@ -53,3 +54,12 @@ export const getAddEventListenerMetadata = (target: any): AddEventListenerMetada
53
54
  export function addEventListenerHost(type: string, options?: AddEventListenerBaseOptions & SwcQueryOptions): MethodDecorator {
54
55
  return addEventListener(':host', type, options);
55
56
  }
57
+
58
+ /**
59
+ * @addEventListenerAppHost decorator - simplified version of @addEventListener for :appHost selector
60
+ * Usage: @addEventListenerAppHost('click')
61
+ * Usage: @addEventListenerAppHost('click', { stopPropagation: true })
62
+ */
63
+ export function addEventListenerAppHost(type: string, options?: AddEventListenerBaseOptions & SwcQueryOptions): MethodDecorator {
64
+ return addEventListener(':appHost', type, options);
65
+ }
@@ -92,6 +92,7 @@ export function attribute(selector: string, options: AttributeFieldOptions = {})
92
92
 
93
93
  const applySetAttribute = (inst: any, targets: HTMLElement[], attrName: string, nv: any) => {
94
94
  targets.forEach(it => {
95
+ // console.log('sssssssssssss', it, attrName, nv);
95
96
  if (it && typeof (it as any).setAttribute === 'function') {
96
97
  if (nv === null) {
97
98
  (it as any).removeAttribute(attrName);
@@ -112,6 +113,7 @@ export function attribute(selector: string, options: AttributeFieldOptions = {})
112
113
 
113
114
  Object.defineProperty(target, propertyKey, {
114
115
  get(this: any) {
116
+ // console.log('------>??gettttt', this, propertyKey);
115
117
  // try {
116
118
  const attrName = options.name || String(propertyKey);
117
119
  const conf = getElementConfig(this);
@@ -136,7 +138,9 @@ export function attribute(selector: string, options: AttributeFieldOptions = {})
136
138
  return null;
137
139
  }
138
140
 
139
- return convertValue(this[privateKey], targetType);
141
+ const data = convertValue(this[privateKey], targetType);
142
+ // console.log('get rrr', data);
143
+ return data;
140
144
  // } catch (err) {
141
145
  // console.error('Error in getter:', err);
142
146
  // throw err;
@@ -144,6 +148,7 @@ export function attribute(selector: string, options: AttributeFieldOptions = {})
144
148
  },
145
149
  set(this: any, nv: any) {
146
150
  // this[propertyKey] = nv;
151
+ // console.log('------>??settttt', this, nv, propertyKey);
147
152
  const attrName = options.name || String(propertyKey);
148
153
  const conf = getElementConfig(this);
149
154
  const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
@@ -172,14 +172,15 @@ const setupPrototype = (proto: any) => {
172
172
  return (typeof window !== 'undefined' ? window : undefined) as Window;
173
173
  };
174
174
 
175
- proto._invokeLifecycleMethod = function (methodName: string | symbol, hostSet: HostSet, extraArgs: any[] = []) {
175
+ proto._invokeLifecycleMethod = function (methodName: string | symbol, hostSet?: HostSet, extraArgs: any[] = []) {
176
176
  ensureInit(this);
177
177
  if (typeof (this as any)[methodName] !== 'function') return;
178
- const app = hostSet.$appHost?.simpleApplication;
179
-
178
+ const useHostSet = hostSet ?? SwcUtils.getHostSet(this);
179
+ const app = useHostSet?.$appHost.simpleApplication;
180
+ // console.log('---->hh',app, this, methodName);
180
181
  if (app) {
181
182
  const otherStorage = new Map<any, any>();
182
- const situations = new SituationTypeContainers([new SituationTypeContainer({ situationType: InjectSituationType.HOST_SET, data: hostSet }), new SituationTypeContainer({ situationType: InjectSituationType.APP_HOST, data: hostSet.$appHost }), new SituationTypeContainer({ situationType: InjectSituationType.APP_HOSTS, data: hostSet.$appHosts }), new SituationTypeContainer({ situationType: InjectSituationType.HOST, data: hostSet.$host }), new SituationTypeContainer({ situationType: InjectSituationType.HOSTS, data: hostSet.$hosts }), new SituationTypeContainer({ situationType: InjectSituationType.FIRST_HOST, data: hostSet.$firstHost }), new SituationTypeContainer({ situationType: InjectSituationType.LAST_HOST, data: hostSet.$lastHost }), new SituationTypeContainer({ situationType: InjectSituationType.FIRST_APP_HOST, data: hostSet.$firstAppHost }), new SituationTypeContainer({ situationType: InjectSituationType.LAST_APP_HOST, data: hostSet.$lastAppHost })]);
183
+ 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 })]);
183
184
  otherStorage.set(SituationTypeContainers, situations);
184
185
 
185
186
  return app.simstanceManager.executeBindParameterSimPromise(
@@ -396,6 +397,13 @@ export const elementDefine =
396
397
  const { selector, options } = meta;
397
398
  const matchedEl = (event.target as HTMLElement).closest(selector);
398
399
  if (matchedEl && (br as any).contains(matchedEl)) {
400
+ // Apply filter if specified
401
+ if (options.filter) {
402
+ const helper = SwcUtils.getHelperAndHostSet(currentWin, matchedEl);
403
+ if (!options.filter(event, helper)) {
404
+ continue; // Skip this listener if filter returns false
405
+ }
406
+ }
399
407
  if (options.stopPropagation) event.stopPropagation();
400
408
  if (options.stopImmediatePropagation) event.stopImmediatePropagation();
401
409
  if (options.preventDefault) event.preventDefault();
@@ -454,6 +462,13 @@ export const elementDefine =
454
462
 
455
463
  bindTargets.forEach(t => {
456
464
  const handler = async (event: Event) => {
465
+ // Apply filter if specified
466
+ if (options.filter) {
467
+ const helper = SwcUtils.getHelperAndHostSet(currentWin, t as HTMLElement);
468
+ if (!options.filter(event, helper)) {
469
+ return; // Skip if filter returns false
470
+ }
471
+ }
457
472
  if (options.stopPropagation) event.stopPropagation();
458
473
  if (options.stopImmediatePropagation) event.stopImmediatePropagation();
459
474
  if (options.preventDefault) event.preventDefault();
@@ -481,6 +496,9 @@ export const elementDefine =
481
496
  // Register to appHost LAST when all lifecycle completed
482
497
  if (appHost && typeof (appHost as any)._connected === 'function') {
483
498
  (appHost as any)._connected(this);
499
+ } else if (appHost && typeof (appHost as any)) {
500
+ (appHost as any)._connected_safari ??= [];
501
+ (appHost as any)._connected_safari.push(this);
484
502
  }
485
503
  };
486
504
 
@@ -8,6 +8,7 @@ export const ON_AFTER_DISCONNECTED_METADATA_KEY = Symbol.for('simple-web-compone
8
8
  export const ON_BEFORE_ADOPTED_METADATA_KEY = Symbol.for('simple-web-component:on-before-adopted');
9
9
  export const ON_AFTER_ADOPTED_METADATA_KEY = Symbol.for('simple-web-component:on-after-adopted');
10
10
  export const ON_ADD_EVENT_LISTENER_METADATA_KEY = Symbol.for('simple-web-component:on-add-event-listener');
11
+ export const ON_CONNECTED_SWC_APP_METADATA_KEY = Symbol.for('simple-web-component:on-connected-swc-app');
11
12
  export const INNER_HTML_METADATA_KEY = Symbol.for('simple-web-component:inner-html');
12
13
 
13
14
  export const ATTRIBUTE_CHANGED_WILDCARD = '*';
@@ -48,6 +49,8 @@ export const onAdopted = onAfterAdopted;
48
49
 
49
50
  export const onAddEventListener = createLifecycleDecorator(ON_ADD_EVENT_LISTENER_METADATA_KEY);
50
51
 
52
+ export const onConnectedSwcApp = createLifecycleDecorator(ON_CONNECTED_SWC_APP_METADATA_KEY);
53
+
51
54
  /**
52
55
  * @onConnectedInnerHtml decorator to define the initial HTML content when connected.
53
56
  */
@@ -42,11 +42,11 @@ export class SwcAppEngine {
42
42
 
43
43
  // Router Selection
44
44
  if (this._config.routeType === 'path') {
45
- this.router = new PathRouter({ window: this._config.window, firstUrl: this._config.path });
45
+ this.router = new PathRouter({ window: this._config.window });
46
46
  } else if (this._config.routeType === 'hash') {
47
- this.router = new HashRouter({ window: this._config.window, firstUrl: this._config.path });
47
+ this.router = new HashRouter({ window: this._config.window });
48
48
  } else if (this._config.routeType === 'element') {
49
- this.router = new ElementRouter({ window: this._config.window, firstUrl: this._config.path });
49
+ this.router = new ElementRouter({ window: this._config.window });
50
50
  }
51
51
 
52
52
  // console.log('vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv', this.router)
@@ -2,16 +2,25 @@ import { SwcAppEngine, SwcAttributeConfigType, SwcConfigType } from './SwcAppEng
2
2
  import { SwcAppInterface } from '../types';
3
3
  import { SwcUtils } from '../utils/Utils';
4
4
  import { FunctionUtils, Subscription } from '@dooboostore/core';
5
- import { RouterEventType } from '@dooboostore/core-web';
5
+ import { Router, RouterEventType } from '@dooboostore/core-web';
6
+ import { ON_CONNECTED_SWC_APP_METADATA_KEY, findAllLifecycleMetadata } from '../decorators/lifecycles';
6
7
  import { getSubscribeSwcAppRouteChangeMetadata } from '../decorators/subscribeSwcAppRouteChange';
7
8
 
8
9
  export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Base: T) {
10
+ //@ts-ignore
9
11
  return class extends Base implements SwcAppInterface {
10
12
  __swc_engine = new SwcAppEngine(this as any);
11
13
  _swc_connected_instance = new Set<any>();
12
14
  _routerSubscription?: Subscription;
13
15
  _lastRouterEvent?: RouterEventType;
14
16
 
17
+ /*
18
+ 사파리 is 일경우
19
+ <script src="https://unpkg.com/@ungap/custom-elements"></script>
20
+ 이걸사용하는데 is 대응하는거다 그런데 이때 처리되는 순서가 크롬이나 표준에서는 부모부터 만들어지고 자식들이 만들어지는데
21
+ 저 polyfill에서는 자식부터 만들어지고 부모가 만들어진다 is일때 아 .. 이문제때문에 자식이 _connected_safari 에 강제로 자기자식넣어준다
22
+ */
23
+ _connected_safari = [];
15
24
  get simpleApplication() {
16
25
  return this.__swc_engine.simpleApplication;
17
26
  }
@@ -19,6 +28,11 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
19
28
  return this.__swc_engine.router;
20
29
  }
21
30
 
31
+ // constructor() {
32
+ // super();
33
+ // console.log('cccccccccccccccccccccc');
34
+ // }
35
+
22
36
  _invokeRouteChangeSubscribers(instance: any, re: RouterEventType) {
23
37
  const routeChangeSubscribers = getSubscribeSwcAppRouteChangeMetadata(instance);
24
38
  if (routeChangeSubscribers && Array.isArray(routeChangeSubscribers)) {
@@ -63,13 +77,15 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
63
77
  }
64
78
 
65
79
  _connected(instance: any) {
66
- // console.log('------------------>', instance);
80
+ // console.log('appmixin--> connected', instance);
67
81
  if (instance) {
68
82
  this._swc_connected_instance.add(instance);
69
-
70
- // Notify current route subscribers immediately after connection
71
- if (this.router && this._lastRouterEvent) {
72
- this._invokeRouteChangeSubscribers(instance, this._lastRouterEvent);
83
+ if (this.simpleApplication) {
84
+ this._invokeOnConnectedSwcAppStarted(instance);
85
+ // Notify current route subscribers immediately after connection
86
+ if (this.router && this._lastRouterEvent) {
87
+ this._invokeRouteChangeSubscribers(instance, this._lastRouterEvent);
88
+ }
73
89
  }
74
90
  }
75
91
  }
@@ -127,19 +143,54 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
127
143
  }
128
144
  }
129
145
 
130
- // console.log('vvvvvvv222222', this.router);
146
+ // 사파리일떄 예외이다 is 일때 polyfill되는데 이떄 부모부터 만들어지는게 아니라 자식부터 만들어진다 그래서 부모가 만들어질때 자식들이 이미 만들어져있어서 부모가 자식들을 등록해주는 형태로 강제로 등록해준다
147
+ this._connected_safari.forEach((instance: any) => {
148
+ this._swc_connected_instance.add(instance);
149
+ });
150
+ // Invoke @onConnectedSwcApp lifecycle methods on all connected component instances
151
+ // const hostSet = SwcUtils.getHostSet(this as any);
152
+ this._swc_connected_instance.forEach((instance: any) => {
153
+ this._invokeOnConnectedSwcAppStarted(instance);
154
+ });
155
+
156
+ // Safari fix: Manually scan DOM tree and register any SWC components that couldn't find parent
157
+ // This handles the case where is="" elements get upgraded in child-first order
158
+ // const allElements = (this as any).querySelectorAll('*');
159
+ // for (const el of allElements) {
160
+ // const isConnected = (el as any).__swc_connected;
161
+ // if (!isConnected && typeof (el as any)._resolveWindow === 'function') {
162
+ // // Element is an SWC component but hasn't registered with app yet
163
+ // try {
164
+ // this._connected(el);
165
+ // if ((el as any)._invokeOnConnectedSwcAppStarted) {
166
+ // this._invokeOnConnectedSwcAppStarted(el);
167
+ // }
168
+ // } catch (e) {
169
+ // console.warn('[SWC] Error registering discovered element:', el.tagName, e);
170
+ // }
171
+ // }
172
+ // }
173
+
131
174
  // Subscribe to router changes after connect
132
175
  if (!this._routerSubscription && this.router) {
133
176
  this._routerSubscription = this.router.observable.subscribe((route: RouterEventType) => {
134
177
  // console.log('Route changed:', route);
135
178
  this._handleRouteChange(route);
136
179
  });
137
-
138
180
  // Navigate to initial path if specified
139
- // const config = this.__swc_engine.config;
140
- // if (config?.path) {
141
- // this.router.go(config.path);
142
- // }
181
+ const config = this.__swc_engine.config;
182
+ if (config?.path) {
183
+ this.router.go(config.path);
184
+ }
185
+ }
186
+ }
187
+
188
+ _invokeOnConnectedSwcAppStarted(instance: any) {
189
+ const startedMethods = findAllLifecycleMetadata(instance, ON_CONNECTED_SWC_APP_METADATA_KEY);
190
+ if (startedMethods) {
191
+ for (const m of startedMethods) {
192
+ instance._invokeLifecycleMethod(m);
193
+ }
143
194
  }
144
195
  }
145
196
 
@@ -177,7 +228,19 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
177
228
  }
178
229
 
179
230
  async routing(path: string) {
180
- await this.__swc_engine.router?.go(path);
231
+ await this.router?.go(path);
232
+ }
233
+
234
+ back(): void {
235
+ this.router?.back();
236
+ }
237
+
238
+ forward(): void {
239
+ this.router?.forward();
240
+ }
241
+
242
+ reload(): void {
243
+ this.router?.reload();
181
244
  }
182
245
  };
183
246
  }
package/src/types.ts CHANGED
@@ -48,4 +48,7 @@ export interface SwcAppInterface extends HTMLElement {
48
48
  router?: Router;
49
49
  connect(config?: SwcAttributeConfigType): Promise<void>;
50
50
  routing(path: string): Promise<void>;
51
+ reload(): void;
52
+ back(): void;
53
+ forward(): void;
51
54
  }
@@ -236,6 +236,56 @@ export namespace SwcUtils {
236
236
  return appHostsWithoutSelf.length > 0 ? appHostsWithoutSelf[appHostsWithoutSelf.length - 1] : undefined;
237
237
  };
238
238
 
239
+ /**
240
+ * Find parent app host by traversing DOM tree directly.
241
+ * Only checks tagName and is attribute - no SWC host discovery.
242
+ * Useful for Safari polyfill compatibility where is="" elements upgrade in child-first order.
243
+ */
244
+ export const findParentAppHostDirect = (el: HTMLElement): SwcAppInterface | null => {
245
+ const appHosts = findAllParentAppHostsDirect(el);
246
+ return appHosts.length > 0 ? appHosts[appHosts.length - 1] : null;
247
+ };
248
+
249
+ /**
250
+ * Find all parent app hosts by traversing DOM tree directly.
251
+ * Returns array of all parent app hosts in [closest-parent, ..., root] order.
252
+ * Only checks tagName and is attribute - no SWC host discovery.
253
+ * Useful for Safari polyfill compatibility where is="" elements upgrade in child-first order.
254
+ */
255
+ export const findAllParentAppHostsDirect = (el: HTMLElement): SwcAppInterface[] => {
256
+ const appHosts: SwcAppInterface[] = [];
257
+
258
+ // Start from shadow root's host if el is inside shadow DOM, otherwise from parentElement
259
+ let current: HTMLElement | null = null;
260
+ const rootNode = el.getRootNode();
261
+ if (rootNode instanceof ShadowRoot) {
262
+ // Element is inside shadow DOM, start from shadow root's host
263
+ current = (rootNode as any).host as HTMLElement;
264
+ } else {
265
+ // Element is in light DOM, start from parent
266
+ current = el.parentElement;
267
+ }
268
+
269
+ while (current) {
270
+ // console.log('vvvvvvv');
271
+ // alert(1)
272
+ // debugger;
273
+ const isAppHost =
274
+ current.tagName.toLowerCase() === 'swc-app' ||
275
+ current.getAttribute('is')?.startsWith('swc-app-');
276
+ if (isAppHost) {
277
+ appHosts.push(current as SwcAppInterface);
278
+ }
279
+ // Handle shadow DOM
280
+ if (current.shadowRoot) {
281
+ current = ((current.shadowRoot as any).host as HTMLElement).parentElement;
282
+ } else {
283
+ current = current.parentElement;
284
+ }
285
+ }
286
+ return appHosts.reverse(); // [root, ..., closest-parent]
287
+ };
288
+
239
289
  export const getHostSet = (el: HTMLElement): HostSet => {
240
290
  const isSwc = !!getElementConfig(el);
241
291
  const ancestors = findAllSwcHosts(el); // [root, ..., parent]
@@ -265,7 +315,7 @@ export namespace SwcUtils {
265
315
  curr = curr.parentElement || (curr.getRootNode() as any).host;
266
316
  }
267
317
 
268
- const $appHosts = $hosts.filter(h => h.tagName.toLowerCase() === 'swc-app' || h.getAttribute('is')?.startsWith('swc-app-')) as SwcAppInterface[];
318
+ const $appHosts = SwcUtils.findAllParentAppHostsDirect(el); //$hosts.filter(h => h.tagName.toLowerCase() === 'swc-app' || h.getAttribute('is')?.startsWith('swc-app-')) as SwcAppInterface[];
269
319
  const $appHost = $appHosts.length > 0 ? ($appHosts[$appHosts.length - 1] === el ? ($appHosts.length > 1 ? $appHosts[$appHosts.length - 2] : null) : $appHosts[$appHosts.length - 1]) : null;
270
320
  const $firstAppHost = $appHosts.length > 0 ? $appHosts[0] : null;
271
321