Skip to content

Commit

Permalink
Merge pull request #23 from qupaya/feature/select-component
Browse files Browse the repository at this point in the history
Feature/select component
  • Loading branch information
patrickjahr authored Apr 30, 2024
2 parents 8d1e840 + af92c80 commit a6cc301
Show file tree
Hide file tree
Showing 34 changed files with 1,079 additions and 8 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 })
),
];
};
6 changes: 4 additions & 2 deletions 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 { appRoutes } from './app.routes';
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),
],
};
17 changes: 17 additions & 0 deletions apps/demo-app/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Route } from '@angular/router';
import { SelectSampleComponent } from './pages/select-sample/select-sample.component';
import { SelectDefaultComponent } from './pages/select-sample/select-default/select-default.component';
import { SelectWithStyleComponent } from './pages/select-sample/select-with-style/select-with-style.component';

const UUID_REGEX = /^[a-z,0-9,-]{36,36}$/;

Expand All @@ -15,6 +18,20 @@ export const appRoutes: Route[] = [
(m) => m.OverviewComponent
),
},
{
path: 'select',
component: SelectSampleComponent,
children: [
{
path: '',
component: SelectDefaultComponent,
},
{
path: 'with-style',
component: SelectWithStyleComponent,
},
],
},
{
path: 'list-sample',
children: [
Expand Down
3 changes: 3 additions & 0 deletions apps/demo-app/src/app/pages/overview/overview.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
<app-card label="WidgetComponent">
<span>Lorem ipsum dolor...</span>
</app-card>
<app-card label="Select component" [routes]="selectRoutes">
<span>Lorem ipsum dolor...</span>
</app-card>
11 changes: 11 additions & 0 deletions apps/demo-app/src/app/pages/overview/overview.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ export class OverviewComponent {
},
];

readonly selectRoutes = [
{
route: '/select/with-style',
label: 'Select Sample with styling',
},
{
route: '/select',
label: 'Select Sample Headless Default',
},
];

readonly widgetLinks = [
{
route: '/widget-sample',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<sk-select [(ngModel)]="selectedValue">
<span skSelectPlaceholder>Select option</span>
<span skSelectLabel>{{ selectedValue?.label }}</span>
@for (option of options; track option.value) {
<sk-select-option [value]="option">
{{ option.label }}
</sk-select-option>
}
</sk-select>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SelectDemoOption } from '../select-sample.component';
import {
faBell,
faCog,
faEnvelope,
faGlobe,
faHeart,
faHome,
faKey,
faLock,
faStar,
faUser,
} from '@fortawesome/free-solid-svg-icons';
import { SelectComponent, SelectOptionComponent } from '@qupaya/sketch';
import { FormsModule } from '@angular/forms';

@Component({
selector: 'app-select-default',
standalone: true,
imports: [CommonModule, SelectComponent, SelectOptionComponent, FormsModule],
templateUrl: './select-default.component.html',
})
export class SelectDefaultComponent {
readonly options: SelectDemoOption[] = [
{ label: 'Option 1', icon: faHome, value: 1 },
{ label: 'Option 2', icon: faUser, value: 2 },
{ label: 'Option 3', icon: faCog, value: 3 },
{ label: 'Option 4', icon: faHeart, value: 4 },
{ label: 'Option 5', icon: faStar, value: 5 },
{ label: 'Option 6', icon: faBell, value: 6 },
{ label: 'Option 7', icon: faEnvelope, value: 7 },
{ label: 'Option 8', icon: faGlobe, value: 8 },
{ label: 'Option 9', icon: faLock, value: 9 },
{ label: 'Option 10', icon: faKey, value: 10 },
];
selectedValue?: SelectDemoOption;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<router-outlet></router-outlet>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SelectSampleComponent } from './select-sample.component';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';

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

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

fixture = TestBed.createComponent(SelectSampleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { RouterOutlet } from '@angular/router';

export interface SelectDemoOption {
label: string;
icon: IconProp;
value: number;
}

@Component({
selector: 'app-select-sample',
standalone: true,
imports: [CommonModule, RouterOutlet],
templateUrl: './select-sample.component.html',
})
export class SelectSampleComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
:host {
display: flex;
flex-direction: column;
width: 100%;
max-height: 200px;
margin-top: 0.5rem;
overflow-x: auto;
}

sk-select-option {
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;
}

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

@media (hover) {
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
@@ -0,0 +1,6 @@
@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
@@ -0,0 +1,25 @@
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, NoopAnimationsModule],
}).compileComponents();

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

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Component, effect, HostBinding, input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { query, transition, trigger } from '@angular/animations';
import { SelectOptionComponent } from '@qupaya/sketch';
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, FaIconComponent],
templateUrl: './select-options-sample.component.html',
styleUrl: './select-options-sample.component.css',
animations: [
trigger('animation', [
transition(
'* => visible',
query('sk-select-option', slideFadeAnimationFactory(), {
optional: true,
})
),
transition(
'* => hidden',
query('sk-select-option', fadeFactory(1, 0, '350ms'), {
optional: true,
})
),
transition(
'visible => void',
query('sk-select-option', fadeFactory(1, 0, '350ms'), {
optional: true,
})
),
]),
],
})
export class SelectOptionsSampleComponent {
options = input.required<SelectDemoOption[]>();
@HostBinding('@animation') animateOptions = 'hidden';

show = input.required<boolean>();

protected readonly toggleShow = effect(() => {
this.animateOptions = this.show() ? 'visible' : 'hidden';
});
}
Loading

0 comments on commit a6cc301

Please sign in to comment.