From 53d31a8769367e50615b43e78621886ea225d53f Mon Sep 17 00:00:00 2001 From: Maksim Ivanov Date: Fri, 20 Oct 2023 16:44:05 +0300 Subject: [PATCH] chore(demo): add example about viewport and dropdown (#5683) --- projects/cdk/abstract/portal-host.ts | 2 +- .../dropdown/dropdown-position.directive.ts | 4 +- projects/demo/src/modules/app/app.routes.ts | 9 ++++ projects/demo/src/modules/app/pages.ts | 6 +++ .../viewport/examples/1/index.html | 22 +++++++++ .../viewport/examples/1/index.less | 45 +++++++++++++++++++ .../viewport/examples/1/index.ts | 24 ++++++++++ .../viewport/examples/2/index.html | 36 +++++++++++++++ .../viewport/examples/2/index.ts | 12 +++++ .../viewport/examples/2/portal-host.ts | 38 ++++++++++++++++ .../viewport/examples/import/providers.md | 31 +++++++++++++ .../viewport/viewport.component.ts | 25 +++++++++++ .../customization/viewport/viewport.module.ts | 23 ++++++++++ .../viewport/viewport.template.html | 39 ++++++++++++++++ 14 files changed, 313 insertions(+), 3 deletions(-) create mode 100644 projects/demo/src/modules/customization/viewport/examples/1/index.html create mode 100644 projects/demo/src/modules/customization/viewport/examples/1/index.less create mode 100644 projects/demo/src/modules/customization/viewport/examples/1/index.ts create mode 100644 projects/demo/src/modules/customization/viewport/examples/2/index.html create mode 100644 projects/demo/src/modules/customization/viewport/examples/2/index.ts create mode 100644 projects/demo/src/modules/customization/viewport/examples/2/portal-host.ts create mode 100644 projects/demo/src/modules/customization/viewport/examples/import/providers.md create mode 100644 projects/demo/src/modules/customization/viewport/viewport.component.ts create mode 100644 projects/demo/src/modules/customization/viewport/viewport.module.ts create mode 100644 projects/demo/src/modules/customization/viewport/viewport.template.html diff --git a/projects/cdk/abstract/portal-host.ts b/projects/cdk/abstract/portal-host.ts index 62066be96865..4fa965984d4c 100644 --- a/projects/cdk/abstract/portal-host.ts +++ b/projects/cdk/abstract/portal-host.ts @@ -25,7 +25,7 @@ export abstract class AbstractTuiPortalHostComponent { constructor( @Inject(INJECTOR) private readonly injector: Injector, - @Inject(ElementRef) private readonly el: ElementRef, + @Inject(ElementRef) protected readonly el: ElementRef, @Inject(AbstractTuiPortalService) portalService: AbstractTuiPortalService, ) { portalService.attach(this); diff --git a/projects/core/directives/dropdown/dropdown-position.directive.ts b/projects/core/directives/dropdown/dropdown-position.directive.ts index 43c715565535..e10ad5e0f16c 100644 --- a/projects/core/directives/dropdown/dropdown-position.directive.ts +++ b/projects/core/directives/dropdown/dropdown-position.directive.ts @@ -40,9 +40,9 @@ export class TuiDropdownPositionDirective extends TuiPositionAccessor { const {minHeight, align, direction, offset} = this.options; const viewport = { top: viewportRect.top - offset, - bottom: viewportRect.bottom - offset, + bottom: viewportRect.bottom + offset, right: viewportRect.right - offset, - left: viewportRect.left - offset, + left: viewportRect.left + offset, } as const; const previous = this.previous || direction || 'bottom'; const available = { diff --git a/projects/demo/src/modules/app/app.routes.ts b/projects/demo/src/modules/app/app.routes.ts index 960f1653a9b1..7e9d016c8641 100644 --- a/projects/demo/src/modules/app/app.routes.ts +++ b/projects/demo/src/modules/app/app.routes.ts @@ -146,6 +146,15 @@ export const ROUTES: Routes = [ title: `Portals`, }, }, + { + path: `viewport`, + loadChildren: async () => + (await import(`../customization/viewport/viewport.module`)) + .ExampleTuiViewportModule, + data: { + title: `Viewport`, + }, + }, // COMPONENTS { path: `components/accordion`, diff --git a/projects/demo/src/modules/app/pages.ts b/projects/demo/src/modules/app/pages.ts index 4813a4648c81..8793dade914b 100644 --- a/projects/demo/src/modules/app/pages.ts +++ b/projects/demo/src/modules/app/pages.ts @@ -1079,6 +1079,12 @@ export const pages: TuiDocPages = [ keywords: `portal, custom, theme, style`, route: `/portals`, }, + { + section: `Customization`, + title: `Viewport`, + keywords: `viewport, вьюпорт, портал, контекст, выпадашка, дропдаун, portal, dropdown`, + route: `/viewport`, + }, // Tools { section: `Tools`, diff --git a/projects/demo/src/modules/customization/viewport/examples/1/index.html b/projects/demo/src/modules/customization/viewport/examples/1/index.html new file mode 100644 index 000000000000..d625cfb2097f --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/examples/1/index.html @@ -0,0 +1,22 @@ + diff --git a/projects/demo/src/modules/customization/viewport/examples/1/index.less b/projects/demo/src/modules/customization/viewport/examples/1/index.less new file mode 100644 index 000000000000..6f7c2cde5dc5 --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/examples/1/index.less @@ -0,0 +1,45 @@ +@import 'taiga-ui-local'; + +.dropdowns { + position: relative; + height: 18.75rem; + width: 50%; + display: block; + resize: both; + overflow: auto; + outline: 0.125rem dotted var(--tui-base-04); + + @media @tui-tablet { + width: 100%; + } +} + +.t1, +.t2, +.t3, +.t4 { + position: absolute; + width: 3.125rem; + height: 3.125rem; + background: var(--tui-primary); +} + +.t1 { + top: 0.625rem; + left: 0.625rem; +} + +.t2 { + top: 0.625rem; + right: 0.625rem; +} + +.t3 { + right: 0.625rem; + bottom: 0.625rem; +} + +.t4 { + left: 0.625rem; + bottom: 0.625rem; +} diff --git a/projects/demo/src/modules/customization/viewport/examples/1/index.ts b/projects/demo/src/modules/customization/viewport/examples/1/index.ts new file mode 100644 index 000000000000..f89708ada71f --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/examples/1/index.ts @@ -0,0 +1,24 @@ +import {Component, ElementRef, Inject} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; +import {tuiAsViewport, TuiRectAccessor} from '@taiga-ui/core'; + +@Component({ + selector: 'tui-viewport-example-1', + templateUrl: './index.html', + styleUrls: ['./index.less'], + providers: [tuiAsViewport(TuiViewportExample1)], + changeDetection, + encapsulation, +}) +export class TuiViewportExample1 extends TuiRectAccessor { + readonly type = 'viewport'; + + constructor(@Inject(ElementRef) private readonly el: ElementRef) { + super(); + } + + getClientRect(): ClientRect { + return this.el.nativeElement.getBoundingClientRect(); + } +} diff --git a/projects/demo/src/modules/customization/viewport/examples/2/index.html b/projects/demo/src/modules/customization/viewport/examples/2/index.html new file mode 100644 index 000000000000..2d4570c0ab29 --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/examples/2/index.html @@ -0,0 +1,36 @@ + + + +

+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's + standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make + a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, + remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing + Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions + of Lorem Ipsum. +

+
diff --git a/projects/demo/src/modules/customization/viewport/examples/2/index.ts b/projects/demo/src/modules/customization/viewport/examples/2/index.ts new file mode 100644 index 000000000000..0e9cbbb82019 --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/examples/2/index.ts @@ -0,0 +1,12 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; + +@Component({ + selector: 'tui-viewport-example-2', + templateUrl: './index.html', + styleUrls: ['../1/index.less'], + changeDetection, + encapsulation, +}) +export class TuiViewportExample2 {} diff --git a/projects/demo/src/modules/customization/viewport/examples/2/portal-host.ts b/projects/demo/src/modules/customization/viewport/examples/2/portal-host.ts new file mode 100644 index 000000000000..29e4d8e5255d --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/examples/2/portal-host.ts @@ -0,0 +1,38 @@ +import {ChangeDetectionStrategy, Component} from '@angular/core'; +import { + AbstractTuiPortalHostComponent, + AbstractTuiPortalService, + TuiDropdownPortalService, +} from '@taiga-ui/cdk'; +import {tuiAsViewport, TuiRectAccessor} from '@taiga-ui/core'; + +@Component({ + selector: `[portalHost]`, + template: ` + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + TuiDropdownPortalService, + { + provide: AbstractTuiPortalService, + useExisting: TuiDropdownPortalService, + }, + { + provide: AbstractTuiPortalHostComponent, + useExisting: PortalHost, + }, + tuiAsViewport(PortalHost), + ], +}) +export class PortalHost + extends AbstractTuiPortalHostComponent + implements TuiRectAccessor +{ + readonly type = `viewport`; + + getClientRect(): ClientRect { + return this.el.nativeElement.getBoundingClientRect(); + } +} diff --git a/projects/demo/src/modules/customization/viewport/examples/import/providers.md b/projects/demo/src/modules/customization/viewport/examples/import/providers.md new file mode 100644 index 000000000000..acdc9c927476 --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/examples/import/providers.md @@ -0,0 +1,31 @@ +```ts +import {Component} from '@angular/core'; +import {TUI_VIEWPORT} from '@taiga-ui/core'; + +@Component({ + // ... + providers: [ + { + provide: TUI_VIEWPORT, + useFactory: () => { + const win = inject(WINDOW); + + return { + type: `viewport`, + getClientRect() { + return { + top: 0, + left: 0, + right: win.innerWidth, + bottom: win.innerHeight, + width: win.innerWidth, + height: win.innerHeight, + }; + }, + }; + }, + }, + ], +}) +export class MyComponent {} +``` diff --git a/projects/demo/src/modules/customization/viewport/viewport.component.ts b/projects/demo/src/modules/customization/viewport/viewport.component.ts new file mode 100644 index 000000000000..f10282a85285 --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/viewport.component.ts @@ -0,0 +1,25 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {TuiDocExample} from '@taiga-ui/addon-doc'; + +@Component({ + selector: 'example-tui-viewport', + templateUrl: './viewport.template.html', + changeDetection, +}) +export class ExampleTuiViewportComponent { + readonly providers = import('./examples/import/providers.md?raw'); + + readonly example1: TuiDocExample = { + TypeScript: import('./examples/1/index.ts?raw'), + HTML: import('./examples/1/index.html?raw'), + LESS: import('./examples/1/index.less?raw'), + }; + + readonly example2: TuiDocExample = { + TypeScript: import('./examples/2/index.ts?raw'), + HTML: import('./examples/2/index.html?raw'), + LESS: import('./examples/1/index.less?raw'), // shared + 'portal-host.component.ts': import('./examples/2/portal-host.ts?raw'), + }; +} diff --git a/projects/demo/src/modules/customization/viewport/viewport.module.ts b/projects/demo/src/modules/customization/viewport/viewport.module.ts new file mode 100644 index 000000000000..15dc0b54f3c0 --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/viewport.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {TuiAddonDocModule, tuiGetDocModules} from '@taiga-ui/addon-doc'; +import {TuiDropdownModule} from '@taiga-ui/core'; + +import {TuiViewportExample1} from './examples/1'; +import {TuiViewportExample2} from './examples/2'; +import {PortalHost} from './examples/2/portal-host'; +import {ExampleTuiViewportComponent} from './viewport.component'; + +@NgModule({ + imports: [ + TuiDropdownModule, + TuiAddonDocModule, + tuiGetDocModules(ExampleTuiViewportComponent), + ], + declarations: [ + ExampleTuiViewportComponent, + TuiViewportExample1, + TuiViewportExample2, + PortalHost, + ], +}) +export class ExampleTuiViewportModule {} diff --git a/projects/demo/src/modules/customization/viewport/viewport.template.html b/projects/demo/src/modules/customization/viewport/viewport.template.html new file mode 100644 index 000000000000..1440c9154011 --- /dev/null +++ b/projects/demo/src/modules/customization/viewport/viewport.template.html @@ -0,0 +1,39 @@ + + +

+ TUI_VIEWPORT + - define the area relative to which the position constraints will be calculated. Also you can use + tuiAsViewport + helper instead of token. +

+ + + + + + + + +
+ + + + +