Skip to content

Commit

Permalink
Merge branch 'main' into 834-sidebar-closes-when-an-option-is-selected
Browse files Browse the repository at this point in the history
  • Loading branch information
iurynogueira authored Sep 28, 2023
2 parents 9568cac + bdeb1c9 commit 9ffc9e5
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 22 deletions.
7 changes: 6 additions & 1 deletion projects/ion/src/lib/core/types/popover.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TemplateRef } from '@angular/core';

import { IonButtonProps } from './button';
import { IconType } from './icon';

Expand All @@ -16,10 +17,14 @@ export enum PopoverPosition {
DEFAULT = 'bottomRight',
}

export interface PopoverButtonsProps extends IonButtonProps {
keepOpenAfterAction?: boolean;
}

export interface PopoverProps {
ionPopoverTitle: string;
ionPopoverBody: TemplateRef<void>;
ionPopoverActions?: IonButtonProps[];
ionPopoverActions?: PopoverButtonsProps[];
ionPopoverIcon?: IconType;
ionPopoverIconColor?: string;
ionPopoverIconClose?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ $arrow-size: 4.5px;
display: flex;
background-color: $neutral-2;
justify-content: space-between;
border-radius: spacing(1) spacing(1) 0 0;
align-items: center;
padding: spacing(1.5) spacing(2);

Expand Down
7 changes: 4 additions & 3 deletions projects/ion/src/lib/popover/component/popover.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Component, Input, TemplateRef } from '@angular/core';
import { Subject } from 'rxjs';
import { PopoverPosition } from '../../core/types/popover';
import { IconType, IonButtonProps } from '../../core/types';

import { IconType } from '../../core/types';
import { PopoverButtonsProps, PopoverPosition } from '../../core/types/popover';

const PRIMARY_6 = '#0858ce';

Expand All @@ -15,7 +16,7 @@ export class IonPopoverComponent {
@Input() ionPopoverTitle: string;
@Input() ionPopoverKeep: boolean;
@Input() ionPopoverBody: TemplateRef<void>;
@Input() ionPopoverActions?: IonButtonProps[];
@Input() ionPopoverActions?: PopoverButtonsProps[];
@Input() ionPopoverIcon?: IconType;
@Input() ionPopoverIconColor? = PRIMARY_6;
@Input() ionPopoverIconClose = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Component } from '@angular/core';
import { PopoverPosition } from '../../core/types/popover';

@Component({
template: `
<style>
div {
height: 400px;
display: flex;
justify-content: center;
align-items: center;
}
</style>
<div>
<ion-button
ionPopover
[ionPopoverTitle]="args.ionPopoverTitle"
[ionPopoverBody]="BodyTemplate"
[ionPopoverIconClose]="args.ionPopoverIconClose"
[ionPopoverPosition]="args.ionPopoverPosition"
[ionPopoverActions]="args.ionPopoverActions"
label="click me"
>
</ion-button>
<ng-template #BodyTemplate> {{ args.ionPopoverBody }} </ng-template>
</div>
`,
})
export class KeepOpenPopoverActionComponent {
args = {
ionPopoverTitle: 'Desafio na Jornada',
ionPopoverBody:
'Você pode escolher avançar corajosamente para a próxima etapa da jornada ou optar por explorar o caminho anterior.',
ionPopoverPosition: PopoverPosition.DEFAULT,
ionPopoverIconClose: true,
ionPopoverActions: [
{ label: 'voltar', keepOpenAfterAction: true },
{ label: 'continuar', keepOpenAfterAction: true },
],
};
}
28 changes: 25 additions & 3 deletions projects/ion/src/lib/popover/popover.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { fireEvent, render, screen } from '@testing-library/angular';

import { IonButtonModule } from '../button/button.module';
import { PopoverPosition } from '../core/types/popover';
import { PopoverButtonsProps, PopoverPosition } from '../core/types/popover';
import { IonDividerModule } from '../divider/divider.module';
import { IonSharedModule } from '../shared.module';
import { IonPopoverComponent } from './component/popover.component';
Expand Down Expand Up @@ -63,7 +64,10 @@ class HostTestComponent {
ionPopoverKeep = false;
ionPopoverIconClose = true;
ionPopoverIcon = 'condominium';
ionPopoverActions = [{ label: 'action 1' }, { label: 'action 2' }];
ionPopoverActions: PopoverButtonsProps[] = [
{ label: 'action 1' },
{ label: 'action 2' },
];

ionOnFirstAction = firstAction;
ionOnSecondAction = secondAction;
Expand Down Expand Up @@ -181,6 +185,24 @@ describe('Directive: popover', () => {
expect(screen.queryByTestId(`popover-${type.dataTestId}`)).toBeNull();
});

it.each([
{ dataTestId: 'action-1', label: 'voltar' },
{ dataTestId: 'action-2', label: 'continuar' },
])(
'should not close pop when click in $label when to have keepOpenAfterAction',
async (type) => {
await sut({
ionPopoverActions: [
{ label: 'voltar', keepOpenAfterAction: true },
{ label: 'continuar', keepOpenAfterAction: true },
],
});
fireEvent.click(screen.getByText(textButton));
fireEvent.click(screen.getByTestId(`btn-${type.label}`));
expect(screen.getByTestId('ion-popover')).toBeInTheDocument();
}
);

it('should emit an event when click on action-1', async () => {
await sut();
fireEvent.click(screen.getByText(textButton));
Expand Down Expand Up @@ -211,7 +233,7 @@ describe('Directive: popover', () => {
await sut();
fireEvent.click(screen.getByText(textButton));
fireEvent.click(document);
expect(screen.queryByTestId('ion-popover')).toBeFalsy();
expect(screen.queryByTestId('ion-popover')).not.toBeInTheDocument();
});

it('should render popover with custom class', async () => {
Expand Down
39 changes: 24 additions & 15 deletions projects/ion/src/lib/popover/popover.directive.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import { DOCUMENT } from '@angular/common';
import {
Directive,
Input,
HostListener,
ApplicationRef,
ComponentFactoryResolver,
Injector,
Inject,
ComponentRef,
ApplicationRef,
Output,
Directive,
EventEmitter,
ViewContainerRef,
HostListener,
Inject,
Injector,
Input,
OnDestroy,
Output,
TemplateRef,
ViewContainerRef,
} from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { pick } from 'lodash';

import { IconType } from '../core/types';
import { PopoverButtonsProps, PopoverPosition } from '../core/types/popover';
import { SafeAny } from './../utils/safe-any';
import { IonPopoverComponent } from './component/popover.component';
import { PopoverPosition } from '../core/types/popover';
import { getPositionsPopover } from './utilsPopover';
import { IonButtonProps, IconType } from '../core/types';
import { pick } from 'lodash';

@Directive({ selector: '[ionPopover]' })
export class IonPopoverDirective implements OnDestroy {
@Input() ionPopoverTitle: string;
@Input() ionPopoverKeep = false;
@Input() ionPopoverBody: TemplateRef<void>;
@Input() ionPopoverActions?: IonButtonProps[];
@Input() ionPopoverActions?: PopoverButtonsProps[];
@Input() ionPopoverIcon?: IconType;
@Input() ionPopoverIconColor?: string;
@Input() ionPopoverIconClose? = false;
Expand Down Expand Up @@ -89,14 +90,22 @@ export class IonPopoverDirective implements OnDestroy {
['ionOnSecondAction', this.ionOnSecondAction],
['ionOnClose', this.ionOnClose],
];
eventSubscriptions.forEach(([event, emitter]) => {
eventSubscriptions.forEach(([event, emitter], index) => {
popoverInstance[event].subscribe(() => {
this.closePopover();
this.handlePopoverAction(index);

emitter.emit();
});
});
}

handlePopoverAction(index: number): void {
const action = this.ionPopoverActions && this.ionPopoverActions[index];
if (!action || !action.keepOpenAfterAction) {
this.closePopover();
}
}

setComponentPosition(hostElement: DOMRect): void {
const hostPositions = pick(hostElement, ['left', 'right', 'top', 'bottom']);
const positions = getPositionsPopover(
Expand Down
12 changes: 12 additions & 0 deletions projects/ion/src/lib/tooltip/tooltip.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
TooltipTrigger,
} from '../core/types';
import { IonTooltipModule } from './tooltip.module';
import { IonTooltipDirective } from './tooltip.directive';

@Component({
template: `
Expand Down Expand Up @@ -130,6 +131,17 @@ describe('Directive: Tooltip', () => {
);
});

it('should close the tooltip when scrolling the page', async () => {
await sut();
const directive = IonTooltipDirective.prototype;
jest.spyOn(directive, 'onScroll');

fireEvent.mouseEnter(screen.getByTestId('hostTooltip'));
fireEvent.scroll(window);
expect(directive.onScroll).toBeCalled();
expect(screen.queryByTestId('ion-tooltip')).not.toBeInTheDocument();
});

describe('trigger: click', () => {
afterEach(async () => {
fireEvent.click(screen.getByTestId('hostTooltip'));
Expand Down
4 changes: 4 additions & 0 deletions projects/ion/src/lib/tooltip/tooltip.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ export class IonTooltipDirective implements OnDestroy, OnInit {
}
}

@HostListener('window:scroll') onScroll(): void {
this.destroyComponent();
}

ngOnDestroy(): void {
this.destroyComponent();
this.subscription$.unsubscribe();
Expand Down
41 changes: 41 additions & 0 deletions stories/PopoverDirectiveKeepAction.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { CommonModule } from '@angular/common';
import { Meta, Story } from '@storybook/angular/types-6-0';

import { PopoverPosition } from '../projects/ion/src/lib/core/types/popover';
import { KeepOpenPopoverActionComponent } from '../projects/ion/src/lib/popover/mock/keep-open-popover-action.component';
import {
IonPopoverModule,
IonSharedModule,
} from '../projects/ion/src/public-api';

const Template: Story<KeepOpenPopoverActionComponent> = (
args: KeepOpenPopoverActionComponent
) => ({
component: KeepOpenPopoverActionComponent,
props: {
...args,
},
moduleMetadata: {
declarations: [KeepOpenPopoverActionComponent],
imports: [CommonModule, IonSharedModule, IonPopoverModule],
entryComponents: [KeepOpenPopoverActionComponent],
},
});

export const DirectiveWithActionsKeepAction = Template.bind({});
DirectiveWithActionsKeepAction.args = {
ionPopoverTitle: 'Desafio na Jornada',
ionPopoverBody:
'Você pode escolher avançar corajosamente para a próxima etapa da jornada ou optar por explorar o caminho anterior.',
ionPopoverPosition: PopoverPosition.DEFAULT,
ionPopoverIconClose: true,
ionPopoverActions: [
{ label: 'voltar', keepOpenAfterAction: true },
{ label: 'continuar', keepOpenAfterAction: true },
],
};

export default {
title: 'Ion/Data Display/Popover',
component: KeepOpenPopoverActionComponent,
} as Meta<KeepOpenPopoverActionComponent>;

0 comments on commit 9ffc9e5

Please sign in to comment.