🆙 Update Avatar-Editor, colors now also scale

This commit is contained in:
duckietm
2026-02-26 16:48:47 +01:00
parent 0678e86d3d
commit 359932f891
6 changed files with 33 additions and 11 deletions
@@ -50,7 +50,6 @@ export const AvatarEditorModelView: FC<{
return (
<div className="flex flex-col overflow-hidden h-full gap-1">
{ /* ── Category / gender selector row ── */ }
<div className="flex items-center px-2 gap-3 shrink-0">
{ (name === AvatarEditorFigureCategory.GENERIC) &&
<>
@@ -85,7 +84,6 @@ export const AvatarEditorModelView: FC<{
</button>
</div>
{ /* ── Colour palette row at bottom ── */ }
<div className={ `flex shrink-0 overflow-hidden gap-2 ${ maxPaletteCount === 2 ? 'dual-palette' : '' }` } style={ { height: '160px' } }>
{ (maxPaletteCount >= 1) &&
<div className="flex-1 min-w-0 overflow-hidden avatar-editor-palette-set-view">
@@ -74,7 +74,7 @@ export const AvatarEditorView: FC<{}> = props =>
return (
<NitroCardView
className={ `nitro-avatar-editor ${ isWardrobeOpen ? 'w-[880px]' : 'w-[620px]' } h-[374px]` }
className={ `nitro-avatar-editor ${ isWardrobeOpen ? 'w-[880px]' : 'w-[620px]' } h-[460px]` }
uniqueKey="avatar-editor">
<NitroCardHeaderView headerText={ LocalizeText('avatareditor.title') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardTabsView classNames={ ['avatar-editor-tabs'] }>
@@ -34,7 +34,7 @@ export const AvatarEditorFigureSetView: FC<{
if(!item) return null;
return (
<AvatarEditorFigureSetItemView isSelected={ isPartItemSelected(item) } partItem={ item } setType={ category.setType } width={ `calc(100% / ${ columnCount }` } onClick={ event => selectEditorPart(category.setType, item.partSet?.id ?? -1) } />
<AvatarEditorFigureSetItemView isSelected={ isPartItemSelected(item) } partItem={ item } setType={ category.setType } width={ `calc(100% / ${ columnCount })` } onClick={ event => selectEditorPart(category.setType, item.partSet?.id ?? -1) } />
);
} } items={ category.partItems } overscan={ columnCount } />
);
@@ -1,17 +1,15 @@
import { ColorConverter, IPartColor } from '@nitrots/nitro-renderer';
import { IPartColor } from '@nitrots/nitro-renderer';
import { FC } from 'react';
import { GetClubMemberLevel, GetConfigurationValue } from '../../../api';
import { ColorUtils, GetClubMemberLevel, GetConfigurationValue } from '../../../api';
import { LayoutCurrencyIcon, LayoutGridItemProps } from '../../../common';
import { InfiniteGrid } from '../../../layout';
export const AvatarEditorPaletteSetItem: FC<{
setType: string;
partColor: IPartColor;
isSelected: boolean;
width?: string;
} & LayoutGridItemProps> = props =>
{
const { setType = null, partColor = null, isSelected = false, width = '100%', ...rest } = props;
const { partColor = null, isSelected = false, style = {}, ...rest } = props;
if(!partColor) return null;
@@ -19,7 +17,17 @@ export const AvatarEditorPaletteSetItem: FC<{
const isLocked = isHC && (GetClubMemberLevel() < partColor.clubLevel);
return (
<InfiniteGrid.Item itemHighlight className={ `clear-bg aspect-square${ isLocked ? ' opacity-50' : '' }` } itemActive={ isSelected } itemColor={ ColorConverter.int2rgb(partColor.rgb) } { ...rest }>
<InfiniteGrid.Item
itemHighlight
className={ `clear-bg${ isLocked ? ' opacity-50' : '' }` }
itemActive={ isSelected }
itemColor={ ColorUtils.makeColorNumberHex(partColor.rgb & 0xFFFFFF) }
style={ {
aspectRatio: '1 / 1',
minHeight: '14px',
...style
} }
{ ...rest }>
{ isHC && <LayoutCurrencyIcon className="absolute inset-e-1 bottom-1" type="hc" /> }
</InfiniteGrid.Item>
);
@@ -29,7 +29,7 @@ export const AvatarEditorPaletteSetView: FC<{
if(!item) return null;
return (
<AvatarEditorPaletteSetItem isSelected={ isPartColorSelected(item) } partColor={ item } setType={ category.setType } width={ `calc(100% / ${ columnCount }` } onClick={ event => selectEditorColor(category.setType, paletteIndex, item.id) } />
<AvatarEditorPaletteSetItem isSelected={ isPartColorSelected(item) } partColor={ item } onClick={ event => selectEditorColor(category.setType, paletteIndex, item.id) } />
);
} } items={ category.colorItems[paletteIndex] } overscan={ columnCount } />
);
+16
View File
@@ -18,6 +18,22 @@ const InfiniteGridRoot = <T,>(props: Props<T>) =>
const { items = [], columnCount = 4, overscan = 5, estimateSize = 45, squareItems = false, itemRender = null } = props;
const parentRef = useRef<HTMLDivElement>(null);
if(squareItems)
{
return (
<div ref={ parentRef } className="overflow-y-auto size-full">
<div className={ `grid grid-cols-${ columnCount } gap-1 w-full` }>
{ items.map((item, index) =>
{
if(!item) return <Fragment key={ `${ index }-empty` } />;
return <Fragment key={ `${ index }-item` }>{ itemRender(item, index % columnCount) }</Fragment>;
}) }
</div>
</div>
);
}
const virtualizer = useVirtualizer({
count: Math.ceil(items.length / columnCount),
overscan,