Skip to content

Commit

Permalink
feat: keep open action
Browse files Browse the repository at this point in the history
  • Loading branch information
pedro-martins-brisa committed Sep 25, 2023
1 parent 38d8fb8 commit a81364e
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 22 deletions.
5 changes: 3 additions & 2 deletions projects/ion/src/lib/core/types/popover.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TemplateRef } from '@angular/core';
import { IonButtonProps } from './button';

import { PopoverButtonsProps } from '../../popover/utilsPopover';
import { IconType } from './icon';

export enum PopoverPosition {
Expand All @@ -19,7 +20,7 @@ export enum PopoverPosition {
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
6 changes: 4 additions & 2 deletions projects/ion/src/lib/popover/component/popover.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Component, Input, TemplateRef } from '@angular/core';
import { Subject } from 'rxjs';

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

const PRIMARY_6 = '#0858ce';

Expand All @@ -15,7 +17,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 },
],
};
}
26 changes: 24 additions & 2 deletions projects/ion/src/lib/popover/popover.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { IonSharedModule } from '../shared.module';
import { IonPopoverComponent } from './component/popover.component';
import { IonPopoverDirective } from './popover.directive';
import { IonPopoverModule } from './popover.module';
import { PopoverButtonsProps } from './utilsPopover';

const textButton = 'Teste';
const confirmText = 'Você tem certeza?';
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
47 changes: 31 additions & 16 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 { 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';
import { getPositionsPopover, PopoverButtonsProps } from './utilsPopover';

@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,9 +90,12 @@ 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();
if (this.shouldClosePopover(index)) {
this.closePopover();
}

emitter.emit();
});
});
Expand Down Expand Up @@ -163,4 +167,15 @@ export class IonPopoverDirective implements OnDestroy {
ngOnDestroy(): void {
this.destroyComponent();
}

private shouldClosePopover(index: number): boolean {
const ionIconCloseIndex = 2;
const action = this.ionPopoverActions && this.ionPopoverActions[index];

if (index === ionIconCloseIndex) {
return true;
}

return !action || !action.keepOpenAfterAction;
}
}
5 changes: 5 additions & 0 deletions projects/ion/src/lib/popover/utilsPopover.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { IonButtonProps } from '../core/types';
import { PopoverPosition } from '../core/types/popover';

interface Hostpositions {
Expand All @@ -11,6 +12,10 @@ export type PopoverPositions = {
[key in PopoverPosition]: Pick<Hostpositions, 'left' | 'top'>;
};

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

export function getPositionsPopover(
{ left, right, top, bottom }: Hostpositions,
arrowAtCenter: boolean
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 a81364e

Please sign in to comment.