Skip to content

Commit

Permalink
fix(core): correct calculations are only in the accessor
Browse files Browse the repository at this point in the history
  • Loading branch information
splincode committed Jan 17, 2025
1 parent af44978 commit bd25f4d
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 85 deletions.
11 changes: 3 additions & 8 deletions projects/core/directives/hint/hint.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
tuiRectAccessorFor,
} from '@taiga-ui/core/classes';
import {TuiPositionService, TuiVisualViewportService} from '@taiga-ui/core/services';
import {TUI_ANIMATIONS_SPEED, TUI_VIEWPORT} from '@taiga-ui/core/tokens';
import {TUI_ANIMATIONS_SPEED} from '@taiga-ui/core/tokens';
import {tuiIsObscured, tuiToAnimationOptions} from '@taiga-ui/core/utils';
import {injectContext, PolymorpheusOutlet} from '@taiga-ui/polymorpheus';
import {map, takeWhile} from 'rxjs';
Expand All @@ -25,8 +25,6 @@ import {TuiHintPointer} from './hint-pointer.directive';
import {TuiHintPosition} from './hint-position.directive';
import {TuiHintUnstyledComponent} from './hint-unstyled.component';

const GAP = 8;

export const TUI_HINT_PROVIDERS = [
TuiPositionService,
TuiHoveredService,
Expand Down Expand Up @@ -63,7 +61,6 @@ export class TuiHintComponent<C = any> {
private readonly el = tuiInjectElement();
private readonly hover = inject(TuiHintHover);
private readonly vvs = inject(TuiVisualViewportService);
private readonly viewport = inject(TUI_VIEWPORT);

protected readonly desktop = {value: '', params: {end: 1, start: 1}};
protected readonly options = tuiToAnimationOptions(
Expand Down Expand Up @@ -126,21 +123,19 @@ export class TuiHintComponent<C = any> {
private update(top: number, left: number): void {
const {clientHeight, clientWidth} = this.el;
const rect = this.accessor.getClientRect();
const viewport = this.viewport.getClientRect();

if (rect === EMPTY_CLIENT_RECT || !clientHeight || !clientWidth) {
return;
}

const safeLeft = tuiClamp(left, GAP, viewport.width - clientWidth - GAP);
const [beakTop, beakLeft] = this.vvs.correct([
rect.top + rect.height / 2 - top,
rect.left + rect.width / 2 - safeLeft,
rect.left + rect.width / 2 - left,
]);

this.apply(
tuiPx(Math.round(top)),
tuiPx(Math.round(safeLeft)),
tuiPx(Math.round(left)),
Math.round((tuiClamp(beakTop, 0, clientHeight) / clientHeight) * 100),
Math.round((tuiClamp(beakLeft, 0, clientWidth) / clientWidth) * 100),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@
left: 0.625rem;
bottom: 0.625rem;
}

.t-centered-axis-xy {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ import {tuiAsViewport, TuiDropdown, TuiRectAccessor} from '@taiga-ui/core';

@Component({
standalone: true,
selector: 'tui-viewport-example-1',
imports: [TuiDropdown],
templateUrl: './index.html',
styleUrls: ['./index.less'],
encapsulation,
changeDetection,
providers: [tuiAsViewport(Example)],
})
export class Example extends TuiRectAccessor {
export default class Example extends TuiRectAccessor {
private readonly el = tuiInjectElement();

public readonly type = 'viewport';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
import {Component} from '@angular/core';
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {TuiDropdown} from '@taiga-ui/core';
import {tuiAsPortal, tuiInjectElement, TuiPortals} from '@taiga-ui/cdk';
import type {TuiRectAccessor} from '@taiga-ui/core';
import {tuiAsViewport, TuiDropdown, TuiDropdownService} from '@taiga-ui/core';

import {PortalHost} from './portal-host';
@Component({
standalone: true,
selector: 'portal-host',
template: `
<ng-content></ng-content>
<ng-container #viewContainer></ng-container>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [tuiAsPortal(TuiDropdownService), tuiAsViewport(PortalHost)],
})
class PortalHost extends TuiPortals implements TuiRectAccessor {
private readonly el = tuiInjectElement();

public readonly type = 'viewport';

public getClientRect(): DOMRect {
return this.el.getBoundingClientRect();
}
}

@Component({
standalone: true,
selector: 'tui-viewport-example-2',
imports: [PortalHost, TuiDropdown],
templateUrl: './index.html',
styleUrls: ['../1/index.less'],
encapsulation,
changeDetection,
})
export class Example {}
export default class Example {}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<portal-host class="dropdowns">
<button
tuiButton
tuiHintDirection="right"
type="button"
class="t-centered-axis-xy"
[tuiHint]="template"
[tuiHintManual]="hintShown"
(click)="toggleHint()"
>
Hint
</button>
</portal-host>

<ng-template #template>
Use
<a
appearance="action-grayscale"
tuiLink
tuiTheme="dark"
class="link"
>
Hint
</a>
</ng-template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {tuiInjectElement, TuiPortals} from '@taiga-ui/cdk';
import type {TuiRectAccessor} from '@taiga-ui/core';
import {tuiAsViewport, TuiButton, TuiHint, TuiLink} from '@taiga-ui/core';

@Component({
standalone: true,
selector: 'portal-host',
template: `
<ng-content></ng-content>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [tuiAsViewport(PortalHost)],
})
class PortalHost extends TuiPortals implements TuiRectAccessor {
private readonly el = tuiInjectElement();

public readonly type = 'viewport';

public getClientRect(): DOMRect {
return this.el.getBoundingClientRect();
}
}

@Component({
standalone: true,
imports: [PortalHost, TuiButton, TuiHint, TuiLink],
templateUrl: './index.html',
styleUrls: ['../1/index.less'],
encapsulation,
changeDetection,
})
export default class Example {
protected hintShown = false;

protected toggleHint(): void {
this.hintShown = !this.hintShown;
}
}
26 changes: 7 additions & 19 deletions projects/demo/src/modules/customization/viewport/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<tui-doc-page
header="Viewport"
package="CORE"
type="customization"
>
<ng-template pageTab>
<p>
Expand All @@ -11,26 +12,13 @@
</p>

<tui-doc-example
id="base"
description="Here we just limit viewport relative to which the position of the dropdown will be calculated"
heading="Dropdown"
class="dropdown"
[content]="example1"
*ngFor="let example of examples; let index = index"
[component]="index + 1 | tuiComponent"
[content]="index + 1 | tuiExample"
[heading]="example"
[id]="example | tuiKebab"
[fullsize]="true"
>
<tui-viewport-example-1 />
</tui-doc-example>

<tui-doc-example
id="portal"
description="If you want your dropdown to open in specific viewport in DOM of your web application, then you need to create your own portal"
heading="Dropdown with custom portal"
class="dropdown"
[content]="example2"
[fullsize]="true"
>
<tui-viewport-example-2 />
</tui-doc-example>
/>
</ng-template>

<ng-template pageTab="Setup">
Expand Down
17 changes: 2 additions & 15 deletions projects/demo/src/modules/customization/viewport/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,14 @@ import {Component} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {TuiDemo} from '@demo/utils';

import {Example as Example1} from './examples/1';
import {Example as Example2} from './examples/2';

@Component({
standalone: true,
imports: [Example1, Example2, TuiDemo],
imports: [TuiDemo],
templateUrl: './index.html',
changeDetection,
})
export default class Page {
protected readonly providers = import('./examples/import/providers.md?raw');

protected readonly example1 = {
TypeScript: import('./examples/1/index.ts?raw'),
HTML: import('./examples/1/index.html?raw'),
LESS: import('./examples/1/index.less?raw'),
};

protected readonly example2 = {
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'),
};
protected examples = ['Dropdown', 'Dropdown and custom portal', 'Hint'];
}
11 changes: 3 additions & 8 deletions projects/experimental/components/hint/hint.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ import {
TuiHintUnstyledComponent,
} from '@taiga-ui/core/directives/hint';
import {TuiPositionService, TuiVisualViewportService} from '@taiga-ui/core/services';
import {TUI_ANIMATIONS_SPEED, TUI_VIEWPORT} from '@taiga-ui/core/tokens';
import {TUI_ANIMATIONS_SPEED} from '@taiga-ui/core/tokens';
import {tuiIsObscured, tuiToAnimationOptions} from '@taiga-ui/core/utils';
import {injectContext, PolymorpheusOutlet} from '@taiga-ui/polymorpheus';
import {map, takeWhile} from 'rxjs';

const GAP = 8;

@Component({
standalone: true,
selector: 'tui-hint',
Expand Down Expand Up @@ -57,7 +55,6 @@ export class TuiHintComponent<C = any> {
private readonly el = tuiInjectElement();
private readonly hover = inject(TuiHintHover);
private readonly vvs = inject(TuiVisualViewportService);
private readonly viewport = inject(TUI_VIEWPORT);

protected readonly dummy = {value: '', params: {end: 1, start: 1}};
protected readonly options = tuiToAnimationOptions(
Expand Down Expand Up @@ -122,21 +119,19 @@ export class TuiHintComponent<C = any> {
private update(top: number, left: number): void {
const {clientHeight, clientWidth} = this.el;
const rect = this.accessor.getClientRect();
const viewport = this.viewport.getClientRect();

if (rect === EMPTY_CLIENT_RECT || !clientHeight || !clientWidth) {
return;
}

const safeLeft = tuiClamp(left, GAP, viewport.width - clientWidth - GAP);
const [beakTop, beakLeft] = this.vvs.correct([
rect.top + rect.height / 2 - top,
rect.left + rect.width / 2 - safeLeft,
rect.left + rect.width / 2 - left,
]);

this.apply(
tuiPx(Math.round(top)),
tuiPx(Math.round(safeLeft)),
tuiPx(Math.round(left)),
Math.round((tuiClamp(beakTop, 0, clientHeight) / clientHeight) * 100),
Math.round((tuiClamp(beakLeft, 0, clientWidth) / clientWidth) * 100),
);
Expand Down

0 comments on commit bd25f4d

Please sign in to comment.