fix: profile lifting
All checks were successful
Deploy to VPS (dist) / deploy (push) Successful in 1m39s
All checks were successful
Deploy to VPS (dist) / deploy (push) Successful in 1m39s
This commit is contained in:
@@ -12,6 +12,11 @@
|
||||
"off": "aus",
|
||||
"on": "an"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Antwort",
|
||||
"1q": "Frage",
|
||||
"title": "FAQ"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Bienenhaus",
|
||||
"cashdesk": "Kasse",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "von"
|
||||
},
|
||||
"support": {
|
||||
"action": "Support kontaktieren",
|
||||
"text": "Wenn Sie Fragen zum Spiel haben, wenden Sie sich bitte an unseren Support."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Kontoinformationen",
|
||||
"back": "Zurück",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Support",
|
||||
"transactionHistory": "Transaktionsverlauf"
|
||||
},
|
||||
"support": {
|
||||
"action": "Support kontaktieren",
|
||||
"text": "Wenn Sie Fragen zum Spiel haben, wenden Sie sich bitte an unseren Support.",
|
||||
"title": "Support"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Datum",
|
||||
"operationType": "Vorgangsart",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "off",
|
||||
"on": "on"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Answer",
|
||||
"1q": "Question",
|
||||
"title": "FAQ"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Apiary",
|
||||
"cashdesk": "Cashdesk",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "of"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contact support",
|
||||
"text": "If you have any questions related to the game, please contact our support team."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Account information",
|
||||
"back": "Back",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Support",
|
||||
"transactionHistory": "Transaction History"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contact support",
|
||||
"text": "If you have any questions related to the game, please contact our support team.",
|
||||
"title": "Support"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Date",
|
||||
"operationType": "Operation type",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "no",
|
||||
"on": "sí"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Respuesta",
|
||||
"1q": "Pregunta",
|
||||
"title": "FAQ"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Apiario",
|
||||
"cashdesk": "Caja",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "de"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contactar soporte",
|
||||
"text": "Si tienes alguna pregunta relacionada con el juego, contacta con nuestro equipo de soporte."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Información de la cuenta",
|
||||
"back": "Volver",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Soporte",
|
||||
"transactionHistory": "Historial de transacciones"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contactar soporte",
|
||||
"text": "Si tienes alguna pregunta relacionada con el juego, contacta con nuestro equipo de soporte.",
|
||||
"title": "Soporte"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Fecha",
|
||||
"operationType": "Tipo de operación",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "non",
|
||||
"on": "oui"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Réponse",
|
||||
"1q": "Question",
|
||||
"title": "FAQ"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Rucher",
|
||||
"cashdesk": "Caisse",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "sur"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contacter le support",
|
||||
"text": "Si vous avez des questions liées au jeu, veuillez contacter notre équipe de support."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Informations du compte",
|
||||
"back": "Retour",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Support",
|
||||
"transactionHistory": "Historique des transactions"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contacter le support",
|
||||
"text": "Si vous avez des questions liées au jeu, veuillez contacter notre équipe de support.",
|
||||
"title": "Support"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Date",
|
||||
"operationType": "Type d'opération",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "mati",
|
||||
"on": "nyala"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Jawaban",
|
||||
"1q": "Pertanyaan",
|
||||
"title": "FAQ"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Peternakan Lebah",
|
||||
"cashdesk": "Kasir",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "dari"
|
||||
},
|
||||
"support": {
|
||||
"action": "Hubungi dukungan",
|
||||
"text": "Jika Anda memiliki pertanyaan terkait permainan, silakan hubungi tim dukungan kami."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Informasi akun",
|
||||
"back": "Kembali",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Dukungan",
|
||||
"transactionHistory": "Riwayat transaksi"
|
||||
},
|
||||
"support": {
|
||||
"action": "Hubungi dukungan",
|
||||
"text": "Jika Anda memiliki pertanyaan terkait permainan, silakan hubungi tim dukungan kami.",
|
||||
"title": "Dukungan"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Tanggal",
|
||||
"operationType": "Jenis operasi",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "no",
|
||||
"on": "sì"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Risposta",
|
||||
"1q": "Domanda",
|
||||
"title": "FAQ"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Apiario",
|
||||
"cashdesk": "Cassa",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "di"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contatta il supporto",
|
||||
"text": "Se hai domande relative al gioco, contatta il nostro team di supporto."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Informazioni account",
|
||||
"back": "Indietro",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Supporto",
|
||||
"transactionHistory": "Cronologia transazioni"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contatta il supporto",
|
||||
"text": "Se hai domande relative al gioco, contatta il nostro team di supporto.",
|
||||
"title": "Supporto"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Data",
|
||||
"operationType": "Tipo di operazione",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "uit",
|
||||
"on": "aan"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Antwoord",
|
||||
"1q": "Vraag",
|
||||
"title": "FAQ"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Bijenstal",
|
||||
"cashdesk": "Kassa",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "van"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contact opnemen",
|
||||
"text": "Als u vragen heeft over het spel, neem dan contact op met ons ondersteuningsteam."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Accountinformatie",
|
||||
"back": "Terug",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Ondersteuning",
|
||||
"transactionHistory": "Transactiegeschiedenis"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contact opnemen",
|
||||
"text": "Als u vragen heeft over het spel, neem dan contact op met ons ondersteuningsteam.",
|
||||
"title": "Ondersteuning"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Datum",
|
||||
"operationType": "Bewerkingstype",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "wył",
|
||||
"on": "wł"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Odpowiedź",
|
||||
"1q": "Pytanie",
|
||||
"title": "FAQ"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Pasieka",
|
||||
"cashdesk": "Kasa",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "z"
|
||||
},
|
||||
"support": {
|
||||
"action": "Skontaktuj się z pomocą",
|
||||
"text": "Jeśli masz pytania dotyczące gry, skontaktuj się z naszym zespołem wsparcia."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Informacje o koncie",
|
||||
"back": "Wstecz",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Wsparcie",
|
||||
"transactionHistory": "Historia transakcji"
|
||||
},
|
||||
"support": {
|
||||
"action": "Skontaktuj się z pomocą",
|
||||
"text": "Jeśli masz pytania dotyczące gry, skontaktuj się z naszym zespołem wsparcia.",
|
||||
"title": "Wsparcie"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Data",
|
||||
"operationType": "Typ operacji",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "não",
|
||||
"on": "sim"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Resposta",
|
||||
"1q": "Pergunta",
|
||||
"title": "FAQ"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Apiário",
|
||||
"cashdesk": "Caixa",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "de"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contactar suporte",
|
||||
"text": "Se tiver dúvidas relacionadas ao jogo, entre em contato com nossa equipe de suporte."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Informações da conta",
|
||||
"back": "Voltar",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Suporte",
|
||||
"transactionHistory": "Histórico de transações"
|
||||
},
|
||||
"support": {
|
||||
"action": "Contactar suporte",
|
||||
"text": "Se tiver dúvidas relacionadas ao jogo, entre em contato com nossa equipe de suporte.",
|
||||
"title": "Suporte"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Data",
|
||||
"operationType": "Tipo de operação",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "выкл",
|
||||
"on": "вкл"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Ответ",
|
||||
"1q": "Вопрос",
|
||||
"title": "ЧаВо"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Пасека",
|
||||
"cashdesk": "Касса",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "из"
|
||||
},
|
||||
"support": {
|
||||
"action": "Связаться с поддержкой",
|
||||
"text": "Если у вас возникли вопросы, связанные с игрой — обратитесь в нашу службу поддержки."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Информация об аккаунте",
|
||||
"back": "Назад",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Поддержка",
|
||||
"transactionHistory": "История транзакций"
|
||||
},
|
||||
"support": {
|
||||
"action": "Связаться с поддержкой",
|
||||
"text": "Если у вас возникли вопросы, связанные с игрой — обратитесь в нашу службу поддержки.",
|
||||
"title": "Поддержка"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Дата",
|
||||
"operationType": "Тип операции",
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"off": "kapalı",
|
||||
"on": "açık"
|
||||
},
|
||||
"faq": {
|
||||
"1a": "Cevap",
|
||||
"1q": "Soru",
|
||||
"title": "SSS"
|
||||
},
|
||||
"nav": {
|
||||
"apiary": "Arılık",
|
||||
"cashdesk": "Kasa",
|
||||
@@ -31,10 +36,6 @@
|
||||
"pagination": {
|
||||
"of": "/"
|
||||
},
|
||||
"support": {
|
||||
"action": "Destek ile iletişime geç",
|
||||
"text": "Oyunla ilgili sorularınız varsa lütfen destek ekibimizle iletişime geçin."
|
||||
},
|
||||
"settings": {
|
||||
"accountInfo": "Hesap bilgileri",
|
||||
"back": "Geri",
|
||||
@@ -44,6 +45,11 @@
|
||||
"support": "Destek",
|
||||
"transactionHistory": "İşlem Geçmişi"
|
||||
},
|
||||
"support": {
|
||||
"action": "Destek ile iletişime geç",
|
||||
"text": "Oyunla ilgili sorularınız varsa lütfen destek ekibimizle iletişime geçin.",
|
||||
"title": "Destek"
|
||||
},
|
||||
"transactionHistory": {
|
||||
"date": "Tarih",
|
||||
"operationType": "İşlem türü",
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import { createContext, useCallback, useContext, useRef, useState } from "react";
|
||||
import type { ReactNode } from "react";
|
||||
import { cloneWithoutAnimations } from "./Liftable";
|
||||
|
||||
type LiftContextValue = {
|
||||
liftedIds: Set<string>;
|
||||
alwaysLiftedIds: Set<string>;
|
||||
modalOpen: boolean;
|
||||
setLiftedIds: (ids: string[]) => void;
|
||||
registerAlways: (id: string) => void;
|
||||
unregisterAlways: (id: string) => void;
|
||||
registerModal: () => void;
|
||||
beginModalClose: () => void;
|
||||
endModalClose: () => void;
|
||||
portalContainer: HTMLElement | null;
|
||||
setPortalContainer: (el: HTMLElement | null) => void;
|
||||
setCloneContainer: (el: HTMLElement | null) => void;
|
||||
};
|
||||
|
||||
const LiftContext = createContext<LiftContextValue | null>(null);
|
||||
@@ -22,13 +28,41 @@ export function useLift(): LiftContextValue {
|
||||
export function LiftProvider({ children }: { children: ReactNode }) {
|
||||
const [liftedIds, setLiftedIdsRaw] = useState<Set<string>>(new Set());
|
||||
const [alwaysLiftedIds, setAlwaysLiftedIds] = useState<Set<string>>(new Set());
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);
|
||||
const alwaysRef = useRef<Set<string>>(new Set());
|
||||
const modalCountRef = useRef(0);
|
||||
const cloneContainerRef = useRef<HTMLElement | null>(null);
|
||||
|
||||
const setLiftedIds = useCallback((ids: string[]) => {
|
||||
setLiftedIdsRaw(new Set(ids));
|
||||
}, []);
|
||||
|
||||
const registerModal = useCallback(() => {
|
||||
modalCountRef.current++;
|
||||
setModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const beginModalClose = useCallback(() => {
|
||||
if (portalContainer && cloneContainerRef.current) {
|
||||
cloneWithoutAnimations(portalContainer, cloneContainerRef.current);
|
||||
}
|
||||
modalCountRef.current--;
|
||||
if (modalCountRef.current === 0) {
|
||||
setModalOpen(false);
|
||||
}
|
||||
}, [portalContainer]);
|
||||
|
||||
const endModalClose = useCallback(() => {
|
||||
if (cloneContainerRef.current) {
|
||||
cloneContainerRef.current.innerHTML = "";
|
||||
}
|
||||
}, []);
|
||||
|
||||
const setCloneContainer = useCallback((el: HTMLElement | null) => {
|
||||
cloneContainerRef.current = el;
|
||||
}, []);
|
||||
|
||||
const registerAlways = useCallback((id: string) => {
|
||||
alwaysRef.current.add(id);
|
||||
setAlwaysLiftedIds(new Set(alwaysRef.current));
|
||||
@@ -44,11 +78,16 @@ export function LiftProvider({ children }: { children: ReactNode }) {
|
||||
value={{
|
||||
liftedIds,
|
||||
alwaysLiftedIds,
|
||||
modalOpen,
|
||||
setLiftedIds,
|
||||
registerAlways,
|
||||
unregisterAlways,
|
||||
registerModal,
|
||||
beginModalClose,
|
||||
endModalClose,
|
||||
portalContainer,
|
||||
setPortalContainer,
|
||||
setCloneContainer,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -3,14 +3,26 @@ import { useLift } from "./LiftContext";
|
||||
import classes from "./LiftLayer.module.css";
|
||||
|
||||
export function LiftLayer() {
|
||||
const { setPortalContainer } = useLift();
|
||||
const { setPortalContainer, setCloneContainer } = useLift();
|
||||
|
||||
const refCallback = useCallback(
|
||||
const portalRef = useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
setPortalContainer(node);
|
||||
},
|
||||
[setPortalContainer],
|
||||
);
|
||||
|
||||
return <div ref={refCallback} className={classes.liftLayer} />;
|
||||
const cloneRef = useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
setCloneContainer(node);
|
||||
},
|
||||
[setCloneContainer],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div ref={portalRef} className={classes.liftLayer} />
|
||||
<div ref={cloneRef} className={classes.liftLayer} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,29 @@
|
||||
import { useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
||||
import { useEffect, useId, useLayoutEffect, useRef } from "react";
|
||||
import type { ReactNode } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { useLift } from "./LiftContext";
|
||||
|
||||
/** Recursively strip CSS animations and transitions from a cloned DOM tree */
|
||||
function stripAnimations(node: Node) {
|
||||
if (node instanceof HTMLElement) {
|
||||
node.style.animation = "none";
|
||||
node.style.transition = "none";
|
||||
node.getAnimations().forEach((a) => a.cancel());
|
||||
}
|
||||
for (const child of Array.from(node.childNodes)) {
|
||||
stripAnimations(child);
|
||||
}
|
||||
}
|
||||
|
||||
function cloneWithoutAnimations(source: HTMLElement, target: HTMLElement) {
|
||||
target.innerHTML = "";
|
||||
for (const child of Array.from(source.children)) {
|
||||
const clone = child.cloneNode(true) as HTMLElement;
|
||||
stripAnimations(clone);
|
||||
target.appendChild(clone);
|
||||
}
|
||||
}
|
||||
|
||||
type LiftableProps = {
|
||||
id?: string;
|
||||
always?: boolean;
|
||||
@@ -23,7 +44,7 @@ export function useLiftable<T extends Record<string, unknown> = Record<string, n
|
||||
...extraProps
|
||||
} = (options ?? {}) as LiftableProps & Record<string, unknown>;
|
||||
const id = idProp ?? autoId;
|
||||
const { liftedIds, alwaysLiftedIds, registerAlways, unregisterAlways } = useLift();
|
||||
const { liftedIds, alwaysLiftedIds, modalOpen, registerAlways, unregisterAlways } = useLift();
|
||||
|
||||
useEffect(() => {
|
||||
if (always) {
|
||||
@@ -32,7 +53,7 @@ export function useLiftable<T extends Record<string, unknown> = Record<string, n
|
||||
}
|
||||
}, [always, id, registerAlways, unregisterAlways]);
|
||||
|
||||
const isLifted = liftedIds.has(id) || alwaysLiftedIds.has(id);
|
||||
const isLifted = liftedIds.has(id) || (alwaysLiftedIds.has(id) && modalOpen);
|
||||
|
||||
const element = (
|
||||
<Liftable id={id}>{render({ isLifted, ...extraProps } as { isLifted: boolean } & T)}</Liftable>
|
||||
@@ -41,13 +62,24 @@ export function useLiftable<T extends Record<string, unknown> = Record<string, n
|
||||
return { id, element };
|
||||
}
|
||||
|
||||
export { cloneWithoutAnimations };
|
||||
|
||||
export function Liftable({ id: idProp, always, children }: Props) {
|
||||
const autoId = useId();
|
||||
const id = idProp ?? autoId;
|
||||
const { liftedIds, alwaysLiftedIds, registerAlways, unregisterAlways, portalContainer } =
|
||||
useLift();
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const [rect, setRect] = useState<DOMRect | null>(null);
|
||||
const {
|
||||
liftedIds,
|
||||
alwaysLiftedIds,
|
||||
modalOpen,
|
||||
registerAlways,
|
||||
unregisterAlways,
|
||||
portalContainer,
|
||||
} = useLift();
|
||||
|
||||
const childrenHostRef = useRef<HTMLDivElement>(null);
|
||||
const inlineSlotRef = useRef<HTMLDivElement>(null);
|
||||
const portalWrapperRef = useRef<HTMLDivElement>(null);
|
||||
const wasLiftedRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (always) {
|
||||
@@ -56,29 +88,43 @@ export function Liftable({ id: idProp, always, children }: Props) {
|
||||
}
|
||||
}, [always, id, registerAlways, unregisterAlways]);
|
||||
|
||||
const isLifted = liftedIds.has(id) || alwaysLiftedIds.has(id);
|
||||
const isLifted = liftedIds.has(id) || (alwaysLiftedIds.has(id) && modalOpen);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (isLifted && wrapperRef.current) {
|
||||
setRect(wrapperRef.current.getBoundingClientRect());
|
||||
}
|
||||
if (!isLifted) {
|
||||
setRect(null);
|
||||
const host = childrenHostRef.current;
|
||||
const inlineSlot = inlineSlotRef.current;
|
||||
const portalWrapper = portalWrapperRef.current;
|
||||
if (!host || !inlineSlot || !portalWrapper) return;
|
||||
|
||||
if (isLifted && !wasLiftedRef.current) {
|
||||
const rect = inlineSlot.getBoundingClientRect();
|
||||
cloneWithoutAnimations(host, inlineSlot);
|
||||
portalWrapper.appendChild(host);
|
||||
portalWrapper.style.cssText = `position:fixed;top:${rect.top}px;left:${rect.left}px;width:${rect.width}px;height:${rect.height}px;pointer-events:auto`;
|
||||
wasLiftedRef.current = true;
|
||||
} else if (!isLifted && wasLiftedRef.current) {
|
||||
inlineSlot.innerHTML = "";
|
||||
inlineSlot.appendChild(host);
|
||||
portalWrapper.style.cssText = "display:none";
|
||||
wasLiftedRef.current = false;
|
||||
}
|
||||
}, [isLifted]);
|
||||
|
||||
// Re-measure on resize while lifted
|
||||
useEffect(() => {
|
||||
if (!isLifted || !wrapperRef.current) return;
|
||||
if (!isLifted || !inlineSlotRef.current || !portalWrapperRef.current) return;
|
||||
const portalWrapper = portalWrapperRef.current;
|
||||
const inlineSlot = inlineSlotRef.current;
|
||||
|
||||
const measure = () => {
|
||||
if (wrapperRef.current) {
|
||||
setRect(wrapperRef.current.getBoundingClientRect());
|
||||
}
|
||||
const rect = inlineSlot.getBoundingClientRect();
|
||||
portalWrapper.style.top = `${rect.top}px`;
|
||||
portalWrapper.style.left = `${rect.left}px`;
|
||||
portalWrapper.style.width = `${rect.width}px`;
|
||||
portalWrapper.style.height = `${rect.height}px`;
|
||||
};
|
||||
|
||||
const observer = new ResizeObserver(measure);
|
||||
observer.observe(wrapperRef.current);
|
||||
observer.observe(inlineSlot);
|
||||
window.addEventListener("resize", measure);
|
||||
|
||||
return () => {
|
||||
@@ -87,35 +133,13 @@ export function Liftable({ id: idProp, always, children }: Props) {
|
||||
};
|
||||
}, [isLifted]);
|
||||
|
||||
// When lifted and we have measurements + portal target, render in portal
|
||||
if (isLifted && rect && portalContainer) {
|
||||
return (
|
||||
<>
|
||||
{/* Placeholder preserves layout space */}
|
||||
<div
|
||||
ref={wrapperRef}
|
||||
style={{ width: rect.width, height: rect.height, visibility: "hidden" }}
|
||||
/>
|
||||
{/* Portal children above blur */}
|
||||
{createPortal(
|
||||
<div
|
||||
style={{
|
||||
position: "fixed",
|
||||
top: rect.top,
|
||||
left: rect.left,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
pointerEvents: "auto",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>,
|
||||
portalContainer,
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Normal inline rendering
|
||||
return <div ref={wrapperRef}>{children}</div>;
|
||||
return (
|
||||
<>
|
||||
<div ref={inlineSlotRef}>
|
||||
<div ref={childrenHostRef}>{children}</div>
|
||||
</div>
|
||||
{portalContainer &&
|
||||
createPortal(<div ref={portalWrapperRef} style={{ display: "none" }} />, portalContainer)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,9 +17,18 @@ type Props = {
|
||||
};
|
||||
|
||||
export default function Modal({ open, children, onClose, liftIds, title, className }: Props) {
|
||||
const { setLiftedIds } = useLift();
|
||||
const { setLiftedIds, registerModal, beginModalClose, endModalClose } = useLift();
|
||||
const prevLiftIdsRef = useRef<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
registerModal();
|
||||
return () => {
|
||||
beginModalClose();
|
||||
};
|
||||
}
|
||||
}, [open, registerModal, beginModalClose]);
|
||||
|
||||
useEffect(() => {
|
||||
const key = liftIds?.join(",") ?? "";
|
||||
|
||||
@@ -45,7 +54,7 @@ export default function Modal({ open, children, onClose, liftIds, title, classNa
|
||||
}, [setLiftedIds]);
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
<AnimatePresence onExitComplete={endModalClose}>
|
||||
{open && (
|
||||
<>
|
||||
<motion.div
|
||||
|
||||
19
src/i18n/resources.d.ts
vendored
19
src/i18n/resources.d.ts
vendored
@@ -1,8 +1,15 @@
|
||||
// Auto-generated by i18nextTypesPlugin — do not edit manually
|
||||
declare const resources: {
|
||||
"accountInfo.paymentBalance": "Einzahlungsguthaben" | "Payment balance" | "Saldo de pagos" | "Solde des paiements" | "Saldo pembayaran" | "Saldo pagamenti" | "Stortingssaldo" | "Saldo wpłat" | "Saldo de pagamentos" | "Баланс пополнений" | "Ödeme bakiyesi";
|
||||
"accountInfo.registrationDate": "Registrierungsdatum" | "Registration date" | "Fecha de registro" | "Date d'inscription" | "Tanggal pendaftaran" | "Data di registrazione" | "Registratiedatum" | "Data rejestracji" | "Data de registro" | "Дата регистрации" | "Kayıt tarihi";
|
||||
"accountInfo.withdrawalBalance": "Auszahlungsguthaben" | "Withdrawal balance" | "Saldo de retiros" | "Solde des retraits" | "Saldo penarikan" | "Saldo prelievi" | "Opnamesaldo" | "Saldo wypłat" | "Saldo de saques" | "Баланс выводов" | "Çekim bakiyesi";
|
||||
"accountInfo.yourId": "Ihre ID" | "Your ID" | "Tu ID" | "Votre ID" | "ID Anda" | "Il tuo ID" | "Uw ID" | "Twoje ID" | "Seu ID" | "Ваш ID" | "Kimliğiniz";
|
||||
"actionModal.close": "Schließen" | "Close" | "Cerrar" | "Fermer" | "Tutup" | "Chiudi" | "Sluiten" | "Zamknij" | "Fechar" | "Закрыть" | "Kapat";
|
||||
"common.off": "aus" | "off" | "no" | "non" | "mati" | "uit" | "wył" | "não" | "выкл" | "kapalı";
|
||||
"common.on": "an" | "on" | "sí" | "oui" | "nyala" | "sì" | "aan" | "wł" | "sim" | "вкл" | "açık";
|
||||
"faq.1a": "Antwort" | "Answer" | "Respuesta" | "Réponse" | "Jawaban" | "Risposta" | "Antwoord" | "Odpowiedź" | "Resposta" | "Ответ" | "Cevap";
|
||||
"faq.1q": "Frage" | "Question" | "Pregunta" | "Pertanyaan" | "Domanda" | "Vraag" | "Pytanie" | "Pergunta" | "Вопрос" | "Soru";
|
||||
"faq.title": "FAQ" | "ЧаВо" | "SSS";
|
||||
"nav.apiary": "Bienenhaus" | "Apiary" | "Apiario" | "Rucher" | "Peternakan Lebah" | "Bijenstal" | "Pasieka" | "Apiário" | "Пасека" | "Arılık";
|
||||
"nav.cashdesk": "Kasse" | "Cashdesk" | "Caja" | "Caisse" | "Kasir" | "Cassa" | "Kassa" | "Kasa" | "Caixa" | "Касса";
|
||||
"nav.earnings": "Einnahmen" | "Earnings" | "Ganancias" | "Gains" | "Penghasilan" | "Guadagni" | "Inkomsten" | "Zarobki" | "Ganhos" | "Заработок" | "Kazançlar";
|
||||
@@ -11,6 +18,10 @@ declare const resources: {
|
||||
"nav.roulette": "Roulette" | "Ruleta" | "Ruletka" | "Roleta" | "Рулетка" | "Rulet";
|
||||
"nav.shop": "Shop" | "Tienda" | "Boutique" | "Toko" | "Negozio" | "Winkel" | "Sklep" | "Loja" | "Магазин" | "Mağaza";
|
||||
"nav.tasks": "Aufgaben" | "Tasks" | "Tareas" | "Tâches" | "Tugas" | "Compiti" | "Taken" | "Zadania" | "Tarefas" | "Задания" | "Görevler";
|
||||
"operationType.deposit": "Einzahlung" | "Deposit" | "Depósito" | "Dépôt" | "Setoran" | "Deposito" | "Storting" | "Wpłata" | "Пополнение" | "Yatırım";
|
||||
"operationType.greeting": "Willkommensbonus" | "Greeting bonus" | "Bono de bienvenida" | "Bonus de bienvenue" | "Bonus sambutan" | "Bonus di benvenuto" | "Welkomstbonus" | "Bonus powitalny" | "Bônus de boas-vindas" | "Приветственный бонус" | "Hoş geldin bonusu";
|
||||
"operationType.referral": "Empfehlungsbonus" | "Referral bonus" | "Bono de referido" | "Bonus de parrainage" | "Bonus referral" | "Verwijzingsbonus" | "Bonus polecający" | "Bônus de indicação" | "Реферальный бонус" | "Referans bonusu";
|
||||
"operationType.withdrawal": "Auszahlung" | "Withdrawal" | "Retiro" | "Retrait" | "Penarikan" | "Prelievo" | "Opname" | "Wypłata" | "Saque" | "Вывод" | "Çekim";
|
||||
"pagination.of": "von" | "of" | "de" | "sur" | "dari" | "di" | "van" | "z" | "из" | "/";
|
||||
"settings.accountInfo": "Kontoinformationen" | "Account information" | "Información de la cuenta" | "Informations du compte" | "Informasi akun" | "Informazioni account" | "Accountinformatie" | "Informacje o koncie" | "Informações da conta" | "Информация об аккаунте" | "Hesap bilgileri";
|
||||
"settings.back": "Zurück" | "Back" | "Volver" | "Retour" | "Kembali" | "Indietro" | "Terug" | "Wstecz" | "Voltar" | "Назад" | "Geri";
|
||||
@@ -19,5 +30,13 @@ declare const resources: {
|
||||
"settings.sound": "Ton" | "Sound" | "Sonido" | "Son" | "Suara" | "Suono" | "Geluid" | "Dźwięk" | "Som" | "Звук" | "Ses";
|
||||
"settings.support": "Support" | "Soporte" | "Dukungan" | "Supporto" | "Ondersteuning" | "Wsparcie" | "Suporte" | "Поддержка" | "Destek";
|
||||
"settings.transactionHistory": "Transaktionsverlauf" | "Transaction History" | "Historial de transacciones" | "Historique des transactions" | "Riwayat transaksi" | "Cronologia transazioni" | "Transactiegeschiedenis" | "Historia transakcji" | "Histórico de transações" | "История транзакций" | "İşlem Geçmişi";
|
||||
"support.action": "Support kontaktieren" | "Contact support" | "Contactar soporte" | "Contacter le support" | "Hubungi dukungan" | "Contatta il supporto" | "Contact opnemen" | "Skontaktuj się z pomocą" | "Contactar suporte" | "Связаться с поддержкой" | "Destek ile iletişime geç";
|
||||
"support.text": "Wenn Sie Fragen zum Spiel haben, wenden Sie sich bitte an unseren Support." | "If you have any questions related to the game, please contact our support team." | "Si tienes alguna pregunta relacionada con el juego, contacta con nuestro equipo de soporte." | "Si vous avez des questions liées au jeu, veuillez contacter notre équipe de support." | "Jika Anda memiliki pertanyaan terkait permainan, silakan hubungi tim dukungan kami." | "Se hai domande relative al gioco, contatta il nostro team di supporto." | "Als u vragen heeft over het spel, neem dan contact op met ons ondersteuningsteam." | "Jeśli masz pytania dotyczące gry, skontaktuj się z naszym zespołem wsparcia." | "Se tiver dúvidas relacionadas ao jogo, entre em contato com nossa equipe de suporte." | "Если у вас возникли вопросы, связанные с игрой — обратитесь в нашу службу поддержки." | "Oyunla ilgili sorularınız varsa lütfen destek ekibimizle iletişime geçin.";
|
||||
"support.title": "Support" | "Soporte" | "Dukungan" | "Supporto" | "Ondersteuning" | "Wsparcie" | "Suporte" | "Поддержка" | "Destek";
|
||||
"transactionHistory.date": "Datum" | "Date" | "Fecha" | "Tanggal" | "Data" | "Дата" | "Tarih";
|
||||
"transactionHistory.operationType": "Vorgangsart" | "Operation type" | "Tipo de operación" | "Type d'opération" | "Jenis operasi" | "Tipo di operazione" | "Bewerkingstype" | "Typ operacji" | "Tipo de operação" | "Тип операции" | "İşlem türü";
|
||||
"transactionHistory.sum": "Summe" | "Sum" | "Suma" | "Somme" | "Jumlah" | "Somma" | "Som" | "Soma" | "Сумма" | "Toplam";
|
||||
"transactionHistory.title": "Transaktionsverlauf" | "Transaction History" | "Historial de transacciones" | "Historique des transactions" | "Riwayat transaksi" | "Cronologia transazioni" | "Transactiegeschiedenis" | "Historia transakcji" | "Histórico de transações" | "История транзакций" | "İşlem Geçmişi";
|
||||
"transactionHistory.yourTransactions": "Ihre Transaktionen" | "Your Transactions" | "Tus transacciones" | "Vos transactions" | "Transaksi Anda" | "Le tue transazioni" | "Uw transacties" | "Twoje transakcje" | "Suas transações" | "Ваши транзакции" | "İşlemleriniz";
|
||||
};
|
||||
export default resources;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
background-image: url("./assets/main-bg.svg");
|
||||
background-size: auto 101%;
|
||||
background-position: center;
|
||||
overflow: hidden;
|
||||
|
||||
.main {
|
||||
height: 100%;
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.left {
|
||||
}
|
||||
|
||||
.avatar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -57,10 +54,4 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.rightTop {
|
||||
}
|
||||
|
||||
.rightBottom {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import classes from "./Profile.module.css";
|
||||
import { motion } from "motion/react";
|
||||
import { Liftable } from "@components/lift";
|
||||
@@ -5,6 +6,9 @@ import { useTelegramUser } from "@/tg";
|
||||
|
||||
export default function Profile() {
|
||||
const user = useTelegramUser();
|
||||
|
||||
const [satue, setSatue] = useState(1);
|
||||
|
||||
return (
|
||||
<Liftable always>
|
||||
<motion.div
|
||||
@@ -20,9 +24,13 @@ export default function Profile() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.right}>
|
||||
<div className={classes.rightTop} />
|
||||
<div className={classes.rightBottom} />
|
||||
<div>
|
||||
{satue}
|
||||
<button onClick={() => setSatue((v) => v + 1)}>+</button>
|
||||
<button onClick={() => setSatue((v) => v - 1)}>-</button>
|
||||
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
</motion.div>
|
||||
</Liftable>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
@layer base {
|
||||
.settings {
|
||||
margin-left: auto;
|
||||
width: 80px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user