mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 15:36:18 +00:00
🆙 Update Avatar-Editor, colors now also scale
This commit is contained in:
@@ -50,7 +50,6 @@ export const AvatarEditorModelView: FC<{
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col overflow-hidden h-full gap-1">
|
<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">
|
<div className="flex items-center px-2 gap-3 shrink-0">
|
||||||
{ (name === AvatarEditorFigureCategory.GENERIC) &&
|
{ (name === AvatarEditorFigureCategory.GENERIC) &&
|
||||||
<>
|
<>
|
||||||
@@ -85,7 +84,6 @@ export const AvatarEditorModelView: FC<{
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ /* ── Colour palette row at bottom ── */ }
|
|
||||||
<div className={ `flex shrink-0 overflow-hidden gap-2 ${ maxPaletteCount === 2 ? 'dual-palette' : '' }` } style={ { height: '160px' } }>
|
<div className={ `flex shrink-0 overflow-hidden gap-2 ${ maxPaletteCount === 2 ? 'dual-palette' : '' }` } style={ { height: '160px' } }>
|
||||||
{ (maxPaletteCount >= 1) &&
|
{ (maxPaletteCount >= 1) &&
|
||||||
<div className="flex-1 min-w-0 overflow-hidden avatar-editor-palette-set-view">
|
<div className="flex-1 min-w-0 overflow-hidden avatar-editor-palette-set-view">
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export const AvatarEditorView: FC<{}> = props =>
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NitroCardView
|
<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">
|
uniqueKey="avatar-editor">
|
||||||
<NitroCardHeaderView headerText={ LocalizeText('avatareditor.title') } onCloseClick={ event => setIsVisible(false) } />
|
<NitroCardHeaderView headerText={ LocalizeText('avatareditor.title') } onCloseClick={ event => setIsVisible(false) } />
|
||||||
<NitroCardTabsView classNames={ ['avatar-editor-tabs'] }>
|
<NitroCardTabsView classNames={ ['avatar-editor-tabs'] }>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export const AvatarEditorFigureSetView: FC<{
|
|||||||
if(!item) return null;
|
if(!item) return null;
|
||||||
|
|
||||||
return (
|
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 } />
|
} } 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 { FC } from 'react';
|
||||||
import { GetClubMemberLevel, GetConfigurationValue } from '../../../api';
|
import { ColorUtils, GetClubMemberLevel, GetConfigurationValue } from '../../../api';
|
||||||
import { LayoutCurrencyIcon, LayoutGridItemProps } from '../../../common';
|
import { LayoutCurrencyIcon, LayoutGridItemProps } from '../../../common';
|
||||||
import { InfiniteGrid } from '../../../layout';
|
import { InfiniteGrid } from '../../../layout';
|
||||||
|
|
||||||
export const AvatarEditorPaletteSetItem: FC<{
|
export const AvatarEditorPaletteSetItem: FC<{
|
||||||
setType: string;
|
|
||||||
partColor: IPartColor;
|
partColor: IPartColor;
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
width?: string;
|
|
||||||
} & LayoutGridItemProps> = props =>
|
} & 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;
|
if(!partColor) return null;
|
||||||
|
|
||||||
@@ -19,7 +17,17 @@ export const AvatarEditorPaletteSetItem: FC<{
|
|||||||
const isLocked = isHC && (GetClubMemberLevel() < partColor.clubLevel);
|
const isLocked = isHC && (GetClubMemberLevel() < partColor.clubLevel);
|
||||||
|
|
||||||
return (
|
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" /> }
|
{ isHC && <LayoutCurrencyIcon className="absolute inset-e-1 bottom-1" type="hc" /> }
|
||||||
</InfiniteGrid.Item>
|
</InfiniteGrid.Item>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export const AvatarEditorPaletteSetView: FC<{
|
|||||||
if(!item) return null;
|
if(!item) return null;
|
||||||
|
|
||||||
return (
|
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 } />
|
} } items={ category.colorItems[paletteIndex] } overscan={ columnCount } />
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -18,6 +18,22 @@ const InfiniteGridRoot = <T,>(props: Props<T>) =>
|
|||||||
const { items = [], columnCount = 4, overscan = 5, estimateSize = 45, squareItems = false, itemRender = null } = props;
|
const { items = [], columnCount = 4, overscan = 5, estimateSize = 45, squareItems = false, itemRender = null } = props;
|
||||||
const parentRef = useRef<HTMLDivElement>(null);
|
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({
|
const virtualizer = useVirtualizer({
|
||||||
count: Math.ceil(items.length / columnCount),
|
count: Math.ceil(items.length / columnCount),
|
||||||
overscan,
|
overscan,
|
||||||
|
|||||||
Reference in New Issue
Block a user