diff --git a/projects/demo/src/modules/app/app.routes.ts b/projects/demo/src/modules/app/app.routes.ts index 2965f3be0e38..38a5129878d0 100644 --- a/projects/demo/src/modules/app/app.routes.ts +++ b/projects/demo/src/modules/app/app.routes.ts @@ -621,6 +621,11 @@ export const ROUTES: Routes = [ title: 'Rating', loadComponent: async () => import('../components/rating'), }), + route({ + path: DemoRoute.Pulse, + title: 'Pulse', + loadComponent: async () => import('../components/pulse'), + }), route({ path: DemoRoute.Range, loadChildren: async () => diff --git a/projects/demo/src/modules/app/demo-routes.ts b/projects/demo/src/modules/app/demo-routes.ts index c2dca2c22bed..f47f786a09a7 100644 --- a/projects/demo/src/modules/app/demo-routes.ts +++ b/projects/demo/src/modules/app/demo-routes.ts @@ -105,6 +105,7 @@ export const DemoRoute = { Pagination: '/navigation/pagination', Radio: '/components/radio', Rating: '/components/rating', + Pulse: '/components/pulse', Range: '/components/range', CalendarRange: '/components/calendar-range', Select: '/components/select', diff --git a/projects/demo/src/modules/app/pages.ts b/projects/demo/src/modules/app/pages.ts index 6d509ced8284..ade80f415663 100644 --- a/projects/demo/src/modules/app/pages.ts +++ b/projects/demo/src/modules/app/pages.ts @@ -713,6 +713,12 @@ export const pages: TuiDocPages = [ keywords: 'рейтинг, оценка, звезда, rating, star, rate', route: DemoRoute.Rating, }, + { + section: 'Components', + title: 'Pulse', + keywords: 'сигнал, пульс, pulse, signal', + route: DemoRoute.Pulse, + }, { section: 'Components', title: 'Selects', diff --git a/projects/demo/src/modules/components/pulse/examples/1/index.html b/projects/demo/src/modules/components/pulse/examples/1/index.html new file mode 100644 index 000000000000..8f723199212f --- /dev/null +++ b/projects/demo/src/modules/components/pulse/examples/1/index.html @@ -0,0 +1,7 @@ + diff --git a/projects/demo/src/modules/components/pulse/examples/1/index.ts b/projects/demo/src/modules/components/pulse/examples/1/index.ts new file mode 100644 index 000000000000..5eef106d80a5 --- /dev/null +++ b/projects/demo/src/modules/components/pulse/examples/1/index.ts @@ -0,0 +1,14 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; +import {TuiButtonDirective} from '@taiga-ui/core'; +import {TuiPulseComponent} from '@taiga-ui/kit'; + +@Component({ + standalone: true, + imports: [TuiPulseComponent, TuiButtonDirective], + templateUrl: './index.html', + encapsulation, + changeDetection, +}) +export default class ExampleComponent {} diff --git a/projects/demo/src/modules/components/pulse/examples/import/import.md b/projects/demo/src/modules/components/pulse/examples/import/import.md new file mode 100644 index 000000000000..6891482115f3 --- /dev/null +++ b/projects/demo/src/modules/components/pulse/examples/import/import.md @@ -0,0 +1,13 @@ +```ts +import {TuiPulseComponent} from '@taiga-ui/kit'; +// ... + +@Component({ + standalone: true, + imports: [ + // ... + TuiPulseComponent, + ], +}) +export class MyComponent {} +``` diff --git a/projects/demo/src/modules/components/pulse/examples/import/template.md b/projects/demo/src/modules/components/pulse/examples/import/template.md new file mode 100644 index 000000000000..706b79132f54 --- /dev/null +++ b/projects/demo/src/modules/components/pulse/examples/import/template.md @@ -0,0 +1,3 @@ +```html + +``` diff --git a/projects/demo/src/modules/components/pulse/index.html b/projects/demo/src/modules/components/pulse/index.html new file mode 100644 index 000000000000..1999b2484986 --- /dev/null +++ b/projects/demo/src/modules/components/pulse/index.html @@ -0,0 +1,16 @@ + + + + + + + diff --git a/projects/demo/src/modules/components/pulse/index.ts b/projects/demo/src/modules/components/pulse/index.ts new file mode 100644 index 000000000000..926e795dfdb3 --- /dev/null +++ b/projects/demo/src/modules/components/pulse/index.ts @@ -0,0 +1,11 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {TuiDemo} from '@demo/utils'; + +@Component({ + standalone: true, + imports: [TuiDemo], + templateUrl: './index.html', + changeDetection, +}) +export default class PageComponent {} diff --git a/projects/kit/components/index.ts b/projects/kit/components/index.ts index 132c02f12768..a770b2474ec3 100644 --- a/projects/kit/components/index.ts +++ b/projects/kit/components/index.ts @@ -26,6 +26,7 @@ export * from '@taiga-ui/kit/components/pdf-viewer'; export * from '@taiga-ui/kit/components/pin'; export * from '@taiga-ui/kit/components/preview'; export * from '@taiga-ui/kit/components/progress'; +export * from '@taiga-ui/kit/components/pulse'; export * from '@taiga-ui/kit/components/push'; export * from '@taiga-ui/kit/components/radio'; export * from '@taiga-ui/kit/components/radio-list'; diff --git a/projects/kit/components/pulse/index.ts b/projects/kit/components/pulse/index.ts new file mode 100644 index 000000000000..4697b515716a --- /dev/null +++ b/projects/kit/components/pulse/index.ts @@ -0,0 +1 @@ +export * from './pulse.component'; diff --git a/projects/kit/components/pulse/ng-package.json b/projects/kit/components/pulse/ng-package.json new file mode 100644 index 000000000000..bebf62dcb5e5 --- /dev/null +++ b/projects/kit/components/pulse/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "index.ts" + } +} diff --git a/projects/kit/components/pulse/pulse.component.ts b/projects/kit/components/pulse/pulse.component.ts new file mode 100644 index 000000000000..c5d9256fd572 --- /dev/null +++ b/projects/kit/components/pulse/pulse.component.ts @@ -0,0 +1,27 @@ +import {ChangeDetectionStrategy, Component, inject, Input} from '@angular/core'; +import { + TUI_ANIMATIONS_SPEED, + tuiFadeIn, + tuiScaleIn, + tuiToAnimationOptions, +} from '@taiga-ui/core'; + +@Component({ + standalone: true, + selector: 'tui-pulse', + template: '', + styleUrls: ['./pulse.style.less'], + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [tuiFadeIn, tuiScaleIn], + host: { + '[@tuiFadeIn]': 'animation', + '[@tuiScaleIn]': 'animation', + '[style.--t-animation-state]': "playing ? 'running' : 'paused'", + }, +}) +export class TuiPulseComponent { + @Input() + public playing = true; + + protected readonly animation = tuiToAnimationOptions(inject(TUI_ANIMATIONS_SPEED)); +} diff --git a/projects/kit/components/pulse/pulse.style.less b/projects/kit/components/pulse/pulse.style.less new file mode 100644 index 000000000000..19f65568ef32 --- /dev/null +++ b/projects/kit/components/pulse/pulse.style.less @@ -0,0 +1,75 @@ +@keyframes tuiPulse { + 0% { + opacity: 0.3; + transform: scale(1); + } + + 20% { + opacity: 0; + transform: scale(0.5); + } + + 25% { + opacity: 0.3; + transform: scale(1); + } + + 45% { + opacity: 0; + transform: scale(0.5); + } + + 50% { + opacity: 0.3; + transform: scale(1); + } + + 70% { + opacity: 0; + transform: scale(0.5); + } + + 75% { + opacity: 0.3; + transform: scale(1); + } + + 95% { + opacity: 0; + transform: scale(0.5); + } + + 100% { + opacity: 0.3; + transform: scale(1); + } +} + +:host { + position: relative; + color: var(--tui-primary); + + &:before { + content: ''; + position: absolute; + top: -0.5rem; + left: -0.5rem; + width: 1rem; + height: 1rem; + border-radius: 100%; + background: currentColor; + opacity: 0.3; + animation: tuiPulse 3s ease-in-out infinite; + animation-play-state: var(--t-animation-state); + } + + &:after { + content: ''; + position: absolute; + width: 0.5rem; + height: 0.5rem; + border-radius: 100%; + transform: translate(-50%, -50%); + background: currentColor; + } +}