Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import colors from other palettes #79

Merged
merged 13 commits into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/app/editor/data-access/color-editor.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Injectable, inject, signal } from '@angular/core';
import { firstValueFrom, tap } from 'rxjs';
import { Color } from '../../shared/model';
import { sleep } from '../../shared/utils/sleep';
import { EditorData } from '../editor.component';

@Injectable({
providedIn: 'root'
Expand All @@ -18,7 +19,7 @@ export class ColorEditorService {
this._isModalOpen.set(true);

const editor = await import('../editor.component').then((c) => c.EditorComponent);
const dialogRef = this._dialog.open<Color | undefined>(editor, {
const dialogRef = this._dialog.open<Color | undefined, EditorData>(editor, {
backdropClass: 'rp-modal-backdrop',
data: {
color,
Expand Down
7 changes: 3 additions & 4 deletions src/app/editor/editor.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<article
#editor
class="mx-auto flex w-full max-w-md flex-col gap-4 rounded bg-neutral-100 p-4 shadow-md dark:border dark:border-neutral-600 dark:bg-neutral-700 dark:shadow-none"
>
<h2 class="font-semibold">{{ color().name }}</h2>
Expand All @@ -13,7 +12,7 @@ <h2 class="font-semibold">{{ color().name }}</h2>
/>

<section class="flex flex-col gap-2">
<rp-editor-range
<rp-color-range-slider
[label]="'common.hue' | translate"
[tooltip]="'editor.properties.hue' | translate"
[value]="shade().hsl.H"
Expand All @@ -24,7 +23,7 @@ <h2 class="font-semibold">{{ color().name }}</h2>
min="0"
/>

<rp-editor-range
<rp-color-range-slider
[label]="'common.saturation' | translate"
[tooltip]="'editor.properties.saturation' | translate"
[value]="shade().hsl.S"
Expand All @@ -33,7 +32,7 @@ <h2 class="font-semibold">{{ color().name }}</h2>
key="saturation"
/>

<rp-editor-range
<rp-color-range-slider
[label]="'common.lightness' | translate"
[tooltip]="'editor.properties.lightness' | translate"
[value]="shade().hsl.L"
Expand Down
69 changes: 40 additions & 29 deletions src/app/editor/editor.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
import { DecimalPipe } from '@angular/common';
import { Component, ElementRef, computed, effect, inject, signal, viewChild } from '@angular/core';
import { Component, computed, effect, inject, signal } from '@angular/core';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { ColorService } from '../shared/data-access/color.service';
import { Color, Shade } from '../shared/model';
import { ColorInputComponent } from '../shared/ui/color-input/color-input.component';
import { ColorRangeSliderComponent } from '../shared/ui/color-range-slider/color-range-slider.component';
import { textColor } from '../shared/utils/text-color';
import { EditorRangeComponent } from './ui/editor-range/editor-range.component';

/**
* Data for the editor dialog.
*/
export type EditorData = {
/**
* Color to edit.
*/
color: Color;
/**
* Shade to open the editor with.
*/
shadeIndex?: number;
};

export enum UpdateType {
HEX = 'hex',
Expand All @@ -18,20 +32,25 @@ export enum UpdateType {
@Component({
selector: 'rp-editor',
standalone: true,
imports: [ColorInputComponent, TranslateModule, DecimalPipe, EditorRangeComponent],
templateUrl: './editor.component.html'
imports: [ColorInputComponent, TranslateModule, DecimalPipe, ColorRangeSliderComponent],
templateUrl: './editor.component.html',
host: {
'[style.--editor-saturation]': 'shade().hsl.S + "%"',
'[style.--editor-lightness]': 'shade().hsl.L + "%"',
'[style.--editor-hue]': 'shade().hsl.H'
}
})
export class EditorComponent {
protected readonly UpdateType = UpdateType;
protected readonly textColor = textColor;

private readonly _data = inject<{ color: Color; shadeIndex?: number }>(DIALOG_DATA);
private readonly _dialogRef = inject(DialogRef);
private readonly _colorService = inject(ColorService);
private readonly _translateService = inject(TranslateService);
readonly #data = inject<EditorData>(DIALOG_DATA);
readonly #dialogRef = inject(DialogRef);
readonly #colorService = inject(ColorService);
readonly #translateService = inject(TranslateService);

protected readonly color = signal(this._data.color.copy());
protected readonly shadeIndex = signal(this._data.shadeIndex ?? 0);
protected readonly color = signal(this.#data.color.copy());
protected readonly shadeIndex = signal(this.#data.shadeIndex ?? 0);

protected readonly shade = computed<Shade>(() => {
const selectedShade = this.color().shades.find((shade) => shade.index === this.shadeIndex());
Expand All @@ -48,20 +67,12 @@ export class EditorComponent {
});

protected readonly hasUnsavedChanges = computed<boolean>(
() => this._data.color.toString() !== this.color().toString()
() => this.#data.color.toString() !== this.color().toString()
);

private readonly _editor = viewChild.required<ElementRef<HTMLElement>>('editor');

public constructor() {
effect(() => {
this._editor().nativeElement.style.setProperty('--editor-hue', `${this.shade().hsl.H}`);
this._editor().nativeElement.style.setProperty('--editor-saturation', `${this.shade().hsl.S}%`);
this._editor().nativeElement.style.setProperty('--editor-lightness', `${this.shade().hsl.L}%`);
});

effect(() => {
this._dialogRef.disableClose = this.hasUnsavedChanges();
this.#dialogRef.disableClose = this.hasUnsavedChanges();
});
}

Expand All @@ -86,7 +97,7 @@ export class EditorComponent {
}

shade.fixed = false;
this._updateColor();
this.updateColor();
}

public update(type: UpdateType, value: string | number): void {
Expand All @@ -108,36 +119,36 @@ export class EditorComponent {
break;
}

this._updateColor();
this.updateColor();

const editedShade = this.color().shades.find((s) => s.hex === shade.hex);
this.shadeIndex.set(editedShade?.index ?? -1);
}

protected cancel(): void {
this._dialogRef.close(undefined);
this.color.set(this._data.color.copy());
this.#dialogRef.close(undefined);
this.color.set(this.#data.color.copy());
}

protected save(): void {
this._dialogRef.close(this.color());
this.#dialogRef.close(this.color());
}

private _updateColor(): void {
private updateColor(): void {
const updatedColor = this.color().copy();
this._colorService.regenerateShades(updatedColor);
this.#colorService.regenerateShades(updatedColor);
this.color.set(updatedColor);
}

protected getTooltip(shade: Shade, selected: boolean): string {
const tooltips: Array<string> = [];

if (!selected) {
tooltips.push(this._translateService.instant('editor.shades'));
tooltips.push(this.#translateService.instant('editor.shades'));
}

if (shade.fixed) {
tooltips.push(this._translateService.instant('editor.unfix'));
tooltips.push(this.#translateService.instant('editor.unfix'));
}

return tooltips.join('\n');
Expand Down
39 changes: 0 additions & 39 deletions src/app/editor/ui/editor-range/editor-range.component.css

This file was deleted.

26 changes: 0 additions & 26 deletions src/app/editor/ui/editor-range/editor-range.component.html

This file was deleted.

3 changes: 2 additions & 1 deletion src/app/export/data-access/export-modal.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Dialog } from '@angular/cdk/dialog';
import { Injectable, inject, signal } from '@angular/core';
import { firstValueFrom, tap } from 'rxjs';
import { Palette } from '../../shared/model';
import { ExportModalData } from '../export-modal.component';

@Injectable({
providedIn: 'root'
Expand All @@ -18,7 +19,7 @@ export class ExportModalService {
this._isModalOpen.set(true);

const exportModal = await import('../export-modal.component').then((c) => c.ExportModalComponent);
const dialogRef = this._dialog.open<void>(exportModal, {
const dialogRef = this._dialog.open<void, ExportModalData>(exportModal, {
backdropClass: 'rp-modal-backdrop',
data: {
palette
Expand Down
12 changes: 11 additions & 1 deletion src/app/export/export-modal.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ import { ExportFormatComponent } from './ui/export-format/export-format.componen
import { ExportSuccessComponent } from './ui/export-success/export-success.component';
import { RequestFormatComponent } from './ui/request-format/request-format.component';

/**
* Data for the export modal.
*/
export type ExportModalData = {
/**
* Palette to export.
*/
palette: Palette;
};

enum ExportModalState {
FORMAT = 'format',
DOWNLOAD = 'download',
Expand All @@ -39,7 +49,7 @@ export class ExportModalComponent {
protected readonly ExportModalState = ExportModalState;
protected readonly ExportFormat = ExportFormat;

private readonly _data = inject<{ palette: Palette }>(DIALOG_DATA);
private readonly _data = inject<ExportModalData>(DIALOG_DATA);
private readonly _dialogRef = inject(DialogRef);
private readonly _toastService = inject(ToastService);
private readonly _exportService = inject(ExportService);
Expand Down
3 changes: 2 additions & 1 deletion src/app/home/home.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { AnalyticsService, AnalyticsServiceMock } from '../shared/data-access/analytics.service';
import { PaletteService, PaletteServiceMock } from '../shared/data-access/palette.service';
import { PaletteService } from '../shared/data-access/palette.service';
import { PaletteServiceMock } from '../shared/data-access/palette.service-mock';
import { HomeService, HomeServiceMock } from './data-access/home.service';
import HomeComponent from './home.component';

Expand Down
3 changes: 2 additions & 1 deletion src/app/list/list.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { ActivatedRoute } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { DialogService, DialogServiceMock } from '../shared/data-access/dialog.service';
import { ListService, ListServiceMock } from '../shared/data-access/list.service';
import { PaletteService, PaletteServiceMock } from '../shared/data-access/palette.service';
import { PaletteService } from '../shared/data-access/palette.service';
import { PaletteServiceMock } from '../shared/data-access/palette.service-mock';
import ListComponent from './list.component';

describe('ListComponent', () => {
Expand Down
46 changes: 25 additions & 21 deletions src/app/shared/constants/tailwind-colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,24 +331,28 @@ export const rose = new Color(
'Rose'
);

export const TailwindRainbow = new Palette('Tailwind Rainbow', [
red,
orange,
amber,
yellow,
lime,
green,
emerald,
teal,
cyan,
sky,
blue,
indigo,
violet,
purple,
fuchsia,
pink,
rose
]);
export const TailwindGrays = new Palette('Tailwind Grays', [slate, gray, zinc, neutral, stone]);
export const Tailwind = new Palette('Tailwind', [...TailwindRainbow.colors, ...TailwindGrays.colors]);
export const TailwindRainbow = new Palette(
'Tailwind Rainbow',
[
red,
orange,
amber,
yellow,
lime,
green,
emerald,
teal,
cyan,
sky,
blue,
indigo,
violet,
purple,
fuchsia,
pink,
rose
],
'tailwind-rainbow'
);
export const TailwindGrays = new Palette('Tailwind Grays', [slate, gray, zinc, neutral, stone], 'tailwind-grays');
export const Tailwind = new Palette('Tailwind', [...TailwindRainbow.colors, ...TailwindGrays.colors], 'tailwind');
3 changes: 2 additions & 1 deletion src/app/shared/data-access/confetti.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TestBed } from '@angular/core/testing';
import { ConfettiService } from './confetti.service';
import { PaletteService, PaletteServiceMock } from './palette.service';
import { PaletteService } from './palette.service';
import { PaletteServiceMock } from './palette.service-mock';

describe('ConfettiService', () => {
let service: ConfettiService;
Expand Down
11 changes: 8 additions & 3 deletions src/app/shared/data-access/list.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ export class ListService {
}

export class ListServiceMock {
public add(_palette: Palette): void {}
public remove(_id: string): void {}
public list$ = new BehaviorSubject<Array<PaletteListItem>>([{ id: 'test-id', name: 'Test palette' }]).asObservable();
readonly #list$ = new BehaviorSubject<Array<PaletteListItem>>([{ id: 'test-id', name: 'Test palette' }]);
public add(palette: Palette): void {
this.#list$.next([...this.#list$.value, palette]);
}
public remove(_id: string): void {
this.#list$.next(this.#list$.value.filter((palette) => palette.id !== _id));
}
public list$ = this.#list$.asObservable();
}
Loading