better grid

This commit is contained in:
2026-03-17 15:47:59 +01:00
parent f57660c994
commit e304fcbf6f
10 changed files with 95 additions and 38 deletions

View File

@@ -1,12 +1,27 @@
<div class="h-full w-full absolute bg-red-300"> @if (isVisible()) {
<div
class="h-full w-full absolute bg-red-300"
animate.enter="animate-slide-in"
animate.leave="animate-slide-out"
>
<div class="py-4 container mx-auto"> <div class="py-4 container mx-auto">
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<p>food-pantry works!</p> <p>food-pantry works!</p>
<ff-button (click)="onClose.emit(true)">X</ff-button> <ff-button (click)="onClose.emit(true)">X</ff-button>
</div> </div>
<ff-grid <ff-grid
[template]="food"
[gridItems]="foods()" [gridItems]="foods()"
(onSelect)="onFoodChosen.emit($event)" (onSelect)="onFoodChosen.emit($event)"
></ff-grid> >
<ng-template #food let-food="item">
<div
class="flex flex-row items-center justify-center overflow-hidden"
>
{{ food.name }}
</div>
</ng-template>
</ff-grid>
</div> </div>
</div> </div>
}

View File

@@ -1,4 +1,4 @@
import { Component, inject, output, OutputEmitterRef, Signal } from '@angular/core'; import { Component, inject, input, InputSignal, output, OutputEmitterRef, Signal } from '@angular/core';
import { ButtonComponent } from "../ui-elements/button/button.component"; import { ButtonComponent } from "../ui-elements/button/button.component";
import { Food } from '../../types/food'; import { Food } from '../../types/food';
import { FoodStore } from '../../api/food.store'; import { FoodStore } from '../../api/food.store';
@@ -10,6 +10,7 @@ import { GridComponent } from "../grid/grid.component";
templateUrl: './food-pantry.component.html', templateUrl: './food-pantry.component.html',
}) })
export class FoodPantryComponent { export class FoodPantryComponent {
public readonly isVisible: InputSignal<boolean> = input.required();
public readonly onClose: OutputEmitterRef<true> = output<true>(); public readonly onClose: OutputEmitterRef<true> = output<true>();
public readonly onFoodChosen: OutputEmitterRef<Food> = output<Food>(); public readonly onFoodChosen: OutputEmitterRef<Food> = output<Food>();

View File

@@ -2,11 +2,15 @@
@for (item of gridItems(); track $index) { @for (item of gridItems(); track $index) {
<div <div
(click)="onSelect.emit(item)" (click)="onSelect.emit(item)"
class="rounded-lg bg-primary-400 cursor-pointer" class="rounded-lg bg-primary-400 cursor-pointer relative"
[ngStyle]="{ [ngStyle]="{
width: size() + 'rem', width: size() + 'rem',
height: size() + 'rem', height: size() + 'rem',
}" }"
></div> >
<ng-container
*ngTemplateOutlet="template(); context: { item }"
></ng-container>
</div>
} }
</div> </div>

View File

@@ -1,13 +1,15 @@
import { NgStyle } from '@angular/common'; import { NgStyle, NgTemplateOutlet } from '@angular/common';
import { Component, input, InputSignal, output, OutputEmitterRef } from '@angular/core'; import { Component, input, InputSignal, output, OutputEmitterRef, TemplateRef } from '@angular/core';
@Component({ @Component({
selector: 'ff-grid', selector: 'ff-grid',
imports: [NgStyle], imports: [NgStyle, NgTemplateOutlet],
templateUrl: './grid.component.html', templateUrl: './grid.component.html',
}) })
export class GridComponent<T> { export class GridComponent<T> {
public readonly gridItems: InputSignal<T[]> = input.required(); public readonly gridItems: InputSignal<T[]> = input.required();
public readonly template: InputSignal<TemplateRef<{ item: T; }>> = input.required();
public readonly attr: InputSignal<string> = input('');
public readonly size: InputSignal<number> = input<number>(5); public readonly size: InputSignal<number> = input<number>(5);
public readonly onSelect: OutputEmitterRef<T> = output<T>(); public readonly onSelect: OutputEmitterRef<T> = output<T>();

View File

@@ -1,4 +1,9 @@
<div class="h-full w-full absolute bg-blue-300"> @if (isVisible()) {
<div
class="h-full w-full absolute bg-blue-300"
animate.enter="animate-slide-in"
animate.leave="animate-slide-out"
>
<div class="py-4 container mx-auto"> <div class="py-4 container mx-auto">
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<p>inventory works!</p> <p>inventory works!</p>
@@ -6,3 +11,4 @@
</div> </div>
</div> </div>
</div> </div>
}

View File

@@ -1,4 +1,4 @@
import { Component, output, OutputEmitterRef } from '@angular/core'; import { Component, input, InputSignal, output, OutputEmitterRef } from '@angular/core';
import { ButtonComponent } from "../ui-elements/button/button.component"; import { ButtonComponent } from "../ui-elements/button/button.component";
@Component({ @Component({
@@ -7,6 +7,7 @@ import { ButtonComponent } from "../ui-elements/button/button.component";
templateUrl: './inventory.component.html', templateUrl: './inventory.component.html',
}) })
export class InventoryComponent { export class InventoryComponent {
public readonly isVisible: InputSignal<boolean> = input.required();
public readonly onClose: OutputEmitterRef<void> = output<void>(); public readonly onClose: OutputEmitterRef<void> = output<void>();
public readonly onItemChosen: OutputEmitterRef<any> = output<any>(); public readonly onItemChosen: OutputEmitterRef<any> = output<any>();

View File

@@ -8,7 +8,7 @@
[routerLink]="['/' + ERouteKey.Interactions + '/' + chibi.id]" [routerLink]="['/' + ERouteKey.Interactions + '/' + chibi.id]"
class="w-full flex flex-row gap-4 bg-primary-200 p-4 rounded-lg cursor-pointer" class="w-full flex flex-row gap-4 bg-primary-200 p-4 rounded-lg cursor-pointer"
> >
<img [src]="chibi.iconPath" class="rounded-full w-3/12" /> <img [src]="chibi.iconPath" class="rounded-full w-12 aspect-square" />
<div> <div>
<div class="flex flex-row items-center gap-2"> <div class="flex flex-row items-center gap-2">
<div <div

View File

@@ -14,15 +14,17 @@
} }
</div> </div>
<div class="h-1/3 min-h-20 bg-primary-300 relative"> <div class="h-1/3 min-h-20 bg-primary-300 relative">
@if (shownMenu == EInteractionMenuState.Pantry) {
<ff-food-pantry <ff-food-pantry
[isVisible]="shownMenu == EInteractionMenuState.Pantry"
(onClose)="closeMenu()" (onClose)="closeMenu()"
(onFoodChosen)="interact(EChibiInteraction.Feed, $event)" (onFoodChosen)="interact(EChibiInteraction.Feed, $event)"
></ff-food-pantry> ></ff-food-pantry>
}
@if (shownMenu == EInteractionMenuState.Inventory) { <ff-inventory
<ff-inventory (onClose)="closeMenu()"></ff-inventory> [isVisible]="shownMenu == EInteractionMenuState.Inventory"
} (onClose)="closeMenu()"
></ff-inventory>
<div class="flex flex-row gap-5 py-4 container mx-auto"> <div class="flex flex-row gap-5 py-4 container mx-auto">
<ff-button (click)="openInventory()">{{ <ff-button (click)="openInventory()">{{
lang.game.actions.giveItem lang.game.actions.giveItem

View File

@@ -1,4 +1,4 @@
import { Component, computed, effect, inject, input, InputSignal, signal, Signal, WritableSignal } from '@angular/core'; import { Component, computed, effect, inject, input, InputSignal, OnDestroy, signal, Signal, WritableSignal } from '@angular/core';
import { HeaderComponent } from "../../components/ui-elements/header/header.component"; import { HeaderComponent } from "../../components/ui-elements/header/header.component";
import { ERouteKey } from '../../types/route-key'; import { ERouteKey } from '../../types/route-key';
import { Chibi, ChibiId } from '../../types/chibi/chibi'; import { Chibi, ChibiId } from '../../types/chibi/chibi';
@@ -12,7 +12,7 @@ import { IBrain } from '../../logic/chibi-behaviour/brain';
import { BRAIN_MAP } from '../../logic/chibi-behaviour/brain-map'; import { BRAIN_MAP } from '../../logic/chibi-behaviour/brain-map';
import { TranslateableComponent } from '../../components/translateable.component'; import { TranslateableComponent } from '../../components/translateable.component';
import { Food } from '../../types/food'; import { Food } from '../../types/food';
import { interval } from 'rxjs'; import { interval, Subscribable, Subscription } from 'rxjs';
import { RandomService } from '../../logic/random.service'; import { RandomService } from '../../logic/random.service';
import { ChibiInteraction } from '../../logic/chibi-behaviour/brains/aperio.brain'; import { ChibiInteraction } from '../../logic/chibi-behaviour/brains/aperio.brain';
@@ -29,7 +29,7 @@ const THINKING_INTERVAL: number = 2000;
imports: [HeaderComponent, InteractionCanvasComponent, FoodPantryComponent, InventoryComponent, ButtonComponent], imports: [HeaderComponent, InteractionCanvasComponent, FoodPantryComponent, InventoryComponent, ButtonComponent],
templateUrl: './interactions.component.html', templateUrl: './interactions.component.html',
}) })
export class InteractionsComponent extends TranslateableComponent { export class InteractionsComponent extends TranslateableComponent implements OnDestroy {
public readonly chibiId: InputSignal<ChibiId> = input.required<ChibiId>(); public readonly chibiId: InputSignal<ChibiId> = input.required<ChibiId>();
private readonly chibiStore: ChibiStore = inject(ChibiStore); private readonly chibiStore: ChibiStore = inject(ChibiStore);
@@ -46,6 +46,8 @@ export class InteractionsComponent extends TranslateableComponent {
private brain!: IBrain; private brain!: IBrain;
private sub: Subscription = new Subscription();
constructor() { constructor() {
super(); super();
effect(() => { effect(() => {
@@ -54,9 +56,13 @@ export class InteractionsComponent extends TranslateableComponent {
this.brain.init(this.chibi(), this.randomService); this.brain.init(this.chibi(), this.randomService);
} }
}) })
interval(THINKING_INTERVAL).subscribe(() => { this.sub.add(interval(THINKING_INTERVAL).subscribe(() => {
this.brain.exist(); this.brain.exist();
}) }));
}
ngOnDestroy() {
this.sub.unsubscribe();
} }
public interact(interaction: EChibiInteraction, item?: Food): void { public interact(interaction: EChibiInteraction, item?: Food): void {

View File

@@ -26,4 +26,24 @@
--color-secondary-900: #651e71; --color-secondary-900: #651e71;
--color-secondary-950: #41074b; --color-secondary-950: #41074b;
--animate-slide-in: slide-in 0.3s ease-in-out;
@keyframes slide-in {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
--animate-slide-out: slide-out 0.3s ease-in-out;
@keyframes slide-out {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
} }