Skip to content

Commit

Permalink
feat(select): add key event functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickjahr committed Apr 18, 2024
1 parent db594bc commit c326877
Show file tree
Hide file tree
Showing 24 changed files with 337 additions and 269 deletions.
12 changes: 12 additions & 0 deletions apps/demo-app/src/app/animations/fade.animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { animate, AnimationMetadata, style } from '@angular/animations';

export const fadeFactory = (
from: number,
to: number,
duration = '200ms'
): AnimationMetadata[] => {
return [
style({ opacity: from }),
animate(`${duration} ease`, style({ opacity: to })),
];
};
20 changes: 20 additions & 0 deletions apps/demo-app/src/app/animations/slide.animation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
animate,
AnimationMetadata,
sequence,
stagger,
style,
} from '@angular/animations';
Expand All @@ -16,3 +17,22 @@ export const slideFadeAnimationFactory = (): AnimationMetadata[] => {
]),
];
};

export const slideDeleteAnimation = (): AnimationMetadata => {
return stagger('80ms', [
sequence([
animate(
`200ms cubic-bezier(0.3, 0, 0.8, 0.15)`,
style({
transform: `translateX(-200%)`,
})
),
animate(
`200ms ease`,
style({
height: 0,
})
),
]),
]);
};
15 changes: 15 additions & 0 deletions apps/demo-app/src/app/animations/zoom.animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { animate, AnimationMetadata, style } from '@angular/animations';

export const zoomFactory = (
from: number,
to: number,
duration = '500ms'
): AnimationMetadata[] => {
return [
style({ opacity: from, scale: from }),
animate(
`${duration} cubic-bezier(0.05, 0.7, 0.1, 1)`,
style({ opacity: to, scale: to })
),
];
};
4 changes: 3 additions & 1 deletion apps/demo-app/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { ApplicationConfig } from '@angular/core';
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { appRoutes } from './app.routes';
import {
provideRouter,
withComponentInputBinding,
withViewTransitions,
} from '@angular/router';
import { provideAnimations } from '@angular/platform-browser/animations';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';

export const appConfig: ApplicationConfig = {
providers: [
Expand All @@ -15,5 +16,6 @@ export const appConfig: ApplicationConfig = {
withComponentInputBinding()
),
provideAnimations(),
importProvidersFrom(FontAwesomeModule),
],
};
5 changes: 4 additions & 1 deletion apps/demo-app/src/app/pages/overview/overview.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
<app-card label="WidgetComponent">
<span>Lorem ipsum dolor...</span>
</app-card>
<app-card label="Select component" [routes]="[{ route: '/select', label: 'Select component'}]">
<app-card
label="Select component"
[routes]="[{ route: '/select', label: 'Select component' }]"
>
<span>Lorem ipsum dolor...</span>
</app-card>
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@
:host {
display: flex;
flex-direction: column;
width: 100%;
margin-top: 0.5rem;
display: flex;
flex-direction: column;
width: 100%;
max-height: 200px;
margin-top: 0.5rem;
overflow-x: auto;
}

sk-select-option {
background-color: #fff;
color: #000;
padding: 0.5rem 1rem;
cursor: pointer;
transition: color 0.3s ease-in-out, font-weight 0.3s ease-in-out,
font-size 0.3s ease-in-out;
display: flex;
gap: 0.5rem;
background-color: #fff;
color: #000;
padding: 0.5rem 1rem;
cursor: pointer;
transition: color 0.3s ease-in-out, font-weight 0.3s ease-in-out;
}

sk-select-option:first-child {
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem;
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem;
}

sk-select-option:last-child {
border-bottom-left-radius: 0.25rem;
border-bottom-right-radius: 0.25rem;
border-bottom-left-radius: 0.25rem;
border-bottom-right-radius: 0.25rem;
}

@media (hover) {
sk-select-option:hover {
color: deeppink;
font-weight: bold;
font-size: 1.5em;
}
sk-select-option:hover {
color: var(--sk-primary-color);
font-weight: bold;
}
}

sk-select-option:focus {
border: none;
color: var(--sk-primary-color);
font-weight: bold;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<sk-select-option [value]="{ data: 1 }">Test 1</sk-select-option>
<sk-select-option [value]="{ data: 2 }">Test 2</sk-select-option>
<sk-select-option [value]="{ data: 3 }">Test 3</sk-select-option>
<sk-select-option [value]="{ data: 4 }">Test 4</sk-select-option>
<sk-select-option [value]="{ data: 5 }">Test 5</sk-select-option>
@for (option of options(); track option.value) {
<sk-select-option [value]="option.value">
<fa-icon [icon]="option.icon"></fa-icon>
<span>{{ option.label }}</span>
</sk-select-option>
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SelectOptionsSampleComponent } from './select-options-sample.component';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';

describe('SelectOptionsSampleComponent', () => {
let component: SelectOptionsSampleComponent;
let fixture: ComponentFixture<SelectOptionsSampleComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SelectOptionsSampleComponent],
imports: [SelectOptionsSampleComponent, NoopAnimationsModule],
}).compileComponents();

fixture = TestBed.createComponent(SelectOptionsSampleComponent);
component = fixture.componentInstance;
const componentRef = fixture.componentRef;
componentRef.setInput('show', true);
componentRef.setInput('options', []);
fixture.detectChanges();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,77 +1,16 @@
import { Component, effect, HostBinding, input } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
animate,
AnimationMetadata,
query,
sequence,
stagger,
style,
transition,
trigger,
} from '@angular/animations';
import { query, transition, trigger } from '@angular/animations';
import { SelectOptionComponent } from '@qupaya/sketch';

export const slideDeleteAnimation = (): AnimationMetadata => {
return stagger('80ms', [
sequence([
animate(
`200ms cubic-bezier(0.3, 0, 0.8, 0.15)`,
style({
transform: `translateX(-200%)`,
})
),
animate(
`200ms ease`,
style({
height: 0,
})
),
]),
]);
};

export const slideFadeAnimationFactory = (): AnimationMetadata[] => {
return [
style({ opacity: 0, transform: 'translateY(-1.5rem)', scale: 0.8 }),
stagger('32ms', [
animate(
'150ms cubic-bezier(0.05, 0.7, 0.1, 1)',
style({ opacity: 1, transform: 'translateY(0)', scale: 1 })
),
]),
];
};

export const fadeFactory = (
from: number,
to: number,
duration = '200ms'
): AnimationMetadata[] => {
return [
style({ opacity: from }),
animate(`${duration} ease`, style({ opacity: to })),
];
};

export const zoomFactory = (
from: number,
to: number,
duration = '500ms'
): AnimationMetadata[] => {
return [
style({ opacity: from, scale: from }),
animate(
`${duration} cubic-bezier(0.05, 0.7, 0.1, 1)`,
style({ opacity: to, scale: to })
),
];
};
import { slideFadeAnimationFactory } from '../../../animations/slide.animation';
import { fadeFactory } from '../../../animations/fade.animations';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { SelectDemoOption } from '../select-sample.component';

@Component({
selector: 'app-select-options-sample',
standalone: true,
imports: [CommonModule, SelectOptionComponent],
imports: [CommonModule, SelectOptionComponent, FaIconComponent],
templateUrl: './select-options-sample.component.html',
styleUrl: './select-options-sample.component.css',
animations: [
Expand All @@ -98,6 +37,7 @@ export const zoomFactory = (
],
})
export class SelectOptionsSampleComponent {
options = input.required<SelectDemoOption[]>();
@HostBinding('@animation') animateOptions = 'hidden';

show = input.required<boolean>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,31 @@
sk-select {
display: block;
margin-top: 1rem;
display: block;
margin-top: 1rem;
}

.sk-label {
padding: 0.5rem 1rem;
border-radius: 8px;
background: rgba(255, 255, 255, 0.1);
color: #fefefe;
box-shadow: rgba(255, 255, 255, 0.05) 0px 6px 24px 0px, rgba(255, 255, 255, 0.08) 0px 0px 0px 1px;
}
display: flex;
align-items: center;
gap: 0.25rem;
padding: 0.5rem 1rem;
border-radius: 8px;
background: rgb(255 255 255 / 10%);
color: #fefefe;
box-shadow: rgb(255 255 255 / 5%) 0 6px 24px 0,
rgb(255 255 255 / 8%) 0 0 0 1px;

.sk-options {
.sk-label-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.25rem;
width: 100%;
margin-top: 0.5rem;
}
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 90%;

sk-select-option {
background-color: #fff;
color: #000;
padding: 0.5rem 1rem;
cursor: pointer;
transition: color 0.3s ease-in-out, font-weight 0.3s ease-in-out,
font-size 0.3s ease-in-out;
}

sk-select-option:first-child {
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem;
}

sk-select-option:last-child {
border-bottom-left-radius: 0.25rem;
border-bottom-right-radius: 0.25rem;
}

@media (hover) {
sk-select-option:hover {
color: deeppink;
font-weight: bold;
font-size: 1.5em;
fa-icon {
width: 1.5rem;
height: 1.5rem;
}
}
}

sk-select-option:not(:last-child) {
border-bottom: 1px solid #000;
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
Multiple: <input type="checkbox" (change)="switchMultiple($event)" />

<sk-select
[(ngModel)]="value"
[skMultiple]="multiple()"
[ngModel]="value"
(ngModelChange)="valueChanged($event)"
[multiple]="multiple()"
[animationDelay]="250"
[closeOnSelect]="true"
(open)="showAnimation.set($event)"
>
<div class="sk-label" skSelectPlaceholder>Please select an option</div>
<div class="sk-label" skSelectLabel>
@if (Array.isArray(value)) {
@for (item of value; track item) {
{{ item.data }}
<div class="sk-label-item">
@for (item of selectedValues(); track item.value) { @if
(selectedValues().length <= 1) {
<fa-icon [icon]="item.icon"></fa-icon>
}
} @else {
{{ value?.data }}
}
{{ item.label }}
}
</div>
</div>

<app-select-options-sample
[show]="showAnimation()"
></app-select-options-sample>
<app-select-options-sample [options]="options" [show]="showAnimation()">
</app-select-options-sample>
</sk-select>
Loading

0 comments on commit c326877

Please sign in to comment.