Merge branch 'origin/dev' into feature/youtube-tv

This commit is contained in:
dank074 2021-09-29 14:30:51 -05:00
commit 22ea73bd4f
256 changed files with 2939 additions and 2007 deletions

View File

@ -5,6 +5,23 @@ module.exports = {
webpack: { webpack: {
configure: (webpackConfig) => ({ configure: (webpackConfig) => ({
...webpackConfig, ...webpackConfig,
optimization: {
...webpackConfig.optimization,
splitChunks: {
cacheGroups: {
vendor: {
name: 'vendors',
test: /[\\/]node_modules[\\/]/,
chunks: 'all',
},
renderer: {
name: 'renderer',
test: /[\\/]node_modules[\\/]@nitrots[\\/]nitro-renderer[\\/]/,
chunks: 'all',
}
}
}
},
module: { module: {
...webpackConfig.module, ...webpackConfig.module,
rules: webpackConfig.module.rules.map((rule) => rules: webpackConfig.module.rules.map((rule) =>

View File

@ -17,6 +17,21 @@ $grid-active-border-color: $white;
$toolbar-height: 55px; $toolbar-height: 55px;
$achievement-width: 650px;
$achievement-height: 400px;
$avatar-editor-width: 620px;
$avatar-editor-height: 374px;
$catalog-width: 620px;
$catalog-height: 400px;
$inventory-width: 528px;
$inventory-height: 320px;
$navigator-width: 400px;
$navigator-height: 420px;
.nitro-app { .nitro-app {
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@ -125,7 +125,8 @@ export const App: FC<{}> = props =>
} }
return ( return (
<div className="nitro-app"> <div className="nitro-app overflow-hidden">
<div id="nitro-alerts-container" />
{ (!isReady || isError) && <LoadingView isError={ isError } message={ message } /> } { (!isReady || isError) && <LoadingView isError={ isError } message={ message } /> }
<TransitionAnimation type={ TransitionAnimationTypes.FADE_IN } inProp={ (isReady && !isError) } timeout={ 300 }> <TransitionAnimation type={ TransitionAnimationTypes.FADE_IN } inProp={ (isReady && !isError) } timeout={ 300 }>
<MainView /> <MainView />

View File

@ -0,0 +1,7 @@
import { CreateLinkEvent } from '..';
export function OpenMessengerChat(friendId: number = -1): void
{
if(friendId === -1) CreateLinkEvent('friends/messenger/open');
else CreateLinkEvent(`friends/messenger/${friendId}`);
}

1
src/api/friends/index.ts Normal file
View File

@ -0,0 +1 @@
export * from './OpenMessengerChat';

View File

@ -1,4 +1,5 @@
export * from './core'; export * from './core';
export * from './friends';
export * from './groups'; export * from './groups';
export * from './navigator'; export * from './navigator';
export * from './nitro'; export * from './nitro';

View File

@ -47,6 +47,8 @@ export function DispatchMouseEvent(roomId: number, canvasId: number, event: Mous
break; break;
case MouseEventType.MOUSE_UP: case MouseEventType.MOUSE_UP:
break; break;
case MouseEventType.RIGHT_CLICK:
break;
default: return; default: return;
} }

View File

@ -0,0 +1,20 @@
import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent';
export class RoomWidgetUpdateDecorateModeEvent extends RoomWidgetUpdateEvent
{
public static UPDATE_DECORATE: string = 'RWUDME_UPDATE_DECORATE';
private _isDecorating: boolean;
constructor(isDecorating: boolean)
{
super(RoomWidgetUpdateDecorateModeEvent.UPDATE_DECORATE);
this._isDecorating = isDecorating;
}
public get isDecorating(): boolean
{
return this._isDecorating;
}
}

View File

@ -14,6 +14,7 @@ export * from './RoomWidgetUpdateChatInputContentEvent';
export * from './RoomWidgetUpdateCreditFurniEvent'; export * from './RoomWidgetUpdateCreditFurniEvent';
export * from './RoomWidgetUpdateCustomStackHeightEvent'; export * from './RoomWidgetUpdateCustomStackHeightEvent';
export * from './RoomWidgetUpdateDanceStatusEvent'; export * from './RoomWidgetUpdateDanceStatusEvent';
export * from './RoomWidgetUpdateDecorateModeEvent';
export * from './RoomWidgetUpdateDimmerEvent'; export * from './RoomWidgetUpdateDimmerEvent';
export * from './RoomWidgetUpdateDimmerStateEvent'; export * from './RoomWidgetUpdateDimmerStateEvent';
export * from './RoomWidgetUpdateEvent'; export * from './RoomWidgetUpdateEvent';

View File

@ -1,7 +1,7 @@
import { IFurnitureData, NitroEvent, ObjectDataFactory, PetFigureData, PetRespectComposer, PetSupplementComposer, PetType, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectOperationType, RoomObjectType, RoomObjectVariable, RoomSessionPetInfoUpdateEvent, RoomSessionUserBadgesEvent, RoomTradingLevelEnum, RoomUnitDropHandItemComposer, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUserData, RoomWidgetEnum, RoomWidgetEnumItemExtradataParameter, Vector3d } from '@nitrots/nitro-renderer'; import { IFurnitureData, NitroEvent, ObjectDataFactory, PetFigureData, PetRespectComposer, PetSupplementComposer, PetType, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectOperationType, RoomObjectType, RoomObjectVariable, RoomSessionPetInfoUpdateEvent, RoomSessionUserBadgesEvent, RoomTradingLevelEnum, RoomUnitDropHandItemComposer, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUserData, RoomWidgetEnum, RoomWidgetEnumItemExtradataParameter, Vector3d } from '@nitrots/nitro-renderer';
import { GetNitroInstance, GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../..'; import { GetNitroInstance, GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../..';
import { InventoryTradeRequestEvent, WiredSelectObjectEvent } from '../../../../../events'; import { InventoryTradeRequestEvent, WiredSelectObjectEvent } from '../../../../../events';
import { FriendListSendFriendRequestEvent } from '../../../../../events/friend-list/FriendListSendFriendRequestEvent'; import { FriendsSendFriendRequestEvent } from '../../../../../events/friends/FriendsSendFriendRequestEvent';
import { dispatchUiEvent } from '../../../../../hooks/events'; import { dispatchUiEvent } from '../../../../../hooks/events';
import { SendMessageHook } from '../../../../../hooks/messages'; import { SendMessageHook } from '../../../../../hooks/messages';
import { PetSupplementEnum } from '../../../../../views/room/widgets/avatar-info/common/PetSupplementEnum'; import { PetSupplementEnum } from '../../../../../views/room/widgets/avatar-info/common/PetSupplementEnum';
@ -76,7 +76,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler
case RoomWidgetRoomObjectMessage.GET_OBJECT_INFO: case RoomWidgetRoomObjectMessage.GET_OBJECT_INFO:
return this.processObjectInfoMessage((message as RoomWidgetRoomObjectMessage)); return this.processObjectInfoMessage((message as RoomWidgetRoomObjectMessage));
case RoomWidgetUserActionMessage.SEND_FRIEND_REQUEST: case RoomWidgetUserActionMessage.SEND_FRIEND_REQUEST:
dispatchUiEvent(new FriendListSendFriendRequestEvent(userId)); dispatchUiEvent(new FriendsSendFriendRequestEvent(userId));
break; break;
case RoomWidgetUserActionMessage.RESPECT_USER: case RoomWidgetUserActionMessage.RESPECT_USER:
GetSessionDataManager().giveRespect(userId); GetSessionDataManager().giveRespect(userId);

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

View File

@ -42,6 +42,14 @@ $utilities: map-merge(
property: overflow, property: overflow,
values: auto hidden visible scroll, values: auto hidden visible scroll,
), ),
"overflow-x": (
property: overflow-x,
values: auto hidden visible scroll,
),
"overflow-y": (
property: overflow-y,
values: auto hidden visible scroll,
),
// scss-docs-end utils-overflow // scss-docs-end utils-overflow
// scss-docs-start utils-display // scss-docs-start utils-display
"display": ( "display": (

View File

@ -85,6 +85,7 @@ $ghost: #c8cad0 !default;
$gray-chateau: #a3a7b1 !default; $gray-chateau: #a3a7b1 !default;
$gable-green: #1C323F !default; $gable-green: #1C323F !default;
$william: #3d5f6e !default; $william: #3d5f6e !default;
$bluewood: #304059 !default;
$success: $green !default; $success: $green !default;
$info: $cyan !default; $info: $cyan !default;
$warning: $yellow !default; $warning: $yellow !default;
@ -385,7 +386,7 @@ $enable-transitions: true !default;
$enable-reduced-motion: true !default; $enable-reduced-motion: true !default;
$enable-smooth-scroll: true !default; $enable-smooth-scroll: true !default;
$enable-grid-classes: true !default; $enable-grid-classes: true !default;
$enable-cssgrid: false !default; $enable-cssgrid: true !default;
$enable-button-pointers: true !default; $enable-button-pointers: true !default;
$enable-rfs: true !default; $enable-rfs: true !default;
$enable-validation-icons: true !default; $enable-validation-icons: true !default;

View File

@ -1,44 +0,0 @@
$grid-options: (
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"
);
.grid-items {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-content: flex-start;
width: 100%;
margin-top: -3px;
overflow: hidden;
@each $option in $grid-options {
&.grid-#{$option} {
.grid-item {
width: calc(1 / #{$option} * 100% - (1 - 1 / #{$option}) * 3px);
&:nth-child(#{$option}n) {
margin-right: 0;
}
}
}
}
}
.row-grid {
margin: 0 !important;
.col {
padding: 0 !important;
}
}
@each $option in $grid-options {
.row-grid {
&.row-cols-#{$option} {
.col:nth-child(#{$option}n) {
padding-left: 10px !important;
}
}
}
}

View File

@ -10,11 +10,11 @@
background-position: center; background-position: center;
&.icon-nitro-light { &.icon-nitro-light {
background-image: url('../images/nitro/nitro-n-light.svg'); background-image: url("../images/nitro/nitro-n-light.svg");
} }
&.icon-nitro-dark { &.icon-nitro-dark {
background-image: url('../images/nitro/nitro-n-dark.svg'); background-image: url("../images/nitro/nitro-n-dark.svg");
} }
&.icon-nitro-light, &.icon-nitro-light,
@ -24,686 +24,697 @@
} }
&.icon-catalog { &.icon-catalog {
background-image: url('../images/toolbar/icons/catalog.png'); background-image: url("../images/toolbar/icons/catalog.png");
width: 37px; width: 37px;
height: 36px; height: 36px;
} }
&.icon-rooms { &.icon-rooms {
background-image: url('../images/toolbar/icons/rooms.png'); background-image: url("../images/toolbar/icons/rooms.png");
width: 44px; width: 44px;
height: 30px; height: 30px;
} }
&.icon-house { &.icon-house {
background-image: url('../images/toolbar/icons/house.png'); background-image: url("../images/toolbar/icons/house.png");
height: 30px; height: 30px;
width: 32px; width: 32px;
} }
&.icon-inventory { &.icon-inventory {
background-image: url('../images/toolbar/icons/inventory.png'); background-image: url("../images/toolbar/icons/inventory.png");
height: 41px; height: 41px;
width: 44px; width: 44px;
} }
&.icon-modtools { &.icon-modtools {
background-image: url('../images/toolbar/icons/modtools.png'); background-image: url("../images/toolbar/icons/modtools.png");
height: 34px; height: 34px;
width: 29px; width: 29px;
} }
&.icon-friendall { &.icon-friendall {
background-image: url('../images/toolbar/icons/friend_all.png'); background-image: url("../images/toolbar/icons/friend_all.png");
height: 33px; height: 33px;
width: 32px; width: 32px;
} }
&.icon-friendsearch { &.icon-friendsearch {
background-image: url('../images/toolbar/icons/friend_search.png'); background-image: url("../images/toolbar/icons/friend_search.png");
height: 33px; height: 33px;
width: 29px; width: 29px;
} }
&.icon-sendmessage { &.icon-sendmessage {
background-image: url('../images/toolbar/icons/sendmessage.png'); background-image: url("../images/toolbar/icons/sendmessage.png");
width: 20px; width: 20px;
height: 21px; height: 21px;
} }
&.icon-me-talents { &.icon-me-talents {
background-image: url('../images/toolbar/icons/me-menu/talents.png'); background-image: url("../images/toolbar/icons/me-menu/talents.png");
width: 32px; width: 32px;
height: 30px; height: 30px;
} }
&.icon-me-helper-tool { &.icon-me-helper-tool {
background-image: url('../images/toolbar/icons/me-menu/helper-tool.png'); background-image: url("../images/toolbar/icons/me-menu/helper-tool.png");
width: 32px; width: 32px;
height: 30px; height: 30px;
} }
&.icon-me-profile { &.icon-me-profile {
background-image: url('../images/toolbar/icons/me-menu/profile.png'); background-image: url("../images/toolbar/icons/me-menu/profile.png");
width: 32px; width: 32px;
height: 30px; height: 30px;
} }
&.icon-me-forums { &.icon-me-forums {
background-image: url('../images/toolbar/icons/me-menu/forums.png'); background-image: url("../images/toolbar/icons/me-menu/forums.png");
width: 32px; width: 32px;
height: 30px; height: 30px;
} }
&.icon-me-rooms { &.icon-me-rooms {
background-image: url('../images/toolbar/icons/me-menu/my-rooms.png'); background-image: url("../images/toolbar/icons/me-menu/my-rooms.png");
width: 30px; width: 30px;
height: 30px; height: 30px;
} }
&.icon-me-achievements { &.icon-me-achievements {
background-image: url('../images/toolbar/icons/me-menu/achievements.png'); background-image: url("../images/toolbar/icons/me-menu/achievements.png");
width: 31px; width: 31px;
height: 30px; height: 30px;
} }
&.icon-me-clothing { &.icon-me-clothing {
background-image: url('../images/toolbar/icons/me-menu/clothing.png'); background-image: url("../images/toolbar/icons/me-menu/clothing.png");
width: 27px; width: 27px;
height: 30px; height: 30px;
} }
&.icon-me-settings { &.icon-me-settings {
background-image: url('../images/toolbar/icons/me-menu/cog.png'); background-image: url("../images/toolbar/icons/me-menu/cog.png");
width: 28px; width: 28px;
height: 34px; height: 34px;
} }
&.icon-cog { &.icon-cog {
background: url('../images/icons/icon_cog.png'); background: url("../images/icons/icon_cog.png");
width: 14px; width: 14px;
height: 15px; height: 15px;
} }
&.icon-help { &.icon-help {
background: url('../images/icons/help.png'); background: url("../images/icons/help.png");
width: 13px; width: 13px;
height: 23px; height: 23px;
} }
&.icon-joinroom { &.icon-joinroom {
background-image: url('../images/toolbar/icons/joinroom.png'); background-image: url("../images/toolbar/icons/joinroom.png");
width: 21px; width: 21px;
height: 21px; height: 21px;
} }
&.icon-habbo { &.icon-habbo {
background-image: url('../images/toolbar/icons/habbo.png'); background-image: url("../images/toolbar/icons/habbo.png");
width: 28px; width: 28px;
height: 28px; height: 28px;
} }
&.icon-camera { &.icon-camera {
background-image: url('../images/toolbar/icons/camera.png'); background-image: url("../images/toolbar/icons/camera.png");
width: 38px; width: 38px;
height: 45px; height: 45px;
} }
&.icon-message { &.icon-message {
background-image: url('../images/toolbar/icons/message.png'); background-image: url("../images/toolbar/icons/message.png");
width: 36px; width: 36px;
height: 32px; height: 32px;
&.is-unseen { &.is-unseen {
background-image: url('../images/toolbar/icons/message_unsee.gif'); background-image: url("../images/toolbar/icons/message_unsee.gif");
} }
} }
&.icon-deny { &.icon-deny {
background: url('../images/icons/deny.png'); background: url("../images/icons/deny.png");
width: 13px; width: 13px;
height: 14px; height: 14px;
} }
&.icon-accept { &.icon-accept {
background: url('../images/icons/accept.png'); background: url("../images/icons/accept.png");
width: 13px; width: 13px;
height: 14px; height: 14px;
} }
&.icon-wired-trigger { &.icon-wired-trigger {
background-image: url('../images/wired/icon_trigger.png'); background-image: url("../images/wired/icon_trigger.png");
width: 13px; width: 13px;
height: 14px; height: 14px;
} }
&.icon-wired-condition { &.icon-wired-condition {
background-image: url('../images/wired/icon_condition.png'); background-image: url("../images/wired/icon_condition.png");
width: 13px; width: 13px;
height: 14px; height: 14px;
} }
&.icon-wired-action { &.icon-wired-action {
background-image: url('../images/wired/icon_action.png'); background-image: url("../images/wired/icon_action.png");
width: 13px; width: 13px;
height: 14px; height: 14px;
} }
&.arrow-left-icon { &.arrow-left-icon {
background-image: url('../images/avatareditor/arrow-left-icon.png'); background-image: url("../images/avatareditor/arrow-left-icon.png");
width: 28px; width: 28px;
height: 21px; height: 21px;
} }
&.arrow-right-icon { &.arrow-right-icon {
background-image: url('../images/avatareditor/arrow-right-icon.png'); background-image: url("../images/avatareditor/arrow-right-icon.png");
width: 28px; width: 28px;
height: 21px; height: 21px;
} }
&.clear-icon { &.clear-icon {
background-image: url('../images/avatareditor/clear-icon.png'); background-image: url("../images/avatareditor/clear-icon.png");
width: 27px; width: 27px;
height: 27px; height: 27px;
} }
&.ca-icon { &.ca-icon {
background-image: url('../images/avatareditor/ca-icon.png'); background-image: url("../images/avatareditor/ca-icon.png");
width: 25px; width: 25px;
height: 25px; height: 25px;
&.selected { &.selected {
background-image: url('../images/avatareditor/ca-selected-icon.png'); background-image: url("../images/avatareditor/ca-selected-icon.png");
} }
} }
&.cc-icon { &.cc-icon {
background-image: url('../images/avatareditor/cc-icon.png'); background-image: url("../images/avatareditor/cc-icon.png");
width: 31px; width: 31px;
height: 29px; height: 29px;
&.selected { &.selected {
background-image: url('../images/avatareditor/cc-selected-icon.png'); background-image: url("../images/avatareditor/cc-selected-icon.png");
} }
} }
&.ch-icon { &.ch-icon {
background-image: url('../images/avatareditor/ch-icon.png'); background-image: url("../images/avatareditor/ch-icon.png");
width: 29px; width: 29px;
height: 24px; height: 24px;
&.selected { &.selected {
background-image: url('../images/avatareditor/ch-selected-icon.png'); background-image: url("../images/avatareditor/ch-selected-icon.png");
} }
} }
&.cp-icon { &.cp-icon {
background-image: url('../images/avatareditor/cp-icon.png'); background-image: url("../images/avatareditor/cp-icon.png");
width: 30px; width: 30px;
height: 24px; height: 24px;
&.selected { &.selected {
background-image: url('../images/avatareditor/cp-selected-icon.png'); background-image: url("../images/avatareditor/cp-selected-icon.png");
} }
} }
&.ea-icon { &.ea-icon {
background-image: url('../images/avatareditor/ea-icon.png'); background-image: url("../images/avatareditor/ea-icon.png");
width: 35px; width: 35px;
height: 16px; height: 16px;
&.selected { &.selected {
background-image: url('../images/avatareditor/ea-selected-icon.png'); background-image: url("../images/avatareditor/ea-selected-icon.png");
} }
} }
&.fa-icon { &.fa-icon {
background-image: url('../images/avatareditor/fa-icon.png'); background-image: url("../images/avatareditor/fa-icon.png");
width: 27px; width: 27px;
height: 20px; height: 20px;
&.selected { &.selected {
background-image: url('../images/avatareditor/fa-selected-icon.png'); background-image: url("../images/avatareditor/fa-selected-icon.png");
} }
} }
&.female-icon { &.female-icon {
background-image: url('../images/avatareditor/female-icon.png'); background-image: url("../images/avatareditor/female-icon.png");
width: 18px; width: 18px;
height: 27px; height: 27px;
&.selected { &.selected {
background-image: url('../images/avatareditor/female-selected-icon.png'); background-image: url("../images/avatareditor/female-selected-icon.png");
} }
} }
&.ha-icon { &.ha-icon {
background-image: url('../images/avatareditor/ha-icon.png'); background-image: url("../images/avatareditor/ha-icon.png");
width: 25px; width: 25px;
height: 22px; height: 22px;
&.selected { &.selected {
background-image: url('../images/avatareditor/ha-selected-icon.png'); background-image: url("../images/avatareditor/ha-selected-icon.png");
} }
} }
&.he-icon { &.he-icon {
background-image: url('../images/avatareditor/he-icon.png'); background-image: url("../images/avatareditor/he-icon.png");
width: 31px; width: 31px;
height: 27px; height: 27px;
&.selected { &.selected {
background-image: url('../images/avatareditor/he-selected-icon.png'); background-image: url("../images/avatareditor/he-selected-icon.png");
} }
} }
&.hr-icon { &.hr-icon {
background-image: url('../images/avatareditor/hr-icon.png'); background-image: url("../images/avatareditor/hr-icon.png");
width: 29px; width: 29px;
height: 25px; height: 25px;
&.selected { &.selected {
background-image: url('../images/avatareditor/hr-selected-icon.png'); background-image: url("../images/avatareditor/hr-selected-icon.png");
} }
} }
&.lg-icon { &.lg-icon {
background-image: url('../images/avatareditor/lg-icon.png'); background-image: url("../images/avatareditor/lg-icon.png");
width: 19px; width: 19px;
height: 20px; height: 20px;
&.selected { &.selected {
background-image: url('../images/avatareditor/lg-selected-icon.png'); background-image: url("../images/avatareditor/lg-selected-icon.png");
} }
} }
&.loading-icon { &.loading-icon {
background-image: url('../images/icons/loading-icon.png'); background-image: url("../images/icons/loading-icon.png");
width: 17px; width: 17px;
height: 21px; height: 21px;
} }
&.male-icon { &.male-icon {
background-image: url('../images/avatareditor/male-icon.png'); background-image: url("../images/avatareditor/male-icon.png");
width: 21px; width: 21px;
height: 21px; height: 21px;
&.selected { &.selected {
background-image: url('../images/avatareditor/male-selected-icon.png'); background-image: url("../images/avatareditor/male-selected-icon.png");
} }
} }
&.sh-icon { &.sh-icon {
background-image: url('../images/avatareditor/sh-icon.png'); background-image: url("../images/avatareditor/sh-icon.png");
width: 37px; width: 37px;
height: 10px; height: 10px;
&.selected { &.selected {
background-image: url('../images/avatareditor/sh-selected-icon.png'); background-image: url("../images/avatareditor/sh-selected-icon.png");
} }
} }
&.wa-icon { &.wa-icon {
background-image: url('../images/avatareditor/wa-icon.png'); background-image: url("../images/avatareditor/wa-icon.png");
width: 36px; width: 36px;
height: 18px; height: 18px;
&.selected { &.selected {
background-image: url('../images/avatareditor/wa-selected-icon.png'); background-image: url("../images/avatareditor/wa-selected-icon.png");
} }
} }
&.sellable-icon { &.sellable-icon {
background-image: url('../images/avatareditor/sellable-icon.png'); background-image: url("../images/avatareditor/sellable-icon.png");
width: 17px; width: 17px;
height: 15px; height: 15px;
} }
&.chatstyles-icon { &.chatstyles-icon {
background-image: url('../images/chat/styles-icon.png'); background-image: url("../images/chat/styles-icon.png");
width: 17px; width: 17px;
height: 19px; height: 19px;
} }
&.pencil-icon { &.pencil-icon {
background-image: url('../images/infostand/pencil-icon.png'); background-image: url("../images/infostand/pencil-icon.png");
width: 17px; width: 17px;
height: 18px; height: 18px;
} }
&.trade-locked-icon { &.trade-locked-icon {
background-image: url('../images/inventory/trading/locked-icon.png'); background-image: url("../images/inventory/trading/locked-icon.png");
width: 29px; width: 29px;
height: 43px; height: 43px;
} }
&.trade-unlocked-icon { &.trade-unlocked-icon {
background-image: url('../images/inventory/trading/unlocked-icon.png'); background-image: url("../images/inventory/trading/unlocked-icon.png");
width: 29px; width: 29px;
height: 43px; height: 43px;
} }
&.modtool-room-icon { &.modtool-room-icon {
background-image: url('../images/modtool/room.png'); background-image: url("../images/modtool/room.png");
width: 20px; width: 20px;
height: 15px; height: 15px;
} }
&.modtool-chatlog-icon { &.modtool-chatlog-icon {
background-image: url('../images/modtool/chatlog.gif'); background-image: url("../images/modtool/chatlog.gif");
width: 20px; width: 20px;
height: 15px; height: 15px;
} }
&.modtool-user-icon{ &.modtool-user-icon {
background-image: url('../images/modtool/user.gif'); background-image: url("../images/modtool/user.gif");
width: 20px; width: 20px;
height: 15px; height: 15px;
} }
&.modtool-reports-icon { &.modtool-reports-icon {
background-image: url('../images/modtool/reports.png'); background-image: url("../images/modtool/reports.png");
width: 20px; width: 20px;
height: 15px; height: 15px;
} }
&.modtool-wrench-icon { &.modtool-wrench-icon {
background-image: url('../images/modtool/wrench.gif'); background-image: url("../images/modtool/wrench.gif");
width: 20px; width: 20px;
height: 15px; height: 15px;
} }
&.modtool-key-icon { &.modtool-key-icon {
background-image: url('../images/modtool/key.gif'); background-image: url("../images/modtool/key.gif");
width: 20px; width: 20px;
height: 15px; height: 15px;
} }
&.icon-catalogue-hc_small { &.icon-catalogue-hc_small {
background-image: url('../images/catalog/hc_small.png'); background-image: url("../images/catalog/hc_small.png");
height: 17px; height: 17px;
width: 31px; width: 31px;
} }
&.icon-catalogue-hc_big { &.icon-catalogue-hc_big {
background: url('../images/catalog/hc_big.png'); background: url("../images/catalog/hc_big.png");
width: 68px; width: 68px;
height: 40px; height: 40px;
} }
&.icon-sign-exclamation { &.icon-sign-exclamation {
background: url('../images/icons/sign-exclamation.png'); background: url("../images/icons/sign-exclamation.png");
width: 7px; width: 7px;
height: 17px; height: 17px;
} }
&.icon-sign-heart { &.icon-sign-heart {
background: url('../images/icons/sign-heart.png'); background: url("../images/icons/sign-heart.png");
width: 15px; width: 15px;
height: 13px; height: 13px;
} }
&.icon-sign-red { &.icon-sign-red {
background: url('../images/icons/sign-red.png'); background: url("../images/icons/sign-red.png");
width: 11px; width: 11px;
height: 19px; height: 19px;
} }
&.icon-sign-yellow { &.icon-sign-yellow {
background: url('../images/icons/sign-yellow.png'); background: url("../images/icons/sign-yellow.png");
width: 11px; width: 11px;
height: 19px; height: 19px;
} }
&.icon-sign-skull { &.icon-sign-skull {
background: url('../images/icons/sign-skull.png'); background: url("../images/icons/sign-skull.png");
width: 12px; width: 12px;
height: 12px; height: 12px;
} }
&.icon-sign-smile { &.icon-sign-smile {
background: url('../images/icons/sign-smile.png'); background: url("../images/icons/sign-smile.png");
width: 7px; width: 7px;
height: 14px; height: 14px;
} }
&.icon-sign-soccer { &.icon-sign-soccer {
background: url('../images/icons/sign-soccer.png'); background: url("../images/icons/sign-soccer.png");
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
&.icon-house-small { &.icon-house-small {
background: url('../images/icons/house-small.png'); background: url("../images/icons/house-small.png");
width: 19px; width: 19px;
height: 14px; height: 14px;
} }
&.icon-camera-small { &.icon-camera-small {
background: url('../images/icons/camera-small.png'); background: url("../images/icons/camera-small.png");
width: 17px; width: 17px;
height: 15px; height: 15px;
} }
&.icon-arrows { &.icon-arrows {
background: url('../images/icons/arrows.png'); background: url("../images/icons/arrows.png");
width: 17px; width: 17px;
height: 15px; height: 15px;
} }
&.icon-fb-profile { &.icon-fb-profile {
background: url('../images/toolbar/icons/friend-bar/profile.png'); background: url("../images/toolbar/icons/friend-bar/profile.png");
width: 21px; width: 21px;
height: 21px; height: 21px;
} }
&.icon-camera-colormatrix { &.icon-camera-colormatrix {
background: url('../images/icons/camera-colormatrix.png'); background: url("../images/icons/camera-colormatrix.png");
width: 32px; width: 32px;
height: 21px; height: 21px;
} }
&.icon-camera-composite { &.icon-camera-composite {
background: url('../images/icons/camera-composite.png'); background: url("../images/icons/camera-composite.png");
width: 32px; width: 32px;
height: 21px; height: 21px;
} }
&.icon-user-profile { &.icon-user-profile {
background: url('../images/icons/user-profile.png'); background: url("../images/icons/user-profile.png");
width: 13px; width: 13px;
height: 11px; height: 11px;
&:hover { &:hover {
background: url('../images/icons/user-profile-hover.png'); background: url("../images/icons/user-profile-hover.png");
} }
} }
&.icon-fb-profile { &.icon-fb-profile {
background: url('../images/toolbar/icons/friend-bar/profile.png'); background: url("../images/toolbar/icons/friend-bar/profile.png");
width: 21px; width: 21px;
height: 21px; height: 21px;
} }
&.icon-fb-chat { &.icon-fb-chat {
background: url('../images/toolbar/icons/friend-bar/chat.png'); background: url("../images/toolbar/icons/friend-bar/chat.png");
width: 20px; width: 20px;
height: 21px; height: 21px;
} }
&.icon-fb-visit { &.icon-fb-visit {
background: url('../images/toolbar/icons/friend-bar/visit.png'); background: url("../images/toolbar/icons/friend-bar/visit.png");
width: 21px; width: 21px;
height: 21px; height: 21px;
} }
&.icon-pf-online { &.icon-pf-online {
background: url('../images/profile/icons/online.gif'); background: url("../images/profile/icons/online.gif");
width: 40px; width: 40px;
height: 16px; height: 16px;
} }
&.icon-pf-offline { &.icon-pf-offline {
background: url('../images/profile/icons/offline.png'); background: url("../images/profile/icons/offline.png");
width: 39px; width: 39px;
height: 16px; height: 16px;
} }
&.icon-pf-tick { &.icon-pf-tick {
background: url('../images/profile/icons/tick.png'); background: url("../images/profile/icons/tick.png");
width: 11px; width: 11px;
height: 10px; height: 10px;
} }
&.icon-relationship-none { &.icon-relationship-none {
background: url('../images/friendlist/icons/icon_relationship_none.png'); background: url("../images/friendlist/icons/icon_relationship_none.png");
width: 16px; width: 16px;
height: 14px; height: 14px;
} }
&.icon-relationship-heart { &.icon-relationship-heart {
background: url('../images/profile/icons/heart.png'); background: url("../images/profile/icons/heart.png");
width: 16px; width: 16px;
height: 14px; height: 14px;
} }
&.icon-relationship-bobba { &.icon-relationship-bobba {
background: url('../images/profile/icons/bobba.png'); background: url("../images/profile/icons/bobba.png");
width: 16px; width: 16px;
height: 14px; height: 14px;
} }
&.icon-relationship-smile { &.icon-relationship-smile {
background: url('../images/profile/icons/smile.png'); background: url("../images/profile/icons/smile.png");
width: 16px; width: 16px;
height: 14px; height: 14px;
} }
&.icon-group-type-0 { &.icon-group-type-0 {
background: url('../images/groups/icons/grouptype_icon_0.png'); background: url("../images/groups/icons/grouptype_icon_0.png");
width: 16px; width: 16px;
height: 16px; height: 16px;
} }
&.icon-group-type-1 { &.icon-group-type-1 {
background: url('../images/groups/icons/grouptype_icon_1.png'); background: url("../images/groups/icons/grouptype_icon_1.png");
width: 16px; width: 16px;
height: 16px; height: 16px;
} }
&.icon-group-type-2 { &.icon-group-type-2 {
background: url('../images/groups/icons/grouptype_icon_2.png'); background: url("../images/groups/icons/grouptype_icon_2.png");
width: 16px; width: 16px;
height: 16px; height: 16px;
} }
&.icon-group-decorate { &.icon-group-decorate {
background: url('../images/groups/icons/group_decorate_icon.png'); background: url("../images/groups/icons/group_decorate_icon.png");
width: 15px; width: 15px;
height: 15px; height: 15px;
} }
&.icon-group-member { &.icon-group-member {
background: url('../images/groups/icons/group_icon_big_member.png'); background: url("../images/groups/icons/group_icon_big_member.png");
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
&.icon-group-admin { &.icon-group-admin {
background: url('../images/groups/icons/group_icon_big_admin.png'); background: url("../images/groups/icons/group_icon_big_admin.png");
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
&.icon-group-owner { &.icon-group-owner {
background: url('../images/groups/icons/group_icon_big_owner.png'); background: url("../images/groups/icons/group_icon_big_owner.png");
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
&.icon-group-favorite { &.icon-group-favorite {
background: url('../images/groups/icons/group_favorite.png'); background: url("../images/groups/icons/group_favorite.png");
width: 14px; width: 14px;
height: 14px; height: 14px;
} }
&.icon-group-not-favorite { &.icon-group-not-favorite {
background: url('../images/groups/icons/group_notfavorite.png'); background: url("../images/groups/icons/group_notfavorite.png");
width: 14px; width: 14px;
height: 14px; height: 14px;
} }
&.icon-group-small-admin { &.icon-group-small-admin {
background: url('../images/groups/icons/group_icon_admin.png'); background: url("../images/groups/icons/group_icon_admin.png");
width: 11px; width: 11px;
height: 13px; height: 13px;
} }
&.icon-group-small-not-admin { &.icon-group-small-not-admin {
background: url('../images/groups/icons/group_icon_not_admin.png'); background: url("../images/groups/icons/group_icon_not_admin.png");
width: 11px; width: 11px;
height: 13px; height: 13px;
} }
&.icon-group-small-owner { &.icon-group-small-owner {
background: url('../images/groups/icons/group_icon_small_owner.png'); background: url("../images/groups/icons/group_icon_small_owner.png");
width: 13px; width: 13px;
height: 13px; height: 13px;
} }
&.icon-navigator-info { &.icon-navigator-info {
background: url('../images/navigator/icons/info.png'); background: url("../images/navigator/icons/info.png");
width: 18px; width: 18px;
height: 18px; height: 18px;
} }
&.icon-navigator-room-locked { &.icon-navigator-room-locked {
background: url('../images/navigator/icons/room_locked.png'); background: url("../images/navigator/icons/room_locked.png");
width: 13px; width: 13px;
height: 16px; height: 16px;
} }
&.icon-navigator-room-password { &.icon-navigator-room-password {
background: url('../images/navigator/icons/room_password.png'); background: url("../images/navigator/icons/room_password.png");
width: 13px; width: 13px;
height: 16px; height: 16px;
} }
&.icon-navigator-room-invisible { &.icon-navigator-room-invisible {
background: url('../images/navigator/icons/room_invisible.png'); background: url("../images/navigator/icons/room_invisible.png");
width: 13px; width: 13px;
height: 16px; height: 16px;
} }
&.icon-navigator-room-group { &.icon-navigator-room-group {
background: url('../images/navigator/icons/room_group.png'); background: url("../images/navigator/icons/room_group.png");
width: 13px; width: 13px;
height: 11px; height: 11px;
} }
&.icon-friendlist-follow { &.icon-friendlist-follow {
background: url('../images/friendlist/icons/icon_follow.png'); background: url("../images/friendlist/icons/icon_follow.png");
width: 16px; width: 16px;
height: 14px; height: 14px;
} }
&.icon-friendlist-chat { &.icon-friendlist-chat {
background: url('../images/friendlist/icons/icon_chat.png'); background: url("../images/friendlist/icons/icon_chat.png");
width: 17px; width: 17px;
height: 16px; height: 16px;
} }
&.icon-youtube-next { &.icon-youtube-next {
background: url('../images/room-widgets/youtube-widget/next.png'); background: url("../images/room-widgets/youtube-widget/next.png");
width: 21px; width: 21px;
height: 16px; height: 16px;
} }
&.icon-youtube-prev { &.icon-youtube-prev {
background: url('../images/room-widgets/youtube-widget/prev.png'); background: url("../images/room-widgets/youtube-widget/prev.png");
width: 21px; width: 21px;
height: 16px; height: 16px;
} }
&.icon-friendlist-warning {
background: url("../images/friendlist/icons/icon_warning.png");
width: 23px;
height: 21px;
}
&.icon-friendlist-new-message {
background: url("../images/friendlist/icons/icon_new_message.png");
width: 14px;
height: 16px;
}
&.spin { &.spin {
animation: rotating 1s linear infinite; animation: rotating 1s linear infinite;

View File

@ -7,7 +7,6 @@
@import '../node_modules/animate.css/animate.min.css'; @import '../node_modules/animate.css/animate.min.css';
@import './scrollbars'; @import './scrollbars';
@import './slider'; @import './slider';
@import './grid';
@import './icons'; @import './icons';
@import './utils'; @import './utils';
@ -15,6 +14,10 @@
min-height: 28px; min-height: 28px;
} }
textarea {
resize: none;
}
/* Chrome, Safari, Edge, Opera */ /* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button, input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button { input::-webkit-inner-spin-button {

View File

@ -1,15 +1,41 @@
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 0.5rem; width: 0.5rem;
&:horizontal {
height: 0.5rem; height: 0.5rem;
}
&:not(:horizontal) {
width: 0.5rem;
}
} }
::-webkit-scrollbar-track { ::-webkit-scrollbar-track {
background-clip: padding-box;
&:horizontal {
border-bottom: 0.25rem solid rgba($black, .1);
}
&:not(:horizontal) {
border-right: 0.25rem solid rgba($black, .1); border-right: 0.25rem solid rgba($black, .1);
}
} }
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
background-clip: padding-box;
&:horizontal {
border-bottom: 0.25rem solid rgba($primary, .4);
&:hover {
border-bottom: 0.25rem solid rgba($primary, .8);
}
&:active {
border-bottom: 0.25rem solid $secondary;
}
}
&:not(:horizontal) {
border-right: 0.25rem solid rgba($primary, .4); border-right: 0.25rem solid rgba($primary, .4);
&:hover { &:hover {
@ -19,4 +45,9 @@
&:active { &:active {
border-right: 0.25rem solid $secondary; border-right: 0.25rem solid $secondary;
} }
}
}
::-webkit-scrollbar-corner {
background: rgba($black, .1);
} }

View File

@ -10,6 +10,14 @@
transform: scale(1) translateZ(0); transform: scale(1) translateZ(0);
} }
.scale-1-25 {
transform: scale(1.25) translateZ(0);
}
.scale-1-50 {
transform: scale(1.50) translateZ(0);
}
.scale-2 { .scale-2 {
transform: scale(2) translateZ(0); transform: scale(2) translateZ(0);
} }

View File

@ -1,2 +0,0 @@
export * from './FriendEnteredRoomEvent';
export * from './FriendListEvent';

View File

@ -1,7 +1,7 @@
import { MessengerFriend } from '../../views/friends/common/MessengerFriend'; import { MessengerFriend } from '../../views/friends/common/MessengerFriend';
import { FriendListEvent } from './FriendListEvent'; import { FriendsEvent } from './FriendsEvent';
export class FriendListContentEvent extends FriendListEvent export class FriendListContentEvent extends FriendsEvent
{ {
public static FRIEND_LIST_CONTENT: string = 'FLSFRE_FRIEND_LIST_CONTENT'; public static FRIEND_LIST_CONTENT: string = 'FLSFRE_FRIEND_LIST_CONTENT';

View File

@ -1,8 +1,10 @@
import { NitroEvent } from '@nitrots/nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class FriendListEvent extends NitroEvent export class FriendsEvent extends NitroEvent
{ {
public static SHOW_FRIEND_LIST: string = 'IE_SHOW_FRIEND_LIST'; public static SHOW_FRIEND_LIST: string = 'IE_SHOW_FRIEND_LIST';
public static TOGGLE_FRIEND_LIST: string = 'IE_TOGGLE_FRIEND_LIST'; public static TOGGLE_FRIEND_LIST: string = 'IE_TOGGLE_FRIEND_LIST';
public static SHOW_FRIEND_MESSENGER: string = 'IE_SHOW_FRIEND_MESSENGER';
public static TOGGLE_FRIEND_MESSENGER: string = 'IE_TOGGLE_FRIEND_MESSENGER';
public static REQUEST_FRIEND_LIST: string = 'FLSFRE_REQUEST_FRIEND_LIST'; public static REQUEST_FRIEND_LIST: string = 'FLSFRE_REQUEST_FRIEND_LIST';
} }

View File

@ -0,0 +1,23 @@
import { NitroEvent } from '@nitrots/nitro-renderer';
export class FriendsMessengerIconEvent extends NitroEvent
{
public static UPDATE_ICON: string = 'FMIE_UPDATE_ICON';
public static HIDE_ICON: number = 0;
public static SHOW_ICON: number = 1;
public static UNREAD_ICON: number = 2;
private _iconType: number;
constructor(type: string, subType: number = FriendsMessengerIconEvent.SHOW_ICON)
{
super(type);
this._iconType = subType;
}
public get iconType(): number
{
return this._iconType;
}
}

View File

@ -1,6 +1,6 @@
import { FriendListEvent } from './FriendListEvent'; import { FriendsEvent } from './FriendsEvent';
export class FriendListSendFriendRequestEvent extends FriendListEvent export class FriendsSendFriendRequestEvent extends FriendsEvent
{ {
public static SEND_FRIEND_REQUEST: string = 'FLSFRE_SEND_FRIEND_REQUEST'; public static SEND_FRIEND_REQUEST: string = 'FLSFRE_SEND_FRIEND_REQUEST';
@ -8,7 +8,7 @@ export class FriendListSendFriendRequestEvent extends FriendListEvent
constructor(userId: number) constructor(userId: number)
{ {
super(FriendListSendFriendRequestEvent.SEND_FRIEND_REQUEST); super(FriendsSendFriendRequestEvent.SEND_FRIEND_REQUEST);
this._userId = userId; this._userId = userId;
} }

View File

@ -0,0 +1,5 @@
export * from './FriendEnteredRoomEvent';
export * from './FriendListContentEvent';
export * from './FriendsEvent';
export * from './FriendsMessengerIconEvent';
export * from './FriendsSendFriendRequestEvent';

View File

@ -1,7 +1,7 @@
export * from './avatar-editor'; export * from './avatar-editor';
export * from './camera'; export * from './camera';
export * from './catalog'; export * from './catalog';
export * from './friend-list'; export * from './friends';
export * from './inventory'; export * from './inventory';
export * from './navigator'; export * from './navigator';
export * from './notification-center'; export * from './notification-center';

View File

@ -1,29 +1,36 @@
import { NitroEvent } from '@nitrots/nitro-renderer'; import { NitroEvent } from '@nitrots/nitro-renderer';
export class SimpleAlertUIEvent extends NitroEvent export class NotificationAlertEvent extends NitroEvent
{ {
public static ALERT: string = 'SAUE_ALERT'; public static ALERT: string = 'NAE_ALERT';
private _message: string; private _messages: string[];
private _alertType: string;
private _clickUrl: string; private _clickUrl: string;
private _clickUrlText: string; private _clickUrlText: string;
private _title: string; private _title: string;
private _imageUrl: string; private _imageUrl: string;
constructor(message: string, clickUrl: string = null, clickUrlText: string = null, title: string = null, imageUrl: string = null) constructor(messages: string[], alertType: string = null, clickUrl: string = null, clickUrlText: string = null, title: string = null, imageUrl: string = null)
{ {
super(SimpleAlertUIEvent.ALERT); super(NotificationAlertEvent.ALERT);
this._message = message; this._messages = messages;
this._alertType = alertType;
this._clickUrl = clickUrl; this._clickUrl = clickUrl;
this._clickUrlText = clickUrlText; this._clickUrlText = clickUrlText;
this._title = title; this._title = title;
this._imageUrl = imageUrl; this._imageUrl = imageUrl;
} }
public get message(): string public get messages(): string[]
{ {
return this._message; return this._messages;
}
public get alertType(): string
{
return this._alertType;
} }
public get clickUrl(): string public get clickUrl(): string

View File

@ -2,7 +2,7 @@ import { NitroEvent } from '@nitrots/nitro-renderer';
export class NotificationBubbleEvent extends NitroEvent export class NotificationBubbleEvent extends NitroEvent
{ {
public static NEW_BUBBLE: string = 'NNBE_NEW_BUBBLE'; public static NEW_BUBBLE: string = 'NBE_NEW_BUBBLE';
private _message: string; private _message: string;
private _notificationType: string; private _notificationType: string;

View File

@ -1,19 +0,0 @@
import { NitroNotification } from '../../views/notification-center/common/Notification';
import { NotificationCenterEvent } from './NotificationCenterEvent';
export class NotificationCenterAddNotificationEvent extends NotificationCenterEvent
{
private _notification: NitroNotification;
constructor(notification: NitroNotification)
{
super(NotificationCenterEvent.ADD_NOTIFICATION);
this._notification = notification;
}
public get notification(): NitroNotification
{
return this._notification;
}
}

View File

@ -1,4 +1,4 @@
export * from './NotificationCenterAddNotificationEvent'; export * from './NotificationAlertEvent';
export * from './NotificationBubbleEvent';
export * from './NotificationCenterAlertEvent'; export * from './NotificationCenterAlertEvent';
export * from './NotificationCenterEvent'; export * from './NotificationCenterEvent';
export * from './SimpleAlertUIEvent';

View File

@ -14,4 +14,8 @@ body {
image-rendering: -moz-crisp-edges; image-rendering: -moz-crisp-edges;
} }
img {
object-fit: none;
}
@import './App'; @import './App';

View File

@ -27,6 +27,7 @@
@import './loading-habbos/LoadingHabbosView'; @import './loading-habbos/LoadingHabbosView';
@import './loading-spinner/LoadingSpinnerView'; @import './loading-spinner/LoadingSpinnerView';
@import './mini-camera/NitroLayoutMiniCameraView'; @import './mini-camera/NitroLayoutMiniCameraView';
@import './notification-alert/NotificationAlertView';
@import './notification-bubble/NotificationBubbleView'; @import './notification-bubble/NotificationBubbleView';
@import './trophy/NitroLayoutTrophyView'; @import './trophy/NitroLayoutTrophyView';
@import './gift-card/NitroLayoutGiftCardView'; @import './gift-card/NitroLayoutGiftCardView';

View File

@ -0,0 +1,28 @@
import { FC, useMemo } from 'react';
import { NitroLayoutBaseProps } from './NitroLayoutBase.types';
export const NitroLayoutBase: FC<NitroLayoutBaseProps> = props =>
{
const { className = '', overflow = null, position = null, gap = null, children = null, ...rest } = props;
const getClassName = useMemo(() =>
{
let newClassName = '';
if(overflow && overflow.length) newClassName += ` overflow-${ overflow }`;
if(position && position.length) newClassName += ` position-${ position }`;
if(gap && gap >= 1) newClassName += ` gap-${ gap }`;
if(className && className.length) newClassName += ` ${ className }`;
return newClassName;
}, [ className, overflow, position, gap ]);
return (
<div className={ getClassName } { ...rest }>
{ children }
</div>
);
}

View File

@ -0,0 +1,9 @@
import { ButtonHTMLAttributes, DetailedHTMLProps } from 'react';
import { NitroLayoutOverflow, NitroLayoutPosition, NitroLayoutSpacing } from '../common';
export interface NitroLayoutBaseProps extends DetailedHTMLProps<ButtonHTMLAttributes<HTMLDivElement>, HTMLDivElement>
{
overflow?: NitroLayoutOverflow;
position?: NitroLayoutPosition;
gap?: NitroLayoutSpacing;
}

2
src/layout/base/index.ts Normal file
View File

@ -0,0 +1,2 @@
export * from './NitroLayoutBase';
export * from './NitroLayoutBase.types';

View File

@ -0,0 +1,26 @@
import { FC, useMemo } from 'react';
import { NitroLayoutButtonProps } from './NitroLayoutButton.types';
export const NitroLayoutButton: FC<NitroLayoutButtonProps> = props =>
{
const { className = '', variant = 'primary', size = null, children = null, ...rest } = props;
const getClassName = useMemo(() =>
{
let newClassName = 'btn';
if(variant && variant.length) newClassName += ` btn-${ variant }`;
if(size && size.length) newClassName += ` btn-${ size }`;
if(className && className.length) newClassName += ` ${ className }`;
return newClassName;
}, [ className, variant, size ]);
return (
<button type="button" className={ getClassName } { ...rest }>
{ children }
</button>
);
}

View File

@ -0,0 +1,8 @@
import { ButtonHTMLAttributes, DetailedHTMLProps } from 'react';
import { NitroLayoutButtonSize, NitroLayoutVariant } from '../common';
export interface NitroLayoutButtonProps extends DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
{
variant?: NitroLayoutVariant;
size?: NitroLayoutButtonSize;
}

View File

@ -0,0 +1,2 @@
export * from './NitroLayoutButton';
export * from './NitroLayoutButton.types';

View File

@ -3,6 +3,7 @@ $nitro-card-tabs-height: 33px;
.nitro-card { .nitro-card {
pointer-events: all; pointer-events: all;
resize: both;
@import './accordion/NitroCardAccordionView'; @import './accordion/NitroCardAccordionView';
@import './content/NitroCardContentView'; @import './content/NitroCardContentView';
@ -19,6 +20,10 @@ $nitro-card-tabs-height: 33px;
height: 100%; height: 100%;
pointer-events: none; pointer-events: none;
.theme-primary {
border: $border-width solid $border-color;
}
@include media-breakpoint-down(lg) { @include media-breakpoint-down(lg) {
.draggable-window { .draggable-window {
@ -31,12 +36,13 @@ $nitro-card-tabs-height: 33px;
} }
.nitro-card { .nitro-card {
width: 100%; max-width: 75%;
height: 100%; max-height: calc(100% - 20px);
margin: 10px auto 10px;
&.rounded { // &.rounded {
border-radius: 0 !important; // border-radius: 0 !important;
} // }
} }
} }
} }

View File

@ -11,7 +11,7 @@ export const NitroCardView: FC<NitroCardViewProps> = props =>
<NitroCardContextProvider value={ { theme, simple } }> <NitroCardContextProvider value={ { theme, simple } }>
<div className="nitro-card-responsive"> <div className="nitro-card-responsive">
<DraggableWindow { ...rest }> <DraggableWindow { ...rest }>
<div className={ 'nitro-card d-flex flex-column rounded border shadow overflow-hidden ' + className }> <div className={ `nitro-card d-flex flex-column rounded shadow overflow-hidden theme-${theme} ${className}` }>
{ children } { children }
</div> </div>
</DraggableWindow> </DraggableWindow>

View File

@ -1,20 +1,14 @@
.content-area { .content-area {
height: 100%;
padding-top: $container-padding-x; padding-top: $container-padding-x;
padding-bottom: $container-padding-x; padding-bottom: $container-padding-x;
overflow: auto; overflow: auto;
&.simple {
padding-left: ($container-padding-x + 25px);
padding-right: ($container-padding-x + 25px);
}
} }
@include media-breakpoint-down(lg) { @include media-breakpoint-down(lg) {
.content-area { .content-area {
height: 100% !important; height: 100% !important;
min-height: auto !important; min-height: auto !important;
max-height: 100% !important; max-height: 100% !important;
resize: none !important;
} }
} }

View File

@ -8,7 +8,7 @@ export const NitroCardContentView: FC<NitroCardContentViewProps> = props =>
const { simple = false } = useNitroCardContext(); const { simple = false } = useNitroCardContext();
return ( return (
<div className={ `container-fluid bg-light content-area ${ (simple ? 'simple' : '') } ${ className || '' }` } { ...rest }> <div className={ `container-fluid bg-light content-area d-flex flex-column overflow-auto ${ (simple ? 'simple' : '') } ${ className || '' }` } { ...rest }>
{ children } { children }
</div> </div>
); );

View File

@ -1,71 +1,6 @@
.nitro-card-grid { .nitro-grid {
width: 100%; --nitro-grid-column-min-width: 45px;
grid-template-columns: repeat(auto-fill, minmax(var(--nitro-grid-column-min-width, 45px), 1fr));
.row-cols-3 {
.col {
padding-right: 0.25rem;
&:nth-child(3n+3) {
padding-right: 0;
}
}
}
.row-cols-4 {
.col {
padding-right: 0.25rem;
&:nth-child(4n+4) {
padding-right: 0;
}
}
}
.row-cols-5 {
.col {
padding-right: 0.25rem;
&:nth-child(5n+5) {
padding-right: 0;
}
}
}
.row-cols-6 {
.col {
padding-right: 0.25rem;
&:nth-child(6n+6) {
padding-right: 0;
}
}
}
.row-cols-7 {
.col {
padding-right: 0.25rem;
&:nth-child(7n+7) {
padding-right: 0;
}
}
}
.row-cols-8 {
.col {
padding-right: 0.25rem;
&:nth-child(8n+8) {
padding-right: 0;
}
}
}
@import './item/NitroCardGridItemView.scss';
} }
@import './item/NitroCardGridItemView.scss';

View File

@ -1,18 +1,35 @@
import { FC } from 'react'; import { FC, useMemo } from 'react';
import { NitroCardGridContextProvider } from './context/NitroCardGridContext'; import { NitroCardGridViewProps } from './NitroCardGridView.types';
import { NitroCardGridThemes, NitroCardGridViewProps } from './NitroCardGridView.types';
export const NitroCardGridView: FC<NitroCardGridViewProps> = props => export const NitroCardGridView: FC<NitroCardGridViewProps> = props =>
{ {
const { columns = 5, theme = NitroCardGridThemes.THEME_DEFAULT, className = '', children = null, ...rest } = props; const { columns = 0, gap = 2, className = '', style = null, children = null, ...rest } = props;
const getClassName = useMemo(() =>
{
let newClassName = `grid gap-${ gap } nitro-grid overflow-auto`;
if(className && className.length) newClassName += ' ' + className;
return newClassName;
}, [ className, gap ]);
const getStyle = useMemo(() =>
{
const newStyle = { ...style };
if(columns && (columns >= 1))
{
newStyle['grid-template-columns'] = 'unset';
newStyle['--bs-columns'] = columns.toString();
}
return newStyle;
}, [ style, columns ]);
return ( return (
<NitroCardGridContextProvider value={ { theme } }> <div className={ getClassName } style={ getStyle } { ...rest }>
<div className={ `h-100 overflow-hidden nitro-card-grid ${ theme } ${ className || '' }` } { ...rest }>
<div className={ `row row-cols-${ columns } align-content-start g-0 w-100 h-100 overflow-auto` }>
{ children } { children }
</div> </div>
</div>
</NitroCardGridContextProvider>
); );
} }

View File

@ -3,11 +3,5 @@ import { DetailsHTMLAttributes } from 'react';
export interface NitroCardGridViewProps extends DetailsHTMLAttributes<HTMLDivElement> export interface NitroCardGridViewProps extends DetailsHTMLAttributes<HTMLDivElement>
{ {
columns?: number; columns?: number;
theme?: string; gap?: number;
}
export class NitroCardGridThemes
{
public static THEME_DEFAULT: string = 'theme-default';
public static THEME_SHADOWED: string = 'theme-shadowed';
} }

View File

@ -1,13 +0,0 @@
import { createContext, FC, useContext } from 'react';
import { INitroCardGridContext, NitroCardGridContextProps } from './NitroCardGridContext.types';
const NitroCardGridContext = createContext<INitroCardGridContext>({
theme: null
});
export const NitroCardGridContextProvider: FC<NitroCardGridContextProps> = props =>
{
return <NitroCardGridContext.Provider value={ props.value }>{ props.children }</NitroCardGridContext.Provider>
}
export const useNitroCardGridContext = () => useContext(NitroCardGridContext);

View File

@ -1,11 +0,0 @@
import { ProviderProps } from 'react';
export interface INitroCardGridContext
{
theme: string;
}
export interface NitroCardGridContextProps extends ProviderProps<INitroCardGridContext>
{
}

View File

@ -1,2 +0,0 @@
export * from './NitroCardGridContext';
export * from './NitroCardGridContext.types';

View File

@ -1,4 +1,3 @@
export * from './context';
export * from './item'; export * from './item';
export * from './NitroCardGridView'; export * from './NitroCardGridView';
export * from './NitroCardGridView.types'; export * from './NitroCardGridView.types';

View File

@ -1,52 +1,17 @@
.grid-item-container { .grid-item {
height: 50px; position: relative;
max-height: 50px;
.grid-item {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
position: relative; height: 50px;
max-height: 50px;
width: 100%; width: 100%;
height: 100%;
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
overflow: hidden;
&.theme-default {
border-radius: $border-radius; border-radius: $border-radius;
border-color: $grid-border-color !important; border-color: $grid-border-color !important;
background-color: $grid-bg-color; background-color: $grid-bg-color;
border: nth(map-values($border-widths), 2) solid; border: nth(map-values($border-widths), 2) solid;
}
&.theme-shadowed {
border-radius: $border-radius;
background-color: $light;
&::after {
position: absolute;
content: '';
top: 0;
bottom: 0;
left: 0;
right: 0;
border-radius: $border-radius;
border-bottom: 2px solid white;
border-right: 2px solid white;
box-shadow: -2px -2px rgba(0, 0, 0, .4), inset 3px 3px rgba(0, 0, 0, .2);
}
&.active {
border: nth(map-values($border-widths), 2) solid;
border-color: $oslo-gray !important;
background-color: #F5F5F5;
&:after {
content: unset;
}
}
}
&.active { &.active {
border-color: $grid-active-border-color !important; border-color: $grid-active-border-color !important;
@ -64,9 +29,7 @@
} }
.avatar-image { .avatar-image {
background-position: center; background-position-y: 10px;
background-repeat: no-repeat;
background-position-y: 12px !important;
} }
.trade-button { .trade-button {
@ -82,5 +45,4 @@
left: 2px; left: 2px;
} }
} }
}
} }

View File

@ -1,27 +1,50 @@
import { FC } from 'react'; import { FC, useMemo } from 'react';
import { LimitedEditionStyledNumberView } from '../../../../views/shared/limited-edition/styled-number/LimitedEditionStyledNumberView'; import { LimitedEditionStyledNumberView } from '../../../../views/shared/limited-edition/styled-number/LimitedEditionStyledNumberView';
import { useNitroCardGridContext } from '../context';
import { NitroCardGridThemes } from '../NitroCardGridView.types';
import { NitroCardGridItemViewProps } from './NitroCardGridItemView.types'; import { NitroCardGridItemViewProps } from './NitroCardGridItemView.types';
export const NitroCardGridItemView: FC<NitroCardGridItemViewProps> = props => export const NitroCardGridItemView: FC<NitroCardGridItemViewProps> = props =>
{ {
const { itemImage = undefined, itemColor = undefined, itemActive = false, itemCount = 1, itemUnique = false, itemUniqueNumber = 0, itemUnseen = false, columns = undefined, className = '', style = {}, children = null, ...rest } = props; const { itemImage = undefined, itemColor = undefined, itemActive = false, itemCount = 1, itemUniqueNumber = -2, itemUnseen = false, className = '', style = {}, children = null, ...rest } = props;
const { theme = NitroCardGridThemes.THEME_DEFAULT } = useNitroCardGridContext();
const imageUrl = `url(${ itemImage })`; const getClassName = useMemo(() =>
{
let newClassName = 'grid-item gap-1 cursor-pointer overflow-hidden';
if(itemActive) newClassName += ' active';
if(itemUniqueNumber === -1) newClassName += ' unique-item sold-out';
if(itemUniqueNumber > 0) newClassName += ' unique-item';
if(itemUnseen) newClassName += ' unseen';
if(itemImage === null) newClassName += ' icon loading-icon';
if(className && className.length) newClassName += ' ' + className;
return newClassName;
}, [ className, itemActive, itemUniqueNumber, itemUnseen, itemImage ]);
const getStyle = useMemo(() =>
{
const newStyle = { ...style };
if(itemImage) newStyle.backgroundImage = `url(${ itemImage })`;
if(itemColor) newStyle.backgroundColor = itemColor;
return newStyle;
}, [ style, itemImage, itemColor ]);
return ( return (
<div className={ `${ columns === undefined ? 'col' : ('col-' + columns) } pb-1 grid-item-container` }> <div className={ getClassName } style={ getStyle } { ...rest }>
<div className={ `grid-item ${ theme } cursor-pointer${ itemActive ? ' active' : '' }${ itemUnique ? ' unique-item' : '' }${ itemUnseen ? ' unseen' : ''}${ (itemImage === null ? ' icon loading-icon': '')} ${ className || '' }` } style={ itemImage ? { ...style, backgroundImage: imageUrl } : (itemColor ? { ...style, backgroundColor: itemColor } : style) } { ...rest }>
{ (itemCount > 1) && { (itemCount > 1) &&
<span className="position-absolute badge border bg-danger px-1 rounded-circle">{ itemCount }</span> } <span className="position-absolute badge border bg-danger px-1 rounded-circle">{ itemCount }</span> }
{ itemUnique && { (itemUniqueNumber > 0) &&
<div className="position-absolute unique-item-counter"> <div className="position-absolute unique-item-counter">
<LimitedEditionStyledNumberView value={ itemUniqueNumber } /> <LimitedEditionStyledNumberView value={ itemUniqueNumber } />
</div> } </div> }
{ children } { children }
</div> </div>
</div>
); );
} }

View File

@ -6,8 +6,6 @@ export interface NitroCardGridItemViewProps extends DetailsHTMLAttributes<HTMLDi
itemColor?: string; itemColor?: string;
itemActive?: boolean; itemActive?: boolean;
itemCount?: number; itemCount?: number;
itemUnique?: boolean;
itemUniqueNumber?: number; itemUniqueNumber?: number;
itemUnseen?: boolean; itemUnseen?: boolean;
columns?: number;
} }

View File

@ -2,7 +2,6 @@
min-height: 33px; min-height: 33px;
max-height: 33px; max-height: 33px;
white-space: nowrap; white-space: nowrap;
overflow: hidden;
.header-text { .header-text {
margin: 0 35px; margin: 0 35px;
@ -10,19 +9,22 @@
&.simple-header { &.simple-header {
min-height: 28px; min-height: 28px;
max-height: 28px;
.header-close {
font-size: 12px;
}
} }
.bg-tertiary-split { .bg-tertiary-split {
position: relative; position: relative;
border: 2px solid darken($quaternary, 4); border-bottom: 2px solid darken($quaternary, 5);
box-shadow: 0 0 0 2px $white; box-shadow: 0 2px white;
width: 100%; width: 100%;
margin: 0 25px; margin: 0;
&:before { &:before {
position: absolute; position: absolute;
content: ' '; content: " ";
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
@ -36,7 +38,12 @@
border-radius: $border-radius; border-radius: $border-radius;
box-shadow: 0 0 0 1.5px $white; box-shadow: 0 0 0 1.5px $white;
border: 2px solid #921911; border: 2px solid #921911;
background: repeating-linear-gradient(rgba(245,80,65,1), rgba(245,80,65,1) 50%, rgba(194,48,39,1) 50%, rgba(194,48,39,1) 100%); background: repeating-linear-gradient(
rgba(245, 80, 65, 1),
rgba(245, 80, 65, 1) 50%,
rgba(194, 48, 39, 1) 50%,
rgba(194, 48, 39, 1) 100%
);
cursor: pointer; cursor: pointer;
line-height: 1; line-height: 1;
padding: 1px 3px; padding: 1px 3px;

View File

@ -18,8 +18,8 @@ export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props =>
return ( return (
<div className="container-fluid bg-light"> <div className="container-fluid bg-light">
<div className="row nitro-card-header simple-header"> <div className="row nitro-card-header simple-header">
<div className="d-flex justify-content-center align-items-center w-100 position-relative"> <div className="d-flex justify-content-center align-items-center w-100 position-relative px-0">
<div className="h5 text-white text-center text-shadow bg-tertiary-split border-top-0 rounded-bottom drag-handler">{ headerText }</div> <div className="h5 text-white text-center text-shadow bg-tertiary-split border-top-0 drag-handler">{ headerText }</div>
<div className="position-absolute header-close" onMouseDownCapture={ onMouseDown } onClick={ onCloseClick }> <div className="position-absolute header-close" onMouseDownCapture={ onMouseDown } onClick={ onCloseClick }>
<i className="fas fa-times" /> <i className="fas fa-times" />
</div> </div>

View File

@ -0,0 +1 @@
export type NitroLayoutButtonSize = 'sm' | 'lg';

View File

@ -0,0 +1 @@
export type NitroLayoutColumns = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;

View File

@ -0,0 +1 @@
export type NitroLayoutOverflow = 'hidden' | 'auto';

View File

@ -0,0 +1 @@
export type NitroLayoutPosition = 'static' | 'relative' | 'fixed' | 'absolute' | 'sticky';

View File

@ -0,0 +1 @@
export type NitroLayoutSpacing = 1 | 2 | 3 | 4 | 5;

View File

@ -0,0 +1 @@
export type NitroLayoutVariant = 'primary' | 'success' | 'danger';

View File

@ -0,0 +1,6 @@
export * from './NitroLayoutButtonSize.type';
export * from './NitroLayoutColumns.type';
export * from './NitroLayoutOverflow.type';
export * from './NitroLayoutPosition.type';
export * from './NitroLayoutSpacing.type';
export * from './NitroLayoutVariant.type';

View File

@ -0,0 +1,19 @@
import { FC, useMemo } from 'react';
import { NitroLayoutFlex } from '../flex/NitroLayoutFlex';
import { NitroLayoutFlexColumnProps } from './NitroLayoutFlexColumn.types';
export const NitroLayoutFlexColumn: FC<NitroLayoutFlexColumnProps> = props =>
{
const { className = '', ...rest } = props;
const getClassName = useMemo(() =>
{
let newClassName = 'flex-column';
if(className && className.length) newClassName += ` ${ className }`;
return newClassName;
}, [ className ]);
return <NitroLayoutFlex className={ getClassName } { ...rest } />;
}

View File

@ -0,0 +1,6 @@
import { NitroLayoutFlexProps } from '../flex/NitroLayoutFlex.types';
export interface NitroLayoutFlexColumnProps extends NitroLayoutFlexProps
{
}

View File

@ -0,0 +1,2 @@
export * from './NitroLayoutFlexColumn';
export * from './NitroLayoutFlexColumn.types';

View File

@ -0,0 +1,19 @@
import { FC, useMemo } from 'react';
import { NitroLayoutBase } from '../base/NitroLayoutBase';
import { NitroLayoutFlexProps } from './NitroLayoutFlex.types';
export const NitroLayoutFlex: FC<NitroLayoutFlexProps> = props =>
{
const { className = '', ...rest } = props;
const getClassName = useMemo(() =>
{
let newClassName = 'd-flex';
if(className && className.length) newClassName += ` ${ className }`;
return newClassName;
}, [ className ]);
return <NitroLayoutBase className={ getClassName } { ...rest } />;
}

View File

@ -0,0 +1,6 @@
import { NitroLayoutBaseProps } from '../base/NitroLayoutBase.types';
export interface NitroLayoutFlexProps extends NitroLayoutBaseProps
{
}

2
src/layout/flex/index.ts Normal file
View File

@ -0,0 +1,2 @@
export * from './NitroLayoutFlex';
export * from './NitroLayoutFlex.types';

View File

@ -0,0 +1,19 @@
import { FC, useMemo } from 'react';
import { NitroLayoutBase } from '../base';
import { NitroLayoutGridProps } from './NitroLayoutGrid.types';
export const NitroLayoutGrid: FC<NitroLayoutGridProps> = props =>
{
const { className = '', gap = 3, ...rest } = props;
const getClassName = useMemo(() =>
{
let newClassName = 'grid h-100';
if(className && className.length) newClassName += ' ' + className;
return newClassName;
}, [ className ]);
return <NitroLayoutBase className={ getClassName } gap={ gap } { ...rest } />;
}

View File

@ -0,0 +1,6 @@
import { NitroLayoutBaseProps } from '../base';
export interface NitroLayoutGridProps extends NitroLayoutBaseProps
{
}

View File

@ -0,0 +1,19 @@
import { FC, useMemo } from 'react';
import { NitroLayoutFlexColumn } from '../../flex-column/NitroLayoutFlexColumn';
import { NitroLayoutGridColumnProps } from './NitroLayoutGridColumn.types';
export const NitroLayoutGridColumn: FC<NitroLayoutGridColumnProps> = props =>
{
const { className = '', size = 12, gap = 3, ...rest } = props;
const getClassName = useMemo(() =>
{
let newClassName = `g-col-${ size }`;
if(className && className.length) newClassName += ' ' + className;
return newClassName;
}, [ className, size ]);
return <NitroLayoutFlexColumn className={ getClassName } gap={ gap } overflow="auto" { ...rest } />
}

View File

@ -0,0 +1,8 @@
import { NitroLayoutColumns, NitroLayoutSpacing } from '../../common';
import { NitroLayoutFlexColumnProps } from '../../flex-column/NitroLayoutFlexColumn.types';
export interface NitroLayoutGridColumnProps extends NitroLayoutFlexColumnProps
{
size?: NitroLayoutColumns;
gap?: NitroLayoutSpacing;
}

View File

@ -0,0 +1,2 @@
export * from './NitroLayoutGridColumn';
export * from './NitroLayoutGridColumn.types';

3
src/layout/grid/index.ts Normal file
View File

@ -0,0 +1,3 @@
export * from './column';
export * from './NitroLayoutGrid';
export * from './NitroLayoutGrid.types';

View File

@ -1,8 +1,15 @@
export * from './button';
export * from './card'; export * from './card';
export * from './common';
export * from './draggable-window'; export * from './draggable-window';
export * from './flex';
export * from './flex-column';
export * from './gift-card'; export * from './gift-card';
export * from './grid';
export * from './loading-habbos';
export * from './loading-spinner'; export * from './loading-spinner';
export * from './mini-camera'; export * from './mini-camera';
export * from './notification-alert';
export * from './notification-bubble'; export * from './notification-bubble';
export * from './transitions'; export * from './transitions';
export * from './trophy'; export * from './trophy';

View File

@ -0,0 +1 @@
export * from './LoadingHabbosView';

View File

@ -0,0 +1,8 @@
.nitro-alert {
width: 350px;
.content-area {
min-height: 125px;
max-height: 300px;
}
}

View File

@ -0,0 +1,17 @@
import { FC } from 'react';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../card';
import { NotificationAlertViewProps } from './NotificationAlertView.types';
export const NotificationAlertView: FC<NotificationAlertViewProps> = props =>
{
const { title = '', close = null, className = '', children = null, ...rest } = props;
return (
<NitroCardView className={ 'nitro-alert ' + className } simple={ true } { ...rest }>
<NitroCardHeaderView headerText={ title } onCloseClick={ close } />
<NitroCardContentView className="d-flex flex-column justify-content-between text-black">
{ children }
</NitroCardContentView>
</NitroCardView>
);
}

View File

@ -0,0 +1,7 @@
import { DetailsHTMLAttributes } from 'react';
export interface NotificationAlertViewProps extends DetailsHTMLAttributes<HTMLDivElement>
{
title: string;
close: () => void;
}

View File

@ -0,0 +1,2 @@
export * from './NotificationAlertView';
export * from './NotificationAlertView.types';

View File

@ -1,10 +1,6 @@
.nitro-achievements { .nitro-achievements {
width: 650px; width: $achievement-width;
height: $achievement-height;
.content-area {
min-height: 376px;
height: 376px;
}
.score { .score {
border-color: $grid-border-color !important; border-color: $grid-border-color !important;
@ -12,13 +8,22 @@
} }
.category { .category {
border-color: $grid-border-color !important;
background-color: $grid-bg-color;
cursor: pointer;
&.active {
border-color: $grid-active-border-color !important;
background-color: $grid-active-bg-color;
}
.category-score { .category-score {
margin-top: 43.5px; margin-top: 43.5px;
} }
} }
.achievements { .achievements {
height: 230px; height: 152px;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
@ -44,4 +49,15 @@
} }
} }
} }
.achievement-image {
height: 80px;
width: 80px;
.badge-image {
width: 80px;
height: 80px;
background-size: contain;
}
}
} }

View File

@ -40,7 +40,7 @@ export const AchievementsView: FC<AchievementsViewProps> = props =>
<AchievementsContextProvider value={ { achievementsState, dispatchAchievementsState } }> <AchievementsContextProvider value={ { achievementsState, dispatchAchievementsState } }>
<AchievementsMessageHandler /> <AchievementsMessageHandler />
{ isVisible && { isVisible &&
<NitroCardView uniqueKey="achievements" className="nitro-achievements"> <NitroCardView uniqueKey="achievements" className="nitro-achievements" simple={ true }>
<NitroCardHeaderView headerText={ LocalizeText('inventory.achievements') } onCloseClick={ event => setIsVisible(false) } /> <NitroCardHeaderView headerText={ LocalizeText('inventory.achievements') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardContentView> <NitroCardContentView>
<div className="row"> <div className="row">

View File

@ -43,13 +43,16 @@ export const AchievementsReducer: Reducer<IAchievementsState, IAchievementsActio
const categories = (action.payload.categories || state.categories || null); const categories = (action.payload.categories || state.categories || null);
let selectedCategoryName = null; let selectedCategoryName = null;
let selectedAchievementId = null;
if(categories.length > 0) if(categories.length > 0)
{ {
selectedCategoryName = categories[0].name; selectedCategoryName = categories[0].name;
if(categories[0].achievements.length > 0) selectedAchievementId = categories[0].achievements[0].achievementId;
} }
return { ...state, categories, selectedCategoryName }; return { ...state, categories, selectedCategoryName, selectedAchievementId };
} }
case AchievementsActions.SET_SCORE: { case AchievementsActions.SET_SCORE: {
const score = (action.payload.score || state.score || null); const score = (action.payload.score || state.score || null);

View File

@ -1,6 +1,6 @@
import classNames from 'classnames';
import { FC, useCallback, useMemo } from 'react'; import { FC, useCallback, useMemo } from 'react';
import { GetConfiguration } from '../../../../api'; import { GetConfiguration } from '../../../../api';
import { NitroCardGridItemView } from '../../../../layout/card/grid/item/NitroCardGridItemView';
import { useAchievementsContext } from '../../context/AchievementsContext'; import { useAchievementsContext } from '../../context/AchievementsContext';
import { AchievementsActions } from '../../reducers/AchievementsReducer'; import { AchievementsActions } from '../../reducers/AchievementsReducer';
import { AchievementCategoryListItemViewProps } from './AchievementCategoryListItemView.types'; import { AchievementCategoryListItemViewProps } from './AchievementCategoryListItemView.types';
@ -58,8 +58,11 @@ export const AchievementCategoryListItemView: FC<AchievementCategoryListItemView
}, [ dispatchAchievementsState ]); }, [ dispatchAchievementsState ]);
return ( return (
<NitroCardGridItemView className="d-flex flex-column justify-content-center align-items-center category border border-2 rounded p-2" itemActive={ isActive } itemImage={ getCategoryImage } onClick={ event => selectCategory(category.name) }> <div className="col mb-3">
<div className={ 'd-flex flex-column justify-content-center align-items-center category border border-2 rounded p-2' + classNames({ ' active': isActive }) } onClick={ () => selectCategory(category.name) }>
<img src={ getCategoryImage } alt="" />
<div className="position-absolute category-score small">{ getCategoryProgress }</div> <div className="position-absolute category-score small">{ getCategoryProgress }</div>
</NitroCardGridItemView> </div>
</div>
); );
} }

View File

@ -1,5 +1,4 @@
import { FC } from 'react'; import { FC } from 'react';
import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView';
import { useAchievementsContext } from '../../context/AchievementsContext'; import { useAchievementsContext } from '../../context/AchievementsContext';
import { AchievementCategoryListItemView } from '../category-list-item/AchievementCategoryListItemView'; import { AchievementCategoryListItemView } from '../category-list-item/AchievementCategoryListItemView';
@ -9,11 +8,11 @@ export const AchievementsListView: FC<{}> = props =>
const { categories = null, selectedCategoryName = null } = achievementsState; const { categories = null, selectedCategoryName = null } = achievementsState;
return ( return (
<NitroCardGridView columns={ 3 }> <div className="row row-cols-3">
{ categories && categories.map((category, index) => { categories && categories.map((category, index) =>
{ {
return <AchievementCategoryListItemView key={ index } category={ category } />; return <AchievementCategoryListItemView key={ index } category={ category } isActive={ selectedCategoryName === category.name } />;
}) } }) }
</NitroCardGridView> </div>
); );
}; };

View File

@ -1,7 +1,7 @@
import { AchievementData } from '@nitrots/nitro-renderer'; import { AchievementData } from '@nitrots/nitro-renderer';
import classNames from 'classnames'; import classNames from 'classnames';
import { FC, useCallback } from 'react'; import { FC, useCallback, useMemo } from 'react';
import { LocalizeText } from '../../../../api'; import { LocalizeBadgeDescription, LocalizeBadgeName, LocalizeText } from '../../../../api';
import { BadgeImageView } from '../../../shared/badge-image/BadgeImageView'; import { BadgeImageView } from '../../../shared/badge-image/BadgeImageView';
import { useAchievementsContext } from '../../context/AchievementsContext'; import { useAchievementsContext } from '../../context/AchievementsContext';
import { AchievementsActions } from '../../reducers/AchievementsReducer'; import { AchievementsActions } from '../../reducers/AchievementsReducer';
@ -34,7 +34,7 @@ export const AchievementCategoryView: FC<AchievementCategoryViewProps> = props =
return badgeId; return badgeId;
}, []); }, []);
const getSelectedAchievement = useCallback(() => const selectedAchievement = useMemo(() =>
{ {
if(!getSelectedCategory()) return null; if(!getSelectedCategory()) return null;
@ -54,15 +54,19 @@ export const AchievementCategoryView: FC<AchievementCategoryViewProps> = props =
return ( return (
<div className="d-flex flex-column h-100"> <div className="d-flex flex-column h-100">
<div className="bg-primary rounded p-2 d-flex align-items-center mb-3"> <div className="bg-primary rounded p-2 d-flex align-items-center mb-2">
<h5 className="m-0 me-2 w-100">{ LocalizeText('quests.' + selectedCategoryName + '.name') }</h5> <h5 className="m-0 me-2 w-100">{ LocalizeText('quests.' + selectedCategoryName + '.name') }</h5>
<div>IMAGE</div> <div>IMAGE</div>
</div> </div>
<div className="bg-muted rounded p-2 mb-3 d-flex"> { selectedAchievement && <div className="bg-secondary rounded p-2 mb-3 d-flex gap-2 align-items-center">
<div className="achievement-image">
<BadgeImageView badgeCode={ getAchievementImage(selectedAchievement) } />
</div>
<div> <div>
<BadgeImageView badgeCode={ getAchievementImage(getSelectedAchievement()) } /> <div>{ LocalizeBadgeName(selectedAchievement.badgeId) }</div>
</div> <div>{ LocalizeBadgeDescription(selectedAchievement.badgeId) }</div>
</div> </div>
</div> }
<div className="achievements"> <div className="achievements">
<div className="row row-cols-4"> <div className="row row-cols-4">
{ getSelectedCategory().achievements.map((achievement, index) => { getSelectedCategory().achievements.map((achievement, index) =>

View File

@ -1,10 +1,6 @@
.nitro-avatar-editor { .nitro-avatar-editor {
width: 620px; width: $avatar-editor-width;
height: $avatar-editor-height;
.content-area {
min-height: 300px;
height: 300px;
}
.category-item { .category-item {
height: 40px; height: 40px;
@ -82,6 +78,37 @@
.wardrobe-grid { .wardrobe-grid {
.grid-item {
height: 140px;
max-height: 140px;
background-color: $ghost;
&:after {
position: absolute;
content: '';
top: 75%;
bottom: 0;
left: 0;
right: 0;
border-radius: 50%;
background-color: $gray-chateau;
box-shadow: 0 0 8px 2px rgba($white,.6);
transform: scale(2);
}
.avatar-image {
position: absolute;
bottom: 0;
background-position-y: -23px !important;
z-index: 4;
}
.figure-button-container {
background-color: $gray-chateau;
z-index: 3;
}
}
.grid-item-container { .grid-item-container {
height: 142px !important; height: 142px !important;
max-height: 142px !important; max-height: 142px !important;

View File

@ -1,6 +1,5 @@
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView'; import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView';
import { NitroCardGridThemes } from '../../../../layout/card/grid/NitroCardGridView.types';
import { AvatarEditorGridPartItem } from '../../common/AvatarEditorGridPartItem'; import { AvatarEditorGridPartItem } from '../../common/AvatarEditorGridPartItem';
import { AvatarEditorFigureSetItemView } from '../figure-set-item/AvatarEditorFigureSetItemView'; import { AvatarEditorFigureSetItemView } from '../figure-set-item/AvatarEditorFigureSetItemView';
import { AvatarEditorFigureSetViewProps } from './AvatarEditorFigureSetView.types'; import { AvatarEditorFigureSetViewProps } from './AvatarEditorFigureSetView.types';
@ -23,7 +22,7 @@ export const AvatarEditorFigureSetView: FC<AvatarEditorFigureSetViewProps> = pro
}, [ model, category, setMaxPaletteCount ]); }, [ model, category, setMaxPaletteCount ]);
return ( return (
<NitroCardGridView columns={ 3 } theme={ NitroCardGridThemes.THEME_SHADOWED }> <NitroCardGridView>
{ (category.parts.length > 0) && category.parts.map((item, index) => { (category.parts.length > 0) && category.parts.map((item, index) =>
{ {
return <AvatarEditorFigureSetItemView key={ index } partItem={ item } onClick={ selectPart } />; return <AvatarEditorFigureSetItemView key={ index } partItem={ item } onClick={ selectPart } />;

View File

@ -71,7 +71,7 @@ export const AvatarEditorModelView: FC<AvatarEditorModelViewProps> = props =>
<div className="col-5 d-flex flex-column h-100"> <div className="col-5 d-flex flex-column h-100">
<AvatarEditorFigureSetView model={ model } category={ activeCategory } setMaxPaletteCount={ setMaxPaletteCount } /> <AvatarEditorFigureSetView model={ model } category={ activeCategory } setMaxPaletteCount={ setMaxPaletteCount } />
</div> </div>
<div className="col-5 d-flex flex-column h-100"> <div className="col-5 d-flex flex-column h-100 gap-2">
{ (maxPaletteCount >= 1) && { (maxPaletteCount >= 1) &&
<AvatarEditorPaletteSetView model={ model } category={ activeCategory } paletteSet={ activeCategory.getPalette(0) } paletteIndex={ 0 } /> } <AvatarEditorPaletteSetView model={ model } category={ activeCategory } paletteSet={ activeCategory.getPalette(0) } paletteIndex={ 0 } /> }
{ (maxPaletteCount === 2) && { (maxPaletteCount === 2) &&

View File

@ -1,6 +1,5 @@
import { FC, useCallback } from 'react'; import { FC, useCallback } from 'react';
import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView'; import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView';
import { NitroCardGridThemes } from '../../../../layout/card/grid/NitroCardGridView.types';
import { AvatarEditorGridColorItem } from '../../common/AvatarEditorGridColorItem'; import { AvatarEditorGridColorItem } from '../../common/AvatarEditorGridColorItem';
import { AvatarEditorPaletteSetItem } from '../palette-set-item/AvatarEditorPaletteSetItem'; import { AvatarEditorPaletteSetItem } from '../palette-set-item/AvatarEditorPaletteSetItem';
import { AvatarEditorPaletteSetViewProps } from './AvatarEditorPaletteSetView.types'; import { AvatarEditorPaletteSetViewProps } from './AvatarEditorPaletteSetView.types';
@ -19,7 +18,7 @@ export const AvatarEditorPaletteSetView: FC<AvatarEditorPaletteSetViewProps> = p
}, [ model, category, paletteSet, paletteIndex ]); }, [ model, category, paletteSet, paletteIndex ]);
return ( return (
<NitroCardGridView columns={ 4 } theme={ NitroCardGridThemes.THEME_SHADOWED } { ...rest }> <NitroCardGridView { ...rest }>
{ (paletteSet.length > 0) && paletteSet.map((item, index) => { (paletteSet.length > 0) && paletteSet.map((item, index) =>
{ {
return <AvatarEditorPaletteSetItem key={ index } colorItem={ item } onClick={ event => selectColor(item) } />; return <AvatarEditorPaletteSetItem key={ index } colorItem={ item } onClick={ event => selectColor(item) } />;

View File

@ -5,7 +5,6 @@ import { GetAvatarRenderManager, GetSessionDataManager } from '../../../../api';
import { SendMessageHook } from '../../../../hooks'; import { SendMessageHook } from '../../../../hooks';
import { NitroCardGridItemView } from '../../../../layout/card/grid/item/NitroCardGridItemView'; import { NitroCardGridItemView } from '../../../../layout/card/grid/item/NitroCardGridItemView';
import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView'; import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView';
import { NitroCardGridThemes } from '../../../../layout/card/grid/NitroCardGridView.types';
import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView'; import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView';
import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon'; import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon';
import { AvatarEditorWardrobeViewProps } from './AvatarEditorWardrobeView.types'; import { AvatarEditorWardrobeViewProps } from './AvatarEditorWardrobeView.types';
@ -68,7 +67,7 @@ export const AvatarEditorWardrobeView: FC<AvatarEditorWardrobeViewProps> = props
return ( return (
<div className="row h-100"> <div className="row h-100">
<div className="col-12 d-flex h-100"> <div className="col-12 d-flex h-100">
<NitroCardGridView className="wardrobe-grid" columns={ 5 } theme={ NitroCardGridThemes.THEME_DEFAULT }> <NitroCardGridView className="wardrobe-grid">
{ figures } { figures }
</NitroCardGridView> </NitroCardGridView>
</div> </div>

View File

@ -1,11 +1,6 @@
.nitro-catalog { .nitro-catalog {
width: 620px; width: $catalog-width;
height: $catalog-height;
.content-area {
min-height: 350px;
height: 350px;
resize: vertical;
}
font[size="16"] { font[size="16"] {
font-size: 20px; font-size: 20px;

View File

@ -10,7 +10,7 @@ import { CatalogMode, CatalogViewProps } from './CatalogView.types';
import { BuildCatalogPageTree } from './common/CatalogUtilities'; import { BuildCatalogPageTree } from './common/CatalogUtilities';
import { CatalogContextProvider } from './context/CatalogContext'; import { CatalogContextProvider } from './context/CatalogContext';
import { CatalogReducer, initialCatalog } from './reducers/CatalogReducer'; import { CatalogReducer, initialCatalog } from './reducers/CatalogReducer';
import { CatalogPageGiftView } from './views/gift/CatalogPageGiftView'; import { CatalogGiftView } from './views/gift/CatalogGiftView';
import { ACTIVE_PAGES, CatalogNavigationView } from './views/navigation/CatalogNavigationView'; import { ACTIVE_PAGES, CatalogNavigationView } from './views/navigation/CatalogNavigationView';
import { CatalogPageView } from './views/page/CatalogPageView'; import { CatalogPageView } from './views/page/CatalogPageView';
@ -205,7 +205,7 @@ export const CatalogView: FC<CatalogViewProps> = props =>
<NitroCardContentView> <NitroCardContentView>
<div className="row h-100"> <div className="row h-100">
{ currentNavigationPage && !navigationHidden && { currentNavigationPage && !navigationHidden &&
<div className="col-3 d-flex flex-column h-100"> <div className="col-3 h-100">
<CatalogNavigationView page={ currentNavigationPage } pendingTree={ pendingTree } setPendingTree={ setPendingTree } /> <CatalogNavigationView page={ currentNavigationPage } pendingTree={ pendingTree } setPendingTree={ setPendingTree } />
</div> } </div> }
<div className="col h-100"> <div className="col h-100">
@ -214,7 +214,7 @@ export const CatalogView: FC<CatalogViewProps> = props =>
</div> </div>
</NitroCardContentView> </NitroCardContentView>
</NitroCardView> } </NitroCardView> }
<CatalogPageGiftView /> <CatalogGiftView />
</CatalogContextProvider> </CatalogContextProvider>
); );
} }

View File

@ -0,0 +1,30 @@
import { CatalogPageMessageOfferData, RoomObjectCategory, RoomObjectPlacementSource } from '@nitrots/nitro-renderer';
import { GetRoomEngine } from '../../../api';
import { IsCatalogOfferDraggable } from './IsCatalogOfferDraggable';
import { ProductTypeEnum } from './ProductTypeEnum';
export const AttemptCatalogPlacement = (offer: CatalogPageMessageOfferData) =>
{
if(!IsCatalogOfferDraggable(offer)) return;
const product = offer.products[0];
let category: number = -1;
switch(product.productType)
{
case ProductTypeEnum.FLOOR:
category = RoomObjectCategory.FLOOR;
break;
case ProductTypeEnum.WALL:
category = RoomObjectCategory.WALL;
break;
}
if(category === -1) return;
if(GetRoomEngine().processRoomObjectPlacement(RoomObjectPlacementSource.CATALOG, -(offer.offerId), category, product.furniClassId, (product.extraParam) ? product.extraParam.toString() : null))
{
}
}

View File

@ -0,0 +1,47 @@
import { FurnitureType } from '@nitrots/nitro-renderer';
import { GetConfiguration, GetRoomEngine, GetSessionDataManager } from '../../../api';
export const GetProductIconUrl = (furniClassId: number, productType: string, customParams: string = null) =>
{
switch(productType.toUpperCase())
{
case FurnitureType.BADGE:
return GetSessionDataManager().getBadgeUrl(customParams);
case FurnitureType.ROBOT:
return undefined;
case FurnitureType.FLOOR:
return GetRoomEngine().getFurnitureFloorIconUrl(furniClassId);
case FurnitureType.WALL: {
const furniData = GetSessionDataManager().getWallItemData(furniClassId);
let iconName = '';
if(furniData)
{
switch(furniData.className)
{
case 'floor':
iconName = [ 'th', furniData.className, customParams ].join('_');
break;
case 'wallpaper':
iconName = [ 'th', 'wall', customParams ].join('_');
break;
case 'landscape':
iconName = [ 'th', furniData.className, customParams.replace('.', '_'), '001' ].join('_');
break;
}
if(iconName !== '')
{
const assetUrl = GetConfiguration<string>('catalog.asset.url');
return `${ assetUrl }/${ iconName }.png`;
}
}
return GetRoomEngine().getFurnitureWallIconUrl(furniClassId, customParams);
}
}
return null;
}

View File

@ -0,0 +1,8 @@
import { CatalogPageMessageOfferData, RoomControllerLevel } from '@nitrots/nitro-renderer';
import { GetRoomSession } from '../../../api';
import { ProductTypeEnum } from './ProductTypeEnum';
export const IsCatalogOfferDraggable = (offer: CatalogPageMessageOfferData) =>
{
return ((GetRoomSession().isRoomOwner || (GetRoomSession().isGuildRoom && (GetRoomSession().controllerLevel >= RoomControllerLevel.GUILD_MEMBER))) && (offer.products.length === 1) && (offer.products[0].productType !== ProductTypeEnum.EFFECT) && (offer.products[0].productType !== ProductTypeEnum.HABBO_CLUB))
}

View File

@ -1,5 +1,4 @@
@import './catalog-icon/CatalogIconView'; @import './catalog-icon/CatalogIconView';
@import './gift/CatalogGiftView';
@import './navigation/CatalogNavigationView'; @import './navigation/CatalogNavigationView';
@import './page/CatalogPageView'; @import './page/CatalogPageView';
@import './search/CatalogSearchView';
@import './gift/CatalogPageGiftView';

View File

@ -1,4 +1,5 @@
.nitro-catalog-gift { .nitro-catalog-gift {
width: 325px;
.gift-preview { .gift-preview {
width: 80px; width: 80px;

View File

@ -10,7 +10,7 @@ import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon';
import { FurniImageView } from '../../../shared/furni-image/FurniImageView'; import { FurniImageView } from '../../../shared/furni-image/FurniImageView';
import { useCatalogContext } from '../../context/CatalogContext'; import { useCatalogContext } from '../../context/CatalogContext';
export const CatalogPageGiftView: FC<{}> = props => export const CatalogGiftView: FC<{}> = props =>
{ {
const { catalogState = null } = useCatalogContext(); const { catalogState = null } = useCatalogContext();
const { giftConfiguration = null } = catalogState; const { giftConfiguration = null } = catalogState;

View File

@ -1,11 +1,21 @@
.nitro-catalog-navigation { .nitro-catalog-navigation-grid {
border-color: $grid-border-color !important; border-radius: 0.25rem;
background-color: $grid-bg-color !important; border-color: #B6BEC5 !important;
background-color: #CDD3D9;
border: 2px solid;
.navigation-container { .grid-item {
overflow-y: auto; font-size: $font-size-sm;
height: 23px !important;
border-color: unset !important;
background-color: #CDD3D9;
border: 0 !important;
padding: 1px 3px;
i.fas {
color: $black;
font-size: 10px;
padding: 1px;
}
} }
} }
@import './item/CatalogNavigationItemView';
@import './set/CatalogNavigationSetView';

Some files were not shown because too many files have changed in this diff Show More