chore: checkpoint current work
@@ -0,0 +1,729 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="it">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Nitro Cards Current Snapshot</title>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--page-bg: #1d1f24;
|
||||||
|
--panel-bg: #2a2d33;
|
||||||
|
--panel-border: #454a54;
|
||||||
|
--text: #f3f4f6;
|
||||||
|
--muted: #b9bec9;
|
||||||
|
--card-border: #283f5d;
|
||||||
|
--card-header: #1e7295;
|
||||||
|
--card-body: #dfdfdf;
|
||||||
|
--tab-bg: #b6bec5;
|
||||||
|
--tab-active: #dfdfdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 24px;
|
||||||
|
background: var(--page-bg);
|
||||||
|
color: var(--text);
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin: 0 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0 0 16px;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 420px minmax(480px, 1fr);
|
||||||
|
gap: 24px;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
background: var(--panel-bg);
|
||||||
|
border: 1px solid var(--panel-border);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-stack {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card {
|
||||||
|
resize: both;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid var(--card-border);
|
||||||
|
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
|
||||||
|
width: 100%;
|
||||||
|
max-width: 380px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card.theme-primary .nitro-card-header {
|
||||||
|
min-height: 33px;
|
||||||
|
max-height: 33px;
|
||||||
|
background: var(--card-header);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card.theme-primary-slim .nitro-card-header {
|
||||||
|
position: relative;
|
||||||
|
min-height: 28px;
|
||||||
|
max-height: 28px;
|
||||||
|
background: repeating-linear-gradient(#2dabc2, #2dabc2 50%, #2b91a7 50%, #2b91a7 100%);
|
||||||
|
border-bottom: 2px solid #257f92;
|
||||||
|
box-shadow: 0 2px white;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card.theme-primary-slim .nitro-card-header::before {
|
||||||
|
position: absolute;
|
||||||
|
content: " ";
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card.theme-primary-slim .nitro-card-header-text {
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
|
||||||
|
font-size: 18px;
|
||||||
|
min-height: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header-inner {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header-text {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ubuntu-close-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 0 0 1.6px #fff;
|
||||||
|
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%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2px;
|
||||||
|
background: #185d79;
|
||||||
|
min-height: 35px;
|
||||||
|
max-height: 35px;
|
||||||
|
padding: 4px 8px 0;
|
||||||
|
border-bottom: 1px solid var(--card-border);
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs-item {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
border-top-left-radius: 6px;
|
||||||
|
border-top-right-radius: 6px;
|
||||||
|
background: var(--tab-bg);
|
||||||
|
padding: 4px 12px;
|
||||||
|
z-index: 1;
|
||||||
|
border-top: 1px solid var(--card-border);
|
||||||
|
border-left: 1px solid var(--card-border);
|
||||||
|
border-right: 1px solid var(--card-border);
|
||||||
|
color: #000;
|
||||||
|
min-width: 96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs-item::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
width: 93%;
|
||||||
|
height: 3px;
|
||||||
|
border-radius: 4px;
|
||||||
|
top: 1.5px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: auto;
|
||||||
|
z-index: 1;
|
||||||
|
background: #c2c9d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs-item.active {
|
||||||
|
background: var(--tab-active);
|
||||||
|
margin-bottom: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs-item.active::before {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-content {
|
||||||
|
height: 220px;
|
||||||
|
padding: 8px;
|
||||||
|
overflow: auto;
|
||||||
|
background: var(--card-body);
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-content p {
|
||||||
|
color: #000;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-block {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 180px;
|
||||||
|
resize: vertical;
|
||||||
|
border: 1px solid #5a6170;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #14161a;
|
||||||
|
color: #e9edf5;
|
||||||
|
padding: 12px;
|
||||||
|
font: 12px/1.5 Consolas, monospace;
|
||||||
|
white-space: pre;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-section {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 980px) {
|
||||||
|
.layout {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>NitroCard attuali</h1>
|
||||||
|
<p>Questo file contiene una preview HTML modificabile e una copia esatta del codice sorgente attuale delle card nel progetto.</p>
|
||||||
|
|
||||||
|
<div class="layout">
|
||||||
|
<section class="panel">
|
||||||
|
<h2>Preview</h2>
|
||||||
|
<div class="preview-stack">
|
||||||
|
<div class="nitro-card theme-primary">
|
||||||
|
<div class="nitro-card-header">
|
||||||
|
<div class="nitro-card-header-inner">
|
||||||
|
<span class="nitro-card-header-text">Primary Card</span>
|
||||||
|
<div class="ubuntu-close-button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="nitro-card-tabs">
|
||||||
|
<div class="nitro-card-tabs-item active">Tab 1</div>
|
||||||
|
<div class="nitro-card-tabs-item">Tab 2</div>
|
||||||
|
<div class="nitro-card-tabs-item">Tab 3</div>
|
||||||
|
</div>
|
||||||
|
<div class="nitro-card-content">
|
||||||
|
<p>Questo blocco riproduce la struttura visiva attuale delle NitroCard del progetto.</p>
|
||||||
|
<p>Header blu, tabs grigie e content area chiara.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nitro-card theme-primary-slim">
|
||||||
|
<div class="nitro-card-header">
|
||||||
|
<div class="nitro-card-header-inner">
|
||||||
|
<span class="nitro-card-header-text">Slim Card</span>
|
||||||
|
<div class="ubuntu-close-button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="nitro-card-content" style="height: 160px;">
|
||||||
|
<p>Versione slim con header a righe come nel CSS attuale.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="panel">
|
||||||
|
<h2>Snapshot codice attuale</h2>
|
||||||
|
|
||||||
|
<div class="code-section">
|
||||||
|
<div class="code-block">Nitro-V3/src/common/card/NitroCardView.tsx
|
||||||
|
|
||||||
|
import { FC, useMemo, useRef } from 'react';
|
||||||
|
import { Column, ColumnProps } from '..';
|
||||||
|
import { DraggableWindow, DraggableWindowPosition, DraggableWindowProps } from '../draggable-window';
|
||||||
|
import { NitroCardContextProvider } from './NitroCardContext';
|
||||||
|
|
||||||
|
export interface NitroCardViewProps extends DraggableWindowProps, ColumnProps
|
||||||
|
{
|
||||||
|
theme?: string;
|
||||||
|
isResizable?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NitroCardView: FC<NitroCardViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { theme = 'primary', uniqueKey = null, handleSelector = '.drag-handler', windowPosition = DraggableWindowPosition.CENTER, disableDrag = false, overflow = 'hidden', position = 'relative', gap = 0, classNames = [], isResizable = true, ...rest } = props;
|
||||||
|
const elementRef = useRef<HTMLDivElement>();
|
||||||
|
|
||||||
|
const getClassNames = useMemo(() =>
|
||||||
|
{
|
||||||
|
const newClassNames: string[] = [ isResizable ? 'resize' : 'resize-none', 'rounded', 'shadow' ];
|
||||||
|
|
||||||
|
// Card Theme Changer
|
||||||
|
newClassNames.push('border border-[#283F5D]');
|
||||||
|
|
||||||
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
|
return newClassNames;
|
||||||
|
}, [ classNames, isResizable ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NitroCardContextProvider value={ { theme } }>
|
||||||
|
<DraggableWindow disableDrag={ disableDrag } handleSelector={ handleSelector } uniqueKey={ uniqueKey } windowPosition={ windowPosition }>
|
||||||
|
<Column classNames={ getClassNames } gap={ gap } innerRef={ elementRef } overflow={ overflow } position={ position } { ...rest } />
|
||||||
|
</DraggableWindow>
|
||||||
|
</NitroCardContextProvider>
|
||||||
|
);
|
||||||
|
};</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="code-section">
|
||||||
|
<div class="code-block">Nitro-V3/src/common/card/NitroCardHeaderView.tsx
|
||||||
|
|
||||||
|
import { FC, MouseEvent } from 'react';
|
||||||
|
import { FaFlag } from 'react-icons/fa';
|
||||||
|
import { Base, Column, ColumnProps, Flex } from '..';
|
||||||
|
|
||||||
|
interface NitroCardHeaderViewProps extends ColumnProps
|
||||||
|
{
|
||||||
|
headerText: string;
|
||||||
|
isGalleryPhoto?: boolean;
|
||||||
|
noCloseButton?: boolean;
|
||||||
|
isInfoToHabboPages?: boolean;
|
||||||
|
onReportPhoto?: (event: MouseEvent) => void;
|
||||||
|
onClickInfoHabboPages?: (event: MouseEvent) => void;
|
||||||
|
onCloseClick: (event: MouseEvent) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { headerText = null, isGalleryPhoto = false, noCloseButton = false, isInfoToHabboPages = false, onReportPhoto = null, onClickInfoHabboPages = null, onCloseClick = null, justifyContent = 'center', alignItems = 'center', classNames = [], children = null, ...rest } = props;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const onMouseDown = (event: MouseEvent<HTMLDivElement>) =>
|
||||||
|
{
|
||||||
|
event.stopPropagation();
|
||||||
|
event.nativeEvent.stopImmediatePropagation();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column center className={ 'relative flex items-center justify-center flex-col drag-handler min-h-card-header max-h-card-header bg-card-header' } { ...rest }>
|
||||||
|
<Flex center fullWidth>
|
||||||
|
<span className="text-xl text-white drop-shadow-lg">{ headerText }</span>
|
||||||
|
{ isGalleryPhoto &&
|
||||||
|
<Base className="inset-e-4 nitro-card-header-report-camera" position="absolute" onClick={ onReportPhoto }>
|
||||||
|
<FaFlag className="fa-icon" />
|
||||||
|
</Base>
|
||||||
|
}
|
||||||
|
{ isInfoToHabboPages &&
|
||||||
|
<Base className="absolute right-8 nitro-card-header-info-habbopages cursor-pointer" position="absolute" onClick={ onClickInfoHabboPages } />
|
||||||
|
}
|
||||||
|
<div className="absolute flex items-center justify-center cursor-pointer right-2 p-[2px] ubuntu-close-button" onClick={ onCloseClick } onMouseDownCapture={ onMouseDown }>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</Flex>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
};</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="code-section">
|
||||||
|
<div class="code-block">Nitro-V3/src/common/card/NitroCardContentView.tsx
|
||||||
|
|
||||||
|
import { FC, useMemo } from 'react';
|
||||||
|
import { Column, ColumnProps } from '..';
|
||||||
|
|
||||||
|
export const NitroCardContentView: FC<ColumnProps> = props =>
|
||||||
|
{
|
||||||
|
const { overflow = 'auto', classNames = [], ...rest } = props;
|
||||||
|
|
||||||
|
const getClassNames = useMemo(() =>
|
||||||
|
{
|
||||||
|
// Theme Changer
|
||||||
|
const newClassNames: string[] = [ 'container-fluid', 'h-full p-[8px] overflow-auto', 'bg-light' ];
|
||||||
|
|
||||||
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
|
return newClassNames;
|
||||||
|
}, [ classNames ]);
|
||||||
|
|
||||||
|
return <Column classNames={ getClassNames } overflow={ overflow } { ...rest } />;
|
||||||
|
};</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="code-section">
|
||||||
|
<div class="code-block">Nitro-V3/src/common/card/tabs/NitroCardTabsView.tsx
|
||||||
|
|
||||||
|
import { FC, useMemo } from 'react';
|
||||||
|
import { Flex, FlexProps } from '../..';
|
||||||
|
|
||||||
|
export const NitroCardTabsView: FC<FlexProps> = props =>
|
||||||
|
{
|
||||||
|
const { justifyContent = 'center', gap = 1, classNames = [], children = null, ...rest } = props;
|
||||||
|
|
||||||
|
const getClassNames = useMemo(() =>
|
||||||
|
{
|
||||||
|
const newClassNames: string[] = [ 'justify-center gap-0.5 flex bg-card-tabs min-h-card-tabs max-h-card-tabs pt-1 border-b border-card-border px-2 -mt-px' ];
|
||||||
|
|
||||||
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
|
return newClassNames;
|
||||||
|
}, [ classNames ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex classNames={ getClassNames } gap={ gap } justifyContent={ justifyContent } { ...rest }>
|
||||||
|
{ children }
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="code-section">
|
||||||
|
<div class="code-block">Nitro-V3/src/common/card/tabs/NitroCardTabsItemView.tsx
|
||||||
|
|
||||||
|
import { FC, useMemo } from 'react';
|
||||||
|
import { Flex, FlexProps } from '../../Flex';
|
||||||
|
import { LayoutItemCountView } from '../../layout';
|
||||||
|
|
||||||
|
interface NitroCardTabsItemViewProps extends FlexProps
|
||||||
|
{
|
||||||
|
isActive?: boolean;
|
||||||
|
count?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NitroCardTabsItemView: FC<NitroCardTabsItemViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { isActive = false, count = 0, overflow = 'hidden', position = 'relative', pointer = true, classNames = [], children = null, ...rest } = props;
|
||||||
|
|
||||||
|
const getClassNames = useMemo(() =>
|
||||||
|
{
|
||||||
|
const newClassNames: string[] = [ 'overflow-hidden relative cursor-pointer rounded-t-md flex bg-card-tab-item px-3 py-1 z-1 border-card-border border-t border-l border-r before:absolute before:w-[93%] before:h-[3px] before:rounded-md before:top-[1.5px] before:left-0 before:right-0 before:m-auto before:z-1 before:bg-[#C2C9D1]',
|
||||||
|
isActive && 'bg-card-tab-item-active -mb-px before:bg-white' ];
|
||||||
|
|
||||||
|
//if (isActive) newClassNames.push('bg-[#dfdfdf] border-b-[1px_solid_black]');
|
||||||
|
|
||||||
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
|
return newClassNames;
|
||||||
|
}, [ isActive, classNames ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex classNames={ getClassNames } overflow={ overflow } pointer={ pointer } position={ position } { ...rest }>
|
||||||
|
<Flex center shrink>
|
||||||
|
{ children }
|
||||||
|
</Flex>
|
||||||
|
{ (count > 0) &&
|
||||||
|
<LayoutItemCountView count={ count } /> }
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="code-section">
|
||||||
|
<div class="code-block">Nitro-V3/src/css/nitrocard/NitroCardView.css
|
||||||
|
|
||||||
|
.nitro-card {
|
||||||
|
resize: both;
|
||||||
|
|
||||||
|
@include media-breakpoint-down(lg) {
|
||||||
|
max-width: 100vw !important;
|
||||||
|
max-height: 100vh !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.theme-primary {
|
||||||
|
border: 1px solid #283F5D;
|
||||||
|
|
||||||
|
.nitro-card-header {
|
||||||
|
min-height: 33px;
|
||||||
|
max-height: 33px;
|
||||||
|
background: #1E7295;
|
||||||
|
|
||||||
|
.nitro-card-header-text {
|
||||||
|
color: #FFF;
|
||||||
|
text-shadow: 0px 4px 4px rgba(#000, 0.25);
|
||||||
|
@include font-size(1.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header-close {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px 2px;
|
||||||
|
line-height: 1;
|
||||||
|
border-radius: .25rem;
|
||||||
|
box-shadow: 0 0 0 1.6px #FFF;
|
||||||
|
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%
|
||||||
|
);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
filter: brightness(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header-report-camera {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 1px 3px;
|
||||||
|
line-height: 1;
|
||||||
|
border-radius: .25rem;
|
||||||
|
box-shadow: 0 0 0 1.6px #FFF;
|
||||||
|
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%
|
||||||
|
);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
filter: brightness(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs {
|
||||||
|
background-color: #185D79;
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
padding: .2rem .8rm;
|
||||||
|
background-color: #B6BEC5;
|
||||||
|
color: #000;
|
||||||
|
z-index: 1;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #DFDFDF;
|
||||||
|
border-color: #283F5D #283F5D #DFDFDF !important;
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
background: #FFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 93%;
|
||||||
|
height: 3px;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
top: 1.5px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: auto;
|
||||||
|
background: #c2c9d1;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-area {
|
||||||
|
background-color: #DFDFDF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.theme-primary-slim {
|
||||||
|
border: 1px solid #283F5D;
|
||||||
|
|
||||||
|
.nitro-card-header {
|
||||||
|
position: relative;
|
||||||
|
min-height: 28px;
|
||||||
|
max-height: 28px;
|
||||||
|
background: repeating-linear-gradient(#2DABC2, #2DABC2 50%, #2B91A7 50%, #2B91A7 100%);
|
||||||
|
border-bottom: 2px solid darken(#2B91A7, 5);
|
||||||
|
box-shadow: 0 2px white;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding-top:2px;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
content: ' ';
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background-color: rgba(#FFF, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header-text {
|
||||||
|
color: #FFF;
|
||||||
|
text-shadow: 0px 4px 4px rgba(#000, 0.25);
|
||||||
|
@include font-size (1.125);
|
||||||
|
min-height: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header-close {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0px 2px;
|
||||||
|
line-height: 1;
|
||||||
|
@include font-size(.675);
|
||||||
|
border-radius: .25rem;
|
||||||
|
box-shadow: 0 0 0 1.6px #FFF;
|
||||||
|
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%
|
||||||
|
);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
filter: brightness(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header-report-camera {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0px 2px;
|
||||||
|
margin-right: 4px;
|
||||||
|
line-height: 1;
|
||||||
|
@include font-size(.675);
|
||||||
|
border-radius: .25rem;
|
||||||
|
box-shadow: 0 0 0 1.6px #FFF;
|
||||||
|
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%
|
||||||
|
);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
filter: brightness(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs {
|
||||||
|
background-color: #185D79;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-area {
|
||||||
|
background-color: #DFDFDF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-area {
|
||||||
|
height: 100%;
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
&.theme-dark {
|
||||||
|
background-color: #1C323F !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-down(lg) {
|
||||||
|
.content-area {
|
||||||
|
height: 100% !important;
|
||||||
|
min-height: auto !important;
|
||||||
|
max-height: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs {
|
||||||
|
height: 100%;
|
||||||
|
min-height: 133px;
|
||||||
|
max-height: 133px;
|
||||||
|
border-bottom: 1px solid #283F5D;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-accordion-set {
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
background: rgba(#FFF, 0.5);
|
||||||
|
border-bottom: 1px solid rgba(#000, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-accordion-set-header {
|
||||||
|
border-bottom: 1px solid rgba(#000, 0.2);
|
||||||
|
}
|
||||||
|
}</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Mockup Assets
|
||||||
|
|
||||||
|
Questa cartella e' pronta per immagini o sprite dedicate ai mockup HTML.
|
||||||
|
|
||||||
|
Uso previsto:
|
||||||
|
- copiare qui versioni statiche di asset che vuoi testare fuori dal progetto
|
||||||
|
- collegarle da `mockup/index.html`
|
||||||
|
- tenere separati i file di esperimento dagli asset reali di `src/assets`
|
||||||
|
|
||||||
|
Percorso base:
|
||||||
|
- `Nitro-V3/mockup/index.html`
|
||||||
|
- `Nitro-V3/mockup/assets/`
|
||||||
@@ -0,0 +1,623 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="it">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Nitro V3 Mockup Lab</title>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg: #17191d;
|
||||||
|
--panel: #252931;
|
||||||
|
--panel-2: #1d2026;
|
||||||
|
--border: #3d4450;
|
||||||
|
--text: #f4f7fb;
|
||||||
|
--muted: #aeb6c4;
|
||||||
|
--card-border: #283f5d;
|
||||||
|
--card-header: #1e7295;
|
||||||
|
--card-content: #dfdfdf;
|
||||||
|
--toolbar: rgba(28, 28, 32, 0.95);
|
||||||
|
--tab: #b6bec5;
|
||||||
|
--tab-active: #dfdfdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 24px;
|
||||||
|
background: radial-gradient(circle at top, #222733 0%, #17191d 60%);
|
||||||
|
color: var(--text);
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
color: var(--muted);
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
background: linear-gradient(180deg, var(--panel) 0%, var(--panel-2) 100%);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-head {
|
||||||
|
padding: 14px 16px;
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.06);
|
||||||
|
background: rgba(255,255,255,0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-head h2 {
|
||||||
|
font-size: 17px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-head p {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-body {
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage {
|
||||||
|
background: #121419;
|
||||||
|
border: 1px solid rgba(255,255,255,0.08);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paths {
|
||||||
|
padding: 12px;
|
||||||
|
background: rgba(0,0,0,0.22);
|
||||||
|
border: 1px solid rgba(255,255,255,0.06);
|
||||||
|
border-radius: 10px;
|
||||||
|
font: 12px/1.5 Consolas, monospace;
|
||||||
|
color: #d5d9e1;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card {
|
||||||
|
width: 320px;
|
||||||
|
border: 1px solid var(--card-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 6px 20px rgba(0,0,0,0.35);
|
||||||
|
resize: both;
|
||||||
|
background: var(--card-content);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header {
|
||||||
|
min-height: 33px;
|
||||||
|
max-height: 33px;
|
||||||
|
background: var(--card-header);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-header-text {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 20px;
|
||||||
|
text-shadow: 0 4px 4px rgba(0,0,0,.25);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ubuntu-close-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 0 0 1.6px #fff;
|
||||||
|
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%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tabs {
|
||||||
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
|
justify-content: center;
|
||||||
|
background: #185d79;
|
||||||
|
padding: 4px 8px 0;
|
||||||
|
border-bottom: 1px solid var(--card-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tab {
|
||||||
|
position: relative;
|
||||||
|
min-width: 90px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: var(--tab);
|
||||||
|
color: #000;
|
||||||
|
text-align: center;
|
||||||
|
border-top-left-radius: 7px;
|
||||||
|
border-top-right-radius: 7px;
|
||||||
|
border-top: 1px solid var(--card-border);
|
||||||
|
border-left: 1px solid var(--card-border);
|
||||||
|
border-right: 1px solid var(--card-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tab::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 1.5px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 93%;
|
||||||
|
height: 3px;
|
||||||
|
margin: auto;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #c2c9d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tab.active {
|
||||||
|
background: var(--tab-active);
|
||||||
|
margin-bottom: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-tab.active::before {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-content {
|
||||||
|
padding: 8px;
|
||||||
|
min-height: 150px;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.purse {
|
||||||
|
width: 200px;
|
||||||
|
background: rgba(30, 30, 42, 0.95);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 6px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.purse-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 54px 30px;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.currency-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.currency-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.currency--1 { background: #e8b125; border: 2px solid #f4d892; }
|
||||||
|
.currency-0 { background: #c364c1; border: 2px solid #ecb3ea; }
|
||||||
|
.currency-5 { background: #6bafaa; border: 2px solid #ace6e2; }
|
||||||
|
|
||||||
|
.subscription {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #212131;
|
||||||
|
border: 2px solid #383853;
|
||||||
|
border-radius: 8px;
|
||||||
|
color: white;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-button {
|
||||||
|
width: 30px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #b69b83;
|
||||||
|
border: 2px solid rgba(255,255,255,.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.seasonal {
|
||||||
|
margin-top: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
background: linear-gradient(to right, #95c3e5, transparent);
|
||||||
|
background-color: #212131;
|
||||||
|
border-radius: 8px;
|
||||||
|
min-height: 30px;
|
||||||
|
color: white;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
min-height: 55px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: var(--toolbar);
|
||||||
|
box-shadow: inset 0 5px #22222799, inset 0 -4px #12121599;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-left, .toolbar-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-icon {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: linear-gradient(180deg, #4a535f, #2d333b);
|
||||||
|
border: 1px solid rgba(255,255,255,.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-me {
|
||||||
|
width: 50px;
|
||||||
|
height: 45px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: linear-gradient(180deg, #8ec6ff, #4f7fb7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigator {
|
||||||
|
width: 420px;
|
||||||
|
border: 1px solid var(--card-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 6px 20px rgba(0,0,0,.35);
|
||||||
|
background: var(--card-content);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigator-body {
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigator-search {
|
||||||
|
height: 34px;
|
||||||
|
border: 1px solid #9ca3af;
|
||||||
|
background: white;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigator-results {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
min-height: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigator-result {
|
||||||
|
height: 34px;
|
||||||
|
background: rgba(0,0,0,.06);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigator-footer {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
border-top: 1px solid #b0b7c2;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-action {
|
||||||
|
flex: 1;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: linear-gradient(180deg, #4c8fd7, #2e66a6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-bubble {
|
||||||
|
width: 240px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #262626;
|
||||||
|
box-shadow: inset 0 5px rgba(38,38,57,.6), inset 0 -4px rgba(25,25,37,.6);
|
||||||
|
color: white;
|
||||||
|
border-radius: .5rem;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.friends-bar {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.friend-pill {
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: linear-gradient(180deg, #dadfe7, #a4afbf);
|
||||||
|
border: 2px solid rgba(255,255,255,.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hotel-view {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 260px;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: linear-gradient(to bottom, #69b4e4 0%, #9fd3f2 55%, #51841e 55%, #51841e 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hotel-slab {
|
||||||
|
position: absolute;
|
||||||
|
inset: 24px 40px 36px;
|
||||||
|
background: linear-gradient(180deg, #d7d1c8 0%, #b8b1a4 100%);
|
||||||
|
border-radius: 14px;
|
||||||
|
box-shadow: 0 18px 40px rgba(0,0,0,.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hotel-hotspot {
|
||||||
|
position: absolute;
|
||||||
|
width: 58px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(255,255,255,.25);
|
||||||
|
border: 1px dashed rgba(255,255,255,.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hotel-hotspot.a { top: 30px; left: 40px; }
|
||||||
|
.hotel-hotspot.b { top: 98px; left: 160px; }
|
||||||
|
.hotel-hotspot.c { top: 150px; right: 90px; }
|
||||||
|
|
||||||
|
@media (max-width: 780px) {
|
||||||
|
body {
|
||||||
|
padding: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigator,
|
||||||
|
.nitro-card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Nitro V3 Mockup Lab</h1>
|
||||||
|
<p class="intro">Mockup HTML standalone dei componenti principali attuali. La resa è pensata per darti una base visiva da modificare rapidamente fuori dal progetto reale.</p>
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-head">
|
||||||
|
<h2>NitroCard</h2>
|
||||||
|
<p>Base card attuale con header blu, tabs grigie e content chiaro.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section-body">
|
||||||
|
<div class="stage">
|
||||||
|
<div class="nitro-card">
|
||||||
|
<div class="nitro-card-header">
|
||||||
|
<div class="nitro-card-header-text">Navigator</div>
|
||||||
|
<div class="ubuntu-close-button"></div>
|
||||||
|
</div>
|
||||||
|
<div class="nitro-card-tabs">
|
||||||
|
<div class="nitro-card-tab active">Hotel</div>
|
||||||
|
<div class="nitro-card-tab">Rooms</div>
|
||||||
|
<div class="nitro-card-tab">+</div>
|
||||||
|
</div>
|
||||||
|
<div class="nitro-card-content">
|
||||||
|
Contenuto card attuale, usato come base da vari componenti.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="paths">Source files:
|
||||||
|
src/common/card/NitroCardView.tsx
|
||||||
|
src/common/card/NitroCardHeaderView.tsx
|
||||||
|
src/common/card/NitroCardContentView.tsx
|
||||||
|
src/common/card/tabs/NitroCardTabsView.tsx
|
||||||
|
src/common/card/tabs/NitroCardTabsItemView.tsx
|
||||||
|
src/css/nitrocard/NitroCardView.css</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-head">
|
||||||
|
<h2>Purse</h2>
|
||||||
|
<p>Layout attuale con currency, box HC, pulsanti laterali e seasonal sotto.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section-body">
|
||||||
|
<div class="stage">
|
||||||
|
<div class="purse">
|
||||||
|
<div class="purse-grid">
|
||||||
|
<div class="currency-list">
|
||||||
|
<div class="currency-row currency--1">3601 ◉</div>
|
||||||
|
<div class="currency-row currency-0">5365 ◎</div>
|
||||||
|
<div class="currency-row currency-5">700 ◈</div>
|
||||||
|
</div>
|
||||||
|
<div class="subscription">
|
||||||
|
<div>HC</div>
|
||||||
|
<div>78 g</div>
|
||||||
|
</div>
|
||||||
|
<div class="side-buttons">
|
||||||
|
<div class="side-button"></div>
|
||||||
|
<div class="side-button"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="seasonal">
|
||||||
|
<span>Stagionale</span>
|
||||||
|
<span>99 999</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="paths">Source files:
|
||||||
|
src/components/purse/PurseView.tsx
|
||||||
|
src/components/purse/views/CurrencyView.tsx
|
||||||
|
src/components/purse/views/SeasonalView.tsx
|
||||||
|
src/css/purse/PurseView.css</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-head">
|
||||||
|
<h2>Toolbar</h2>
|
||||||
|
<p>Barra bassa attuale con area me, icone centrali e blocco friend/message.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section-body">
|
||||||
|
<div class="stage">
|
||||||
|
<div class="toolbar">
|
||||||
|
<div class="toolbar-left">
|
||||||
|
<div class="toolbar-me"></div>
|
||||||
|
<div class="toolbar-icon"></div>
|
||||||
|
<div class="toolbar-icon"></div>
|
||||||
|
<div class="toolbar-icon"></div>
|
||||||
|
<div class="toolbar-icon"></div>
|
||||||
|
</div>
|
||||||
|
<div style="flex:1; height:34px; border-radius:8px; background:rgba(255,255,255,.07);"></div>
|
||||||
|
<div class="toolbar-right">
|
||||||
|
<div class="toolbar-icon"></div>
|
||||||
|
<div class="toolbar-icon"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="paths">Source files:
|
||||||
|
src/components/toolbar/ToolbarView.tsx
|
||||||
|
src/components/toolbar/ToolbarItemView.tsx
|
||||||
|
src/components/toolbar/ToolbarMeView.tsx</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-head">
|
||||||
|
<h2>Navigator</h2>
|
||||||
|
<p>Finestra navigator attuale con card base, search e footer actions.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section-body">
|
||||||
|
<div class="stage">
|
||||||
|
<div class="navigator">
|
||||||
|
<div class="nitro-card-header">
|
||||||
|
<div class="nitro-card-header-text">Navigator</div>
|
||||||
|
<div class="ubuntu-close-button"></div>
|
||||||
|
</div>
|
||||||
|
<div class="nitro-card-tabs">
|
||||||
|
<div class="nitro-card-tab active">Saved</div>
|
||||||
|
<div class="nitro-card-tab">Rooms</div>
|
||||||
|
<div class="nitro-card-tab">+</div>
|
||||||
|
</div>
|
||||||
|
<div class="navigator-body">
|
||||||
|
<div class="navigator-search"></div>
|
||||||
|
<div class="navigator-results">
|
||||||
|
<div class="navigator-result"></div>
|
||||||
|
<div class="navigator-result"></div>
|
||||||
|
<div class="navigator-result"></div>
|
||||||
|
</div>
|
||||||
|
<div class="navigator-footer">
|
||||||
|
<div class="nav-action"></div>
|
||||||
|
<div class="nav-action" style="background:linear-gradient(180deg,#64a86b,#41794c);"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="paths">Source files:
|
||||||
|
src/components/navigator/NavigatorView.tsx
|
||||||
|
src/components/navigator/NavigatorView.scss
|
||||||
|
src/css/room/NavigatorRoomSettings.css</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-head">
|
||||||
|
<h2>Notifications</h2>
|
||||||
|
<p>Bubble attuale con fondo scuro e inner shadow.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section-body">
|
||||||
|
<div class="stage">
|
||||||
|
<div class="notification-bubble">
|
||||||
|
Hai ricevuto una nuova notifica. Questo box rappresenta lo stato attuale delle bubble notifications.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="paths">Source files:
|
||||||
|
src/components/notification-center/NotificationCenterView.tsx
|
||||||
|
src/css/notification/NotificationCenterView.css</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-head">
|
||||||
|
<h2>Friends</h2>
|
||||||
|
<p>Barra amici e blocchi friend pill attuali.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section-body">
|
||||||
|
<div class="stage">
|
||||||
|
<div class="friends-bar">
|
||||||
|
<div class="friend-pill"></div>
|
||||||
|
<div class="friend-pill"></div>
|
||||||
|
<div class="friend-pill"></div>
|
||||||
|
<div class="friend-pill"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="paths">Source files:
|
||||||
|
src/components/friends/FriendsView.tsx
|
||||||
|
src/css/friends/FriendsView.css</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-head">
|
||||||
|
<h2>HotelView</h2>
|
||||||
|
<p>Mockup della scena hotel attuale con sfondo e hotspot.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section-body">
|
||||||
|
<div class="stage">
|
||||||
|
<div class="hotel-view">
|
||||||
|
<div class="hotel-slab"></div>
|
||||||
|
<div class="hotel-hotspot a"></div>
|
||||||
|
<div class="hotel-hotspot b"></div>
|
||||||
|
<div class="hotel-hotspot c"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="paths">Source files:
|
||||||
|
src/components/hotel-view/HotelView.tsx
|
||||||
|
src/css/hotelview/HotelView.css</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -14,7 +14,6 @@ export const App: FC<{}> = props =>
|
|||||||
const [ isReady, setIsReady ] = useState(false);
|
const [ isReady, setIsReady ] = useState(false);
|
||||||
const [ errorMessage, setErrorMessage ] = useState('');
|
const [ errorMessage, setErrorMessage ] = useState('');
|
||||||
const [ homeUrl, setHomeUrl ] = useState('');
|
const [ homeUrl, setHomeUrl ] = useState('');
|
||||||
|
|
||||||
const showSessionExpired = useCallback(() =>
|
const showSessionExpired = useCallback(() =>
|
||||||
{
|
{
|
||||||
const baseUrl = window.location.origin + '/';
|
const baseUrl = window.location.origin + '/';
|
||||||
@@ -37,6 +36,8 @@ export const App: FC<{}> = props =>
|
|||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
|
let heartbeatInterval: number = null;
|
||||||
|
|
||||||
const prepare = async (width: number, height: number) =>
|
const prepare = async (width: number, height: number) =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -51,6 +52,11 @@ export const App: FC<{}> = props =>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rawUseBackBuffer = window.NitroConfig['renderer.useBackBuffer'];
|
||||||
|
const useBackBuffer = (rawUseBackBuffer === undefined)
|
||||||
|
? true
|
||||||
|
: ((rawUseBackBuffer === true) || (rawUseBackBuffer === 'true'));
|
||||||
|
|
||||||
const renderer = await PrepareRenderer({
|
const renderer = await PrepareRenderer({
|
||||||
width: Math.floor(width),
|
width: Math.floor(width),
|
||||||
height: Math.floor(height),
|
height: Math.floor(height),
|
||||||
@@ -61,7 +67,7 @@ export const App: FC<{}> = props =>
|
|||||||
eventMode: 'none',
|
eventMode: 'none',
|
||||||
failIfMajorPerformanceCaveat: false,
|
failIfMajorPerformanceCaveat: false,
|
||||||
roundPixels: true,
|
roundPixels: true,
|
||||||
useBackBuffer: true // Enable back buffer for blend filters
|
useBackBuffer // Keep disabled by default unless explicitly enabled in NitroConfig
|
||||||
});
|
});
|
||||||
|
|
||||||
await GetConfiguration().init();
|
await GetConfiguration().init();
|
||||||
@@ -93,7 +99,7 @@ export const App: FC<{}> = props =>
|
|||||||
|
|
||||||
HabboWebTools.sendHeartBeat();
|
HabboWebTools.sendHeartBeat();
|
||||||
|
|
||||||
setInterval(() => HabboWebTools.sendHeartBeat(), 10000);
|
heartbeatInterval = window.setInterval(() => HabboWebTools.sendHeartBeat(), 10000);
|
||||||
|
|
||||||
GetTicker().add(ticker => GetRoomEngine().update(ticker));
|
GetTicker().add(ticker => GetRoomEngine().update(ticker));
|
||||||
GetTicker().add(ticker => renderer.render(GetStage()));
|
GetTicker().add(ticker => renderer.render(GetStage()));
|
||||||
@@ -109,6 +115,11 @@ export const App: FC<{}> = props =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
prepare(window.innerWidth, window.innerHeight);
|
prepare(window.innerWidth, window.innerHeight);
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
if(heartbeatInterval !== null) window.clearInterval(heartbeatInterval);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -120,4 +131,4 @@ export const App: FC<{}> = props =>
|
|||||||
<Base id="draggable-windows-container" />
|
<Base id="draggable-windows-container" />
|
||||||
</Base>
|
</Base>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export class MessengerThread
|
|||||||
{
|
{
|
||||||
public static MESSAGE_RECEIVED: string = 'MT_MESSAGE_RECEIVED';
|
public static MESSAGE_RECEIVED: string = 'MT_MESSAGE_RECEIVED';
|
||||||
public static THREAD_ID: number = 0;
|
public static THREAD_ID: number = 0;
|
||||||
|
private static MAX_CHATS: number = 250;
|
||||||
|
|
||||||
private _threadId: number;
|
private _threadId: number;
|
||||||
private _participant: MessengerFriend;
|
private _participant: MessengerFriend;
|
||||||
@@ -38,6 +39,7 @@ export class MessengerThread
|
|||||||
const chat = new MessengerThreadChat(senderId, message, secondsSinceSent, extraData, type);
|
const chat = new MessengerThreadChat(senderId, message, secondsSinceSent, extraData, type);
|
||||||
|
|
||||||
group.addChat(chat);
|
group.addChat(chat);
|
||||||
|
this.pruneChats();
|
||||||
|
|
||||||
this._lastUpdated = new Date();
|
this._lastUpdated = new Date();
|
||||||
|
|
||||||
@@ -46,6 +48,27 @@ export class MessengerThread
|
|||||||
return chat;
|
return chat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private pruneChats(): void
|
||||||
|
{
|
||||||
|
let totalChats = this._groups.reduce((total, current) => (total + current.chats.length), 0);
|
||||||
|
|
||||||
|
while(totalChats > MessengerThread.MAX_CHATS)
|
||||||
|
{
|
||||||
|
const firstGroup = this._groups[0];
|
||||||
|
|
||||||
|
if(!firstGroup) break;
|
||||||
|
|
||||||
|
if(firstGroup.chats.length) firstGroup.chats.shift();
|
||||||
|
|
||||||
|
if(!firstGroup.chats.length)
|
||||||
|
{
|
||||||
|
this._groups.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
totalChats--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getLastGroup(userId: number): MessengerThreadChatGroup
|
private getLastGroup(userId: number): MessengerThreadChatGroup
|
||||||
{
|
{
|
||||||
let group = this._groups[(this._groups.length - 1)];
|
let group = this._groups[(this._groups.length - 1)];
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1010 B |
|
After Width: | Height: | Size: 676 B |
|
After Width: | Height: | Size: 255 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 206 B |
|
After Width: | Height: | Size: 133 B |
|
After Width: | Height: | Size: 547 B |
|
After Width: | Height: | Size: 322 B |
|
After Width: | Height: | Size: 211 B |
|
After Width: | Height: | Size: 265 B |
|
After Width: | Height: | Size: 274 B |
|
After Width: | Height: | Size: 198 B |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 113 B |
|
After Width: | Height: | Size: 299 B |
|
After Width: | Height: | Size: 293 B |
|
After Width: | Height: | Size: 153 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 442 B |
|
After Width: | Height: | Size: 426 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 443 B |
|
After Width: | Height: | Size: 423 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 437 B |
|
After Width: | Height: | Size: 598 B |
|
After Width: | Height: | Size: 428 B |
|
After Width: | Height: | Size: 428 B |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 358 B |
|
After Width: | Height: | Size: 286 B |
|
After Width: | Height: | Size: 174 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 445 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 447 B |
|
After Width: | Height: | Size: 452 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 430 B |
|
After Width: | Height: | Size: 430 B |
|
After Width: | Height: | Size: 138 B |
|
After Width: | Height: | Size: 431 B |
|
After Width: | Height: | Size: 430 B |
|
After Width: | Height: | Size: 426 B |
|
After Width: | Height: | Size: 431 B |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 182 B |
|
After Width: | Height: | Size: 175 B |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 441 B |
|
After Width: | Height: | Size: 447 B |
|
After Width: | Height: | Size: 455 B |
|
After Width: | Height: | Size: 430 B |
|
After Width: | Height: | Size: 213 B |
|
After Width: | Height: | Size: 1.6 KiB |