@dooboostore/simple-web-component 1.0.43 → 1.0.45

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 (146) hide show
  1. package/README.md +312 -63
  2. package/dist/cjs/SwcAppEngine.js +3 -1
  3. package/dist/cjs/SwcAppEngine.js.map +2 -2
  4. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  5. package/dist/cjs/decorators/applyAttribute.js +66 -43
  6. package/dist/cjs/decorators/applyAttribute.js.map +2 -2
  7. package/dist/cjs/decorators/applyClass.js +110 -43
  8. package/dist/cjs/decorators/applyClass.js.map +3 -3
  9. package/dist/cjs/decorators/applyNode.js +200 -112
  10. package/dist/cjs/decorators/applyNode.js.map +2 -2
  11. package/dist/cjs/decorators/applyProperty.js +49 -45
  12. package/dist/cjs/decorators/applyProperty.js.map +2 -2
  13. package/dist/cjs/decorators/applyStyle.js +92 -37
  14. package/dist/cjs/decorators/applyStyle.js.map +3 -3
  15. package/dist/cjs/decorators/{changedAttributeThis.js → changedAttribute.js} +6 -6
  16. package/dist/cjs/decorators/changedAttribute.js.map +7 -0
  17. package/dist/cjs/decorators/elementDefine.js +81 -31
  18. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  19. package/dist/cjs/decorators/emitCustomEvent.js +80 -52
  20. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  21. package/dist/cjs/decorators/index.js +1 -1
  22. package/dist/cjs/decorators/index.js.map +2 -2
  23. package/dist/cjs/decorators/publishSwcAppMessage.js +5 -5
  24. package/dist/cjs/decorators/publishSwcAppMessage.js.map +3 -3
  25. package/dist/cjs/decorators/query.js +133 -147
  26. package/dist/cjs/decorators/query.js.map +3 -3
  27. package/dist/cjs/decorators/queryAll.js +143 -132
  28. package/dist/cjs/decorators/queryAll.js.map +3 -3
  29. package/dist/cjs/decorators/subscribeSwcAppMessageWhileConnected.js +2 -0
  30. package/dist/cjs/decorators/subscribeSwcAppMessageWhileConnected.js.map +2 -2
  31. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -0
  32. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
  33. package/dist/cjs/elements/SwcAppMixin.js +17 -2
  34. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  35. package/dist/cjs/examples/RxJSOperatorsExample.js +285 -0
  36. package/dist/cjs/examples/RxJSOperatorsExample.js.map +7 -0
  37. package/dist/cjs/index.js +1 -0
  38. package/dist/cjs/index.js.map +2 -2
  39. package/dist/cjs/router/ElementRouter.js +4 -0
  40. package/dist/cjs/router/ElementRouter.js.map +2 -2
  41. package/dist/cjs/types/window.d.js.map +1 -1
  42. package/dist/esm/SwcAppEngine.js +3 -1
  43. package/dist/esm/SwcAppEngine.js.map +2 -2
  44. package/dist/esm/decorators/addEventListener.js.map +2 -2
  45. package/dist/esm/decorators/applyAttribute.js +66 -43
  46. package/dist/esm/decorators/applyAttribute.js.map +2 -2
  47. package/dist/esm/decorators/applyClass.js +110 -43
  48. package/dist/esm/decorators/applyClass.js.map +3 -3
  49. package/dist/esm/decorators/applyNode.js +200 -112
  50. package/dist/esm/decorators/applyNode.js.map +2 -2
  51. package/dist/esm/decorators/applyProperty.js +49 -45
  52. package/dist/esm/decorators/applyProperty.js.map +2 -2
  53. package/dist/esm/decorators/applyStyle.js +92 -37
  54. package/dist/esm/decorators/applyStyle.js.map +3 -3
  55. package/dist/esm/decorators/{changedAttributeThis.js → changedAttribute.js} +3 -3
  56. package/dist/esm/decorators/changedAttribute.js.map +7 -0
  57. package/dist/esm/decorators/elementDefine.js +79 -29
  58. package/dist/esm/decorators/elementDefine.js.map +2 -2
  59. package/dist/esm/decorators/emitCustomEvent.js +80 -52
  60. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  61. package/dist/esm/decorators/index.js +1 -1
  62. package/dist/esm/decorators/index.js.map +1 -1
  63. package/dist/esm/decorators/publishSwcAppMessage.js +5 -5
  64. package/dist/esm/decorators/publishSwcAppMessage.js.map +3 -3
  65. package/dist/esm/decorators/query.js +133 -147
  66. package/dist/esm/decorators/query.js.map +3 -3
  67. package/dist/esm/decorators/queryAll.js +143 -132
  68. package/dist/esm/decorators/queryAll.js.map +3 -3
  69. package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js +2 -0
  70. package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js.map +2 -2
  71. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -0
  72. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
  73. package/dist/esm/elements/SwcAppMixin.js +18 -3
  74. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  75. package/dist/esm/examples/RxJSOperatorsExample.js +266 -0
  76. package/dist/esm/examples/RxJSOperatorsExample.js.map +7 -0
  77. package/dist/esm/index.js +1 -0
  78. package/dist/esm/index.js.map +2 -2
  79. package/dist/esm/router/ElementRouter.js +4 -0
  80. package/dist/esm/router/ElementRouter.js.map +2 -2
  81. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +1118 -633
  82. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  83. package/dist/types/SwcAppEngine.d.ts.map +1 -1
  84. package/dist/types/decorators/addEventListener.d.ts +19 -15
  85. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  86. package/dist/types/decorators/applyAttribute.d.ts +45 -26
  87. package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
  88. package/dist/types/decorators/applyClass.d.ts +19 -38
  89. package/dist/types/decorators/applyClass.d.ts.map +1 -1
  90. package/dist/types/decorators/applyNode.d.ts +175 -32
  91. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  92. package/dist/types/decorators/applyProperty.d.ts +38 -25
  93. package/dist/types/decorators/applyProperty.d.ts.map +1 -1
  94. package/dist/types/decorators/applyStyle.d.ts +10 -9
  95. package/dist/types/decorators/applyStyle.d.ts.map +1 -1
  96. package/dist/types/decorators/{changedAttributeThis.d.ts → changedAttribute.d.ts} +2 -2
  97. package/dist/types/decorators/changedAttribute.d.ts.map +1 -0
  98. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  99. package/dist/types/decorators/emitCustomEvent.d.ts +6 -12
  100. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  101. package/dist/types/decorators/index.d.ts +1 -1
  102. package/dist/types/decorators/index.d.ts.map +1 -1
  103. package/dist/types/decorators/publishSwcAppMessage.d.ts +1 -1
  104. package/dist/types/decorators/publishSwcAppMessage.d.ts.map +1 -1
  105. package/dist/types/decorators/query.d.ts +16 -29
  106. package/dist/types/decorators/query.d.ts.map +1 -1
  107. package/dist/types/decorators/queryAll.d.ts +16 -23
  108. package/dist/types/decorators/queryAll.d.ts.map +1 -1
  109. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts +1 -0
  110. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts.map +1 -1
  111. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts +2 -0
  112. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts.map +1 -1
  113. package/dist/types/elements/SwcAppMixin.d.ts +4 -4
  114. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  115. package/dist/types/examples/RxJSOperatorsExample.d.ts +94 -0
  116. package/dist/types/examples/RxJSOperatorsExample.d.ts.map +1 -0
  117. package/dist/types/index.d.ts +1 -0
  118. package/dist/types/index.d.ts.map +1 -1
  119. package/dist/types/router/ElementRouter.d.ts.map +1 -1
  120. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +1118 -633
  121. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  122. package/package.json +1 -1
  123. package/src/SwcAppEngine.ts +3 -1
  124. package/src/decorators/addEventListener.ts +31 -25
  125. package/src/decorators/applyAttribute.ts +164 -86
  126. package/src/decorators/applyClass.ts +161 -41
  127. package/src/decorators/applyNode.ts +408 -108
  128. package/src/decorators/applyProperty.ts +100 -89
  129. package/src/decorators/applyStyle.ts +131 -37
  130. package/src/decorators/{changedAttributeThis.ts → changedAttribute.ts} +1 -1
  131. package/src/decorators/elementDefine.ts +96 -30
  132. package/src/decorators/emitCustomEvent.ts +92 -60
  133. package/src/decorators/index.ts +1 -1
  134. package/src/decorators/publishSwcAppMessage.ts +1 -1
  135. package/src/decorators/query.ts +155 -162
  136. package/src/decorators/queryAll.ts +157 -139
  137. package/src/decorators/subscribeSwcAppMessageWhileConnected.ts +1 -0
  138. package/src/decorators/subscribeSwcAppRouteChangeWhileConnected.ts +3 -1
  139. package/src/elements/SwcAppMixin.ts +43 -24
  140. package/src/examples/RxJSOperatorsExample.ts +279 -0
  141. package/src/index.ts +2 -0
  142. package/src/router/ElementRouter.ts +4 -0
  143. package/src/types/window.d.ts +3 -0
  144. package/dist/cjs/decorators/changedAttributeThis.js.map +0 -7
  145. package/dist/esm/decorators/changedAttributeThis.js.map +0 -7
  146. package/dist/types/decorators/changedAttributeThis.d.ts.map +0 -1
@@ -1,8 +1,10 @@
1
1
  import {ActionExpression, FunctionUtils, ReflectUtils} from '@dooboostore/core';
2
+ import {Observable, Subject} from '@dooboostore/core';
3
+ import {debounceTime, throttleTime, distinctUntilChanged} from '@dooboostore/core/message/operators';
2
4
  import {getAddEventListenerMetadata} from './addEventListener';
3
5
  import {findAllLifecycleMetadata, findAllOnConnectedAfterMetadata, findAllOnConnectedBeforeMetadata, findAllOnConnectedMetadata, ON_AFTER_ADOPTED_METADATA_KEY, ON_AFTER_DISCONNECTED_METADATA_KEY, ON_BEFORE_ADOPTED_METADATA_KEY, ON_BEFORE_DISCONNECTED_METADATA_KEY, ON_CONNECTED_COMPLETED_METADATA_KEY, ON_INITIALIZE_METADATA_KEY} from './lifecycles';
4
6
  import {getEmitCustomEventMetadataList} from './emitCustomEvent';
5
- import {convertAttributeValue, findAllAttributeChangedMetadata} from './changedAttributeThis';
7
+ import {convertAttributeValue, findAllAttributeChangedMetadata} from './changedAttribute';
6
8
  import {findAllAttributeApplyMetadata, findAllAttributeMetadata, getAttributeValue} from './applyAttribute';
7
9
  import {getQueryMetadata} from './query';
8
10
  import {getQueryAllMetadata} from './queryAll';
@@ -465,7 +467,9 @@ export const elementDefine =
465
467
  const nonDelegateListeners: typeof addEventListenerList = [];
466
468
 
467
469
  addEventListenerList.forEach(meta => {
468
- if (meta.options.delegate && meta.selector !== '$window' && meta.selector !== '$document' && meta.selector !== '$host' && meta.selector !== '$appHost' && meta.selector !== '$firstHost' && meta.selector !== '$lastHost' && meta.selector !== '$firstAppHost' && meta.selector !== '$lastAppHost' && meta.selector !== '$hosts' && meta.selector !== '$appHosts' && meta.selector !== '$this' && meta.selector !== '') {
470
+ // Function-based selectors cannot be used with delegate listeners
471
+ const isStringSelector = typeof meta.selector === 'string';
472
+ if (meta.options.delegate && isStringSelector && meta.selector !== '$window' && meta.selector !== '$document' && meta.selector !== '$host' && meta.selector !== '$appHost' && meta.selector !== '$firstHost' && meta.selector !== '$lastHost' && meta.selector !== '$firstAppHost' && meta.selector !== '$lastAppHost' && meta.selector !== '$hosts' && meta.selector !== '$appHosts' && meta.selector !== '$this' && meta.selector !== '') {
469
473
  delegateListeners.push(meta);
470
474
  } else {
471
475
  nonDelegateListeners.push(meta);
@@ -535,6 +539,25 @@ export const elementDefine =
535
539
  const opts = {capture: options.capture, once: options.once, passive: options.passive};
536
540
  const bindTargets: EventTarget[] = [];
537
541
  const r = options.root || 'auto';
542
+
543
+ // Resolve selector if it's a function
544
+ let resolvedSelector: string | null = null;
545
+ if (typeof selector === 'function') {
546
+ const hostSet = SwcUtils.getHelperAndHostSet(currentWin, this);
547
+ const result = selector(this, hostSet);
548
+ if (typeof result === 'string') {
549
+ resolvedSelector = result;
550
+ } else if (result instanceof currentWin.Element) {
551
+ bindTargets.push(result as EventTarget);
552
+ } else if (result instanceof currentWin.NodeList) {
553
+ bindTargets.push(...Array.from(result as EventTarget[]));
554
+ } else if (Array.isArray(result)) {
555
+ bindTargets.push(...(result as EventTarget[]));
556
+ }
557
+ } else {
558
+ resolvedSelector = selector;
559
+ }
560
+
538
561
  const applyRootOption = (target: any) => {
539
562
  if (!target) return;
540
563
  if (r === 'auto') {
@@ -545,31 +568,33 @@ export const elementDefine =
545
568
  }
546
569
  };
547
570
 
548
- if (selector === '$window') bindTargets.push(currentWin);
549
- else if (selector === '$document') bindTargets.push(currentWin.document);
550
- else if (selector === '$host') applyRootOption(helperHostSet.$host);
551
- else if (selector === '$parentHost') applyRootOption(helperHostSet.$parentHost);
552
- else if (selector === '$appHost') applyRootOption(helperHostSet.$appHost);
553
- else if (selector === '$firstHost') applyRootOption(helperHostSet.$firstHost);
554
- else if (selector === '$lastHost') applyRootOption(helperHostSet.$lastHost);
555
- else if (selector === '$firstAppHost') applyRootOption(helperHostSet.$firstAppHost);
556
- else if (selector === '$lastAppHost') applyRootOption(helperHostSet.$lastAppHost);
557
- else if (selector === '$hosts') helperHostSet.$hosts.forEach(applyRootOption);
558
- else if (selector === '$appHosts') helperHostSet.$appHosts.forEach(applyRootOption);
559
- else if (selector === '$this' || !selector) applyRootOption(this);
560
- else {
561
- const searchRoots: (HTMLElement | ShadowRoot)[] = [];
562
- if (r === 'auto') searchRoots.push(this.shadowRoot || (this as any));
563
- else if (r === 'light') searchRoots.push(this as any);
564
- else if (r === 'shadow' && this.shadowRoot) searchRoots.push(this.shadowRoot);
565
- else if (r === 'all') {
566
- searchRoots.push(this as any);
567
- if (this.shadowRoot) searchRoots.push(this.shadowRoot);
568
- }
571
+ if (resolvedSelector) {
572
+ if (resolvedSelector === '$window') bindTargets.push(currentWin);
573
+ else if (resolvedSelector === '$document') bindTargets.push(currentWin.document);
574
+ else if (resolvedSelector === '$host') applyRootOption(helperHostSet.$host);
575
+ else if (resolvedSelector === '$parentHost') applyRootOption(helperHostSet.$parentHost);
576
+ else if (resolvedSelector === '$appHost') applyRootOption(helperHostSet.$appHost);
577
+ else if (resolvedSelector === '$firstHost') applyRootOption(helperHostSet.$firstHost);
578
+ else if (resolvedSelector === '$lastHost') applyRootOption(helperHostSet.$lastHost);
579
+ else if (resolvedSelector === '$firstAppHost') applyRootOption(helperHostSet.$firstAppHost);
580
+ else if (resolvedSelector === '$lastAppHost') applyRootOption(helperHostSet.$lastAppHost);
581
+ else if (resolvedSelector === '$hosts') helperHostSet.$hosts.forEach(applyRootOption);
582
+ else if (resolvedSelector === '$appHosts') helperHostSet.$appHosts.forEach(applyRootOption);
583
+ else if (resolvedSelector === '$this' || !resolvedSelector) applyRootOption(this);
584
+ else {
585
+ const searchRoots: (HTMLElement | ShadowRoot)[] = [];
586
+ if (r === 'auto') searchRoots.push(this.shadowRoot || (this as any));
587
+ else if (r === 'light') searchRoots.push(this as any);
588
+ else if (r === 'shadow' && this.shadowRoot) searchRoots.push(this.shadowRoot);
589
+ else if (r === 'all') {
590
+ searchRoots.push(this as any);
591
+ if (this.shadowRoot) searchRoots.push(this.shadowRoot);
592
+ }
569
593
 
570
- searchRoots.forEach(sr => {
571
- sr.querySelectorAll(selector).forEach(el => bindTargets.push(el));
572
- });
594
+ searchRoots.forEach(sr => {
595
+ sr.querySelectorAll(resolvedSelector).forEach(el => bindTargets.push(el));
596
+ });
597
+ }
573
598
  }
574
599
 
575
600
  bindTargets.forEach(t => {
@@ -586,10 +611,45 @@ export const elementDefine =
586
611
  if (options.preventDefault) event.preventDefault();
587
612
  const currentHostSet = SwcUtils.getHostSet(this as any);
588
613
  const args = {event, ...currentHostSet, $el: t, $root: t};
589
- await (this as any)[meta.propertyKey](event, {currentHostSet, $$matchedElement: event.currentTarget}, args);
614
+ await (this as any)[meta.propertyKey](event, {currentHostSet, $matchedElement: event.currentTarget}, args);
590
615
  };
591
- t.addEventListener(type, handler, opts);
592
- (this as any)._boundListeners.push({target: t, type, handler, options: opts});
616
+
617
+ // Create event stream with Observable-based operators
618
+ const eventSubject = new Subject<Event>();
619
+ let eventStream = eventSubject as any;
620
+
621
+ // Apply operators from @dooboostore/core/operators
622
+ if (options.debounceTime !== undefined && options.debounceTime > 0) {
623
+ eventStream = eventStream.pipe(debounceTime(options.debounceTime));
624
+ }
625
+
626
+ if (options.throttleTime !== undefined && options.throttleTime > 0) {
627
+ eventStream = eventStream.pipe(throttleTime(options.throttleTime));
628
+ }
629
+
630
+ if (options.distinctUntilChanged !== undefined && options.distinctUntilChanged !== false) {
631
+ if (typeof options.distinctUntilChanged === 'function') {
632
+ eventStream = eventStream.pipe(distinctUntilChanged(options.distinctUntilChanged));
633
+ } else {
634
+ eventStream = eventStream.pipe(distinctUntilChanged());
635
+ }
636
+ }
637
+
638
+ // Subscribe to the event stream
639
+ const subscription = eventStream.subscribe({
640
+ next: (event: Event) => {
641
+ handler(event).catch((err: any) => console.error('Event handler error:', err));
642
+ },
643
+ error: (err: any) => console.error('Event stream error:', err)
644
+ });
645
+
646
+ // Create wrapper handler that emits to the subject
647
+ const wrappedHandler = (event: Event) => {
648
+ eventSubject.next(event);
649
+ };
650
+
651
+ t.addEventListener(type, wrappedHandler, opts);
652
+ (this as any)._boundListeners.push({target: t, type, handler: wrappedHandler, options: opts, subscription});
593
653
  });
594
654
  });
595
655
 
@@ -640,7 +700,13 @@ export const elementDefine =
640
700
  for (const m of bMethods) (this as any)._invokeLifecycleMethod(m.propertyKey, helperHostSet);
641
701
 
642
702
  if ((this as any)._boundListeners) {
643
- (this as any)._boundListeners.forEach((l: any) => l.target.removeEventListener(l.type, l.handler, l.options));
703
+ (this as any)._boundListeners.forEach((l: any) => {
704
+ l.target.removeEventListener(l.type, l.handler, l.options);
705
+ // Cleanup Observable subscription if present
706
+ if (l.subscription && typeof l.subscription.unsubscribe === 'function') {
707
+ l.subscription.unsubscribe();
708
+ }
709
+ });
644
710
  (this as any)._boundListeners = [];
645
711
  }
646
712
 
@@ -3,6 +3,8 @@ import { SpecialSelector, SwcQueryOptions, HelperHostSet } from '../types';
3
3
  import {ensureInit, getElementConfig} from './elementDefine';
4
4
  import {SwcUtils} from '../utils/Utils';
5
5
 
6
+ export type EmitCustomEventSelector = string | ((currentThis: any, helper: HelperHostSet) => NodeList | Element | Element[] | null);
7
+
6
8
  export interface EmitCustomEventBaseOptions {
7
9
  bubbles?: boolean;
8
10
  composed?: boolean;
@@ -30,23 +32,51 @@ type Options = (EmitCustomEventBaseOptions & SwcQueryOptions) | (EmitCustomEvent
30
32
 
31
33
  export interface EmitCustomEventMetadata {
32
34
  propertyKey: string | symbol;
33
- selector: string;
35
+ selector: EmitCustomEventSelector;
34
36
  type: string;
35
37
  options: Options;
36
38
  }
37
39
 
38
40
  export const EMIT_CUSTOM_EVENT_METADATA_KEY = Symbol.for('simple-web-component:emit-custom-event');
39
41
 
40
- export function emitCustomEvent(target: SpecialSelector, type: string, options?: Options): MethodDecorator;
41
- export function emitCustomEvent(selector: string, type: string, options?: Options): MethodDecorator;
42
+ export function emitCustomEvent(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
43
+ export function emitCustomEvent(selector: EmitCustomEventSelector, type: string, options?: Options): MethodDecorator;
44
+ export function emitCustomEvent(type: string, options?: Options): MethodDecorator;
42
45
  /**
43
46
  * @emitCustomEvent decorator to dispatch custom events to a target.
47
+ *
48
+ * Usage:
49
+ * - @emitCustomEvent('$this', 'event-name', options) - Emit from $this
50
+ * - @emitCustomEvent('$appHost', 'event-name', options) - Emit from $appHost
51
+ * - @emitCustomEvent((this, helper) => '.button', 'event-name', options) - Function-based selector
52
+ * - @emitCustomEvent('event-name', options) - Emit from $this (defaults to $this)
53
+ * - @emitCustomEvent('event-name') - Emit from $this with no options
44
54
  */
45
- export function emitCustomEvent(selectorOrTarget: string, type: string, options: any = {}): MethodDecorator {
55
+ export function emitCustomEvent(selectorOrTarget: any, typeOrPropertyKey?: any, optionsOrDescriptor?: any): any {
56
+ // Case 1: Bare decorator on property
57
+ if (typeof selectorOrTarget === 'object' && typeof typeOrPropertyKey === 'string' && typeof optionsOrDescriptor === 'object' && 'value' in optionsOrDescriptor) {
58
+ throw new Error(`@emitCustomEvent decorator cannot be used on properties. (Property: ${String(typeOrPropertyKey)})`);
59
+ }
60
+
61
+ // Case 2: With selector and type - @emitCustomEvent('selector', 'event-name', options)
62
+ if ((typeof selectorOrTarget === 'string' || typeof selectorOrTarget === 'function') && typeof typeOrPropertyKey === 'string') {
63
+ return createEmitDecorator(selectorOrTarget, typeOrPropertyKey, optionsOrDescriptor as Options);
64
+ }
65
+
66
+ // Case 3: Without selector (type only) - @emitCustomEvent('event-name', options)
67
+ if (typeof selectorOrTarget === 'string' && typeOrPropertyKey !== 'string') {
68
+ return createEmitDecorator('$this', selectorOrTarget, typeOrPropertyKey as Options);
69
+ }
70
+
71
+ // Fallback
72
+ throw new Error('Invalid @emitCustomEvent usage');
73
+ }
74
+
75
+ function createEmitDecorator(selector: EmitCustomEventSelector, type: string, options?: Options) {
46
76
  return (targetObj: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
47
77
  const constructor = targetObj.constructor;
48
78
 
49
- const fullOptions: any = {...options, type};
79
+ const fullOptions: any = {...(options || {}), type};
50
80
 
51
81
  if (fullOptions.bubbles === undefined) fullOptions.bubbles = true;
52
82
  if (fullOptions.composed === undefined) fullOptions.composed = true;
@@ -56,7 +86,7 @@ export function emitCustomEvent(selectorOrTarget: string, type: string, options:
56
86
  list = [];
57
87
  ReflectUtils.defineMetadata(EMIT_CUSTOM_EVENT_METADATA_KEY, list, constructor);
58
88
  }
59
- list.push({propertyKey, selector: selectorOrTarget, type, options: fullOptions});
89
+ list.push({propertyKey, selector, type, options: fullOptions});
60
90
 
61
91
  const original = descriptor.value;
62
92
  descriptor.value = function (...args: any[]) {
@@ -71,47 +101,68 @@ export function emitCustomEvent(selectorOrTarget: string, type: string, options:
71
101
  cancelable: fullOptions.cancelable
72
102
  });
73
103
 
74
- const hostSet = SwcUtils.getHostSet(this as any);
75
104
  const conf = getElementConfig(this);
76
105
  const currentWin = (this as any)._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as Window);
106
+ const hostSet = SwcUtils.getHelperAndHostSet(currentWin, this as any);
77
107
 
78
108
  const eventTargets: EventTarget[] = [];
79
- if (selectorOrTarget === '$window') eventTargets.push(currentWin);
80
- else if (selectorOrTarget === '$document') eventTargets.push(currentWin.document);
81
- else if (selectorOrTarget === '$host') {
82
- if (hostSet.$host) eventTargets.push(hostSet.$host);
83
- } else if (selectorOrTarget === '$parentHost') {
84
- if (hostSet.$parentHost) eventTargets.push(hostSet.$parentHost);
85
- } else if (selectorOrTarget === '$appHost') {
86
- if (hostSet.$appHost) eventTargets.push(hostSet.$appHost);
87
- } else if (selectorOrTarget === '$firstHost') {
88
- if (hostSet.$firstHost) eventTargets.push(hostSet.$firstHost);
89
- } else if (selectorOrTarget === '$lastHost') {
90
- if (hostSet.$lastHost) eventTargets.push(hostSet.$lastHost);
91
- } else if (selectorOrTarget === '$firstAppHost') {
92
- if (hostSet.$firstAppHost) eventTargets.push(hostSet.$firstAppHost);
93
- } else if (selectorOrTarget === '$lastAppHost') {
94
- if (hostSet.$lastAppHost) eventTargets.push(hostSet.$lastAppHost);
95
- } else if (selectorOrTarget === '$hosts') {
96
- hostSet.$hosts.forEach(h => eventTargets.push(h));
97
- } else if (selectorOrTarget === '$appHosts') {
98
- hostSet.$appHosts.forEach(h => eventTargets.push(h));
99
- } else if (selectorOrTarget === '$this' || !selectorOrTarget) {
100
- eventTargets.push(this as any);
109
+
110
+ // Resolve selector if it's a function
111
+ let resolvedSelector: string | Element | NodeList | Element[] | null = selector as any;
112
+ if (typeof selector === 'function') {
113
+ resolvedSelector = selector(this, hostSet);
114
+ }
115
+
116
+ // If selector function returned elements directly, use them
117
+ if (resolvedSelector instanceof currentWin.Element) {
118
+ eventTargets.push(resolvedSelector as EventTarget);
119
+ } else if (resolvedSelector instanceof currentWin.NodeList) {
120
+ eventTargets.push(...Array.from(resolvedSelector as EventTarget[]));
121
+ } else if (Array.isArray(resolvedSelector)) {
122
+ eventTargets.push(...(resolvedSelector as EventTarget[]));
123
+ } else if (resolvedSelector === null) {
124
+ // No targets
101
125
  } else {
102
- const r = fullOptions.root || 'auto';
103
- const searchRoots: (HTMLElement | ShadowRoot)[] = [];
104
- if (r === 'auto') searchRoots.push(this.shadowRoot || (this as any));
105
- else if (r === 'light') searchRoots.push(this as any);
106
- else if (r === 'shadow' && this.shadowRoot) searchRoots.push(this.shadowRoot);
107
- else if (r === 'all') {
108
- searchRoots.push(this as any);
109
- if (this.shadowRoot) searchRoots.push(this.shadowRoot);
126
+ // Handle string selector
127
+ const stringSelector = resolvedSelector as string;
128
+
129
+ if (stringSelector === '$window') eventTargets.push(currentWin);
130
+ else if (stringSelector === '$document') eventTargets.push(currentWin.document);
131
+ else if (stringSelector === '$host') {
132
+ if (hostSet.$host) eventTargets.push(hostSet.$host);
133
+ } else if (stringSelector === '$parentHost') {
134
+ if (hostSet.$parentHost) eventTargets.push(hostSet.$parentHost);
135
+ } else if (stringSelector === '$appHost') {
136
+ if (hostSet.$appHost) eventTargets.push(hostSet.$appHost);
137
+ } else if (stringSelector === '$firstHost') {
138
+ if (hostSet.$firstHost) eventTargets.push(hostSet.$firstHost);
139
+ } else if (stringSelector === '$lastHost') {
140
+ if (hostSet.$lastHost) eventTargets.push(hostSet.$lastHost);
141
+ } else if (stringSelector === '$firstAppHost') {
142
+ if (hostSet.$firstAppHost) eventTargets.push(hostSet.$firstAppHost);
143
+ } else if (stringSelector === '$lastAppHost') {
144
+ if (hostSet.$lastAppHost) eventTargets.push(hostSet.$lastAppHost);
145
+ } else if (stringSelector === '$hosts') {
146
+ hostSet.$hosts.forEach(h => eventTargets.push(h));
147
+ } else if (stringSelector === '$appHosts') {
148
+ hostSet.$appHosts.forEach(h => eventTargets.push(h));
149
+ } else if (stringSelector === '$this' || !stringSelector) {
150
+ eventTargets.push(this as any);
151
+ } else {
152
+ const r = fullOptions.root || 'auto';
153
+ const searchRoots: (HTMLElement | ShadowRoot)[] = [];
154
+ if (r === 'auto') searchRoots.push(this.shadowRoot || (this as any));
155
+ else if (r === 'light') searchRoots.push(this as any);
156
+ else if (r === 'shadow' && this.shadowRoot) searchRoots.push(this.shadowRoot);
157
+ else if (r === 'all') {
158
+ searchRoots.push(this as any);
159
+ if (this.shadowRoot) searchRoots.push(this.shadowRoot);
160
+ }
161
+
162
+ searchRoots.forEach(sr => {
163
+ sr.querySelectorAll(stringSelector).forEach(el => eventTargets.push(el));
164
+ });
110
165
  }
111
-
112
- searchRoots.forEach(sr => {
113
- sr.querySelectorAll(selectorOrTarget).forEach(el => eventTargets.push(el));
114
- });
115
166
  }
116
167
 
117
168
  eventTargets.forEach(t => {
@@ -140,22 +191,3 @@ export const getEmitCustomEventMetadataList = (target: any): EmitCustomEventMeta
140
191
 
141
192
  // --- Aliases: emit... ---
142
193
  export const emit = emitCustomEvent;
143
-
144
- /**
145
- * @emitCustomEventThis decorator - simplified version of @emitCustomEvent for $this selector
146
- */
147
- export function emitCustomEventThis(type: string, options: EmitCustomEventBaseOptions & SwcQueryOptions & { attributeName?: string }): MethodDecorator ;
148
- export function emitCustomEventThis(type: string, attributeName: string): MethodDecorator ;
149
- export function emitCustomEventThis(type: string): MethodDecorator;
150
- export function emitCustomEventThis(type: string, optionsOrAttributeaName?: string | (EmitCustomEventBaseOptions & SwcQueryOptions & { attributeName?: string })): MethodDecorator {
151
- if (optionsOrAttributeaName && typeof optionsOrAttributeaName === 'string') {
152
- return emitCustomEventThis(type, {attributeName: optionsOrAttributeaName});
153
- } else if (optionsOrAttributeaName && typeof optionsOrAttributeaName === 'object') {
154
- if (!optionsOrAttributeaName.attributeName) {
155
- optionsOrAttributeaName.attributeName = `on-emit-${type}`;
156
- }
157
- return emitCustomEvent('$this', type, optionsOrAttributeaName);
158
- } else {
159
- return emitCustomEvent('$this', type, {attributeName: `on-emit-${type}`});
160
- }
161
- }
@@ -1,7 +1,7 @@
1
1
  export * from './addEventListener';
2
2
  export * from './applyAttribute';
3
3
  export * from './elementDefine';
4
- export * from './changedAttributeThis';
4
+ export * from './changedAttribute';
5
5
  export * from './emitCustomEvent';
6
6
  export * from './applyNode';
7
7
  export * from './lifecycles';
@@ -134,7 +134,7 @@ export function publishSwcAppMessage(targetOrMessageTypeOrOptions?: any, propert
134
134
  }
135
135
 
136
136
  // --- Aliases: publish... ---
137
- export const publish = publishSwcAppMessage;
137
+ export const publishMessage = publishSwcAppMessage;
138
138
 
139
139
  // Helper function to retrieve publish message metadata
140
140
  export const getPublishSwcAppMessageMetadata = (target: any): PublishSwcAppMessageMetadata[] | undefined => {