@dooboostore/simple-web-component 1.0.42 → 1.0.43

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 (69) hide show
  1. package/README.md +423 -68
  2. package/dist/cjs/decorators/addEventListener.js +10 -0
  3. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  4. package/dist/cjs/decorators/applyAttribute.js +11 -2
  5. package/dist/cjs/decorators/applyAttribute.js.map +2 -2
  6. package/dist/cjs/decorators/applyClass.js +9 -2
  7. package/dist/cjs/decorators/applyClass.js.map +2 -2
  8. package/dist/cjs/decorators/applyNode.js +11 -2
  9. package/dist/cjs/decorators/applyNode.js.map +2 -2
  10. package/dist/cjs/decorators/applyProperty.js +10 -2
  11. package/dist/cjs/decorators/applyProperty.js.map +2 -2
  12. package/dist/cjs/decorators/applySlot.js +11 -2
  13. package/dist/cjs/decorators/applySlot.js.map +2 -2
  14. package/dist/cjs/decorators/applyStyle.js +9 -2
  15. package/dist/cjs/decorators/applyStyle.js.map +2 -2
  16. package/dist/cjs/decorators/emitCustomEvent.js +2 -0
  17. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  18. package/dist/cjs/decorators/publishSwcAppMessage.js +37 -23
  19. package/dist/cjs/decorators/publishSwcAppMessage.js.map +2 -2
  20. package/dist/esm/decorators/addEventListener.js +10 -0
  21. package/dist/esm/decorators/addEventListener.js.map +2 -2
  22. package/dist/esm/decorators/applyAttribute.js +11 -2
  23. package/dist/esm/decorators/applyAttribute.js.map +2 -2
  24. package/dist/esm/decorators/applyClass.js +9 -2
  25. package/dist/esm/decorators/applyClass.js.map +2 -2
  26. package/dist/esm/decorators/applyNode.js +11 -2
  27. package/dist/esm/decorators/applyNode.js.map +2 -2
  28. package/dist/esm/decorators/applyProperty.js +10 -2
  29. package/dist/esm/decorators/applyProperty.js.map +2 -2
  30. package/dist/esm/decorators/applySlot.js +11 -2
  31. package/dist/esm/decorators/applySlot.js.map +2 -2
  32. package/dist/esm/decorators/applyStyle.js +9 -2
  33. package/dist/esm/decorators/applyStyle.js.map +2 -2
  34. package/dist/esm/decorators/emitCustomEvent.js +2 -0
  35. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  36. package/dist/esm/decorators/publishSwcAppMessage.js +37 -23
  37. package/dist/esm/decorators/publishSwcAppMessage.js.map +2 -2
  38. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +146 -71
  39. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +3 -3
  40. package/dist/types/decorators/addEventListener.d.ts +5 -0
  41. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  42. package/dist/types/decorators/applyAttribute.d.ts +26 -0
  43. package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
  44. package/dist/types/decorators/applyClass.d.ts +6 -0
  45. package/dist/types/decorators/applyClass.d.ts.map +1 -1
  46. package/dist/types/decorators/applyNode.d.ts +6 -0
  47. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  48. package/dist/types/decorators/applyProperty.d.ts +26 -0
  49. package/dist/types/decorators/applyProperty.d.ts.map +1 -1
  50. package/dist/types/decorators/applySlot.d.ts +6 -0
  51. package/dist/types/decorators/applySlot.d.ts.map +1 -1
  52. package/dist/types/decorators/applyStyle.d.ts +6 -0
  53. package/dist/types/decorators/applyStyle.d.ts.map +1 -1
  54. package/dist/types/decorators/emitCustomEvent.d.ts +17 -0
  55. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  56. package/dist/types/decorators/publishSwcAppMessage.d.ts +19 -0
  57. package/dist/types/decorators/publishSwcAppMessage.d.ts.map +1 -1
  58. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +146 -71
  59. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +3 -3
  60. package/package.json +7 -9
  61. package/src/decorators/addEventListener.ts +7 -0
  62. package/src/decorators/applyAttribute.ts +58 -2
  63. package/src/decorators/applyClass.ts +24 -2
  64. package/src/decorators/applyNode.ts +26 -2
  65. package/src/decorators/applyProperty.ts +57 -2
  66. package/src/decorators/applySlot.ts +24 -10
  67. package/src/decorators/applyStyle.ts +24 -2
  68. package/src/decorators/emitCustomEvent.ts +19 -0
  69. package/src/decorators/publishSwcAppMessage.ts +71 -27
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')
@@ -421,28 +478,204 @@ onconstructor() {
421
478
  }
422
479
  ```
423
480
 
424
- ### 7. **Lifecycle Hooks**
481
+ ### 7. **DOM Manipulation with @applyNode**
482
+
483
+ Surgically add, replace, or remove nodes in the DOM with fine-grained control.
425
484
 
426
485
  ```typescript
427
- @onConnected
428
- onConnected() {
429
- // Called when element enters DOM
486
+ @elementDefine('content-updater')
487
+ class ContentUpdater extends HTMLElement {
488
+ @addEventListener('button', 'click')
489
+ @replaceChildrenLightNodeThis
490
+ updateContent() {
491
+ return `<div>New content</div>`;
492
+ }
493
+
494
+ @addEventListener('.append-btn', 'click')
495
+ @beforeEndLightNodeThis
496
+ appendContent() {
497
+ return `<p>Appended content</p>`;
498
+ }
499
+
500
+ @addEventListener('.prepend-btn', 'click')
501
+ @afterBeginLightNodeThis
502
+ prependContent() {
503
+ return `<p>Prepended content</p>`;
504
+ }
505
+
506
+ @onConnectedLight
507
+ render() {
508
+ return `
509
+ <div>
510
+ <button class="append-btn">Append</button>
511
+ <button class="prepend-btn">Prepend</button>
512
+ <button>Replace</button>
513
+ </div>
514
+ `;
515
+ }
430
516
  }
517
+ ```
518
+
519
+ **@applyNode Decorator Variants:**
520
+ - `replaceChildrenNodeThis()` - Replace all children
521
+ - `replaceChildrenLightNodeThis()` - Replace children in light DOM
522
+ - `beforeEndNodeThis()` - Append to end
523
+ - `beforeEndLightNodeThis()` - Append to light DOM end
524
+ - `afterBeginNodeThis()` - Prepend to beginning
525
+ - `afterBeginLightNodeThis()` - Prepend to light DOM beginning
526
+ - `innerHtmlNodeThis()` - Set innerHTML
527
+ - `innerHtmlLightNodeThis()` - Set innerHTML in light DOM
528
+ - `innerTextNodeThis()` - Set innerText
529
+
530
+ **Position Options:**
531
+ ```typescript
532
+ export type ApplyNodePosition =
533
+ | 'beforeBegin' // Before element
534
+ | 'afterBegin' // After element opens
535
+ | 'beforeEnd' // Before element closes
536
+ | 'afterEnd' // After element closes
537
+ | 'replace' // Replace element
538
+ | 'replaceChildren' // Replace children
539
+ | 'innerHtml' // Set innerHTML
540
+ | 'innerText' // Set innerText
541
+ | 'remove'; // Remove element
542
+ ```
543
+
544
+ ### 7.5 **Style & Class Management**
545
+
546
+ Apply styles and classes dynamically with `@applyStyle` and `@applyClass`.
547
+
548
+ ```typescript
549
+ @elementDefine('styled-component')
550
+ class StyledComponent extends HTMLElement {
551
+ @state('isActive')
552
+ isActive = false;
553
+
554
+ @addEventListener('button', 'click')
555
+ @updateStyleThis
556
+ toggleStyle() {
557
+ return {
558
+ color: this.isActive ? 'green' : 'red',
559
+ fontSize: '16px'
560
+ };
561
+ }
431
562
 
432
- @onDisconnected
433
- onDisconnected() {
434
- // Called when element leaves DOM
563
+ @addEventListener('.toggle-btn', 'click')
564
+ @updateClassThis
565
+ toggleClass() {
566
+ return {
567
+ 'active': this.isActive,
568
+ 'disabled': !this.isActive
569
+ };
570
+ }
571
+
572
+ @onConnectedLight
573
+ render() {
574
+ return `
575
+ <div>
576
+ <button class="toggle-btn">Toggle</button>
577
+ <button>Update Style</button>
578
+ </div>
579
+ `;
580
+ }
435
581
  }
582
+ ```
583
+
584
+ **@applyStyle Variants:**
585
+ - `setStyleThis()` - Clear and set styles
586
+ - `updateStyleThis()` - Update/merge styles
587
+ - `removeStyleThis()` - Remove specific styles
588
+
589
+ **@applyClass Variants:**
590
+ - `setClassThis()` - Replace all classes
591
+ - `updateClassThis()` - Toggle classes
592
+ - `addClassThis()` - Add classes
593
+ - `removeClassThis()` - Remove classes
594
+ - `toggleClassThis()` - Toggle classes
595
+
596
+ ### 7.6 **Lifecycle Hooks**
597
+
598
+ 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.
599
+
600
+ ```typescript
601
+ @elementDefine('my-component')
602
+ class MyComponent extends HTMLElement {
603
+ @onInitialize({ order: 0 })
604
+ onInit() {
605
+ // Called during component construction
606
+ console.log('Component initialized');
607
+ }
436
608
 
609
+ @onConnectedBefore({ order: 0 })
610
+ beforeConnected() {
611
+ // Called before element connects to DOM
612
+ }
613
+
614
+ @onConnectedAfter({ order: 1 })
615
+ afterConnected() {
616
+ // Called after element connects to DOM
617
+ }
618
+
619
+ @onConnected
620
+ onConnected() {
621
+ // Called when element enters DOM
622
+ }
623
+
624
+ @onDisconnectedBefore
625
+ beforeDisconnected() {
626
+ // Called before element disconnects from DOM
627
+ }
628
+
629
+ @onDisconnected
630
+ onDisconnected() {
631
+ // Called when element leaves DOM
632
+ }
633
+
634
+ @onAdoptedBefore
635
+ beforeAdopted() {
636
+ // Called before element is adopted into new document
637
+ }
638
+
639
+ @onAdopted
640
+ onAdopted() {
641
+ // Called when element is adopted into new document
642
+ }
643
+
644
+ @onConnectedSwcApp({ order: 0 })
645
+ onSwcAppConnected() {
646
+ // Called after SwcApp.connect() completes
647
+ // Full DI support available through hostSet
648
+ }
437
649
 
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!');
650
+ @onConnectedCompleted({ order: 0 })
651
+ onConnectedCompleted() {
652
+ // Called after all connected lifecycle hooks complete
653
+ }
443
654
  }
444
655
  ```
445
656
 
657
+ **Lifecycle Execution Order:**
658
+ - `@onInitialize` - Component construction
659
+ - `@onConnectedBefore` - Before DOM connection
660
+ - `@onConnectedAfter` - After DOM connection
661
+ - `@onConnected` - DOM connection (with HTML rendering)
662
+ - `@onConnectedSwcApp` - After SwcApp initialization
663
+ - `@onConnectedCompleted` - All connected hooks done
664
+ - `@onDisconnectedBefore` - Before DOM disconnection
665
+ - `@onDisconnected` - DOM disconnection
666
+ - `@onAdoptedBefore` - Before document adoption
667
+ - `@onAdopted` - Document adoption
668
+
669
+ **Order Parameter:**
670
+ All lifecycle decorators support `order?: number` for controlling execution sequence:
671
+ ```typescript
672
+ @onConnectedBefore({ order: 0 }) // Runs first
673
+ onFirst() { }
674
+
675
+ @onConnectedBefore({ order: 1 }) // Runs second
676
+ onSecond() { }
677
+ ```
678
+
446
679
  ### 8. **Structural Directives**
447
680
 
448
681
  Structural Directives allow declarative conditional rendering, list iteration, async handling, and routing with automatic attribute substitution and dynamic expressions.
@@ -528,6 +761,28 @@ class LoginForm extends HTMLElement {
528
761
  }
529
762
  ```
530
763
 
764
+ **@publishSwcAppMessage Decorator Variants:**
765
+ - `publishSwcAppMessage()` - Publish without message type
766
+ - `publishSwcAppMessage(messageType)` - Publish with specific message type
767
+ - `publishSwcAppMessage(messageType, { valueKey: 'customKey' })` - Publish with custom value extraction
768
+ - `publishSwcAppMessage({ messageType: 'type', valueKey: 'customKey' })` - Publish with options object
769
+ - `publish()` - Short alias
770
+ - `publish(messageType)` - Short alias with message type
771
+ - `publish(messageType, options)` - Short alias with options
772
+
773
+ **Using valueKey for Multiple Decorators:**
774
+
775
+ ```typescript
776
+ @publishSwcAppMessage('event1', { valueKey: 'detail1' })
777
+ @publishSwcAppMessage('event2', { valueKey: 'detail2' })
778
+ handleMultipleEvents() {
779
+ return {
780
+ detail1: { type: 'event1', data: 'value1' },
781
+ detail2: { type: 'event2', data: 'value2' }
782
+ };
783
+ }
784
+ ```
785
+
531
786
  **SwcAppMessage Structure:**
532
787
  ```typescript
533
788
  type SwcAppMessage<T = any> = {
@@ -647,17 +902,15 @@ w.document.addEventListener('DOMContentLoaded', async () => {
647
902
 
648
903
  ```typescript
649
904
  // Component factory
650
- import {defineSwcApp} from "./SwcApp";
651
-
652
905
  export default (w: Window) => {
653
906
  const tagName = 'my-component';
654
907
  const existing = w.customElements.get(tagName);
655
908
  if (existing) return tagName;
656
909
 
657
- @elementDefine(tagName, {window: w})
910
+ @elementDefine(tagName, { window: w })
658
911
  class MyComponent extends w.HTMLElement {
659
912
  @onInitialize
660
- onconstructor(service: MyService) {
913
+ onconstructor(@inject(MyService.SYMBOL) service: MyService) {
661
914
  this.service = service;
662
915
  }
663
916
  }
@@ -672,7 +925,7 @@ export default (w: Window, container: symbol) => {
672
925
 
673
926
  // Entry point
674
927
  const container = Symbol('app');
675
- await defineSwcAppBody(w)
928
+ await defineSwcAppBody(w);
676
929
  const appElement = w.document.querySelector('#app') as SwcAppInterface;
677
930
  appElement.connect({
678
931
  container,
@@ -684,7 +937,7 @@ appElement.connect({
684
937
  });
685
938
  ```
686
939
 
687
- ### 11. **Routing with @subscribeSwcAppRouteChangeWhileConnected**
940
+ #### 11. **Routing with @subscribeSwcAppRouteChangeWhileConnected**
688
941
 
689
942
  SWC provides declarative routing with automatic path matching, order-based execution, and optional propagation control.
690
943
 
@@ -723,10 +976,11 @@ class RootRouter extends HTMLElement {
723
976
  #### Route Handler Features
724
977
 
725
978
  **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)
979
+ - **No path pattern** (omit path): `@subscribeSwcAppRouteChangeWhileConnected({ order: -1 })` - matches all routes
980
+ - **Exact match**: `['', '/']` - matches home route only
981
+ - **Prefix match**: `['/products']` - matches `/products` and `/products/...`
982
+ - **Dynamic segments**: `['/product/{id}']` - captures `id` parameter
983
+ - **Wildcard**: `['/{tail:.*}']` - matches any remaining path (use for 404)
730
984
 
731
985
  **2. Order-Based Execution**
732
986
  Routes are executed in order of `order` value (lowest first). First matching route with a return value stops propagation:
@@ -750,7 +1004,7 @@ handleAdmin(routerPathSet: RouterEventType) {
750
1004
  }
751
1005
 
752
1006
  // This handler continues propagation (no return value)
753
- @subscribeSwcAppRouteChangeWhileConnected(['{other:.*}'], { order: -1 })
1007
+ @subscribeSwcAppRouteChangeWhileConnected({ order: -1 })
754
1008
  onRouteChange(routerPathSet: RouterEventType) {
755
1009
  console.log('Route changed:', routerPathSet.path);
756
1010
  // No return value → continues to next handler
@@ -762,8 +1016,8 @@ onRouteChange(routerPathSet: RouterEventType) {
762
1016
  ```typescript
763
1017
  @elementDefine('accommodation-router')
764
1018
  class AccommodationRouter extends HTMLElement {
765
- // Global route logger (order: -1 runs first, no return value)
766
- @subscribeSwcAppRouteChangeWhileConnected(['*'], { order: -1 })
1019
+ // Global route logger (order: -1 runs first, no path pattern = matches all routes)
1020
+ @subscribeSwcAppRouteChangeWhileConnected({ order: -1 })
767
1021
  onRouteChange(routerPathSet: RouterEventType) {
768
1022
  console.log('[Route Change]', {
769
1023
  path: routerPathSet.path,
@@ -851,6 +1105,97 @@ URL: /product/123
851
1105
  pathData: { id: '123' }
852
1106
  ```
853
1107
 
1108
+ #### Multiple Decorators with Shared Return Value
1109
+
1110
+ 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.
1111
+
1112
+ **How It Works:**
1113
+ 1. Each decorator has a default symbol key (e.g., `ATTRIBUTE_METADATA_KEY`, `PROPERTY_METADATA_KEY`)
1114
+ 2. When a method returns an object, each decorator checks if its key exists in the object
1115
+ 3. If the key exists, the decorator uses that value; otherwise uses the entire return value
1116
+ 4. This allows multiple decorators to extract different values from the same return object
1117
+
1118
+ **Method 1: Using Default Symbol Keys**
1119
+
1120
+ ```typescript
1121
+ import {
1122
+ ATTRIBUTE_METADATA_KEY,
1123
+ PROPERTY_METADATA_KEY,
1124
+ STYLE_METADATA_KEY,
1125
+ CLASS_METADATA_KEY
1126
+ } from '@dooboostore/simple-web-component';
1127
+
1128
+ @elementDefine('multi-decorator-example')
1129
+ class MultiDecoratorExample extends HTMLElement {
1130
+ @setAttribute('selector')
1131
+ @setProperty('selector')
1132
+ @updateStyleThis
1133
+ @updateClassThis
1134
+ handleUpdate() {
1135
+ return {
1136
+ [ATTRIBUTE_METADATA_KEY]: 'attribute-value',
1137
+ [PROPERTY_METADATA_KEY]: 'property-value',
1138
+ [STYLE_METADATA_KEY]: { color: 'red', fontSize: '16px' },
1139
+ [CLASS_METADATA_KEY]: { 'active': true, 'disabled': false }
1140
+ };
1141
+ }
1142
+ }
1143
+ ```
1144
+
1145
+ **Method 2: Using Custom valueKey Option**
1146
+
1147
+ For more readable code, use the `valueKey` option to specify custom keys:
1148
+
1149
+ ```typescript
1150
+ @elementDefine('custom-key-example')
1151
+ class CustomKeyExample extends HTMLElement {
1152
+ @setAttribute('selector', { valueKey: 'attrValue' })
1153
+ @setProperty('selector', { valueKey: 'propValue' })
1154
+ @updateStyleThis({ valueKey: 'styleValue' })
1155
+ @updateClassThis({ valueKey: 'classValue' })
1156
+ handleUpdate() {
1157
+ return {
1158
+ attrValue: 'attribute-value',
1159
+ propValue: 'property-value',
1160
+ styleValue: { color: 'red', fontSize: '16px' },
1161
+ classValue: { 'active': true, 'disabled': false }
1162
+ };
1163
+ }
1164
+ }
1165
+ ```
1166
+
1167
+ **Method 3: Mixing Symbol Keys and Custom Keys**
1168
+
1169
+ You can mix both approaches in the same method:
1170
+
1171
+ ```typescript
1172
+ @elementDefine('mixed-keys-example')
1173
+ class MixedKeysExample extends HTMLElement {
1174
+ @setAttribute('selector') // Uses default ATTRIBUTE_METADATA_KEY
1175
+ @setProperty('selector', { valueKey: 'customProp' }) // Uses custom key
1176
+ @updateStyleThis({ valueKey: 'styles' }) // Uses custom key
1177
+ handleUpdate() {
1178
+ return {
1179
+ [ATTRIBUTE_METADATA_KEY]: 'attr-value',
1180
+ customProp: 'prop-value',
1181
+ styles: { color: 'blue' }
1182
+ };
1183
+ }
1184
+ }
1185
+ ```
1186
+
1187
+ **Supported Decorators with valueKey:**
1188
+ - `@applyAttribute` / `@setAttribute` / `@setAttributeThis`
1189
+ - `@applyProperty` / `@setProperty` / `@setPropertyThis`
1190
+ - `@applySlot` / `@clearSlot` / `@appendHtmlSlot` / etc.
1191
+ - `@applyNode` / `@replaceChildrenNodeThis` / etc.
1192
+ - `@applyStyle` / `@updateStyleThis` / etc.
1193
+ - `@applyClass` / `@updateClassThis` / etc.
1194
+ - `@emitCustomEvent` / `@emit` / `@emitCustomEventThis`
1195
+ - `@publishSwcAppMessage` / `@publish`
1196
+
1197
+ Each decorator will use only its corresponding value from the return object, preventing conflicts and allowing clean separation of concerns.
1198
+
854
1199
  ---
855
1200
 
856
1201
  ### 12. **Accommodation Pattern**
@@ -858,29 +1203,39 @@ Factory-based component registration with explicit DI.
858
1203
 
859
1204
  ```typescript
860
1205
  // 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
1206
  export default (w: Window) => {
1207
+ const tagName = 'my-component';
870
1208
  const existing = w.customElements.get(tagName);
871
- if (existing) return existing;
1209
+ if (existing) return tagName;
872
1210
 
873
1211
  @elementDefine(tagName, { window: w })
874
- class MyComponentImp extends w.HTMLElement implements MyComponent{
875
- value: string = 'value';
1212
+ class MyComponent extends w.HTMLElement {
876
1213
  @onInitialize
877
- onconstructor(service: MyService) {
1214
+ onconstructor(@inject(MyService.SYMBOL) service: MyService) {
878
1215
  this.service = service;
879
1216
  }
880
1217
  }
881
- return w.customElements.whenDefined(swcAppTagName);
1218
+
1219
+ return tagName;
1220
+ };
1221
+
1222
+ // Boot factory
1223
+ export default (w: Window, container: symbol) => {
1224
+ serviceFactories.forEach(s => s(container));
882
1225
  };
883
1226
 
1227
+ // Entry point
1228
+ const container = Symbol('app');
1229
+ await defineSwcAppBody(w);
1230
+ const appElement = w.document.querySelector('#app') as SwcAppInterface;
1231
+ appElement.connect({
1232
+ container,
1233
+ window: w,
1234
+ onStartedLazyDefineComponent: [...pageFactories, ...componentFactories],
1235
+ onEngineStarted: () => {
1236
+ appElement.innerHTML = '<root-router></root-router>';
1237
+ }
1238
+ });
884
1239
  ```
885
1240
  ---
886
1241
 
@@ -27,6 +27,11 @@ __export(addEventListener_exports, {
27
27
  addEventListenerDocument: () => addEventListenerDocument,
28
28
  addEventListenerThis: () => addEventListenerThis,
29
29
  addEventListenerWindow: () => addEventListenerWindow,
30
+ event: () => event,
31
+ eventDelegate: () => eventDelegate,
32
+ eventDelegateAllDom: () => eventDelegateAllDom,
33
+ eventDelegateLightDom: () => eventDelegateLightDom,
34
+ eventDelegateShadowDom: () => eventDelegateShadowDom,
30
35
  getAddEventListenerMetadata: () => getAddEventListenerMetadata
31
36
  });
32
37
  module.exports = __toCommonJS(addEventListener_exports);
@@ -55,6 +60,11 @@ function addEventListenerDelegateAllDom(selector, type, options) {
55
60
  function addEventListenerDelegate(selector, type, options) {
56
61
  return addEventListener(selector, type, { ...options ?? {}, root: "auto", delegate: true });
57
62
  }
63
+ const event = addEventListener;
64
+ const eventDelegateLightDom = addEventListenerDelegateLightDom;
65
+ const eventDelegateShadowDom = addEventListenerDelegateShadowDom;
66
+ const eventDelegateAllDom = addEventListenerDelegateAllDom;
67
+ const eventDelegate = addEventListenerDelegate;
58
68
  function addEventListenerThis(type, options) {
59
69
  return addEventListener("$this", type, options);
60
70
  }