@dooboostore/simple-web-component 1.0.16 → 1.0.18

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 (130) hide show
  1. package/README.md +109 -48
  2. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  3. package/dist/cjs/decorators/appendChild.js +48 -0
  4. package/dist/cjs/decorators/appendChild.js.map +7 -0
  5. package/dist/cjs/decorators/elementDefine.js +216 -67
  6. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  7. package/dist/cjs/decorators/index.js +2 -1
  8. package/dist/cjs/decorators/index.js.map +2 -2
  9. package/dist/cjs/decorators/{innerHtml.js → onConnectedInnerHtml.js} +8 -8
  10. package/dist/cjs/decorators/onConnectedInnerHtml.js.map +7 -0
  11. package/dist/cjs/decorators/query.js +38 -0
  12. package/dist/cjs/decorators/query.js.map +2 -2
  13. package/dist/cjs/decorators/queryAll.js +32 -0
  14. package/dist/cjs/decorators/queryAll.js.map +2 -2
  15. package/dist/cjs/decorators/replaceChildren.js +53 -0
  16. package/dist/cjs/decorators/replaceChildren.js.map +7 -0
  17. package/dist/cjs/elements/SwcAppEngine.js +2 -1
  18. package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
  19. package/dist/cjs/elements/SwcAsync.js +188 -0
  20. package/dist/cjs/elements/SwcAsync.js.map +7 -0
  21. package/dist/cjs/elements/SwcChoose.js +155 -0
  22. package/dist/cjs/elements/SwcChoose.js.map +7 -0
  23. package/dist/cjs/elements/SwcIf.js +167 -0
  24. package/dist/cjs/elements/SwcIf.js.map +7 -0
  25. package/dist/cjs/elements/SwcLoop.js +246 -0
  26. package/dist/cjs/elements/SwcLoop.js.map +7 -0
  27. package/dist/cjs/elements/SwcSubTemplates.js +65 -0
  28. package/dist/cjs/elements/SwcSubTemplates.js.map +7 -0
  29. package/dist/cjs/elements/index.js +7 -0
  30. package/dist/cjs/elements/index.js.map +2 -2
  31. package/dist/cjs/index.js +12 -2
  32. package/dist/cjs/index.js.map +2 -2
  33. package/dist/cjs/types.js.map +1 -1
  34. package/dist/cjs/utils/Utils.js +74 -37
  35. package/dist/cjs/utils/Utils.js.map +3 -3
  36. package/dist/esm/decorators/addEventListener.js.map +2 -2
  37. package/dist/esm/decorators/appendChild.js +29 -0
  38. package/dist/esm/decorators/appendChild.js.map +7 -0
  39. package/dist/esm/decorators/elementDefine.js +216 -67
  40. package/dist/esm/decorators/elementDefine.js.map +3 -3
  41. package/dist/esm/decorators/index.js +2 -1
  42. package/dist/esm/decorators/index.js.map +2 -2
  43. package/dist/esm/decorators/{innerHtml.js → onConnectedInnerHtml.js} +5 -5
  44. package/dist/esm/decorators/onConnectedInnerHtml.js.map +7 -0
  45. package/dist/esm/decorators/query.js +38 -0
  46. package/dist/esm/decorators/query.js.map +2 -2
  47. package/dist/esm/decorators/queryAll.js +32 -0
  48. package/dist/esm/decorators/queryAll.js.map +2 -2
  49. package/dist/esm/decorators/replaceChildren.js +34 -0
  50. package/dist/esm/decorators/replaceChildren.js.map +7 -0
  51. package/dist/esm/elements/SwcAppEngine.js +2 -1
  52. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  53. package/dist/esm/elements/SwcAsync.js +169 -0
  54. package/dist/esm/elements/SwcAsync.js.map +7 -0
  55. package/dist/esm/elements/SwcChoose.js +136 -0
  56. package/dist/esm/elements/SwcChoose.js.map +7 -0
  57. package/dist/esm/elements/SwcIf.js +148 -0
  58. package/dist/esm/elements/SwcIf.js.map +7 -0
  59. package/dist/esm/elements/SwcLoop.js +227 -0
  60. package/dist/esm/elements/SwcLoop.js.map +7 -0
  61. package/dist/esm/elements/SwcSubTemplates.js +46 -0
  62. package/dist/esm/elements/SwcSubTemplates.js.map +7 -0
  63. package/dist/esm/elements/index.js +7 -0
  64. package/dist/esm/elements/index.js.map +2 -2
  65. package/dist/esm/index.js +8 -2
  66. package/dist/esm/index.js.map +2 -2
  67. package/dist/esm/types.js.map +1 -1
  68. package/dist/esm/utils/Utils.js +74 -37
  69. package/dist/esm/utils/Utils.js.map +3 -3
  70. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +1226 -149
  71. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  72. package/dist/types/decorators/addEventListener.d.ts +1 -0
  73. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  74. package/dist/types/decorators/appendChild.d.ts +17 -0
  75. package/dist/types/decorators/appendChild.d.ts.map +1 -0
  76. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  77. package/dist/types/decorators/index.d.ts +2 -1
  78. package/dist/types/decorators/index.d.ts.map +1 -1
  79. package/dist/types/decorators/onConnectedInnerHtml.d.ts +15 -0
  80. package/dist/types/decorators/onConnectedInnerHtml.d.ts.map +1 -0
  81. package/dist/types/decorators/query.d.ts +0 -2
  82. package/dist/types/decorators/query.d.ts.map +1 -1
  83. package/dist/types/decorators/queryAll.d.ts +0 -2
  84. package/dist/types/decorators/queryAll.d.ts.map +1 -1
  85. package/dist/types/decorators/replaceChildren.d.ts +9 -0
  86. package/dist/types/decorators/replaceChildren.d.ts.map +1 -0
  87. package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
  88. package/dist/types/elements/SwcAsync.d.ts +16 -0
  89. package/dist/types/elements/SwcAsync.d.ts.map +1 -0
  90. package/dist/types/elements/SwcChoose.d.ts +13 -0
  91. package/dist/types/elements/SwcChoose.d.ts.map +1 -0
  92. package/dist/types/elements/SwcIf.d.ts +15 -0
  93. package/dist/types/elements/SwcIf.d.ts.map +1 -0
  94. package/dist/types/elements/SwcLoop.d.ts +20 -0
  95. package/dist/types/elements/SwcLoop.d.ts.map +1 -0
  96. package/dist/types/elements/SwcSubTemplates.d.ts +13 -0
  97. package/dist/types/elements/SwcSubTemplates.d.ts.map +1 -0
  98. package/dist/types/elements/index.d.ts +7 -0
  99. package/dist/types/elements/index.d.ts.map +1 -1
  100. package/dist/types/index.d.ts +5 -2
  101. package/dist/types/index.d.ts.map +1 -1
  102. package/dist/types/types.d.ts +8 -0
  103. package/dist/types/types.d.ts.map +1 -1
  104. package/dist/types/utils/Utils.d.ts +16 -10
  105. package/dist/types/utils/Utils.d.ts.map +1 -1
  106. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +1226 -149
  107. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  108. package/package.json +10 -3
  109. package/src/decorators/addEventListener.ts +1 -0
  110. package/src/decorators/appendChild.ts +42 -0
  111. package/src/decorators/elementDefine.ts +225 -71
  112. package/src/decorators/index.ts +2 -1
  113. package/src/decorators/{innerHtml.ts → onConnectedInnerHtml.ts} +7 -6
  114. package/src/decorators/query.ts +32 -2
  115. package/src/decorators/queryAll.ts +32 -2
  116. package/src/decorators/replaceChildren.ts +35 -0
  117. package/src/elements/SwcAppEngine.ts +2 -1
  118. package/src/elements/SwcAsync.ts +163 -0
  119. package/src/elements/SwcChoose.ts +127 -0
  120. package/src/elements/SwcIf.ts +134 -0
  121. package/src/elements/SwcLoop.ts +215 -0
  122. package/src/elements/SwcSubTemplates.ts +19 -0
  123. package/src/elements/index.ts +8 -3
  124. package/src/index.ts +5 -2
  125. package/src/types.ts +9 -1
  126. package/src/utils/Utils.ts +86 -36
  127. package/dist/cjs/decorators/innerHtml.js.map +0 -7
  128. package/dist/esm/decorators/innerHtml.js.map +0 -7
  129. package/dist/types/decorators/innerHtml.d.ts +0 -12
  130. package/dist/types/decorators/innerHtml.d.ts.map +0 -1
package/README.md CHANGED
@@ -42,13 +42,13 @@ Registers the class as a custom element.
42
42
  | `observedAttributes` | `string[]` | (Optional) Extra attributes to observe. |
43
43
  | `window` | `Window` | (Optional) Custom window object (useful for SSR). |
44
44
 
45
- ### 2. `@innerHtml(options?)`
46
- Defines the template for the component.
45
+ ### 2. `@onConnectedInnerHtml(options?)`
46
+ Defines the template for the component. Executed when the component is connected to the DOM.
47
47
 
48
48
  ```typescript
49
49
  @elementDefine('my-el')
50
50
  class MyEl extends HTMLElement {
51
- @innerHtml({ useShadow: true })
51
+ @onConnectedInnerHtml({ useShadow: true })
52
52
  render() {
53
53
  return `<style>:host { color: blue; }</style><div>Hello World</div>`;
54
54
  }
@@ -80,7 +80,7 @@ class MyCounter extends HTMLElement {
80
80
  ```
81
81
 
82
82
  ### 4. Powerful Queries (`@query`, `@queryAll`)
83
- Inject internal elements directly into properties. Supports the **`:host`** selector.
83
+ Inject internal elements directly into properties. Supports the **`:host`** selector and precise root control. Assigning `null` or `[]` to these properties will surgically remove the target elements from the DOM.
84
84
 
85
85
  | Root Option | Description |
86
86
  |---|---|
@@ -89,24 +89,14 @@ Inject internal elements directly into properties. Supports the **`:host`** sele
89
89
  | `light` | **Strictly** search in Light DOM (`this`). |
90
90
  | `all` | Search in **both** Shadow and Light DOM. |
91
91
 
92
- Inject elements directly into properties. Supports `:host` and scoped root control.
93
-
94
92
  ```typescript
95
- @elementDefine('query-demo')
96
- class QueryDemo extends HTMLElement {
97
- @query('.title') titleEl!: HTMLElement;
98
- @queryAll('.items') list!: NodeListOf<HTMLElement>;
99
-
100
- // Reference the component itself
101
- @query(':host') self!: HTMLElement;
102
-
103
- // Root options: 'light' | 'shadow' | 'all' | 'auto' (default)
104
- @query('.btn', { root: 'shadow' }) shadowBtn!: HTMLButtonElement;
105
- }
93
+ @query('.title') titleEl!: HTMLElement;
94
+ @query('.btn', { root: 'shadow' }) shadowBtn!: HTMLButtonElement;
95
+ @query(':host') self!: HTMLElement; // References the component itself
106
96
  ```
107
97
 
108
98
  ### 5. Smart Event Binding (`@addEventListener`)
109
- Bind events declaratively with support for **Event Delegation**.
99
+ Bind events declaratively with support for **Event Delegation** and special targets like `:window` and `:document`.
110
100
 
111
101
  ```typescript
112
102
  @elementDefine('event-demo')
@@ -115,11 +105,55 @@ class EventDemo extends HTMLElement {
115
105
  @addEventListener('.static-btn', 'click')
116
106
  onStaticClick(event: MouseEvent) { ... }
117
107
 
118
- // 2. Event Delegation (Works for dynamic nodes added LATER)
108
+ // 2. Event Delegation (Handles dynamic nodes)
119
109
  @addEventListener('.item', 'click', { delegate: true })
120
110
  onItemClick(event: MouseEvent, { $host }: HostSet, target: HTMLElement) {
121
111
  console.log('Clicked dynamic item:', target.textContent);
122
112
  }
113
+
114
+ // 3. Global Events with Auto-Cleanup
115
+ @addEventListener(':window', 'resize', { removeOnDisconnected: true })
116
+ onResize() { ... }
117
+ }
118
+ ```
119
+
120
+ ### 6. `@replaceChildren(selector)`
121
+ Surgically replaces the children of a target element with the method's return value (`string`, `Node`, or `Array<Node|string>`).
122
+
123
+ ```typescript
124
+ @elementDefine('surgical-demo')
125
+ class SurgicalDemo extends HTMLElement {
126
+ // Replaces all children of #display-area with the new content
127
+ @replaceChildren('#display-area')
128
+ updateView(title: string) {
129
+ return `<h2>${title}</h2><p>Updated successfully.</p>`;
130
+ }
131
+ }
132
+ ```
133
+
134
+ ### 7. `@appendChild(selector, options?)`
135
+ Appends or inserts the method's return value relative to a target element.
136
+ - **position**: `'lastChild'` (default), `'firstChild'`, `'nextSibling'`, `'previousSibling'`.
137
+
138
+ ```typescript
139
+ @elementDefine('list-manager')
140
+ class ListManager extends HTMLElement {
141
+ // Prepends a new item to the top of the #my-list element
142
+ @appendChild('#my-list', { position: 'firstChild' })
143
+ addNewItem(text: string) {
144
+ return `<li>${text}</li>`;
145
+ }
146
+ }
147
+ ```
148
+
149
+ ```typescript
150
+ @elementDefine('list-manager')
151
+ class ListManager extends HTMLElement {
152
+ // Prepends a new item to the top of the #my-list element
153
+ @appendChild('#my-list', { position: 'firstChild' })
154
+ addNewItem(text: string) {
155
+ return `<li>${text}</li>`;
156
+ }
123
157
  }
124
158
  ```
125
159
 
@@ -130,14 +164,13 @@ class EventDemo extends HTMLElement {
130
164
  SWC provides a revolutionary way to build SPAs where **each component scope is an independent application**.
131
165
 
132
166
  ### 1. Isolated App Scopes (Micro-Frontends)
133
- Use the `<swc-app>` tag to create an isolated universe. Each instance has its own **DI Container** and **Router**. You can run multiple independent SPAs on a single page without URL conflicts.
167
+ Use the `<swc-app>` tag to create an isolated universe. Each instance has its own **DI Container** and **Router**.
134
168
 
135
169
  ```html
136
170
  <!-- index.html -->
137
171
  <swc-app swc-get-application-config="myAppConfig(this)"></swc-app>
138
172
 
139
173
  <script>
140
- // This function returns the configuration needed to bootstrap the SWC App
141
174
  window.myAppConfig = (host) => {
142
175
  return {
143
176
  rootRouter: RootRouter, // The entry point class (must be @Sim)
@@ -147,35 +180,24 @@ Use the `<swc-app>` tag to create an isolated universe. Each instance has its ow
147
180
  };
148
181
  };
149
182
 
150
- // 4. External Control (Anywhere in your JS)
183
+ // External Control
151
184
  function navigateFromOutside() {
152
185
  const app = document.querySelector('swc-app');
153
- // Programmatically trigger routing from outside the component
154
186
  app.routing('/users/detail/2');
155
187
  }
156
188
  </script>
157
-
158
- <button onclick="navigateFromOutside()">External Link to User 2</button>
159
189
  ```
160
190
 
161
191
  ### 2. DI-Powered Routing
162
- Define routes using decorators. Components are automatically instantiated and managed by the DI container.
163
-
164
192
  ```typescript
165
- import { Router } from '@dooboostore/simple-boot/decorators/route/Router';
166
- import { Sim } from '@dooboostore/simple-boot/decorators/SimDecorator';
167
-
168
193
  @Sim
169
194
  @Router({
170
195
  path: '/users',
171
- route: {
172
- '/list': UserList,
173
- '/detail/:id': UserDetail
174
- }
196
+ route: { '/list': UserList, '/detail/:id': UserDetail }
175
197
  })
176
198
  @elementDefine('user-router')
177
199
  class UserRouter extends HTMLElement implements RouterAction.CanActivate {
178
- @innerHtml({ useShadow: true })
200
+ @onConnectedInnerHtml({ useShadow: true })
179
201
  render() {
180
202
  return `<header>User System</header><main><slot></slot></main>`;
181
203
  }
@@ -185,21 +207,17 @@ class UserRouter extends HTMLElement implements RouterAction.CanActivate {
185
207
  }
186
208
  }
187
209
 
188
- // Pure Service (Business Logic)
189
210
  @Sim
190
211
  class UserService {
191
- async getProfile(id: string) {
192
- return { id, name: 'Standard User' };
193
- }
212
+ async getProfile(id: string) { return { id, name: 'Standard User' }; }
194
213
  }
195
214
 
196
- // Example Page Components
197
215
  @Sim
198
216
  @elementDefine('user-list')
199
217
  class UserList extends HTMLElement {
200
218
  constructor(private router: Router, private userService: UserService) { super(); }
201
219
 
202
- @innerHtml
220
+ @onConnectedInnerHtml
203
221
  render() {
204
222
  return `
205
223
  <ul><li>User A</li><li>User B</li></ul>
@@ -220,22 +238,18 @@ class UserDetail extends HTMLElement {
220
238
  console.log('Viewing User:', profile.name);
221
239
  }
222
240
 
223
- @innerHtml
241
+ @onConnectedInnerHtml
224
242
  render() { return `<div>User Detail View <button swc-on-click="$host.router.back()">Back</button></div>`; }
225
243
  }
226
244
  ```
227
245
 
228
246
  ### 3. Lifecycle @Inject
229
- Inject services or component context directly into lifecycle methods. This is the ultimate way to handle side effects cleanly.
230
-
231
247
  ```typescript
232
248
  import { Inject } from '@dooboostore/simple-boot/decorators/inject/Inject';
233
249
  import { InjectSituationType, onConnected, HostSet } from '@dooboostore/simple-web-component';
234
- import { Router } from '@dooboostore/core-web/routers/Router';
235
250
 
236
251
  @elementDefine('profile-page')
237
252
  class ProfilePage extends HTMLElement {
238
-
239
253
  @onConnected
240
254
  async init(
241
255
  @Inject({ situationType: InjectSituationType.HOST_SET }) hostSet: HostSet,
@@ -244,7 +258,6 @@ class ProfilePage extends HTMLElement {
244
258
  ) {
245
259
  console.log('App scope:', hostSet.$appHost);
246
260
  const user = await api.getProfile();
247
- // Navigate programmatically using injected router
248
261
  if (!user) router.go('/login');
249
262
  }
250
263
  }
@@ -271,10 +284,58 @@ Executed in **Parent -> Child** order.
271
284
 
272
285
  ---
273
286
 
287
+ ## 🔄 Structural Directives (Advanced)
288
+
289
+ SWC provides 4 core templates: `swc-loop`, `swc-if`, `swc-choose`, and `swc-async`.
290
+
291
+ ### Common Attributes:
292
+ - **`on-get-value`**: Script to fetch data.
293
+ - **`on-clone-nodes`**: Callback after a group of nodes is cloned.
294
+ - **`on-clone-node`**: Callback for each individual node.
295
+ - **`on-get-portal`**: Script that returns an `Element` or selector for portal rendering.
296
+
297
+ ### 1. `swc-if` (Conditional Rendering)
298
+ ```html
299
+ <template is="swc-if" on-get-value="isAdmin">
300
+ <template is="swc-default"><p>Please login.</p></template>
301
+ <div class="admin-panel">Welcome!</div>
302
+ </template>
303
+ ```
304
+
305
+ ### 2. `swc-loop` (High-Performance Iteration)
306
+ ```html
307
+ <template is="swc-loop" on-get-value="users"
308
+ on-clone-node="if($isElement) $node.querySelector('.name').textContent = $item.name">
309
+ <template is="swc-default"><p>No users found.</p></template>
310
+ <div class="user-row"><span class="name"></span></div>
311
+ </template>
312
+ ```
313
+
314
+ ### 3. `swc-choose` (Switch-Case Logic)
315
+ ```html
316
+ <template is="swc-choose" on-get-value="user.role">
317
+ <template is="swc-default">Select a role.</template>
318
+ <template is="swc-when" value="admin">Admin Dashboard</template>
319
+ <template is="swc-otherwise">Access Denied</template>
320
+ </template>
321
+ ```
322
+
323
+ ### 4. `swc-async` (Declarative Promises)
324
+ ```html
325
+ <template is="swc-async" on-get-value="fetchData()"
326
+ on-clone-node="if($isElement && $node.className === 'content') $node.textContent = $value?.title || $error?.message">
327
+ <template is="swc-loading">🌀 Loading...</template>
328
+ <template is="swc-error"><div class="content"></div></template>
329
+ <template is="swc-success"><div class="content"></div></template>
330
+ </template>
331
+ ```
332
+
333
+ ---
334
+
274
335
  ## ⚡ Performance
275
336
  - **Zero "Deep Scan"**: Listeners are only bound to specific selectors.
276
337
  - **Surgical Updates**: Manipulate DOM directly in `@changedAttribute` instead of full re-renders.
277
- - **Zero Background Overhead**: No polling, no background observers.
338
+ - **Smart Delegation**: Host-level delegation with `__swc_handled` duplicate protection.
278
339
 
279
340
  ---
280
341
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/decorators/addEventListener.ts"],
4
- "sourcesContent": ["import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';\n\nexport interface AddEventListenerOptions extends EventListenerOptions {\n root?: 'light' | 'shadow' | 'all' | 'auto';\n capture?: boolean;\n once?: boolean;\n passive?: boolean;\n stopPropagation?: boolean;\n stopImmediatePropagation?: boolean;\n preventDefault?: boolean;\n delegate?: boolean;\n}\n\nexport interface AddEventListenerMetadata {\n selector: string;\n type: string;\n options: AddEventListenerOptions;\n propertyKey: string | symbol;\n}\n\nexport const ADD_EVENT_LISTENER_METADATA_KEY = Symbol('simple-web-component:add-event-listener');\n\n/**\n * @addEventListener decorator to bind events to elements.\n * Usage: @addEventListener('.btn', 'click') onClick() { ... }\n * Usage: @addEventListener('', 'scroll', { passive: true }) onScroll() { ... }\n */\nexport function addEventListener(selector: string, type: string, options: AddEventListenerOptions = {}): MethodDecorator {\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\n const constructor = target.constructor;\n\n let listeners = ReflectUtils.getMetadata<AddEventListenerMetadata[]>(ADD_EVENT_LISTENER_METADATA_KEY, constructor);\n if (!listeners) {\n listeners = [];\n ReflectUtils.defineMetadata(ADD_EVENT_LISTENER_METADATA_KEY, listeners, constructor);\n }\n listeners.push({ selector, type, options, propertyKey });\n };\n}\n\nexport const getAddEventListenerMetadata = (target: any): AddEventListenerMetadata[] | undefined => {\n const constructor = target instanceof Function ? target : target.constructor;\n return ReflectUtils.getMetadata(ADD_EVENT_LISTENER_METADATA_KEY, constructor);\n};\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAA6B;AAoBtB,MAAM,kCAAkC,OAAO,yCAAyC;AAOxF,SAAS,iBAAiB,UAAkB,MAAc,UAAmC,CAAC,GAAoB;AACvH,SAAO,CAAC,QAAgB,aAA8B,eAAmC;AACvF,UAAM,cAAc,OAAO;AAE3B,QAAI,YAAY,iCAAa,YAAwC,iCAAiC,WAAW;AACjH,QAAI,CAAC,WAAW;AACd,kBAAY,CAAC;AACb,uCAAa,eAAe,iCAAiC,WAAW,WAAW;AAAA,IACrF;AACA,cAAU,KAAK,EAAE,UAAU,MAAM,SAAS,YAAY,CAAC;AAAA,EACzD;AACF;AAEO,MAAM,8BAA8B,CAAC,WAAwD;AAClG,QAAM,cAAc,kBAAkB,WAAW,SAAS,OAAO;AACjE,SAAO,iCAAa,YAAY,iCAAiC,WAAW;AAC9E;",
4
+ "sourcesContent": ["import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';\n\nexport interface AddEventListenerOptions extends EventListenerOptions {\n root?: 'light' | 'shadow' | 'all' | 'auto';\n capture?: boolean;\n once?: boolean;\n passive?: boolean;\n stopPropagation?: boolean;\n stopImmediatePropagation?: boolean;\n preventDefault?: boolean;\n delegate?: boolean;\n removeOnDisconnected?: boolean;\n}\n\nexport interface AddEventListenerMetadata {\n selector: string;\n type: string;\n options: AddEventListenerOptions;\n propertyKey: string | symbol;\n}\n\nexport const ADD_EVENT_LISTENER_METADATA_KEY = Symbol('simple-web-component:add-event-listener');\n\n/**\n * @addEventListener decorator to bind events to elements.\n * Usage: @addEventListener('.btn', 'click') onClick() { ... }\n * Usage: @addEventListener('', 'scroll', { passive: true }) onScroll() { ... }\n */\nexport function addEventListener(selector: string, type: string, options: AddEventListenerOptions = {}): MethodDecorator {\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\n const constructor = target.constructor;\n\n let listeners = ReflectUtils.getMetadata<AddEventListenerMetadata[]>(ADD_EVENT_LISTENER_METADATA_KEY, constructor);\n if (!listeners) {\n listeners = [];\n ReflectUtils.defineMetadata(ADD_EVENT_LISTENER_METADATA_KEY, listeners, constructor);\n }\n listeners.push({ selector, type, options, propertyKey });\n };\n}\n\nexport const getAddEventListenerMetadata = (target: any): AddEventListenerMetadata[] | undefined => {\n const constructor = target instanceof Function ? target : target.constructor;\n return ReflectUtils.getMetadata(ADD_EVENT_LISTENER_METADATA_KEY, constructor);\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAA6B;AAqBtB,MAAM,kCAAkC,OAAO,yCAAyC;AAOxF,SAAS,iBAAiB,UAAkB,MAAc,UAAmC,CAAC,GAAoB;AACvH,SAAO,CAAC,QAAgB,aAA8B,eAAmC;AACvF,UAAM,cAAc,OAAO;AAE3B,QAAI,YAAY,iCAAa,YAAwC,iCAAiC,WAAW;AACjH,QAAI,CAAC,WAAW;AACd,kBAAY,CAAC;AACb,uCAAa,eAAe,iCAAiC,WAAW,WAAW;AAAA,IACrF;AACA,cAAU,KAAK,EAAE,UAAU,MAAM,SAAS,YAAY,CAAC;AAAA,EACzD;AACF;AAEO,MAAM,8BAA8B,CAAC,WAAwD;AAClG,QAAM,cAAc,kBAAkB,WAAW,SAAS,OAAO;AACjE,SAAO,iCAAa,YAAY,iCAAiC,WAAW;AAC9E;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,48 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var appendChild_exports = {};
19
+ __export(appendChild_exports, {
20
+ APPEND_CHILD_METADATA_KEY: () => APPEND_CHILD_METADATA_KEY,
21
+ appendChild: () => appendChild,
22
+ findAllAppendChildMetadata: () => findAllAppendChildMetadata
23
+ });
24
+ module.exports = __toCommonJS(appendChild_exports);
25
+ var import_ReflectUtils = require("@dooboostore/core/reflect/ReflectUtils");
26
+ const APPEND_CHILD_METADATA_KEY = Symbol("simple-web-component:append-child");
27
+ function appendChild(selector, options = { position: "lastChild" }) {
28
+ return (target, propertyKey) => {
29
+ const constructor = target.constructor;
30
+ let meta = import_ReflectUtils.ReflectUtils.getOwnMetadata(APPEND_CHILD_METADATA_KEY, constructor);
31
+ if (!meta) {
32
+ meta = /* @__PURE__ */ new Map();
33
+ import_ReflectUtils.ReflectUtils.defineMetadata(APPEND_CHILD_METADATA_KEY, meta, constructor);
34
+ }
35
+ meta.set(propertyKey, { propertyKey, selector, options });
36
+ };
37
+ }
38
+ const findAllAppendChildMetadata = (target) => {
39
+ const result = /* @__PURE__ */ new Map();
40
+ const maps = import_ReflectUtils.ReflectUtils.findAllMetadata(APPEND_CHILD_METADATA_KEY, target);
41
+ maps.forEach((map) => {
42
+ if (map instanceof Map) {
43
+ map.forEach((v, k) => result.set(k, v));
44
+ }
45
+ });
46
+ return result;
47
+ };
48
+ //# sourceMappingURL=appendChild.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/decorators/appendChild.ts"],
4
+ "sourcesContent": ["import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';\n\nexport type AppendChildPosition = 'firstChild' | 'lastChild' | 'nextSibling' | 'previousSibling';\n\nexport interface AppendChildOptions {\n position?: AppendChildPosition;\n}\n\nexport interface AppendChildMetadata {\n propertyKey: string | symbol;\n selector: string;\n options: AppendChildOptions;\n}\n\nexport const APPEND_CHILD_METADATA_KEY = Symbol('simple-web-component:append-child');\n\n/**\n * @appendChild decorator to surgically add nodes to a target element.\n * Usage: @appendChild('#list') addItem() { return '<li>New Item</li>'; }\n */\nexport function appendChild(selector: string, options: AppendChildOptions = { position: 'lastChild' }): MethodDecorator {\n return (target: Object, propertyKey: string | symbol) => {\n const constructor = target.constructor;\n let meta = ReflectUtils.getOwnMetadata(APPEND_CHILD_METADATA_KEY, constructor) as Map<string | symbol, AppendChildMetadata>;\n if (!meta) {\n meta = new Map<string | symbol, AppendChildMetadata>();\n ReflectUtils.defineMetadata(APPEND_CHILD_METADATA_KEY, meta, constructor);\n }\n meta.set(propertyKey, { propertyKey, selector, options });\n };\n}\n\nexport const findAllAppendChildMetadata = (target: any): Map<string | symbol, AppendChildMetadata> => {\n const result = new Map<string | symbol, AppendChildMetadata>();\n const maps = ReflectUtils.findAllMetadata<Map<string | symbol, AppendChildMetadata>>(APPEND_CHILD_METADATA_KEY, target);\n maps.forEach(map => {\n if (map instanceof Map) {\n map.forEach((v, k) => result.set(k, v));\n }\n });\n return result;\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAA6B;AActB,MAAM,4BAA4B,OAAO,mCAAmC;AAM5E,SAAS,YAAY,UAAkB,UAA8B,EAAE,UAAU,YAAY,GAAoB;AACtH,SAAO,CAAC,QAAgB,gBAAiC;AACvD,UAAM,cAAc,OAAO;AAC3B,QAAI,OAAO,iCAAa,eAAe,2BAA2B,WAAW;AAC7E,QAAI,CAAC,MAAM;AACT,aAAO,oBAAI,IAA0C;AACrD,uCAAa,eAAe,2BAA2B,MAAM,WAAW;AAAA,IAC1E;AACA,SAAK,IAAI,aAAa,EAAE,aAAa,UAAU,QAAQ,CAAC;AAAA,EAC1D;AACF;AAEO,MAAM,6BAA6B,CAAC,WAA2D;AACpG,QAAM,SAAS,oBAAI,IAA0C;AAC7D,QAAM,OAAO,iCAAa,gBAA2D,2BAA2B,MAAM;AACtH,OAAK,QAAQ,SAAO;AAClB,QAAI,eAAe,KAAK;AACtB,UAAI,QAAQ,CAAC,GAAG,MAAM,OAAO,IAAI,GAAG,CAAC,CAAC;AAAA,IACxC;AAAA,EACF,CAAC;AACD,SAAO;AACT;",
6
+ "names": []
7
+ }