@dooboostore/simple-web-component 1.0.22 → 1.0.23
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.
- package/README.md +361 -19
- package/dist/cjs/decorators/applyNode.js +98 -24
- package/dist/cjs/decorators/applyNode.js.map +2 -2
- package/dist/cjs/decorators/attribute.js +0 -1
- package/dist/cjs/decorators/attribute.js.map +2 -2
- package/dist/cjs/decorators/classList.js +39 -19
- package/dist/cjs/decorators/classList.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +1 -2
- package/dist/cjs/decorators/elementDefine.js.map +2 -2
- package/dist/cjs/decorators/index.js +0 -1
- package/dist/cjs/decorators/index.js.map +2 -2
- package/dist/cjs/decorators/lifecycles.js +25 -0
- package/dist/cjs/decorators/lifecycles.js.map +2 -2
- package/dist/cjs/decorators/query.js.map +2 -2
- package/dist/cjs/decorators/style.js +39 -13
- package/dist/cjs/decorators/style.js.map +2 -2
- package/dist/cjs/utils/TemplateUtils.js +6 -0
- package/dist/cjs/utils/TemplateUtils.js.map +2 -2
- package/dist/esm/decorators/applyNode.js +98 -24
- package/dist/esm/decorators/applyNode.js.map +2 -2
- package/dist/esm/decorators/attribute.js +0 -1
- package/dist/esm/decorators/attribute.js.map +2 -2
- package/dist/esm/decorators/classList.js +39 -19
- package/dist/esm/decorators/classList.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +1 -2
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/index.js +0 -1
- package/dist/esm/decorators/index.js.map +2 -2
- package/dist/esm/decorators/lifecycles.js +25 -0
- package/dist/esm/decorators/lifecycles.js.map +2 -2
- package/dist/esm/decorators/query.js.map +2 -2
- package/dist/esm/decorators/style.js +39 -13
- package/dist/esm/decorators/style.js.map +2 -2
- package/dist/esm/utils/TemplateUtils.js +6 -0
- package/dist/esm/utils/TemplateUtils.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +204 -81
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +3 -3
- package/dist/types/decorators/applyNode.d.ts +84 -1
- package/dist/types/decorators/applyNode.d.ts.map +1 -1
- package/dist/types/decorators/classList.d.ts +12 -10
- package/dist/types/decorators/classList.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/index.d.ts +0 -1
- package/dist/types/decorators/index.d.ts.map +1 -1
- package/dist/types/decorators/lifecycles.d.ts +14 -0
- package/dist/types/decorators/lifecycles.d.ts.map +1 -1
- package/dist/types/decorators/query.d.ts +0 -3
- package/dist/types/decorators/query.d.ts.map +1 -1
- package/dist/types/decorators/style.d.ts +28 -3
- package/dist/types/decorators/style.d.ts.map +1 -1
- package/dist/types/utils/TemplateUtils.d.ts +5 -0
- package/dist/types/utils/TemplateUtils.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +204 -81
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +3 -3
- package/package.json +3 -3
- package/src/decorators/applyNode.ts +199 -36
- package/src/decorators/attribute.ts +1 -1
- package/src/decorators/classList.ts +45 -22
- package/src/decorators/elementDefine.ts +1 -2
- package/src/decorators/index.ts +0 -1
- package/src/decorators/lifecycles.ts +40 -0
- package/src/decorators/query.ts +0 -2
- package/src/decorators/style.ts +64 -13
- package/src/utils/TemplateUtils.ts +9 -0
- package/dist/cjs/decorators/onConnectedInnerHtml.js +0 -48
- package/dist/cjs/decorators/onConnectedInnerHtml.js.map +0 -7
- package/dist/esm/decorators/onConnectedInnerHtml.js +0 -29
- package/dist/esm/decorators/onConnectedInnerHtml.js.map +0 -7
- package/dist/types/decorators/onConnectedInnerHtml.d.ts +0 -15
- package/dist/types/decorators/onConnectedInnerHtml.d.ts.map +0 -1
- package/src/decorators/onConnectedInnerHtml.ts +0 -42
package/README.md
CHANGED
|
@@ -312,56 +312,119 @@ class ReactiveInput extends HTMLElement {
|
|
|
312
312
|
}
|
|
313
313
|
```
|
|
314
314
|
|
|
315
|
-
#### 12. `@setAttribute(name, options?)`
|
|
316
|
-
Reflect method's return value to a DOM attribute. One-way binding (class → DOM).
|
|
315
|
+
#### 12. `@setAttribute(selector, name, options?)`
|
|
316
|
+
Reflect method's return value to a target element's DOM attribute. One-way binding (class → DOM).
|
|
317
317
|
|
|
318
318
|
```typescript
|
|
319
319
|
@elementDefine('status-badge')
|
|
320
320
|
class StatusBadge extends HTMLElement {
|
|
321
321
|
private status: 'active' | 'inactive' | 'pending' = 'pending';
|
|
322
|
+
private items: any[] = [];
|
|
322
323
|
|
|
323
|
-
// Reflect status to
|
|
324
|
-
@setAttribute('data-status')
|
|
324
|
+
// Reflect status to host element's data-status attribute
|
|
325
|
+
@setAttribute(':host', 'data-status')
|
|
325
326
|
getStatus() {
|
|
326
327
|
return this.status;
|
|
327
328
|
}
|
|
328
329
|
|
|
329
|
-
// Reflect computed data to
|
|
330
|
-
@setAttribute('count')
|
|
330
|
+
// Reflect computed data to specific element
|
|
331
|
+
@setAttribute('#count-display', 'data-count')
|
|
331
332
|
getItemCount() {
|
|
332
|
-
return this.
|
|
333
|
+
return this.items.length.toString();
|
|
333
334
|
}
|
|
334
335
|
|
|
335
|
-
// Reflect to Shadow DOM element
|
|
336
|
-
@setAttribute('aria-label', { root: 'shadow' })
|
|
336
|
+
// Reflect to Shadow DOM element's aria-label
|
|
337
|
+
@setAttribute('.badge-label', 'aria-label', { root: 'shadow' })
|
|
337
338
|
getAriaLabel() {
|
|
338
339
|
return `Status is ${this.status}`;
|
|
339
340
|
}
|
|
340
341
|
|
|
341
|
-
private getItems() {
|
|
342
|
-
return [];
|
|
343
|
-
}
|
|
344
|
-
|
|
345
342
|
@onConnectedInnerHtml
|
|
346
343
|
render() {
|
|
347
344
|
return `
|
|
348
|
-
<div
|
|
349
|
-
Status: ${this.status}
|
|
345
|
+
<div data-status="${this.status}">
|
|
346
|
+
<span class="badge-label">Status: ${this.status}</span>
|
|
347
|
+
<span id="count-display" data-count="${this.items.length}">Items: ${this.items.length}</span>
|
|
350
348
|
</div>
|
|
351
349
|
`;
|
|
352
350
|
}
|
|
353
351
|
|
|
354
|
-
// Change status and update DOM
|
|
352
|
+
// Change status and update DOM attributes
|
|
355
353
|
setStatus(newStatus: typeof this.status) {
|
|
356
354
|
this.status = newStatus;
|
|
357
|
-
this.getStatus();
|
|
355
|
+
this.getStatus(); // Updates :host[data-status]
|
|
356
|
+
this.getItemCount(); // Updates #count-display[data-count]
|
|
357
|
+
this.getAriaLabel(); // Updates .badge-label[aria-label]
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
360
|
```
|
|
361
361
|
|
|
362
|
+
**Signature:**
|
|
363
|
+
- `@setAttribute(selector, attributeName, options?)`
|
|
364
|
+
- Returns method's value → reflects to target's attribute
|
|
365
|
+
|
|
366
|
+
**Selectors:**
|
|
367
|
+
- `':host'` - The component itself
|
|
368
|
+
- `'#element-id'` - Element by ID
|
|
369
|
+
- `'.class-name'` - Element by class
|
|
370
|
+
- `selector` - Any CSS selector
|
|
371
|
+
|
|
372
|
+
#### 12b. `@setAttributeHost(name, options?)` - Shorthand for `:host`
|
|
373
|
+
Simplified version of `@setAttribute` that always targets `:host`.
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
@elementDefine('counter')
|
|
377
|
+
class Counter extends HTMLElement {
|
|
378
|
+
private count = 0;
|
|
379
|
+
|
|
380
|
+
// Equivalent to @setAttribute(':host', 'aria-label')
|
|
381
|
+
@setAttributeHost('aria-label')
|
|
382
|
+
getAriaLabel() {
|
|
383
|
+
return `Count is ${this.count}`;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
@setAttributeHost('data-count')
|
|
387
|
+
getCountValue() {
|
|
388
|
+
return this.count.toString();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
@setAttributeHost('aria-disabled')
|
|
392
|
+
getDisabledState() {
|
|
393
|
+
return (this.count >= 10).toString();
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
@onConnectedInnerHtml
|
|
397
|
+
render() {
|
|
398
|
+
return `
|
|
399
|
+
<div>
|
|
400
|
+
<p>Count: ${this.count}</p>
|
|
401
|
+
<button swc-on-click="$host.increment()">+</button>
|
|
402
|
+
</div>
|
|
403
|
+
`;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
increment() {
|
|
407
|
+
this.count++;
|
|
408
|
+
this.getAriaLabel(); // Updates :host[aria-label]
|
|
409
|
+
this.getCountValue(); // Updates :host[data-count]
|
|
410
|
+
this.getDisabledState(); // Updates :host[aria-disabled]
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
**Usage:**
|
|
416
|
+
```typescript
|
|
417
|
+
// Full form
|
|
418
|
+
@setAttribute(':host', 'data-status')
|
|
419
|
+
// vs
|
|
420
|
+
// Shorthand for :host
|
|
421
|
+
@setAttributeHost('data-status')
|
|
422
|
+
```
|
|
423
|
+
|
|
362
424
|
**Key Differences:**
|
|
363
425
|
- **`@attributeHost`** - Two-way binding: DOM ↔ Class (Bidirectional)
|
|
364
|
-
- **`@setAttribute`** - One-way binding: Class → DOM (
|
|
426
|
+
- **`@setAttribute`** - One-way binding: Class → DOM (Any selector)
|
|
427
|
+
- **`@setAttributeHost`** - One-way binding: Class → DOM (`:host` only)
|
|
365
428
|
- **`@changedAttributeHost`** - Watch DOM attribute changes (Reactive handler)
|
|
366
429
|
|
|
367
430
|
**Options:**
|
|
@@ -425,6 +488,62 @@ class ListRenderer extends HTMLElement {
|
|
|
425
488
|
}
|
|
426
489
|
```
|
|
427
490
|
|
|
491
|
+
#### 14b. Removing Elements via `null` or `undefined`
|
|
492
|
+
Both `@query` and `@queryAll` support element removal by setting the property to `null` or `undefined`. This triggers automatic removal of the matching element(s).
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
@elementDefine('todo-list')
|
|
496
|
+
class TodoList extends HTMLElement {
|
|
497
|
+
@query('.notification') notification?: HTMLElement;
|
|
498
|
+
@queryAll('.todo-item') todoItems?: HTMLElement[];
|
|
499
|
+
|
|
500
|
+
removeNotification() {
|
|
501
|
+
// Setting to null triggers automatic removal
|
|
502
|
+
this.notification = null;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
removeTodoItem(id: string) {
|
|
506
|
+
// Find and remove a specific todo item
|
|
507
|
+
const item = this.querySelector(`[data-id="${id}"]`);
|
|
508
|
+
if (item) {
|
|
509
|
+
// Setting @query to null removes the element from DOM
|
|
510
|
+
this.notification = null;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
clearAllTodos() {
|
|
515
|
+
// Setting @queryAll to null/undefined removes all matching elements
|
|
516
|
+
this.todoItems = null; // Removes all .todo-item elements
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
@onConnectedInnerHtml
|
|
520
|
+
render() {
|
|
521
|
+
return `
|
|
522
|
+
<div class="notification">New todos available!</div>
|
|
523
|
+
<ul>
|
|
524
|
+
<li class="todo-item" data-id="1">Task 1</li>
|
|
525
|
+
<li class="todo-item" data-id="2">Task 2</li>
|
|
526
|
+
<li class="todo-item" data-id="3">Task 3</li>
|
|
527
|
+
</ul>
|
|
528
|
+
<button swc-on-click="$host.removeNotification()">Clear Notification</button>
|
|
529
|
+
<button swc-on-click="$host.clearAllTodos()">Clear All Tasks</button>
|
|
530
|
+
`;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
**Removal Rules:**
|
|
536
|
+
- `@query`: Setting to `null` or `undefined` removes the single element
|
|
537
|
+
- `@queryAll`: Setting to `null` or `undefined` removes all matching elements
|
|
538
|
+
- Special selectors (`:host`, `:window`, `:document`, etc.) are **NOT removed** (protected)
|
|
539
|
+
- Only affects Light DOM by default; use `{ root: 'shadow' }` to remove from Shadow DOM
|
|
540
|
+
|
|
541
|
+
**Use Cases:**
|
|
542
|
+
- Close notification banners
|
|
543
|
+
- Clear dynamic list items
|
|
544
|
+
- Remove temporary overlays
|
|
545
|
+
- Clean up modal dialogs
|
|
546
|
+
|
|
428
547
|
---
|
|
429
548
|
|
|
430
549
|
### Event & Messaging Decorators
|
|
@@ -571,6 +690,7 @@ Surgically add, update, or replace DOM nodes at specific positions.
|
|
|
571
690
|
@elementDefine('counter-display')
|
|
572
691
|
class CounterDisplay extends HTMLElement {
|
|
573
692
|
private count = 0;
|
|
693
|
+
private errorMessage = '';
|
|
574
694
|
|
|
575
695
|
// Replace all children with new content
|
|
576
696
|
@applyNode('#display', { position: 'replaceChildren' })
|
|
@@ -596,6 +716,12 @@ class CounterDisplay extends HTMLElement {
|
|
|
596
716
|
return this.count.toString();
|
|
597
717
|
}
|
|
598
718
|
|
|
719
|
+
// Remove element if condition is truthy
|
|
720
|
+
@applyNode('#error-banner', { position: 'remove' })
|
|
721
|
+
dismissError() {
|
|
722
|
+
return this.errorMessage === ''; // Remove if no error
|
|
723
|
+
}
|
|
724
|
+
|
|
599
725
|
@onConnectedInnerHtml
|
|
600
726
|
render() {
|
|
601
727
|
return `
|
|
@@ -604,6 +730,7 @@ class CounterDisplay extends HTMLElement {
|
|
|
604
730
|
<div id="status"></div>
|
|
605
731
|
<button swc-on-click="$host.count++; $host.updateDisplayCount?.()">+</button>
|
|
606
732
|
<div id="history"></div>
|
|
733
|
+
<div id="error-banner" style="display: ${this.errorMessage ? 'block' : 'none'};"></div>
|
|
607
734
|
`;
|
|
608
735
|
}
|
|
609
736
|
}
|
|
@@ -618,12 +745,207 @@ class CounterDisplay extends HTMLElement {
|
|
|
618
745
|
- `'replaceChildren'` - Replace all children
|
|
619
746
|
- `'innerHtml'` - Set `innerHTML`
|
|
620
747
|
- `'innerText'` - Set `innerText`
|
|
748
|
+
- `'remove'` - Remove element if returned value is truthy
|
|
749
|
+
|
|
750
|
+
**Root Option:**
|
|
751
|
+
Control which DOM tree is searched with the `root` option:
|
|
752
|
+
- `'auto'` (default) - Search shadow DOM first, then light DOM
|
|
753
|
+
- `'shadow'` - Search only shadow DOM
|
|
754
|
+
- `'light'` - Search only light DOM
|
|
755
|
+
- `'all'` - Search all ancestors
|
|
756
|
+
|
|
757
|
+
#### Convenience Decorators
|
|
758
|
+
|
|
759
|
+
Shorthand decorators for common position-specific operations:
|
|
760
|
+
|
|
761
|
+
**Position-Specific Variants:**
|
|
762
|
+
```typescript
|
|
763
|
+
@applyBeforeBeginNode('#target') prependTarget() { return `<div>Before</div>`; }
|
|
764
|
+
@applyAfterBeginNode('#target') afterBeginTarget() { return `<div>After Begin</div>`; }
|
|
765
|
+
@applyBeforeEndNode('#target') beforeEndTarget() { return `<div>Before End</div>`; }
|
|
766
|
+
@applyAfterEndNode('#target') afterEndTarget() { return `<div>After</div>`; }
|
|
767
|
+
@applyReplaceNode('#target') replaceTarget() { return `<div>Replaced</div>`; }
|
|
768
|
+
@applyReplaceChildrenNode('#target') replaceChildrenTarget() { return `<div>New Children</div>`; }
|
|
769
|
+
@applyInnerHtmlNode('#target') setInnerHtml() { return `<b>Bold</b>`; }
|
|
770
|
+
@applyInnerTextNode('#target') setInnerText() { return 'Plain text'; }
|
|
771
|
+
@applyRemoveNode('#target') removeTarget() { return true; }
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
**Host-Targeted Variants (`:host` selector):**
|
|
775
|
+
```typescript
|
|
776
|
+
@applyBeforeBeginNodeHost() prependHost() { return `<div>Before Host</div>`; }
|
|
777
|
+
@applyAfterBeginNodeHost() afterBeginHost() { return `<div>After Begin</div>`; }
|
|
778
|
+
@applyBeforeEndNodeHost() beforeEndHost() { return `<div>Before End</div>`; }
|
|
779
|
+
@applyAfterEndNodeHost({ root: 'shadow' }) afterEndHost() { return `<div>After Host</div>`; }
|
|
780
|
+
@applyReplaceNodeHost() replaceHost() { return `<div>Replaced Host</div>`; }
|
|
781
|
+
@applyReplaceChildrenNodeHost() replaceChildrenHost() { return `<div>Shadow Children</div>`; }
|
|
782
|
+
@applyInnerHtmlNodeHost() setHostInnerHtml() { return `<b>Host Content</b>`; }
|
|
783
|
+
@applyInnerTextNodeHost() setHostInnerText() { return 'Host text'; }
|
|
784
|
+
@applyRemoveNodeHost() removeHost() { return this.shouldRemove; }
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
---
|
|
788
|
+
|
|
789
|
+
#### 18. `@setStyle(selector, options?)` / `@updateStyle(selector, options?)` / `@removeStyle(selector, options?)`
|
|
790
|
+
|
|
791
|
+
Manipulate CSS styles on elements with full Shadow DOM support.
|
|
792
|
+
|
|
793
|
+
**Core Features:**
|
|
794
|
+
- `@setStyle` - Set inline style (replaces all)
|
|
795
|
+
- `@updateStyle` - Merge with existing styles
|
|
796
|
+
- `@removeStyle` - Remove specific properties
|
|
797
|
+
- `root` option for Shadow DOM / Light DOM targeting
|
|
798
|
+
- Support for multiple elements with `querySelectorAll`
|
|
799
|
+
|
|
800
|
+
```typescript
|
|
801
|
+
@elementDefine('styled-component')
|
|
802
|
+
class StyledComponent extends HTMLElement {
|
|
803
|
+
private isActive = false;
|
|
804
|
+
|
|
805
|
+
@setStyle('.button', { root: 'shadow' })
|
|
806
|
+
setPrimaryButtonStyle() {
|
|
807
|
+
return {
|
|
808
|
+
backgroundColor: '#0066cc',
|
|
809
|
+
color: 'white',
|
|
810
|
+
padding: '10px 20px',
|
|
811
|
+
border: 'none',
|
|
812
|
+
borderRadius: '4px'
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
@updateStyle('.button', { root: 'shadow' })
|
|
817
|
+
highlightButton() {
|
|
818
|
+
return {
|
|
819
|
+
boxShadow: '0 0 10px rgba(0, 102, 204, 0.5)',
|
|
820
|
+
transform: 'scale(1.05)'
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
@removeStyle('.button', { root: 'shadow' })
|
|
825
|
+
clearHighlight() {
|
|
826
|
+
return ['boxShadow', 'transform'];
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
@onConnectedInnerHtml({ useShadow: true })
|
|
830
|
+
render() {
|
|
831
|
+
return `
|
|
832
|
+
<style>
|
|
833
|
+
.button { cursor: pointer; transition: all 0.2s; }
|
|
834
|
+
</style>
|
|
835
|
+
<button class="button">Styled</button>
|
|
836
|
+
`;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
**Host-Targeted Variants:**
|
|
842
|
+
```typescript
|
|
843
|
+
@setStyleHost({ root: 'shadow' })
|
|
844
|
+
setHostStyle() {
|
|
845
|
+
return { display: 'flex', gap: '10px' };
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
@updateStyleHost({ root: 'shadow' })
|
|
849
|
+
updateHostStyle() {
|
|
850
|
+
return { backgroundColor: '#f0f0f0' };
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
@removeStyleHost({ root: 'shadow' })
|
|
854
|
+
clearHostStyle() {
|
|
855
|
+
return ['backgroundColor'];
|
|
856
|
+
}
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
---
|
|
860
|
+
|
|
861
|
+
#### 19. `@setClassList(selector, options?)` / `@addClassList(selector, options?)` / `@removeClassList(selector, options?)` / `@toggleClassList(selector, options?)` / `@updateClassList(selector, options?)`
|
|
862
|
+
|
|
863
|
+
Manipulate CSS classes on elements declaratively with Shadow DOM support.
|
|
864
|
+
|
|
865
|
+
**Core Features:**
|
|
866
|
+
- `@addClassList` - Add classes
|
|
867
|
+
- `@removeClassList` - Remove classes
|
|
868
|
+
- `@toggleClassList` - Toggle classes (returns boolean or bool array)
|
|
869
|
+
- `@setClassList` - Replace all classes
|
|
870
|
+
- `@updateClassList` - Merge with existing classes
|
|
871
|
+
- `root` option for DOM layer targeting
|
|
872
|
+
- Support for multiple elements
|
|
873
|
+
|
|
874
|
+
```typescript
|
|
875
|
+
@elementDefine('tab-component')
|
|
876
|
+
class TabComponent extends HTMLElement {
|
|
877
|
+
activeTab = 'home';
|
|
878
|
+
|
|
879
|
+
@addClassList('.tab', { root: 'shadow' })
|
|
880
|
+
addTabClasses() {
|
|
881
|
+
return ['interactive', 'focusable'];
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
@toggleClassList('.tab', { root: 'shadow' })
|
|
885
|
+
toggleActiveTab() {
|
|
886
|
+
return this.activeTab === 'home'; // Returns boolean for all matched elements
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
@removeClassList('.tab-inactive', { root: 'shadow' })
|
|
890
|
+
removeInactiveClass() {
|
|
891
|
+
return ['disabled'];
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
@setClassList('.tab-pane', { root: 'shadow' })
|
|
895
|
+
updateTabPane() {
|
|
896
|
+
return [`pane-${this.activeTab}`, 'content'];
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
@onConnectedInnerHtml({ useShadow: true })
|
|
900
|
+
render() {
|
|
901
|
+
return `
|
|
902
|
+
<style>
|
|
903
|
+
.tab { cursor: pointer; padding: 10px; }
|
|
904
|
+
.tab.active { border-bottom: 2px solid blue; }
|
|
905
|
+
</style>
|
|
906
|
+
<div class="tabs">
|
|
907
|
+
<div class="tab" swc-on-click="$host.activeTab='home'; $host.toggleActiveTab?.();">Home</div>
|
|
908
|
+
<div class="tab" swc-on-click="$host.activeTab='about'; $host.toggleActiveTab?.();">About</div>
|
|
909
|
+
</div>
|
|
910
|
+
<div class="tab-pane">Content here</div>
|
|
911
|
+
`;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
**Host-Targeted Variants:**
|
|
917
|
+
```typescript
|
|
918
|
+
@addClassListHost({ root: 'shadow' })
|
|
919
|
+
addHostClasses() {
|
|
920
|
+
return ['component', 'interactive'];
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
@removeClassListHost({ root: 'shadow' })
|
|
924
|
+
removeHostClasses() {
|
|
925
|
+
return ['loading'];
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
@toggleClassListHost({ root: 'shadow' })
|
|
929
|
+
toggleHostClass() {
|
|
930
|
+
return this.isOpen; // Apply 'open' class if true
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
@setClassListHost({ root: 'shadow' })
|
|
934
|
+
setHostClasses() {
|
|
935
|
+
return this.isOpen ? ['open', 'expanded'] : ['closed'];
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
@updateClassListHost({ root: 'shadow' })
|
|
939
|
+
updateHostClasses() {
|
|
940
|
+
return ['visible'];
|
|
941
|
+
}
|
|
942
|
+
```
|
|
621
943
|
|
|
622
944
|
---
|
|
623
945
|
|
|
624
946
|
### Dependency Injection & Singleton
|
|
625
947
|
|
|
626
|
-
####
|
|
948
|
+
#### 20. `@Sim`
|
|
627
949
|
Marks a class as a **Singleton** in the `<swc-app>` DI container for **constructor injection**.
|
|
628
950
|
|
|
629
951
|
**Two DI Mechanisms:**
|
|
@@ -1270,6 +1592,26 @@ class TextRenderer extends HTMLElement {
|
|
|
1270
1592
|
}
|
|
1271
1593
|
```
|
|
1272
1594
|
|
|
1595
|
+
### 2b. `commentNode` - HTML Comments
|
|
1596
|
+
|
|
1597
|
+
Create HTML comment nodes (useful for debugging, markers, or template documentation).
|
|
1598
|
+
|
|
1599
|
+
```typescript
|
|
1600
|
+
@elementDefine('debug-component')
|
|
1601
|
+
class DebugComponent extends HTMLElement {
|
|
1602
|
+
@appendChild('#debug-area')
|
|
1603
|
+
addDebugComment(message: string) {
|
|
1604
|
+
// Create HTML comment node
|
|
1605
|
+
return commentNode`DEBUG: ${message} at ${new Date().toISOString()}`;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
@onConnectedInnerHtml
|
|
1609
|
+
render() {
|
|
1610
|
+
return `<div id="debug-area"></div>`;
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
```
|
|
1614
|
+
|
|
1273
1615
|
### 3. Element Factories (`html***Element`)
|
|
1274
1616
|
|
|
1275
1617
|
Specific factories for common tags. Each returns a **typed element instance**.
|
|
@@ -18,8 +18,26 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
18
18
|
var applyNode_exports = {};
|
|
19
19
|
__export(applyNode_exports, {
|
|
20
20
|
APPLY_NODE_METADATA_KEY: () => APPLY_NODE_METADATA_KEY,
|
|
21
|
+
applyAfterBeginNode: () => applyAfterBeginNode,
|
|
22
|
+
applyAfterBeginNodeHost: () => applyAfterBeginNodeHost,
|
|
23
|
+
applyAfterEndNode: () => applyAfterEndNode,
|
|
24
|
+
applyAfterEndNodeHost: () => applyAfterEndNodeHost,
|
|
25
|
+
applyBeforeBeginNode: () => applyBeforeBeginNode,
|
|
26
|
+
applyBeforeBeginNodeHost: () => applyBeforeBeginNodeHost,
|
|
27
|
+
applyBeforeEndNode: () => applyBeforeEndNode,
|
|
28
|
+
applyBeforeEndNodeHost: () => applyBeforeEndNodeHost,
|
|
29
|
+
applyInnerHtmlNode: () => applyInnerHtmlNode,
|
|
30
|
+
applyInnerHtmlNodeHost: () => applyInnerHtmlNodeHost,
|
|
31
|
+
applyInnerTextNode: () => applyInnerTextNode,
|
|
32
|
+
applyInnerTextNodeHost: () => applyInnerTextNodeHost,
|
|
21
33
|
applyNode: () => applyNode,
|
|
22
34
|
applyNodeHost: () => applyNodeHost,
|
|
35
|
+
applyRemoveNode: () => applyRemoveNode,
|
|
36
|
+
applyRemoveNodeHost: () => applyRemoveNodeHost,
|
|
37
|
+
applyReplaceChildrenNode: () => applyReplaceChildrenNode,
|
|
38
|
+
applyReplaceChildrenNodeHost: () => applyReplaceChildrenNodeHost,
|
|
39
|
+
applyReplaceNode: () => applyReplaceNode,
|
|
40
|
+
applyReplaceNodeHost: () => applyReplaceNodeHost,
|
|
23
41
|
findAllApplyNodeMetadata: () => findAllApplyNodeMetadata
|
|
24
42
|
});
|
|
25
43
|
module.exports = __toCommonJS(applyNode_exports);
|
|
@@ -51,32 +69,70 @@ function applyNode(selector, options = { position: "beforeEnd" }) {
|
|
|
51
69
|
const conf = (0, import_elementDefine.getElementConfig)(this);
|
|
52
70
|
const currentWin = this._resolveWindow?.(conf) || (typeof window !== "undefined" ? window : void 0);
|
|
53
71
|
const currentDoc = currentWin.document;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
72
|
+
const pos = options.position || "beforeEnd";
|
|
73
|
+
const r = options.root || "auto";
|
|
74
|
+
const getTargetRoot = () => {
|
|
75
|
+
if (r === "shadow")
|
|
76
|
+
return this.shadowRoot;
|
|
77
|
+
if (r === "light")
|
|
78
|
+
return this;
|
|
79
|
+
if (r === "all")
|
|
80
|
+
return this.shadowRoot || this;
|
|
81
|
+
return this.shadowRoot || this;
|
|
82
|
+
};
|
|
83
|
+
if (pos === "remove") {
|
|
84
|
+
if (res) {
|
|
85
|
+
if (selector === ":host" || !selector) {
|
|
86
|
+
if (r === "shadow" && this.shadowRoot) {
|
|
87
|
+
this.shadowRoot.replaceChildren();
|
|
88
|
+
} else {
|
|
89
|
+
this.remove();
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
const targetRoot = getTargetRoot();
|
|
93
|
+
if (targetRoot) {
|
|
94
|
+
const targets = targetRoot.querySelectorAll(selector);
|
|
95
|
+
targets.forEach((el) => el.remove());
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
57
99
|
} else {
|
|
58
|
-
targetEl =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
} else if (pos === "replaceChildren") {
|
|
66
|
-
targetEl.replaceChildren(...nodes);
|
|
67
|
-
} else if (pos === "innerHtml") {
|
|
68
|
-
targetEl.innerHTML = res !== void 0 && res !== null ? String(res) : "";
|
|
69
|
-
} else if (pos === "innerText") {
|
|
70
|
-
targetEl.innerText = res !== void 0 && res !== null ? String(res) : "";
|
|
100
|
+
let targetEl = null;
|
|
101
|
+
if (selector === ":host" || !selector) {
|
|
102
|
+
if (r === "shadow") {
|
|
103
|
+
targetEl = this.shadowRoot;
|
|
104
|
+
} else {
|
|
105
|
+
targetEl = this;
|
|
106
|
+
}
|
|
71
107
|
} else {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
108
|
+
const targetRoot = getTargetRoot();
|
|
109
|
+
targetEl = targetRoot ? targetRoot.querySelector(selector) : null;
|
|
110
|
+
}
|
|
111
|
+
if (targetEl) {
|
|
112
|
+
const isShadowRoot = targetEl instanceof ShadowRoot;
|
|
113
|
+
const nodes = normalizeNodes(res, currentDoc);
|
|
114
|
+
if (pos === "replace") {
|
|
115
|
+
if (!isShadowRoot) {
|
|
116
|
+
targetEl.replaceWith(...nodes);
|
|
117
|
+
}
|
|
118
|
+
} else if (pos === "replaceChildren") {
|
|
119
|
+
targetEl.replaceChildren(...nodes);
|
|
120
|
+
} else if (pos === "innerHtml") {
|
|
121
|
+
targetEl.innerHTML = res !== void 0 && res !== null ? String(res) : "";
|
|
122
|
+
} else if (pos === "innerText") {
|
|
123
|
+
if (targetEl.innerText !== void 0) {
|
|
124
|
+
targetEl.innerText = res !== void 0 && res !== null ? String(res) : "";
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
if (pos === "beforeEnd")
|
|
128
|
+
targetEl.append(...nodes);
|
|
129
|
+
else if (pos === "afterBegin")
|
|
130
|
+
targetEl.prepend(...nodes);
|
|
131
|
+
else if (pos === "beforeBegin" && !isShadowRoot)
|
|
132
|
+
targetEl.before(...nodes);
|
|
133
|
+
else if (pos === "afterEnd" && !isShadowRoot)
|
|
134
|
+
targetEl.after(...nodes);
|
|
135
|
+
}
|
|
80
136
|
}
|
|
81
137
|
}
|
|
82
138
|
}
|
|
@@ -97,4 +153,22 @@ const findAllApplyNodeMetadata = (target) => {
|
|
|
97
153
|
function applyNodeHost(options = { position: "beforeEnd" }) {
|
|
98
154
|
return applyNode(":host", options);
|
|
99
155
|
}
|
|
156
|
+
const applyBeforeBeginNode = (selector, options = {}) => applyNode(selector, { ...options, position: "beforeBegin" });
|
|
157
|
+
const applyAfterBeginNode = (selector, options = {}) => applyNode(selector, { ...options, position: "afterBegin" });
|
|
158
|
+
const applyBeforeEndNode = (selector, options = {}) => applyNode(selector, { ...options, position: "beforeEnd" });
|
|
159
|
+
const applyAfterEndNode = (selector, options = {}) => applyNode(selector, { ...options, position: "afterEnd" });
|
|
160
|
+
const applyReplaceNode = (selector, options = {}) => applyNode(selector, { ...options, position: "replace" });
|
|
161
|
+
const applyReplaceChildrenNode = (selector, options = {}) => applyNode(selector, { ...options, position: "replaceChildren" });
|
|
162
|
+
const applyInnerHtmlNode = (selector, options = {}) => applyNode(selector, { ...options, position: "innerHtml" });
|
|
163
|
+
const applyInnerTextNode = (selector, options = {}) => applyNode(selector, { ...options, position: "innerText" });
|
|
164
|
+
const applyRemoveNode = (selector, options = {}) => applyNode(selector, { ...options, position: "remove" });
|
|
165
|
+
const applyBeforeBeginNodeHost = (options = {}) => applyNode(":host", { ...options, position: "beforeBegin" });
|
|
166
|
+
const applyAfterBeginNodeHost = (options = {}) => applyNode(":host", { ...options, position: "afterBegin" });
|
|
167
|
+
const applyBeforeEndNodeHost = (options = {}) => applyNode(":host", { ...options, position: "beforeEnd" });
|
|
168
|
+
const applyAfterEndNodeHost = (options = {}) => applyNode(":host", { ...options, position: "afterEnd" });
|
|
169
|
+
const applyReplaceNodeHost = (options = {}) => applyNode(":host", { ...options, position: "replace" });
|
|
170
|
+
const applyReplaceChildrenNodeHost = (options = {}) => applyNode(":host", { ...options, position: "replaceChildren" });
|
|
171
|
+
const applyInnerHtmlNodeHost = (options = {}) => applyNode(":host", { ...options, position: "innerHtml" });
|
|
172
|
+
const applyInnerTextNodeHost = (options = {}) => applyNode(":host", { ...options, position: "innerText" });
|
|
173
|
+
const applyRemoveNodeHost = (options = {}) => applyNode(":host", { ...options, position: "remove" });
|
|
100
174
|
//# sourceMappingURL=applyNode.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/decorators/applyNode.ts"],
|
|
4
|
-
"sourcesContent": ["import { ReflectUtils } from '@dooboostore/core';\nimport { ensureInit, getElementConfig } from './elementDefine';\n\nexport type ApplyNodePosition = 'beforeBegin' | 'afterBegin' | 'beforeEnd' | 'afterEnd' | 'replace' | 'replaceChildren' | 'innerHtml' | 'innerText';\n\nexport interface ApplyNodeOptions {\n position?: ApplyNodePosition;\n}\n\nexport interface ApplyNodeMetadata {\n propertyKey: string | symbol;\n selector: string;\n options: ApplyNodeOptions;\n}\n\nexport const APPLY_NODE_METADATA_KEY = Symbol('simple-web-component:apply-node');\n\nconst normalizeNodes = (res: any, doc: Document): Node[] => {\n const items = Array.isArray(res) ? res : [res];\n return items.map(it => {\n if (it instanceof Node) return it;\n return doc.createTextNode(it !== undefined && it !== null ? String(it) : '');\n });\n};\n\n/**\n * @applyNode decorator to surgically add/replace nodes to a target element.\n * \n * Usage examples:\n * @applyNode('#list') addItem() { return '<li>New Item</li>'; } // append at end\n * @applyNode('#header', { position: 'afterBegin' }) prependItem() { return '<h1>Title</h1>'; } // prepend at start\n * @applyNode('#item', { position: 'replace' }) replaceItem() { return '<div>Replaced</div>'; } // replace element\n * @applyNode('#list', { position: 'replaceChildren' }) updateList() { return [item1, item2]; } // replace all children\n * \n * Positions:\n * - 'beforeEnd' (default): Append at end of target\n * - 'afterBegin': Prepend at start of target\n * - 'beforeBegin': Insert before target\n * - 'afterEnd': Insert after target\n * - 'replace': Replace the entire target element\n * - 'replaceChildren': Replace all children of target element\n * - 'innerHtml': Set target's innerHTML\n * - 'innerText': Set target's innerText\n */\nexport function applyNode(selector: string, options: ApplyNodeOptions = { position: 'beforeEnd' }): MethodDecorator {\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\n const constructor = target.constructor;\n let metaList = ReflectUtils.getOwnMetadata(APPLY_NODE_METADATA_KEY, constructor) as Map<string | symbol, ApplyNodeMetadata>;\n if (!metaList) {\n metaList = new Map<string | symbol, ApplyNodeMetadata>();\n ReflectUtils.defineMetadata(APPLY_NODE_METADATA_KEY, metaList, constructor);\n }\n metaList.set(propertyKey, { propertyKey, selector, options });\n\n const original = descriptor.value;\n descriptor.value = async function (...args: any[]) {\n ensureInit(this);\n const res = await original.apply(this, args);\n if (res !== undefined) {\n const conf = getElementConfig(this);\n const currentWin = (this as any)._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as Window);\n const currentDoc = currentWin.document;\n\n let targetEl: HTMLElement | null = null;\n if (selector === ':host' || !selector) {\n targetEl = this as any;\n } else {\n targetEl = (this.shadowRoot || (this as any)).querySelector(selector);\n }\n\n if (targetEl) {\n const nodes = normalizeNodes(res, currentDoc);\n const pos = options.position || 'beforeEnd';\n\n if (pos === 'replace') {\n // Replace the entire target element with new nodes\n targetEl.replaceWith(...nodes);\n } else if (pos === 'replaceChildren') {\n // Replace all children of target element\n targetEl.replaceChildren(...nodes);\n } else if (pos === 'innerHtml') {\n // Set innerHTML\n targetEl.innerHTML = res !== undefined && res !== null ? String(res) : '';\n } else if (pos === 'innerText') {\n // Set innerText\n targetEl.innerText = res !== undefined && res !== null ? String(res) : '';\n } else {\n /*\n <!-- beforebegin -->\n <p>\n <!-- afterbegin -->\n foo\n <!-- beforeend -->\n </p>\n <!-- afterend -->\n */\n if (pos === 'beforeEnd') targetEl.append(...nodes);\n else if (pos === 'afterBegin') targetEl.prepend(...nodes);\n else if (pos === 'beforeBegin') targetEl.before(...nodes);\n else if (pos === 'afterEnd') targetEl.after(...nodes);\n }\n }\n }\n return res;\n };\n };\n}\n\nexport const findAllApplyNodeMetadata = (target: any): Map<string | symbol, ApplyNodeMetadata> => {\n const result = new Map<string | symbol, ApplyNodeMetadata>();\n const maps = ReflectUtils.findAllMetadata<Map<string | symbol, ApplyNodeMetadata>>(APPLY_NODE_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\n/**\n * @applyNodeHost decorator - simplified version of @applyNode for :host selector\n * Usage: @applyNodeHost() addItem() { return '<li>New Item</li>'; }\n * Usage: @applyNodeHost({ position: 'afterBegin' }) prependItem() { return '<h1>Title</h1>'; }\n */\nexport function applyNodeHost(options: ApplyNodeOptions = { position: 'beforeEnd' }): MethodDecorator {\n return applyNode(':host', options);\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA
|
|
4
|
+
"sourcesContent": ["import { ReflectUtils } from '@dooboostore/core';\nimport { ensureInit, getElementConfig } from './elementDefine';\nimport { SwcRootType } from '../types';\n\nexport type ApplyNodePosition = 'beforeBegin' | 'afterBegin' | 'beforeEnd' | 'afterEnd' | 'replace' | 'replaceChildren' | 'innerHtml' | 'innerText' | 'remove';\n\nexport interface ApplyNodeOptions {\n position?: ApplyNodePosition;\n root?: SwcRootType;\n}\n\nexport interface ApplyNodeMetadata {\n propertyKey: string | symbol;\n selector: string;\n options: ApplyNodeOptions;\n}\n\nexport const APPLY_NODE_METADATA_KEY = Symbol('simple-web-component:apply-node');\n\nconst normalizeNodes = (res: any, doc: Document): Node[] => {\n const items = Array.isArray(res) ? res : [res];\n return items.map(it => {\n if (it instanceof Node) return it;\n return doc.createTextNode(it !== undefined && it !== null ? String(it) : '');\n });\n};\n\n/**\n * @applyNode decorator to surgically add/replace nodes to a target element.\n * \n * Usage examples:\n * @applyNode('#list') addItem() { return '<li>New Item</li>'; } // append at end\n * @applyNode('#header', { position: 'afterBegin' }) prependItem() { return '<h1>Title</h1>'; } // prepend at start\n * @applyNode('#item', { position: 'replace' }) replaceItem() { return '<div>Replaced</div>'; } // replace element\n * @applyNode('#list', { position: 'replaceChildren' }) updateList() { return [item1, item2]; } // replace all children\n * @applyNode('#notification', { position: 'remove' }) dismissNotification() { return shouldDismiss; } // remove if truthy\n * @applyNode('.items', { position: 'remove', root: 'shadow' }) clearItems() { return true; } // remove shadow DOM elements\n * \n * Positions:\n * - 'beforeEnd' (default): Append at end of target\n * - 'afterBegin': Prepend at start of target\n * - 'beforeBegin': Insert before target\n * - 'afterEnd': Insert after target\n * - 'replace': Replace the entire target element\n * - 'replaceChildren': Replace all children of target element\n * - 'innerHtml': Set target's innerHTML\n * - 'innerText': Set target's innerText\n * - 'remove': Remove target element if returned value is truthy\n * \n * Root Options:\n * - 'auto' (default): Search shadow DOM first, then light DOM\n * - 'shadow': Search only in shadow DOM\n * - 'light': Search only in light DOM\n * - 'all': Use both (shadow preferred for query, both for remove)\n */\nexport function applyNode(selector: string, options: ApplyNodeOptions = { position: 'beforeEnd' }): MethodDecorator {\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\n const constructor = target.constructor;\n let metaList = ReflectUtils.getOwnMetadata(APPLY_NODE_METADATA_KEY, constructor) as Map<string | symbol, ApplyNodeMetadata>;\n if (!metaList) {\n metaList = new Map<string | symbol, ApplyNodeMetadata>();\n ReflectUtils.defineMetadata(APPLY_NODE_METADATA_KEY, metaList, constructor);\n }\n metaList.set(propertyKey, { propertyKey, selector, options });\n\n const original = descriptor.value;\n descriptor.value = async function (...args: any[]) {\n ensureInit(this);\n const res = await original.apply(this, args);\n if (res !== undefined) {\n const conf = getElementConfig(this);\n const currentWin = (this as any)._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as Window);\n const currentDoc = currentWin.document;\n\n const pos = options.position || 'beforeEnd';\n const r = options.root || 'auto';\n\n const getTargetRoot = () => {\n if (r === 'shadow') return this.shadowRoot;\n if (r === 'light') return this as any;\n if (r === 'all') return this.shadowRoot || (this as any);\n return this.shadowRoot || (this as any); // auto\n };\n\n if (pos === 'remove') {\n // Remove element(s) if returned value is truthy\n if (res) {\n if (selector === ':host' || !selector) {\n if (r === 'shadow' && this.shadowRoot) {\n // Remove all children from shadow DOM\n this.shadowRoot.replaceChildren();\n } else {\n // Remove the component itself\n (this as any).remove();\n }\n } else {\n const targetRoot = getTargetRoot();\n if (targetRoot) {\n const targets = targetRoot.querySelectorAll(selector);\n targets.forEach((el: Element) => el.remove());\n }\n }\n }\n } else {\n let targetEl: any = null;\n if (selector === ':host' || !selector) {\n if (r === 'shadow') {\n targetEl = this.shadowRoot; // Target shadow DOM root\n } else {\n targetEl = this as any; // Target the component itself\n }\n } else {\n const targetRoot = getTargetRoot();\n targetEl = targetRoot ? targetRoot.querySelector(selector) : null;\n }\n\n if (targetEl) {\n const isShadowRoot = targetEl instanceof ShadowRoot;\n const nodes = normalizeNodes(res, currentDoc);\n\n if (pos === 'replace') {\n // ShadowRoot doesn't support replaceWith\n if (!isShadowRoot) {\n targetEl.replaceWith(...nodes);\n }\n } else if (pos === 'replaceChildren') {\n // Replace all children of target element\n targetEl.replaceChildren(...nodes);\n } else if (pos === 'innerHtml') {\n // Set innerHTML\n targetEl.innerHTML = res !== undefined && res !== null ? String(res) : '';\n } else if (pos === 'innerText') {\n // Set innerText\n if (targetEl.innerText !== undefined) {\n targetEl.innerText = res !== undefined && res !== null ? String(res) : '';\n }\n } else {\n /*\n <!-- beforebegin -->\n <p>\n <!-- afterbegin -->\n foo\n <!-- beforeend -->\n </p>\n <!-- afterend -->\n */\n if (pos === 'beforeEnd') targetEl.append(...nodes);\n else if (pos === 'afterBegin') targetEl.prepend(...nodes);\n else if (pos === 'beforeBegin' && !isShadowRoot) targetEl.before(...nodes);\n else if (pos === 'afterEnd' && !isShadowRoot) targetEl.after(...nodes);\n }\n }\n }\n }\n return res;\n };\n };\n}\n\nexport const findAllApplyNodeMetadata = (target: any): Map<string | symbol, ApplyNodeMetadata> => {\n const result = new Map<string | symbol, ApplyNodeMetadata>();\n const maps = ReflectUtils.findAllMetadata<Map<string | symbol, ApplyNodeMetadata>>(APPLY_NODE_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\n/**\n * @applyNodeHost decorator - simplified version of @applyNode for :host selector\n * Usage: @applyNodeHost() addItem() { return '<li>New Item</li>'; }\n * Usage: @applyNodeHost({ position: 'afterBegin' }) prependItem() { return '<h1>Title</h1>'; }\n */\nexport function applyNodeHost(options: ApplyNodeOptions = { position: 'beforeEnd' }): MethodDecorator {\n return applyNode(':host', options);\n}\n\n// Convenience decorators for specific positions\n\n/**\n * @applyBeforeBeginNode - Insert before target element\n */\nexport const applyBeforeBeginNode = (selector: string, options: ApplyNodeOptions = {}) => \n applyNode(selector, { ...options, position: 'beforeBegin' });\n\n/**\n * @applyAfterBeginNode - Prepend to target element\n */\nexport const applyAfterBeginNode = (selector: string, options: ApplyNodeOptions = {}) => \n applyNode(selector, { ...options, position: 'afterBegin' });\n\n/**\n * @applyBeforeEndNode - Append to target element (default)\n */\nexport const applyBeforeEndNode = (selector: string, options: ApplyNodeOptions = {}) => \n applyNode(selector, { ...options, position: 'beforeEnd' });\n\n/**\n * @applyAfterEndNode - Insert after target element\n */\nexport const applyAfterEndNode = (selector: string, options: ApplyNodeOptions = {}) => \n applyNode(selector, { ...options, position: 'afterEnd' });\n\n/**\n * @applyReplaceNode - Replace entire target element\n */\nexport const applyReplaceNode = (selector: string, options: ApplyNodeOptions = {}) => \n applyNode(selector, { ...options, position: 'replace' });\n\n/**\n * @applyReplaceChildrenNode - Replace all children of target element\n */\nexport const applyReplaceChildrenNode = (selector: string, options: ApplyNodeOptions = {}) => \n applyNode(selector, { ...options, position: 'replaceChildren' });\n\n/**\n * @applyInnerHtmlNode - Set target's innerHTML\n */\nexport const applyInnerHtmlNode = (selector: string, options: ApplyNodeOptions = {}) => \n applyNode(selector, { ...options, position: 'innerHtml' });\n\n/**\n * @applyInnerTextNode - Set target's innerText\n */\nexport const applyInnerTextNode = (selector: string, options: ApplyNodeOptions = {}) => \n applyNode(selector, { ...options, position: 'innerText' });\n\n/**\n * @applyRemoveNode - Remove target element if truthy\n */\nexport const applyRemoveNode = (selector: string, options: ApplyNodeOptions = {}) => \n applyNode(selector, { ...options, position: 'remove' });\n\n// Host versions\n\n/**\n * @applyBeforeBeginNodeHost - Insert before :host\n */\nexport const applyBeforeBeginNodeHost = (options: ApplyNodeOptions = {}) => \n applyNode(':host', { ...options, position: 'beforeBegin' });\n\n/**\n * @applyAfterBeginNodeHost - Prepend to :host\n */\nexport const applyAfterBeginNodeHost = (options: ApplyNodeOptions = {}) => \n applyNode(':host', { ...options, position: 'afterBegin' });\n\n/**\n * @applyBeforeEndNodeHost - Append to :host\n */\nexport const applyBeforeEndNodeHost = (options: ApplyNodeOptions = {}) => \n applyNode(':host', { ...options, position: 'beforeEnd' });\n\n/**\n * @applyAfterEndNodeHost - Insert after :host\n */\nexport const applyAfterEndNodeHost = (options: ApplyNodeOptions = {}) => \n applyNode(':host', { ...options, position: 'afterEnd' });\n\n/**\n * @applyReplaceNodeHost - Replace :host\n */\nexport const applyReplaceNodeHost = (options: ApplyNodeOptions = {}) => \n applyNode(':host', { ...options, position: 'replace' });\n\n/**\n * @applyReplaceChildrenNodeHost - Replace children of :host\n */\nexport const applyReplaceChildrenNodeHost = (options: ApplyNodeOptions = {}) => \n applyNode(':host', { ...options, position: 'replaceChildren' });\n\n/**\n * @applyInnerHtmlNodeHost - Set :host innerHTML\n */\nexport const applyInnerHtmlNodeHost = (options: ApplyNodeOptions = {}) => \n applyNode(':host', { ...options, position: 'innerHtml' });\n\n/**\n * @applyInnerTextNodeHost - Set :host innerText\n */\nexport const applyInnerTextNodeHost = (options: ApplyNodeOptions = {}) => \n applyNode(':host', { ...options, position: 'innerText' });\n\n/**\n * @applyRemoveNodeHost - Remove :host if truthy\n */\nexport const applyRemoveNodeHost = (options: ApplyNodeOptions = {}) => \n applyNode(':host', { ...options, position: 'remove' });\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|