@dooboostore/simple-web-component 1.0.42 → 1.0.44

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 (153) hide show
  1. package/README.md +689 -85
  2. package/dist/cjs/SwcAppEngine.js +3 -1
  3. package/dist/cjs/SwcAppEngine.js.map +2 -2
  4. package/dist/cjs/decorators/addEventListener.js +10 -0
  5. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  6. package/dist/cjs/decorators/applyAttribute.js +41 -30
  7. package/dist/cjs/decorators/applyAttribute.js.map +2 -2
  8. package/dist/cjs/decorators/applyClass.js +66 -23
  9. package/dist/cjs/decorators/applyClass.js.map +3 -3
  10. package/dist/cjs/decorators/applyNode.js +176 -107
  11. package/dist/cjs/decorators/applyNode.js.map +2 -2
  12. package/dist/cjs/decorators/applyProperty.js +21 -30
  13. package/dist/cjs/decorators/applyProperty.js.map +2 -2
  14. package/dist/cjs/decorators/applySlot.js +11 -2
  15. package/dist/cjs/decorators/applySlot.js.map +2 -2
  16. package/dist/cjs/decorators/applyStyle.js +48 -17
  17. package/dist/cjs/decorators/applyStyle.js.map +3 -3
  18. package/dist/cjs/decorators/{changedAttributeThis.js → changedAttribute.js} +6 -6
  19. package/dist/cjs/decorators/changedAttribute.js.map +7 -0
  20. package/dist/cjs/decorators/elementDefine.js +37 -6
  21. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  22. package/dist/cjs/decorators/emitCustomEvent.js +58 -42
  23. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  24. package/dist/cjs/decorators/index.js +1 -1
  25. package/dist/cjs/decorators/index.js.map +2 -2
  26. package/dist/cjs/decorators/publishSwcAppMessage.js +37 -23
  27. package/dist/cjs/decorators/publishSwcAppMessage.js.map +3 -3
  28. package/dist/cjs/decorators/query.js +96 -145
  29. package/dist/cjs/decorators/query.js.map +3 -3
  30. package/dist/cjs/decorators/queryAll.js +104 -131
  31. package/dist/cjs/decorators/queryAll.js.map +3 -3
  32. package/dist/cjs/decorators/subscribeSwcAppMessageWhileConnected.js +2 -0
  33. package/dist/cjs/decorators/subscribeSwcAppMessageWhileConnected.js.map +2 -2
  34. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -0
  35. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
  36. package/dist/cjs/elements/SwcAppMixin.js +17 -2
  37. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  38. package/dist/cjs/examples/RxJSOperatorsExample.js +285 -0
  39. package/dist/cjs/examples/RxJSOperatorsExample.js.map +7 -0
  40. package/dist/cjs/index.js +1 -0
  41. package/dist/cjs/index.js.map +2 -2
  42. package/dist/cjs/router/ElementRouter.js +4 -0
  43. package/dist/cjs/router/ElementRouter.js.map +2 -2
  44. package/dist/esm/SwcAppEngine.js +3 -1
  45. package/dist/esm/SwcAppEngine.js.map +2 -2
  46. package/dist/esm/decorators/addEventListener.js +10 -0
  47. package/dist/esm/decorators/addEventListener.js.map +2 -2
  48. package/dist/esm/decorators/applyAttribute.js +41 -30
  49. package/dist/esm/decorators/applyAttribute.js.map +2 -2
  50. package/dist/esm/decorators/applyClass.js +66 -23
  51. package/dist/esm/decorators/applyClass.js.map +3 -3
  52. package/dist/esm/decorators/applyNode.js +176 -107
  53. package/dist/esm/decorators/applyNode.js.map +2 -2
  54. package/dist/esm/decorators/applyProperty.js +21 -30
  55. package/dist/esm/decorators/applyProperty.js.map +2 -2
  56. package/dist/esm/decorators/applySlot.js +11 -2
  57. package/dist/esm/decorators/applySlot.js.map +2 -2
  58. package/dist/esm/decorators/applyStyle.js +48 -17
  59. package/dist/esm/decorators/applyStyle.js.map +3 -3
  60. package/dist/esm/decorators/{changedAttributeThis.js → changedAttribute.js} +3 -3
  61. package/dist/esm/decorators/changedAttribute.js.map +7 -0
  62. package/dist/esm/decorators/elementDefine.js +35 -4
  63. package/dist/esm/decorators/elementDefine.js.map +2 -2
  64. package/dist/esm/decorators/emitCustomEvent.js +58 -42
  65. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  66. package/dist/esm/decorators/index.js +1 -1
  67. package/dist/esm/decorators/index.js.map +1 -1
  68. package/dist/esm/decorators/publishSwcAppMessage.js +37 -23
  69. package/dist/esm/decorators/publishSwcAppMessage.js.map +3 -3
  70. package/dist/esm/decorators/query.js +96 -145
  71. package/dist/esm/decorators/query.js.map +3 -3
  72. package/dist/esm/decorators/queryAll.js +104 -131
  73. package/dist/esm/decorators/queryAll.js.map +3 -3
  74. package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js +2 -0
  75. package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js.map +2 -2
  76. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -0
  77. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
  78. package/dist/esm/elements/SwcAppMixin.js +18 -3
  79. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  80. package/dist/esm/examples/RxJSOperatorsExample.js +266 -0
  81. package/dist/esm/examples/RxJSOperatorsExample.js.map +7 -0
  82. package/dist/esm/index.js +1 -0
  83. package/dist/esm/index.js.map +2 -2
  84. package/dist/esm/router/ElementRouter.js +4 -0
  85. package/dist/esm/router/ElementRouter.js.map +2 -2
  86. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +900 -578
  87. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  88. package/dist/types/SwcAppEngine.d.ts.map +1 -1
  89. package/dist/types/decorators/addEventListener.d.ts +22 -14
  90. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  91. package/dist/types/decorators/applyAttribute.d.ts +61 -20
  92. package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
  93. package/dist/types/decorators/applyClass.d.ts +22 -36
  94. package/dist/types/decorators/applyClass.d.ts.map +1 -1
  95. package/dist/types/decorators/applyNode.d.ts +178 -30
  96. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  97. package/dist/types/decorators/applyProperty.d.ts +53 -18
  98. package/dist/types/decorators/applyProperty.d.ts.map +1 -1
  99. package/dist/types/decorators/applySlot.d.ts +6 -0
  100. package/dist/types/decorators/applySlot.d.ts.map +1 -1
  101. package/dist/types/decorators/applyStyle.d.ts +13 -7
  102. package/dist/types/decorators/applyStyle.d.ts.map +1 -1
  103. package/dist/types/decorators/{changedAttributeThis.d.ts → changedAttribute.d.ts} +2 -2
  104. package/dist/types/decorators/changedAttribute.d.ts.map +1 -0
  105. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  106. package/dist/types/decorators/emitCustomEvent.d.ts +20 -10
  107. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  108. package/dist/types/decorators/index.d.ts +1 -1
  109. package/dist/types/decorators/index.d.ts.map +1 -1
  110. package/dist/types/decorators/publishSwcAppMessage.d.ts +19 -0
  111. package/dist/types/decorators/publishSwcAppMessage.d.ts.map +1 -1
  112. package/dist/types/decorators/query.d.ts +3 -26
  113. package/dist/types/decorators/query.d.ts.map +1 -1
  114. package/dist/types/decorators/queryAll.d.ts +3 -20
  115. package/dist/types/decorators/queryAll.d.ts.map +1 -1
  116. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts +1 -0
  117. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts.map +1 -1
  118. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts +2 -0
  119. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts.map +1 -1
  120. package/dist/types/elements/SwcAppMixin.d.ts +4 -4
  121. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  122. package/dist/types/examples/RxJSOperatorsExample.d.ts +94 -0
  123. package/dist/types/examples/RxJSOperatorsExample.d.ts.map +1 -0
  124. package/dist/types/index.d.ts +1 -0
  125. package/dist/types/index.d.ts.map +1 -1
  126. package/dist/types/router/ElementRouter.d.ts.map +1 -1
  127. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +900 -578
  128. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  129. package/package.json +7 -9
  130. package/src/SwcAppEngine.ts +3 -1
  131. package/src/decorators/addEventListener.ts +35 -24
  132. package/src/decorators/applyAttribute.ts +167 -65
  133. package/src/decorators/applyClass.ts +113 -17
  134. package/src/decorators/applyNode.ts +383 -102
  135. package/src/decorators/applyProperty.ts +99 -65
  136. package/src/decorators/applySlot.ts +24 -10
  137. package/src/decorators/applyStyle.ts +83 -13
  138. package/src/decorators/{changedAttributeThis.ts → changedAttribute.ts} +1 -1
  139. package/src/decorators/elementDefine.ts +47 -4
  140. package/src/decorators/emitCustomEvent.ts +62 -35
  141. package/src/decorators/index.ts +1 -1
  142. package/src/decorators/publishSwcAppMessage.ts +71 -27
  143. package/src/decorators/query.ts +90 -159
  144. package/src/decorators/queryAll.ts +92 -134
  145. package/src/decorators/subscribeSwcAppMessageWhileConnected.ts +1 -0
  146. package/src/decorators/subscribeSwcAppRouteChangeWhileConnected.ts +3 -1
  147. package/src/elements/SwcAppMixin.ts +43 -24
  148. package/src/examples/RxJSOperatorsExample.ts +279 -0
  149. package/src/index.ts +2 -0
  150. package/src/router/ElementRouter.ts +4 -0
  151. package/dist/cjs/decorators/changedAttributeThis.js.map +0 -7
  152. package/dist/esm/decorators/changedAttributeThis.js.map +0 -7
  153. package/dist/types/decorators/changedAttributeThis.d.ts.map +0 -1
package/README.md CHANGED
@@ -70,18 +70,14 @@ replaceChildren(node: Node) {
70
70
  ```
71
71
  ### 3.5 **Slot Management with @applySlot**
72
72
 
73
- Manage dynamic content insertion into named slots using the `@applySlot` decorator. Slots are placeholders in templates that can be updated dynamically.
73
+ Manage dynamic content insertion into named slots using slot decorators. Slots are placeholders in templates that can be updated dynamically.
74
74
 
75
75
  ```typescript
76
- import {clearSlot} from "./applySlot";
77
-
78
76
  @elementDefine('content-manager')
79
77
  class ContentManager extends HTMLElement {
80
-
81
-
82
78
  // Method: Replace children in slot with HTML
83
79
  @addEventListener('.update-btn', 'click')
84
- @replaceChildrenSlot('main-content')
80
+ @replaceChildrenHtmlSlot('main-content')
85
81
  updateContent() {
86
82
  return '<div>Updated content here</div>';
87
83
  }
@@ -105,7 +101,6 @@ class ContentManager extends HTMLElement {
105
101
  return true;
106
102
  }
107
103
 
108
-
109
104
  @onConnectedLight
110
105
  render() {
111
106
  return `
@@ -130,17 +125,13 @@ class ContentManager extends HTMLElement {
130
125
  - `<!--[[ slot-id ]]-->` - Named slot placeholder (HTML comment syntax)
131
126
 
132
127
  **@applySlot Decorator Variants:**
133
- - clearSlot
134
- - prependHtmlSlot
135
- - prependSlot
136
- - prependTextSlot
137
- - appendHtmlSlot
138
- - appendTextSlot
139
- - appendSlot
140
- - replaceChildrenHtmlSlot
141
- - replaceChildrenSlot
142
- - replaceChildrenTextSlot
143
-
128
+ - `clearSlot(slotId)` - Clear all content
129
+ - `prependHtmlSlot(slotId)` - Add HTML at beginning
130
+ - `prependTextSlot(slotId)` - Add text at beginning
131
+ - `appendHtmlSlot(slotId)` - Add HTML at end
132
+ - `appendTextSlot(slotId)` - Add text at end
133
+ - `replaceChildrenHtmlSlot(slotId)` - Replace all with HTML
134
+ - `replaceChildrenTextSlot(slotId)` - Replace all with text
144
135
 
145
136
  **Position Options:**
146
137
  ```typescript
@@ -207,7 +198,7 @@ class CounterApp extends HTMLElement {
207
198
 
208
199
  **State Syntax in Templates:**
209
200
 
210
- **Reading State Values:**
201
+ **Reading State Values(read only):**
211
202
  - `@stateName@` - Read state value as text/attribute
212
203
  - `@stateName@()` - Call state property as function (if it's a function)
213
204
  - `@expression@` - Evaluate expressions with state variables
@@ -231,6 +222,23 @@ class CounterApp extends HTMLElement {
231
222
  - `@expression@` - Evaluate JavaScript expressions
232
223
  - All state variables available in template expressions
233
224
 
225
+ **Important: State Properties are Read-Only in Templates**
226
+ State values accessed in templates via `@stateName@` syntax are read-only. You cannot assign values to state properties from within template expressions. State must be updated from component methods:
227
+
228
+ ```typescript
229
+ // ✅ CORRECT - Update state from method
230
+ @addEventListener('button', 'click')
231
+ increment() {
232
+ this.count++; // Direct property assignment in code
233
+ }
234
+
235
+ // ❌ WRONG - Cannot assign in template
236
+ <!--[text @count = 5@ ]--> // This won't work - read-only in templates
237
+
238
+ // ✅ CORRECT - Call method from template
239
+ <button e:click="@increment@()">Increment</button>
240
+ ```
241
+
234
242
  **Advanced Example:**
235
243
  ```typescript
236
244
  @elementDefine('user-profile')
@@ -288,16 +296,21 @@ onCriticalClick(event: Event) {
288
296
  }
289
297
  ```
290
298
 
291
- **other Event decorators**
292
- - addEventListenerDelegateLightDom
293
- - addEventListenerDelegateShadowDom
294
- - addEventListenerDelegateAllDom
295
- - addEventListenerDelegate
296
- - addEventListenerThis
297
- - addEventListenerAppHost
298
- - addEventListenerWindow
299
- - addEventListenerDocument
300
-
299
+ **@addEventListener Decorator Variants:**
300
+ - `addEventListener(selector, type, options)` - Full form
301
+ - `event(selector, type, options)` - Short alias
302
+ - `addEventListenerThis(type, options)` - Listen on $this element
303
+ - `addEventListenerAppHost(type, options)` - Listen on $appHost
304
+ - `addEventListenerWindow(type, options)` - Listen on window
305
+ - `addEventListenerDocument(type, options)` - Listen on document
306
+ - `addEventListenerDelegate(selector, type, options)` - Event delegation
307
+ - `eventDelegate(selector, type, options)` - Short alias
308
+ - `addEventListenerDelegateLightDom(selector, type, options)` - Delegate in light DOM
309
+ - `eventDelegateLightDom(selector, type, options)` - Short alias
310
+ - `addEventListenerDelegateShadowDom(selector, type, options)` - Delegate in shadow DOM
311
+ - `eventDelegateShadowDom(selector, type, options)` - Short alias
312
+ - `addEventListenerDelegateAllDom(selector, type, options)` - Delegate in all DOM
313
+ - `eventDelegateAllDom(selector, type, options)` - Short alias
301
314
 
302
315
  #### @emitCustomEvent
303
316
  Emit custom events with data.
@@ -310,6 +323,50 @@ async onLogin() {
310
323
  }
311
324
  ```
312
325
 
326
+ **@emitCustomEvent Decorator Variants:**
327
+ - `emitCustomEvent(target, type, options)` - Full form
328
+ - `emit(target, type, options)` - Short alias
329
+ - `emitCustomEventThis(type, options)` - Emit from $this element
330
+
331
+ #### @publishSwcAppMessage
332
+ Publish messages through the message bus when method completes.
333
+
334
+ ```typescript
335
+ @publishSwcAppMessage()
336
+ async onLogin() {
337
+ const user = await this.authService.login();
338
+ return user; // Published as message with data: user
339
+ }
340
+
341
+ @publishSwcAppMessage('user-profile-updated')
342
+ updateProfile() {
343
+ const profile = { name: this.name, email: this.email };
344
+ return profile; // Published as message with type: 'user-profile-updated'
345
+ }
346
+ ```
347
+
348
+ **@publishSwcAppMessage Decorator Variants:**
349
+ - `publishSwcAppMessage()` - Publish without message type
350
+ - `publishSwcAppMessage(messageType)` - Publish with specific message type
351
+ - `publishSwcAppMessage(messageType, { valueKey: 'customKey' })` - Publish with custom value extraction
352
+ - `publishSwcAppMessage({ messageType: 'type', valueKey: 'customKey' })` - Publish with options object
353
+ - `publish()` - Short alias
354
+ - `publish(messageType)` - Short alias with message type
355
+ - `publish(messageType, options)` - Short alias with options
356
+
357
+ **Using valueKey for Multiple Decorators:**
358
+
359
+ ```typescript
360
+ @publishSwcAppMessage('event1', { valueKey: 'detail1' })
361
+ @publishSwcAppMessage('event2', { valueKey: 'detail2' })
362
+ handleMultipleEvents() {
363
+ return {
364
+ detail1: { type: 'event1', data: 'value1' },
365
+ detail2: { type: 'event2', data: 'value2' }
366
+ };
367
+ }
368
+ ```
369
+
313
370
  #### @emitCustomEventThis
314
371
  Emit events from a method with custom event name mapping.
315
372
 
@@ -321,7 +378,7 @@ onNavClick(e: any) {
321
378
  ```
322
379
 
323
380
  #### @addEventListenerThis
324
- Listen to events on the component element itself (`@host` selector).
381
+ Listen to events on the component element itself (`$this` selector).
325
382
 
326
383
  ```typescript
327
384
  @addEventListenerThis('click')
@@ -395,55 +452,366 @@ printTag() {
395
452
 
396
453
  ### 6. **Attribute Binding**
397
454
 
398
- #### @attribute
399
- Bind HTML attributes to properties (automatic sync).
455
+ #### @attribute (Field Decorator)
456
+ Bind HTML attributes to properties with automatic read/write synchronization.
457
+
458
+ Intelligently distinguishes between attribute names and CSS selectors:
400
459
 
401
460
  ```typescript
402
- @attributeThis
403
- width: string = '100px'; // Bind to this.width
461
+ @elementDefine('product-card')
462
+ class ProductCard extends HTMLElement {
463
+ // Attribute name on $this (auto-detected)
464
+ @attribute('product-id')
465
+ productId: string;
404
466
 
405
- @attribute('data-id')
406
- resourceId: string; // element attribute first
467
+ // Attribute name on selector
468
+ @attribute('#user', 'data-id')
469
+ userId: string;
470
+
471
+ // Bare decorator (uses field name as attribute)
472
+ @attribute
473
+ title: string;
474
+
475
+ @onInitialize
476
+ onconstructor() {
477
+ if (this.productId) {
478
+ this.loadProduct(this.productId);
479
+ }
480
+ }
481
+ }
407
482
  ```
408
483
 
409
- #### @attributeThis
410
- Bind attributes on host element itself.
484
+ #### @setAttribute (Method Decorator)
485
+ Set element attributes from method return values.
411
486
 
412
487
  ```typescript
413
- @attributeThis('product-id')
414
- productId?: string;
488
+ @elementDefine('status-updater')
489
+ class StatusUpdater extends HTMLElement {
490
+ // Set attribute on $this
491
+ @setAttribute('data-status')
492
+ updateStatus() {
493
+ return this.isActive ? 'active' : 'inactive';
494
+ }
415
495
 
416
- @onInitialize
417
- onconstructor() {
418
- if (this.productId) {
419
- this.loadProduct(this.productId);
496
+ // Set attribute on selector
497
+ @setAttribute('#user', 'data-name')
498
+ setUserName() {
499
+ return this.userName;
500
+ }
501
+
502
+ // Bare decorator (uses method name as attribute)
503
+ @setAttribute
504
+ setValue() {
505
+ return this.computedValue;
420
506
  }
421
507
  }
422
508
  ```
423
509
 
424
- ### 7. **Lifecycle Hooks**
510
+ **Usage Patterns:**
511
+ - `@attribute('attr-name')` - Attribute name on $this (auto-detected)
512
+ - `@attribute('#selector', 'attr-name')` - Attribute name on selector
513
+ - `@attribute('attr-name', options)` - Attribute name on $this with options
514
+ - `@attribute('#selector', 'attr-name', options)` - Attribute name on selector with options
515
+ - `@attribute` - Bare decorator (uses field name as attribute on $this)
516
+
517
+ **@setAttribute Patterns:**
518
+ - `@setAttribute('attr-name')` - Set attribute on $this
519
+ - `@setAttribute('#selector', 'attr-name')` - Set attribute on selector
520
+ - `@setAttribute('attr-name', options)` - Set attribute on $this with options
521
+ - `@setAttribute('#selector', 'attr-name', options)` - Set attribute on selector with options
522
+ - `@setAttribute` - Bare decorator (uses method name as attribute on $this)
523
+
524
+ #### @changedAttribute (Method Decorator)
525
+ Listen for attribute changes on the component this element.
425
526
 
426
527
  ```typescript
427
- @onConnected
428
- onConnected() {
429
- // Called when element enters DOM
528
+ @elementDefine('reactive-component')
529
+ class ReactiveComponent extends HTMLElement {
530
+ @changedAttribute('product-id')
531
+ onProductIdChanged(newValue: string, oldValue: string) {
532
+ console.log(`Product changed from ${oldValue} to ${newValue}`);
533
+ this.loadProduct(newValue);
534
+ }
535
+
536
+ @changedAttribute('data-status', { type: Boolean })
537
+ onStatusChanged(newValue: boolean) {
538
+ console.log(`Status is now: ${newValue}`);
539
+ }
540
+
541
+ // Listen to any attribute change
542
+ @changedAttribute()
543
+ onAnyAttributeChanged(newValue: any, oldValue: any) {
544
+ console.log('An attribute changed');
545
+ }
430
546
  }
547
+ ```
548
+
549
+ **@changedAttribute Options:**
550
+ - `attributeName` - Attribute name to listen for (optional, defaults to method name)
551
+ - `type` - Type converter: `Number`, `Boolean`, or `String`
552
+ - `while` - Execution condition: `'connected'` (only while connected to DOM)
431
553
 
432
- @onDisconnected
433
- onDisconnected() {
434
- // Called when element leaves DOM
554
+ ### 6.5 **Property Binding**
555
+
556
+ #### @property (Field Decorator)
557
+ Bind element properties to component fields with automatic read/write synchronization.
558
+
559
+ ```typescript
560
+ @elementDefine('input-wrapper')
561
+ class InputWrapper extends HTMLElement {
562
+ // Property on $this (auto-detected)
563
+ @property('value')
564
+ inputValue: string;
565
+
566
+ // Property on selector
567
+ @property('#submit-btn', 'disabled')
568
+ isSubmitDisabled: boolean;
569
+
570
+ // Bare decorator (uses field name as property)
571
+ @property
572
+ checked: boolean;
435
573
  }
574
+ ```
436
575
 
576
+ #### @setProperty (Method Decorator)
577
+ Set element properties from method return values.
437
578
 
438
- @onConnectedBefore
439
- onAppReady(router: Router) {
440
- // Called after SwcApp.connect() completes on all already-connected components
441
- // Full DI support available through hostSet
442
- console.log('Application initialization complete!');
579
+ ```typescript
580
+ @elementDefine('form-handler')
581
+ class FormHandler extends HTMLElement {
582
+ // Set property on $this
583
+ @setProperty('disabled')
584
+ disableForm() {
585
+ return !this.isValid();
586
+ }
587
+
588
+ // Set property on selector
589
+ @setProperty('#submit-btn', 'disabled')
590
+ updateSubmitState() {
591
+ return this.hasErrors;
592
+ }
593
+
594
+ // Bare decorator (uses method name as property)
595
+ @setProperty
596
+ setValue() {
597
+ return this.computedValue;
598
+ }
443
599
  }
444
600
  ```
445
601
 
446
- ### 8. **Structural Directives**
602
+ **Usage Patterns:**
603
+ - `@property('propertyName')` - Property on $this
604
+ - `@property('#selector', 'propertyName')` - Property on selector
605
+ - `@property('propertyName', options)` - Property on $this with options
606
+ - `@property('#selector', 'propertyName', options)` - Property on selector with options
607
+ - `@property` - Bare decorator (uses field name as property on $this)
608
+
609
+ **@setProperty Patterns:**
610
+ - `@setProperty('propertyName')` - Set property on $this
611
+ - `@setProperty('#selector', 'propertyName')` - Set property on selector
612
+ - `@setProperty('propertyName', options)` - Set property on $this with options
613
+ - `@setProperty('#selector', 'propertyName', options)` - Set property on selector with options
614
+ - `@setProperty` - Bare decorator (uses method name as property on $this)
615
+
616
+ ### 7. **DOM Manipulation with applyNode**
617
+
618
+ Surgically add, replace, or remove nodes in the DOM with fine-grained control.
619
+
620
+ ```typescript
621
+ @elementDefine('content-updater')
622
+ class ContentUpdater extends HTMLElement {
623
+ @addEventListener('button', 'click')
624
+ @replaceChildrenNode()
625
+ updateContent() {
626
+ return `<div>New content</div>`;
627
+ }
628
+
629
+ @addEventListener('.append-btn', 'click')
630
+ @beforeEndNode()
631
+ appendContent() {
632
+ return `<p>Appended content</p>`;
633
+ }
634
+
635
+ @addEventListener('.prepend-btn', 'click')
636
+ @afterBeginNode()
637
+ prependContent() {
638
+ return `<p>Prepended content</p>`;
639
+ }
640
+
641
+ @onConnectedLight
642
+ render() {
643
+ return `
644
+ <div>
645
+ <button class="append-btn">Append</button>
646
+ <button class="prepend-btn">Prepend</button>
647
+ <button>Replace</button>
648
+ </div>
649
+ `;
650
+ }
651
+ }
652
+ ```
653
+
654
+ **@applyNode Decorator Variants:**
655
+ - `replaceChildrenNode()` - Replace all children
656
+ - `replaceChildrenLightNode()` - Replace children in light DOM
657
+ - `beforeEndNode()` - Append to end
658
+ - `beforeEndLightNode()` - Append to light DOM end
659
+ - `afterBeginNode()` - Prepend to beginning
660
+ - `afterBeginLightNode()` - Prepend to light DOM beginning
661
+ - `innerHtmlNode()` - Set innerHTML
662
+ - `innerHtmlLightNode()` - Set innerHTML in light DOM
663
+ - `innerTextNode()` - Set innerText
664
+
665
+ **Position Options:**
666
+ ```typescript
667
+ export type ApplyNodePosition =
668
+ | 'beforeBegin' // Before element
669
+ | 'afterBegin' // After element opens
670
+ | 'beforeEnd' // Before element closes
671
+ | 'afterEnd' // After element closes
672
+ | 'replace' // Replace element
673
+ | 'replaceChildren' // Replace children
674
+ | 'innerHtml' // Set innerHTML
675
+ | 'innerText' // Set innerText
676
+ | 'remove'; // Remove element
677
+ ```
678
+
679
+ ### 8. **Style & Class Management**
680
+
681
+ Apply styles and classes dynamically with `@applyStyle` and `@applyClass`.
682
+
683
+ ```typescript
684
+ @elementDefine('styled-component')
685
+ class StyledComponent extends HTMLElement {
686
+ @state('isActive')
687
+ isActive = false;
688
+
689
+ @addEventListener('button', 'click')
690
+ @updateStyle()
691
+ toggleStyle() {
692
+ return {
693
+ color: this.isActive ? 'green' : 'red',
694
+ fontSize: '16px'
695
+ };
696
+ }
697
+
698
+ @addEventListener('.toggle-btn', 'click')
699
+ @updateClass()
700
+ toggleClass() {
701
+ return {
702
+ 'active': this.isActive,
703
+ 'disabled': !this.isActive
704
+ };
705
+ }
706
+
707
+ @onConnectedLight
708
+ render() {
709
+ return `
710
+ <div>
711
+ <button class="toggle-btn">Toggle</button>
712
+ <button>Update Style</button>
713
+ </div>
714
+ `;
715
+ }
716
+ }
717
+ ```
718
+
719
+ **@applyStyle Variants:**
720
+ - `setStyleThis()` - Clear and set styles
721
+ - `updateStyleThis()` - Update/merge styles
722
+ - `removeStyleThis()` - Remove specific styles
723
+
724
+ **@applyClass Variants:**
725
+ - `setClassThis()` - Replace all classes
726
+ - `updateClassThis()` - Toggle classes
727
+ - `addClassThis()` - Add classes
728
+ - `removeClassThis()` - Remove classes
729
+ - `toggleClassThis()` - Toggle classes
730
+
731
+ ### 8.5 **Lifecycle Hooks**
732
+
733
+ Lifecycle hooks allow you to execute code at specific points in a component's lifecycle. All lifecycle decorators support optional `order` parameter for execution ordering.
734
+
735
+ ```typescript
736
+ @elementDefine('my-component')
737
+ class MyComponent extends HTMLElement {
738
+ @onInitialize({ order: 0 })
739
+ onInit() {
740
+ // Called during component construction
741
+ console.log('Component initialized');
742
+ }
743
+
744
+ @onConnectedBefore({ order: 0 })
745
+ beforeConnected() {
746
+ // Called before element connects to DOM
747
+ }
748
+
749
+ @onConnectedAfter({ order: 1 })
750
+ afterConnected() {
751
+ // Called after element connects to DOM
752
+ }
753
+
754
+ @onConnected
755
+ onConnected() {
756
+ // Called when element enters DOM
757
+ }
758
+
759
+ @onDisconnectedBefore
760
+ beforeDisconnected() {
761
+ // Called before element disconnects from DOM
762
+ }
763
+
764
+ @onDisconnected
765
+ onDisconnected() {
766
+ // Called when element leaves DOM
767
+ }
768
+
769
+ @onAdoptedBefore
770
+ beforeAdopted() {
771
+ // Called before element is adopted into new document
772
+ }
773
+
774
+ @onAdopted
775
+ onAdopted() {
776
+ // Called when element is adopted into new document
777
+ }
778
+
779
+ @onConnectedSwcApp({ order: 0 })
780
+ onSwcAppConnected() {
781
+ // Called after SwcApp.connect() completes
782
+ // Full DI support available through hostSet
783
+ }
784
+
785
+ @onConnectedCompleted({ order: 0 })
786
+ onConnectedCompleted() {
787
+ // Called after all connected lifecycle hooks complete
788
+ }
789
+ }
790
+ ```
791
+
792
+ **Lifecycle Execution Order:**
793
+ - `@onInitialize` - Component construction
794
+ - `@onConnectedBefore` - Before DOM connection
795
+ - `@onConnectedAfter` - After DOM connection
796
+ - `@onConnected` - DOM connection (with HTML rendering)
797
+ - `@onConnectedSwcApp` - After SwcApp initialization
798
+ - `@onConnectedCompleted` - All connected hooks done
799
+ - `@onDisconnectedBefore` - Before DOM disconnection
800
+ - `@onDisconnected` - DOM disconnection
801
+ - `@onAdoptedBefore` - Before document adoption
802
+ - `@onAdopted` - Document adoption
803
+
804
+ **Order Parameter:**
805
+ All lifecycle decorators support `order?: number` for controlling execution sequence:
806
+ ```typescript
807
+ @onConnectedBefore({ order: 0 }) // Runs first
808
+ onFirst() { }
809
+
810
+ @onConnectedBefore({ order: 1 }) // Runs second
811
+ onSecond() { }
812
+ ```
813
+
814
+ ### 9. **Structural Directives**
447
815
 
448
816
  Structural Directives allow declarative conditional rendering, list iteration, async handling, and routing with automatic attribute substitution and dynamic expressions.
449
817
 
@@ -528,6 +896,28 @@ class LoginForm extends HTMLElement {
528
896
  }
529
897
  ```
530
898
 
899
+ **@publishSwcAppMessage Decorator Variants:**
900
+ - `publishSwcAppMessage()` - Publish without message type
901
+ - `publishSwcAppMessage(messageType)` - Publish with specific message type
902
+ - `publishSwcAppMessage(messageType, { valueKey: 'customKey' })` - Publish with custom value extraction
903
+ - `publishSwcAppMessage({ messageType: 'type', valueKey: 'customKey' })` - Publish with options object
904
+ - `publishMessage()` - Short alias
905
+ - `publishMessage(messageType)` - Short alias with message type
906
+ - `publishMessage(messageType, options)` - Short alias with options
907
+
908
+ **Using valueKey for Multiple Decorators:**
909
+
910
+ ```typescript
911
+ @publishSwcAppMessage('event1', { valueKey: 'detail1' })
912
+ @publishSwcAppMessage('event2', { valueKey: 'detail2' })
913
+ handleMultipleEvents() {
914
+ return {
915
+ detail1: { type: 'event1', data: 'value1' },
916
+ detail2: { type: 'event2', data: 'value2' }
917
+ };
918
+ }
919
+ ```
920
+
531
921
  **SwcAppMessage Structure:**
532
922
  ```typescript
533
923
  type SwcAppMessage<T = any> = {
@@ -570,7 +960,7 @@ class ProductDetail extends HTMLElement {
570
960
 
571
961
  ---
572
962
 
573
- ### 10. **SwcApp - Multiple Element Types with Mixin Pattern**
963
+ ### 11. **SwcApp - Multiple Element Types with Mixin Pattern**
574
964
 
575
965
  SWC provides a flexible Mixin-based architecture for creating SwcApp elements that extend different HTMLElement types. This enables building SPAs with any semantic HTML element as the root.
576
966
 
@@ -647,17 +1037,15 @@ w.document.addEventListener('DOMContentLoaded', async () => {
647
1037
 
648
1038
  ```typescript
649
1039
  // Component factory
650
- import {defineSwcApp} from "./SwcApp";
651
-
652
1040
  export default (w: Window) => {
653
1041
  const tagName = 'my-component';
654
1042
  const existing = w.customElements.get(tagName);
655
1043
  if (existing) return tagName;
656
1044
 
657
- @elementDefine(tagName, {window: w})
1045
+ @elementDefine(tagName, { window: w })
658
1046
  class MyComponent extends w.HTMLElement {
659
1047
  @onInitialize
660
- onconstructor(service: MyService) {
1048
+ onconstructor(@inject(MyService.SYMBOL) service: MyService) {
661
1049
  this.service = service;
662
1050
  }
663
1051
  }
@@ -672,7 +1060,7 @@ export default (w: Window, container: symbol) => {
672
1060
 
673
1061
  // Entry point
674
1062
  const container = Symbol('app');
675
- await defineSwcAppBody(w)
1063
+ await defineSwcAppBody(w);
676
1064
  const appElement = w.document.querySelector('#app') as SwcAppInterface;
677
1065
  appElement.connect({
678
1066
  container,
@@ -684,7 +1072,7 @@ appElement.connect({
684
1072
  });
685
1073
  ```
686
1074
 
687
- ### 11. **Routing with @subscribeSwcAppRouteChangeWhileConnected**
1075
+ #### 12. **Routing with @subscribeSwcAppRouteChangeWhileConnected**
688
1076
 
689
1077
  SWC provides declarative routing with automatic path matching, order-based execution, and optional propagation control.
690
1078
 
@@ -723,10 +1111,11 @@ class RootRouter extends HTMLElement {
723
1111
  #### Route Handler Features
724
1112
 
725
1113
  **1. Path Matching**
726
- - Exact match: `['', '/']` - matches home route
727
- - Prefix match: `['/products']` - matches `/products` and `/products/...`
728
- - Dynamic segments: `['/product/{id}']` - captures `id` parameter
729
- - Wildcard: `['/{tail:.*}']` - matches any remaining path (use for 404)
1114
+ - **No path pattern** (omit path): `@subscribeSwcAppRouteChangeWhileConnected({ order: -1 })` - matches all routes
1115
+ - **Exact match**: `['', '/']` - matches home route only
1116
+ - **Prefix match**: `['/products']` - matches `/products` and `/products/...`
1117
+ - **Dynamic segments**: `['/product/{id}']` - captures `id` parameter
1118
+ - **Wildcard**: `['/{tail:.*}']` - matches any remaining path (use for 404)
730
1119
 
731
1120
  **2. Order-Based Execution**
732
1121
  Routes are executed in order of `order` value (lowest first). First matching route with a return value stops propagation:
@@ -750,7 +1139,7 @@ handleAdmin(routerPathSet: RouterEventType) {
750
1139
  }
751
1140
 
752
1141
  // This handler continues propagation (no return value)
753
- @subscribeSwcAppRouteChangeWhileConnected(['{other:.*}'], { order: -1 })
1142
+ @subscribeSwcAppRouteChangeWhileConnected({ order: -1 })
754
1143
  onRouteChange(routerPathSet: RouterEventType) {
755
1144
  console.log('Route changed:', routerPathSet.path);
756
1145
  // No return value → continues to next handler
@@ -762,8 +1151,8 @@ onRouteChange(routerPathSet: RouterEventType) {
762
1151
  ```typescript
763
1152
  @elementDefine('accommodation-router')
764
1153
  class AccommodationRouter extends HTMLElement {
765
- // Global route logger (order: -1 runs first, no return value)
766
- @subscribeSwcAppRouteChangeWhileConnected(['*'], { order: -1 })
1154
+ // Global route logger (order: -1 runs first, no path pattern = matches all routes)
1155
+ @subscribeSwcAppRouteChangeWhileConnected({ order: -1 })
767
1156
  onRouteChange(routerPathSet: RouterEventType) {
768
1157
  console.log('[Route Change]', {
769
1158
  path: routerPathSet.path,
@@ -851,37 +1240,252 @@ URL: /product/123
851
1240
  pathData: { id: '123' }
852
1241
  ```
853
1242
 
1243
+ #### Multiple Decorators with Shared Return Value
1244
+
1245
+ When using multiple decorators on the same method, each decorator can extract its own value from the return object using its symbol key or custom `valueKey` option.
1246
+
1247
+ **How It Works:**
1248
+ 1. Each decorator has a default symbol key (e.g., `ATTRIBUTE_METADATA_KEY`, `PROPERTY_METADATA_KEY`)
1249
+ 2. When a method returns an object, each decorator checks if its key exists in the object
1250
+ 3. If the key exists, the decorator uses that value; otherwise uses the entire return value
1251
+ 4. This allows multiple decorators to extract different values from the same return object
1252
+
1253
+ **Method 1: Using Default Symbol Keys**
1254
+
1255
+ ```typescript
1256
+ import {
1257
+ ATTRIBUTE_METADATA_KEY,
1258
+ PROPERTY_METADATA_KEY,
1259
+ STYLE_METADATA_KEY,
1260
+ CLASS_METADATA_KEY
1261
+ } from '@dooboostore/simple-web-component';
1262
+
1263
+ @elementDefine('multi-decorator-example')
1264
+ class MultiDecoratorExample extends HTMLElement {
1265
+ @setAttribute('selector')
1266
+ @setProperty('selector')
1267
+ @updateStyle()
1268
+ @updateClass()
1269
+ handleUpdate() {
1270
+ return {
1271
+ [ATTRIBUTE_METADATA_KEY]: 'attribute-value',
1272
+ [PROPERTY_METADATA_KEY]: 'property-value',
1273
+ [STYLE_METADATA_KEY]: { color: 'red', fontSize: '16px' },
1274
+ [CLASS_METADATA_KEY]: { 'active': true, 'disabled': false }
1275
+ };
1276
+ }
1277
+ }
1278
+ ```
1279
+
1280
+ **Method 2: Using Custom valueKey Option**
1281
+
1282
+ For more readable code, use the `valueKey` option to specify custom keys:
1283
+
1284
+ ```typescript
1285
+ @elementDefine('custom-key-example')
1286
+ class CustomKeyExample extends HTMLElement {
1287
+ @setAttribute('selector', { valueKey: 'attrValue' })
1288
+ @setProperty('selector', { valueKey: 'propValue' })
1289
+ @updateStyle({ valueKey: 'styleValue' })
1290
+ @updateClass({ valueKey: 'classValue' })
1291
+ handleUpdate() {
1292
+ return {
1293
+ attrValue: 'attribute-value',
1294
+ propValue: 'property-value',
1295
+ styleValue: { color: 'red', fontSize: '16px' },
1296
+ classValue: { 'active': true, 'disabled': false }
1297
+ };
1298
+ }
1299
+ }
1300
+ ```
1301
+
1302
+ **Method 3: Mixing Symbol Keys and Custom Keys**
1303
+
1304
+ You can mix both approaches in the same method:
1305
+
1306
+ ```typescript
1307
+ @elementDefine('mixed-keys-example')
1308
+ class MixedKeysExample extends HTMLElement {
1309
+ @setAttribute('selector') // Uses default ATTRIBUTE_METADATA_KEY
1310
+ @setProperty('selector', { valueKey: 'customProp' }) // Uses custom key
1311
+ @updateStyle({ valueKey: 'styles' }) // Uses custom key
1312
+ handleUpdate() {
1313
+ return {
1314
+ [ATTRIBUTE_METADATA_KEY]: 'attr-value',
1315
+ customProp: 'prop-value',
1316
+ styles: { color: 'blue' }
1317
+ };
1318
+ }
1319
+ }
1320
+ ```
1321
+
1322
+ **Supported Decorators with valueKey:**
1323
+ - `@applyAttribute` / `@setAttribute`
1324
+ - `@applyProperty` / `@setProperty`
1325
+ - `@applySlot` / `@clearSlot` / `@appendHtmlSlot` / etc.
1326
+ - `@applyNode` / `@replaceChildrenNode` / etc.
1327
+ - `@applyStyle` / `@updateStyle` / etc.
1328
+ - `@applyClass` / `@updateClass` / etc.
1329
+ - `@emitCustomEvent` / `@emit`
1330
+ - `@publishSwcAppMessage` / `@publish`
1331
+
1332
+ Each decorator will use only its corresponding value from the return object, preventing conflicts and allowing clean separation of concerns.
1333
+
854
1334
  ---
855
1335
 
856
- ### 12. **Accommodation Pattern**
1336
+ ### 13. **Accommodation Pattern**
857
1337
  Factory-based component registration with explicit DI.
858
1338
 
859
1339
  ```typescript
860
1340
  // Component factory
861
- import {SwcUtils, createElement, CreateElementConfig} from '@dooboostore/simple-web-component';
862
- const tagName = 'my-component';
863
- export interface MyComponent extends HTMLElement {
864
- value: string;
865
- }
866
- export const MyComponent = (w: Window|Document, data?: CreateElementConfig) => {
867
- return createElement<HTMLElement>(w, tagName, data);
868
- };
869
1341
  export default (w: Window) => {
1342
+ const tagName = 'my-component';
870
1343
  const existing = w.customElements.get(tagName);
871
- if (existing) return existing;
1344
+ if (existing) return tagName;
872
1345
 
873
1346
  @elementDefine(tagName, { window: w })
874
- class MyComponentImp extends w.HTMLElement implements MyComponent{
875
- value: string = 'value';
1347
+ class MyComponent extends w.HTMLElement {
876
1348
  @onInitialize
877
- onconstructor(service: MyService) {
1349
+ onconstructor(@inject(MyService.SYMBOL) service: MyService) {
878
1350
  this.service = service;
879
1351
  }
880
1352
  }
881
- return w.customElements.whenDefined(swcAppTagName);
1353
+
1354
+ return tagName;
1355
+ };
1356
+
1357
+ // Boot factory
1358
+ export default (w: Window, container: symbol) => {
1359
+ serviceFactories.forEach(s => s(container));
882
1360
  };
883
1361
 
1362
+ // Entry point
1363
+ const container = Symbol('app');
1364
+ await defineSwcAppBody(w);
1365
+ const appElement = w.document.querySelector('#app') as SwcAppInterface;
1366
+ appElement.connect({
1367
+ container,
1368
+ window: w,
1369
+ onStartedLazyDefineComponent: [...pageFactories, ...componentFactories],
1370
+ onEngineStarted: () => {
1371
+ appElement.innerHTML = '<root-router></root-router>';
1372
+ }
1373
+ });
1374
+ ```
1375
+ ---
1376
+
1377
+ ## 🔄 Decorator API - Consolidated Pattern (v1.0.43+)
1378
+
1379
+ ### Simplified Decorator API
1380
+
1381
+ The decorator API uses a consolidated pattern where all decorators support **optional selector parameter** that defaults to `$this` when omitted. This eliminates redundant `*This` functions.
1382
+
1383
+ #### Current Usage Pattern
1384
+ ```typescript
1385
+ // Single function with optional selector
1386
+ @applyClass('selector', 'update')
1387
+ method() { ... }
1388
+
1389
+ @applyClass('update') // Selector defaults to $this
1390
+ method() { ... }
1391
+
1392
+ @applyClass // Bare decorator - selector defaults to $this
1393
+ method() { ... }
1394
+ ```
1395
+
1396
+ #### Decorator Functions (Current API)
1397
+
1398
+ **applyClass.ts:**
1399
+ - `applyClass(selector?, options?)` - Set/update/add/remove/toggle classes
1400
+ - `setClass(selector?, options?)` - Replace all classes
1401
+ - `updateClass(selector?, options?)` - Toggle classes
1402
+ - `addClass(selector?, options?)` - Add classes
1403
+ - `removeClass(selector?, options?)` - Remove classes
1404
+ - `toggleClass(selector?, options?)` - Toggle classes
1405
+
1406
+ **applyStyle.ts:**
1407
+ - `applyStyle(selector?, options?)` - Set/update/remove styles
1408
+ - `setStyle(selector?, options?)` - Clear and set styles
1409
+ - `updateStyle(selector?, options?)` - Update/merge styles
1410
+ - `removeStyle(selector?, options?)` - Remove specific styles
1411
+
1412
+ **applyProperty.ts:**
1413
+ - `property(selector?, options?)` - Get/set element properties
1414
+ - `setProperty(selector?, options?)` - Set element properties
1415
+
1416
+ **applyAttribute.ts:**
1417
+ - `attribute(selector?, options?)` - Get/set element attributes
1418
+ - `setAttribute(selector?, options?)` - Set element attributes
1419
+
1420
+ **query.ts:**
1421
+ - `query(selector?, options?)` - Query single element (supports $this, $host, $appHost, etc.)
1422
+
1423
+ **queryAll.ts:**
1424
+ - `queryAll(selector?, options?)` - Query multiple elements
1425
+
1426
+ **emitCustomEvent.ts:**
1427
+ - `emitCustomEvent(target, type, options?)` - Emit custom events
1428
+ - `emit(target, type, options?)` - Short alias
1429
+
1430
+ #### Usage Examples
1431
+
1432
+ ```typescript
1433
+ @elementDefine('my-component')
1434
+ class MyComponent extends HTMLElement {
1435
+ // Class management - all default to $this
1436
+ @updateClass()
1437
+ toggleActive() {
1438
+ return { 'active': this.isActive };
1439
+ }
1440
+
1441
+ // Style management - all default to $this
1442
+ @updateStyle()
1443
+ applyTheme() {
1444
+ return { color: this.theme.color, fontSize: '16px' };
1445
+ }
1446
+
1447
+ // Property binding - all default to $this
1448
+ @setProperty()
1449
+ updateValue() {
1450
+ return this.computedValue;
1451
+ }
1452
+
1453
+ // Attribute binding - all default to $this
1454
+ @setAttribute()
1455
+ updateId() {
1456
+ return this.elementId;
1457
+ }
1458
+
1459
+ // Query elements
1460
+ @query('#input')
1461
+ inputElement?: HTMLInputElement;
1462
+
1463
+ @queryAll('li')
1464
+ listItems?: HTMLLIElement[];
1465
+
1466
+ // Emit custom events
1467
+ @addEventListener('button', 'click')
1468
+ @emitCustomEvent('$this', 'item-selected')
1469
+ onItemSelect() {
1470
+ return { itemId: this.selectedId };
1471
+ }
1472
+
1473
+ // With selector
1474
+ @updateClass('.card', 'update')
1475
+ updateCardClass() {
1476
+ return { 'highlighted': true };
1477
+ }
1478
+ }
884
1479
  ```
1480
+
1481
+ #### Key Features
1482
+
1483
+ 1. **Reduced API Surface** - Consolidated decorators eliminate redundant `*This` functions
1484
+ 2. **Cleaner Code** - Single function name with multiple overloads
1485
+ 3. **Better Discoverability** - Intuitive parameter patterns
1486
+ 4. **Flexible Usage** - Supports bare decorators, with options, and with selectors
1487
+ 5. **Type Safe** - Full TypeScript support with proper type inference
1488
+
885
1489
  ---
886
1490
 
887
1491
  ## ⚠️ Critical Rules