@mcp-elements/angular 0.1.0 → 0.1.2
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/dist/index.d.ts +506 -0
- package/dist/index.js +2738 -0
- package/dist/index.js.map +1 -0
- package/package.json +28 -11
- package/src/accordion.component.ts +0 -74
- package/src/ai-badge.component.ts +0 -26
- package/src/alert.component.ts +0 -25
- package/src/avatar.component.ts +0 -24
- package/src/badge.component.ts +0 -17
- package/src/button.component.ts +0 -27
- package/src/card.component.ts +0 -46
- package/src/chat-bubble.component.ts +0 -53
- package/src/chips.component.ts +0 -33
- package/src/counter.component.ts +0 -48
- package/src/dialog.component.ts +0 -42
- package/src/drawer.component.ts +0 -48
- package/src/dropdown-menu.component.ts +0 -62
- package/src/feedback.component.ts +0 -71
- package/src/index.ts +0 -86
- package/src/input.component.ts +0 -46
- package/src/loader.component.ts +0 -12
- package/src/mcp/index.ts +0 -9
- package/src/mcp/mcp-app-frame.component.ts +0 -60
- package/src/mcp/mcp-consent-dialog.component.ts +0 -63
- package/src/mcp/mcp-resource-browser.component.ts +0 -86
- package/src/mcp/mcp-scope-inspector.component.ts +0 -81
- package/src/mcp/mcp-server-status.component.ts +0 -44
- package/src/mcp/mcp-tool-call.component.ts +0 -105
- package/src/mcp/mcp-tool-form.component.ts +0 -127
- package/src/password-input.component.ts +0 -35
- package/src/popover.component.ts +0 -40
- package/src/progress.component.ts +0 -20
- package/src/prompt-input.component.ts +0 -70
- package/src/select.component.ts +0 -106
- package/src/separator.component.ts +0 -15
- package/src/skeleton.component.ts +0 -11
- package/src/source-card.component.ts +0 -34
- package/src/streaming-text.component.ts +0 -43
- package/src/suggestion-chips.component.ts +0 -23
- package/src/switch.component.ts +0 -32
- package/src/tabs.component.ts +0 -95
- package/src/textarea.component.ts +0 -22
- package/src/toast.component.ts +0 -62
- package/src/tooltip.directive.ts +0 -63
package/src/select.component.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { Component, input, output, signal, computed, ElementRef, viewChild, HostListener } from '@angular/core'
|
|
2
|
-
import { createSelect, type SelectOption } from '@mcp-elements/core'
|
|
3
|
-
|
|
4
|
-
@Component({
|
|
5
|
-
selector: 'mcpe-select',
|
|
6
|
-
standalone: true,
|
|
7
|
-
template: `
|
|
8
|
-
<div class="relative" #container>
|
|
9
|
-
<button
|
|
10
|
-
class="mcpe-select-trigger"
|
|
11
|
-
[attr.aria-expanded]="isOpen()"
|
|
12
|
-
aria-haspopup="listbox"
|
|
13
|
-
(click)="toggle()"
|
|
14
|
-
(keydown)="onKeyDown($event)"
|
|
15
|
-
>
|
|
16
|
-
<span>{{ selectedLabel() || placeholder() }}</span>
|
|
17
|
-
<svg class="h-4 w-4 opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
18
|
-
<path d="m6 9 6 6 6-6" />
|
|
19
|
-
</svg>
|
|
20
|
-
</button>
|
|
21
|
-
@if (isOpen()) {
|
|
22
|
-
<div class="mcpe-select-content absolute top-full mt-1 w-full">
|
|
23
|
-
<div class="mcpe-select-viewport" role="listbox">
|
|
24
|
-
@for (option of options(); track option.value; let i = $index) {
|
|
25
|
-
<div
|
|
26
|
-
role="option"
|
|
27
|
-
[attr.aria-selected]="option.value === selectedValue()"
|
|
28
|
-
[attr.aria-disabled]="option.disabled"
|
|
29
|
-
[class]="getItemClasses(option, i)"
|
|
30
|
-
(click)="selectOption(option)"
|
|
31
|
-
(mouseenter)="highlightedIndex.set(i)"
|
|
32
|
-
>
|
|
33
|
-
{{ option.label }}
|
|
34
|
-
</div>
|
|
35
|
-
}
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
}
|
|
39
|
-
</div>
|
|
40
|
-
`,
|
|
41
|
-
host: {
|
|
42
|
-
'(document:click)': 'onDocumentClick($event)',
|
|
43
|
-
},
|
|
44
|
-
})
|
|
45
|
-
export class SnxSelectComponent {
|
|
46
|
-
options = input<SelectOption[]>([])
|
|
47
|
-
placeholder = input('Select...')
|
|
48
|
-
valueChange = output<string>()
|
|
49
|
-
|
|
50
|
-
isOpen = signal(false)
|
|
51
|
-
selectedValue = signal<string | null>(null)
|
|
52
|
-
highlightedIndex = signal(0)
|
|
53
|
-
|
|
54
|
-
container = viewChild<ElementRef>('container')
|
|
55
|
-
|
|
56
|
-
selectedLabel = computed(() => {
|
|
57
|
-
const val = this.selectedValue()
|
|
58
|
-
return this.options().find(o => o.value === val)?.label ?? ''
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
toggle() { this.isOpen.update(v => !v) }
|
|
62
|
-
|
|
63
|
-
selectOption(option: SelectOption) {
|
|
64
|
-
if (option.disabled) return
|
|
65
|
-
this.selectedValue.set(option.value)
|
|
66
|
-
this.valueChange.emit(option.value)
|
|
67
|
-
this.isOpen.set(false)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getItemClasses(option: SelectOption, index: number): string {
|
|
71
|
-
return [
|
|
72
|
-
'mcpe-select-item',
|
|
73
|
-
index === this.highlightedIndex() ? 'mcpe-select-item-active' : '',
|
|
74
|
-
option.value === this.selectedValue() ? 'mcpe-select-item-selected' : '',
|
|
75
|
-
].filter(Boolean).join(' ')
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
onKeyDown(event: KeyboardEvent) {
|
|
79
|
-
const opts = this.options().filter(o => !o.disabled)
|
|
80
|
-
if (event.key === 'ArrowDown') {
|
|
81
|
-
event.preventDefault()
|
|
82
|
-
if (!this.isOpen()) { this.isOpen.set(true); return }
|
|
83
|
-
this.highlightedIndex.update(i => (i + 1) % opts.length)
|
|
84
|
-
} else if (event.key === 'ArrowUp') {
|
|
85
|
-
event.preventDefault()
|
|
86
|
-
this.highlightedIndex.update(i => (i - 1 + opts.length) % opts.length)
|
|
87
|
-
} else if (event.key === 'Enter' || event.key === ' ') {
|
|
88
|
-
event.preventDefault()
|
|
89
|
-
if (this.isOpen()) {
|
|
90
|
-
const opt = opts[this.highlightedIndex()]
|
|
91
|
-
if (opt) this.selectOption(opt)
|
|
92
|
-
} else {
|
|
93
|
-
this.isOpen.set(true)
|
|
94
|
-
}
|
|
95
|
-
} else if (event.key === 'Escape') {
|
|
96
|
-
this.isOpen.set(false)
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
onDocumentClick(event: MouseEvent) {
|
|
101
|
-
const el = this.container()?.nativeElement
|
|
102
|
-
if (el && !el.contains(event.target as Node)) {
|
|
103
|
-
this.isOpen.set(false)
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Component, input, computed } from '@angular/core'
|
|
2
|
-
|
|
3
|
-
@Component({
|
|
4
|
-
selector: 'mcpe-separator',
|
|
5
|
-
standalone: true,
|
|
6
|
-
template: `<div [class]="classes()" role="separator" [attr.aria-orientation]="orientation()"></div>`,
|
|
7
|
-
})
|
|
8
|
-
export class SnxSeparatorComponent {
|
|
9
|
-
orientation = input<'horizontal' | 'vertical'>('horizontal')
|
|
10
|
-
class = input('')
|
|
11
|
-
|
|
12
|
-
classes = computed(() =>
|
|
13
|
-
['mcpe-separator', `mcpe-separator-${this.orientation()}`, this.class()].filter(Boolean).join(' ')
|
|
14
|
-
)
|
|
15
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Component, input, computed } from '@angular/core'
|
|
2
|
-
|
|
3
|
-
@Component({
|
|
4
|
-
selector: 'mcpe-skeleton',
|
|
5
|
-
standalone: true,
|
|
6
|
-
template: `<div [class]="classes()"></div>`,
|
|
7
|
-
})
|
|
8
|
-
export class SnxSkeletonComponent {
|
|
9
|
-
class = input('')
|
|
10
|
-
classes = computed(() => ['mcpe-skeleton', this.class()].filter(Boolean).join(' '))
|
|
11
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Component, input } from '@angular/core'
|
|
2
|
-
|
|
3
|
-
@Component({
|
|
4
|
-
selector: 'mcpe-source-cards',
|
|
5
|
-
standalone: true,
|
|
6
|
-
template: `<div class="mcpe-source-cards"><ng-content /></div>`,
|
|
7
|
-
})
|
|
8
|
-
export class SnxSourceCardsComponent {}
|
|
9
|
-
|
|
10
|
-
@Component({
|
|
11
|
-
selector: 'mcpe-source-card',
|
|
12
|
-
standalone: true,
|
|
13
|
-
template: `
|
|
14
|
-
<a [href]="href()" class="mcpe-source-card" target="_blank" rel="noopener noreferrer">
|
|
15
|
-
@if (favicon()) {
|
|
16
|
-
<img class="mcpe-source-card-favicon" [src]="favicon()" [alt]="domain()" />
|
|
17
|
-
}
|
|
18
|
-
<div class="mcpe-source-card-body">
|
|
19
|
-
<p class="mcpe-source-card-title">{{ title() }}</p>
|
|
20
|
-
<p class="mcpe-source-card-domain">{{ domain() }}</p>
|
|
21
|
-
</div>
|
|
22
|
-
@if (index()) {
|
|
23
|
-
<span class="mcpe-source-card-index">{{ index() }}</span>
|
|
24
|
-
}
|
|
25
|
-
</a>
|
|
26
|
-
`,
|
|
27
|
-
})
|
|
28
|
-
export class SnxSourceCardComponent {
|
|
29
|
-
href = input.required<string>()
|
|
30
|
-
favicon = input('')
|
|
31
|
-
title = input('')
|
|
32
|
-
domain = input('')
|
|
33
|
-
index = input<number | undefined>(undefined)
|
|
34
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Component } from '@angular/core'
|
|
2
|
-
|
|
3
|
-
@Component({
|
|
4
|
-
selector: 'mcpe-streaming-text',
|
|
5
|
-
standalone: true,
|
|
6
|
-
template: `<div class="mcpe-streaming-text-cursor"><ng-content /></div>`,
|
|
7
|
-
})
|
|
8
|
-
export class SnxStreamingTextComponent {}
|
|
9
|
-
|
|
10
|
-
@Component({
|
|
11
|
-
selector: 'mcpe-streaming-text-fade-in',
|
|
12
|
-
standalone: true,
|
|
13
|
-
template: `<span class="mcpe-streaming-text-fade-in"><ng-content /></span>`,
|
|
14
|
-
})
|
|
15
|
-
export class SnxStreamingTextFadeInComponent {}
|
|
16
|
-
|
|
17
|
-
@Component({
|
|
18
|
-
selector: 'mcpe-streaming-text-word',
|
|
19
|
-
standalone: true,
|
|
20
|
-
template: `<span class="mcpe-streaming-text-word"><ng-content /></span>`,
|
|
21
|
-
})
|
|
22
|
-
export class SnxStreamingTextWordComponent {}
|
|
23
|
-
|
|
24
|
-
@Component({
|
|
25
|
-
selector: 'mcpe-streaming-text-line',
|
|
26
|
-
standalone: true,
|
|
27
|
-
template: `<div class="mcpe-streaming-text-line"><ng-content /></div>`,
|
|
28
|
-
})
|
|
29
|
-
export class SnxStreamingTextLineComponent {}
|
|
30
|
-
|
|
31
|
-
@Component({
|
|
32
|
-
selector: 'mcpe-streaming-text-skeleton',
|
|
33
|
-
standalone: true,
|
|
34
|
-
template: `<div class="mcpe-streaming-text-skeleton"><ng-content /></div>`,
|
|
35
|
-
})
|
|
36
|
-
export class SnxStreamingTextSkeletonComponent {}
|
|
37
|
-
|
|
38
|
-
@Component({
|
|
39
|
-
selector: 'mcpe-streaming-text-skeleton-line',
|
|
40
|
-
standalone: true,
|
|
41
|
-
template: `<div class="mcpe-streaming-text-skeleton-line"></div>`,
|
|
42
|
-
})
|
|
43
|
-
export class SnxStreamingTextSkeletonLineComponent {}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Component, input, computed } from '@angular/core'
|
|
2
|
-
|
|
3
|
-
type SuggestionChipVariant = 'default' | 'primary' | 'outline'
|
|
4
|
-
|
|
5
|
-
@Component({
|
|
6
|
-
selector: 'mcpe-suggestion-chips',
|
|
7
|
-
standalone: true,
|
|
8
|
-
template: `<div class="mcpe-suggestion-chips"><ng-content /></div>`,
|
|
9
|
-
})
|
|
10
|
-
export class SnxSuggestionChipsComponent {}
|
|
11
|
-
|
|
12
|
-
@Component({
|
|
13
|
-
selector: 'mcpe-suggestion-chip',
|
|
14
|
-
standalone: true,
|
|
15
|
-
template: `<button [class]="classes()" type="button"><ng-content /></button>`,
|
|
16
|
-
})
|
|
17
|
-
export class SnxSuggestionChipComponent {
|
|
18
|
-
variant = input<SuggestionChipVariant>('default')
|
|
19
|
-
class = input('')
|
|
20
|
-
classes = computed(() =>
|
|
21
|
-
['mcpe-suggestion-chip', `mcpe-suggestion-chip-${this.variant()}`, this.class()].filter(Boolean).join(' ')
|
|
22
|
-
)
|
|
23
|
-
}
|
package/src/switch.component.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { Component, input, output, signal, computed } from '@angular/core'
|
|
2
|
-
|
|
3
|
-
@Component({
|
|
4
|
-
selector: 'mcpe-switch',
|
|
5
|
-
standalone: true,
|
|
6
|
-
template: `
|
|
7
|
-
<button
|
|
8
|
-
type="button"
|
|
9
|
-
role="switch"
|
|
10
|
-
[attr.aria-checked]="checked()"
|
|
11
|
-
[attr.aria-disabled]="disabled()"
|
|
12
|
-
[disabled]="disabled()"
|
|
13
|
-
[class]="'mcpe-switch'"
|
|
14
|
-
(click)="toggle()"
|
|
15
|
-
(keydown.space)="$event.preventDefault(); toggle()"
|
|
16
|
-
(keydown.enter)="$event.preventDefault(); toggle()"
|
|
17
|
-
>
|
|
18
|
-
<span class="mcpe-switch-thumb"></span>
|
|
19
|
-
</button>
|
|
20
|
-
`,
|
|
21
|
-
})
|
|
22
|
-
export class SnxSwitchComponent {
|
|
23
|
-
checked = signal(false)
|
|
24
|
-
disabled = input(false)
|
|
25
|
-
checkedChange = output<boolean>()
|
|
26
|
-
|
|
27
|
-
toggle() {
|
|
28
|
-
if (this.disabled()) return
|
|
29
|
-
this.checked.update(v => !v)
|
|
30
|
-
this.checkedChange.emit(this.checked())
|
|
31
|
-
}
|
|
32
|
-
}
|
package/src/tabs.component.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { Component, input, output, signal, computed, effect, contentChildren, ElementRef } from '@angular/core'
|
|
2
|
-
import { createTabs, type TabItem } from '@mcp-elements/core'
|
|
3
|
-
|
|
4
|
-
@Component({
|
|
5
|
-
selector: 'mcpe-tabs',
|
|
6
|
-
standalone: true,
|
|
7
|
-
template: `<div><ng-content /></div>`,
|
|
8
|
-
})
|
|
9
|
-
export class SnxTabsComponent {
|
|
10
|
-
items = input<TabItem[]>([])
|
|
11
|
-
defaultValue = input<string>('')
|
|
12
|
-
activeValue = signal('')
|
|
13
|
-
|
|
14
|
-
private api = computed(() =>
|
|
15
|
-
createTabs(this.items(), {
|
|
16
|
-
defaultValue: this.defaultValue(),
|
|
17
|
-
onValueChange: (v) => this.activeValue.set(v),
|
|
18
|
-
})
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
effect(() => {
|
|
23
|
-
const def = this.defaultValue()
|
|
24
|
-
const items = this.items()
|
|
25
|
-
if (def) {
|
|
26
|
-
this.activeValue.set(def)
|
|
27
|
-
} else if (items.length > 0) {
|
|
28
|
-
this.activeValue.set(items[0].value)
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getTabProps(value: string) {
|
|
34
|
-
return this.api().getTriggerProps(value, this.activeValue())
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
getPanelProps(value: string) {
|
|
38
|
-
return this.api().getPanelProps(value, this.activeValue())
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
isActive(value: string): boolean {
|
|
42
|
-
return this.activeValue() === value
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
select(value: string) {
|
|
46
|
-
this.activeValue.set(value)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
@Component({
|
|
51
|
-
selector: 'mcpe-tabs-list',
|
|
52
|
-
standalone: true,
|
|
53
|
-
template: `<div role="tablist" class="mcpe-tabs-list"><ng-content /></div>`,
|
|
54
|
-
})
|
|
55
|
-
export class SnxTabsListComponent {}
|
|
56
|
-
|
|
57
|
-
@Component({
|
|
58
|
-
selector: 'mcpe-tabs-trigger',
|
|
59
|
-
standalone: true,
|
|
60
|
-
template: `
|
|
61
|
-
<button
|
|
62
|
-
role="tab"
|
|
63
|
-
[class]="classes()"
|
|
64
|
-
[attr.aria-selected]="isActive()"
|
|
65
|
-
[attr.tabindex]="isActive() ? 0 : -1"
|
|
66
|
-
(click)="onClick.emit()"
|
|
67
|
-
>
|
|
68
|
-
<ng-content />
|
|
69
|
-
</button>
|
|
70
|
-
`,
|
|
71
|
-
})
|
|
72
|
-
export class SnxTabsTriggerComponent {
|
|
73
|
-
isActive = input(false)
|
|
74
|
-
onClick = output<void>()
|
|
75
|
-
class = input('')
|
|
76
|
-
|
|
77
|
-
classes = computed(() =>
|
|
78
|
-
['mcpe-tabs-trigger', this.isActive() ? 'mcpe-tabs-trigger-active' : '', this.class()]
|
|
79
|
-
.filter(Boolean)
|
|
80
|
-
.join(' ')
|
|
81
|
-
)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
@Component({
|
|
85
|
-
selector: 'mcpe-tabs-content',
|
|
86
|
-
standalone: true,
|
|
87
|
-
template: `
|
|
88
|
-
@if (isActive()) {
|
|
89
|
-
<div role="tabpanel" class="mcpe-tabs-content"><ng-content /></div>
|
|
90
|
-
}
|
|
91
|
-
`,
|
|
92
|
-
})
|
|
93
|
-
export class SnxTabsContentComponent {
|
|
94
|
-
isActive = input(false)
|
|
95
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Component, input, computed } from '@angular/core'
|
|
2
|
-
|
|
3
|
-
@Component({
|
|
4
|
-
selector: 'mcpe-textarea',
|
|
5
|
-
standalone: true,
|
|
6
|
-
template: `
|
|
7
|
-
<textarea
|
|
8
|
-
[class]="classes()"
|
|
9
|
-
[placeholder]="placeholder()"
|
|
10
|
-
[disabled]="disabled()"
|
|
11
|
-
[rows]="rows()"
|
|
12
|
-
><ng-content /></textarea>
|
|
13
|
-
`,
|
|
14
|
-
})
|
|
15
|
-
export class SnxTextareaComponent {
|
|
16
|
-
placeholder = input('')
|
|
17
|
-
disabled = input(false)
|
|
18
|
-
rows = input(3)
|
|
19
|
-
class = input('')
|
|
20
|
-
|
|
21
|
-
classes = computed(() => ['mcpe-textarea', this.class()].filter(Boolean).join(' '))
|
|
22
|
-
}
|
package/src/toast.component.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Component, Injectable, signal } from '@angular/core'
|
|
2
|
-
|
|
3
|
-
export interface ToastData {
|
|
4
|
-
id: string
|
|
5
|
-
title?: string
|
|
6
|
-
description?: string
|
|
7
|
-
variant?: 'default' | 'destructive' | 'success'
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
@Injectable({ providedIn: 'root' })
|
|
11
|
-
export class SnxToastService {
|
|
12
|
-
toasts = signal<ToastData[]>([])
|
|
13
|
-
private counter = 0
|
|
14
|
-
|
|
15
|
-
show(toast: Omit<ToastData, 'id'>, duration = 5000): string {
|
|
16
|
-
const id = `toast-${++this.counter}`
|
|
17
|
-
this.toasts.update(t => [...t, { id, ...toast }])
|
|
18
|
-
if (duration > 0) {
|
|
19
|
-
setTimeout(() => this.dismiss(id), duration)
|
|
20
|
-
}
|
|
21
|
-
return id
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
success(title: string, description?: string) {
|
|
25
|
-
return this.show({ title, description, variant: 'success' })
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
error(title: string, description?: string) {
|
|
29
|
-
return this.show({ title, description, variant: 'destructive' })
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
dismiss(id: string) {
|
|
33
|
-
this.toasts.update(t => t.filter(x => x.id !== id))
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
@Component({
|
|
38
|
-
selector: 'mcpe-toaster',
|
|
39
|
-
standalone: true,
|
|
40
|
-
template: `
|
|
41
|
-
<div class="mcpe-toaster mcpe-toaster-bottom-right">
|
|
42
|
-
@for (t of toastService.toasts(); track t.id) {
|
|
43
|
-
<div
|
|
44
|
-
[class]="'mcpe-toast group' + (t.variant === 'destructive' ? ' mcpe-toast-destructive' : '') + (t.variant === 'success' ? ' mcpe-toast-success' : '')"
|
|
45
|
-
>
|
|
46
|
-
<div class="flex-1">
|
|
47
|
-
@if (t.title) { <div class="mcpe-toast-title">{{ t.title }}</div> }
|
|
48
|
-
@if (t.description) { <div class="mcpe-toast-description">{{ t.description }}</div> }
|
|
49
|
-
</div>
|
|
50
|
-
<button class="mcpe-toast-close" (click)="toastService.dismiss(t.id)" aria-label="Close">
|
|
51
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
52
|
-
<path d="M18 6 6 18" /><path d="m6 6 12 12" />
|
|
53
|
-
</svg>
|
|
54
|
-
</button>
|
|
55
|
-
</div>
|
|
56
|
-
}
|
|
57
|
-
</div>
|
|
58
|
-
`,
|
|
59
|
-
})
|
|
60
|
-
export class SnxToasterComponent {
|
|
61
|
-
constructor(public toastService: SnxToastService) {}
|
|
62
|
-
}
|
package/src/tooltip.directive.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Directive, input, HostListener, ElementRef, Renderer2, OnDestroy } from '@angular/core'
|
|
2
|
-
|
|
3
|
-
@Directive({
|
|
4
|
-
selector: '[mcpeTooltip]',
|
|
5
|
-
standalone: true,
|
|
6
|
-
})
|
|
7
|
-
export class SnxTooltipDirective implements OnDestroy {
|
|
8
|
-
mcpeTooltip = input<string>('')
|
|
9
|
-
tooltipDelay = input(700)
|
|
10
|
-
|
|
11
|
-
private tooltipEl: HTMLElement | null = null
|
|
12
|
-
private timeoutId: ReturnType<typeof setTimeout> | null = null
|
|
13
|
-
|
|
14
|
-
constructor(private el: ElementRef, private renderer: Renderer2) {}
|
|
15
|
-
|
|
16
|
-
@HostListener('mouseenter')
|
|
17
|
-
@HostListener('focus')
|
|
18
|
-
onShow() {
|
|
19
|
-
this.clearDelay()
|
|
20
|
-
this.timeoutId = setTimeout(() => this.show(), this.tooltipDelay())
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
@HostListener('mouseleave')
|
|
24
|
-
@HostListener('blur')
|
|
25
|
-
onHide() {
|
|
26
|
-
this.clearDelay()
|
|
27
|
-
this.hide()
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
private show() {
|
|
31
|
-
if (this.tooltipEl) return
|
|
32
|
-
this.tooltipEl = this.renderer.createElement('div')
|
|
33
|
-
this.renderer.addClass(this.tooltipEl, 'mcpe-tooltip-content')
|
|
34
|
-
this.renderer.setStyle(this.tooltipEl, 'position', 'absolute')
|
|
35
|
-
this.renderer.setStyle(this.tooltipEl, 'bottom', '100%')
|
|
36
|
-
this.renderer.setStyle(this.tooltipEl, 'left', '50%')
|
|
37
|
-
this.renderer.setStyle(this.tooltipEl, 'transform', 'translateX(-50%)')
|
|
38
|
-
this.renderer.setStyle(this.tooltipEl, 'margin-bottom', '0.5rem')
|
|
39
|
-
const text = this.renderer.createText(this.mcpeTooltip())
|
|
40
|
-
this.renderer.appendChild(this.tooltipEl, text)
|
|
41
|
-
this.renderer.setStyle(this.el.nativeElement, 'position', 'relative')
|
|
42
|
-
this.renderer.appendChild(this.el.nativeElement, this.tooltipEl)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
private hide() {
|
|
46
|
-
if (this.tooltipEl) {
|
|
47
|
-
this.renderer.removeChild(this.el.nativeElement, this.tooltipEl)
|
|
48
|
-
this.tooltipEl = null
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private clearDelay() {
|
|
53
|
-
if (this.timeoutId !== null) {
|
|
54
|
-
clearTimeout(this.timeoutId)
|
|
55
|
-
this.timeoutId = null
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
ngOnDestroy() {
|
|
60
|
-
this.clearDelay()
|
|
61
|
-
this.hide()
|
|
62
|
-
}
|
|
63
|
-
}
|