[chore] prettify + config prettier

This commit is contained in:
MathieuG-P
2023-07-01 22:12:47 +02:00
parent 0f85e0dcf9
commit f47a1de05e
330 changed files with 42816 additions and 41968 deletions
@@ -7,27 +7,24 @@ type Props<T> = {
tabs: BsContentNavBarTab<T>[];
renderTab: (props: DetailedHTMLProps<React.HTMLAttributes<any>, any>, tab?: BsContentNavBarTab<T>, activeTab?: BsContentNavBarTab<T>) => JSX.Element;
onTabChange?: (index: number, tab?: BsContentNavBarTab<T>) => void;
}
};
export type BsContentNavBarTab<T = unknown> = {
text: string;
icon?: BsmIconType;
extra?: T
}
export function BsContentNavBar<T>({className, tabIndex, tabs, renderTab, onTabChange}: Props<T>) {
extra?: T;
};
export function BsContentNavBar<T>({ className, tabIndex, tabs, renderTab, onTabChange }: Props<T>) {
const handleTabClick = (index: number) => {
onTabChange?.(index, tabs[index]);
}
};
return (
<nav className={`h-full grid grid-flow-row ${className ?? ""}`}>
{tabs.map((tab, i) => (
<Fragment key={JSON.stringify(tab)}>
{ renderTab({onClick: () => handleTabClick(i)}, tab, tabs[tabIndex]) }
</Fragment>
<Fragment key={JSON.stringify(tab)}>{renderTab({ onClick: () => handleTabClick(i) }, tab, tabs[tabIndex])}</Fragment>
))}
</nav>
)
);
}
@@ -14,4 +14,4 @@
100% {
transform: rotate(360deg);
}
}
}
@@ -1,17 +1,17 @@
import { CSSProperties } from "react"
import "./bsm-basic-spinner.component.css"
import { CSSProperties } from "react";
import "./bsm-basic-spinner.component.css";
type Props = {
className?: string,
style?: CSSProperties,
spinnerClassName?: string,
thikness?: string
}
className?: string;
style?: CSSProperties;
spinnerClassName?: string;
thikness?: string;
};
export function BsmBasicSpinner({className, style, spinnerClassName, thikness = "5px"}: Props) {
return (
<div className={className} style={style}>
<span className={`${spinnerClassName} loader`} style={{border: `${thikness} solid currentColor`, borderBottomColor: "transparent"}}/>
</div>
)
export function BsmBasicSpinner({ className, style, spinnerClassName, thikness = "5px" }: Props) {
return (
<div className={className} style={style}>
<span className={`${spinnerClassName} loader`} style={{ border: `${thikness} solid currentColor`, borderBottomColor: "transparent" }} />
</div>
);
}
@@ -1,4 +1,4 @@
import { BsmIcon, BsmIconType } from "../svgs/bsm-icon.component"
import { BsmIcon, BsmIconType } from "../svgs/bsm-icon.component";
import { useRef, CSSProperties, MouseEvent } from "react";
import { BsmImage } from "./bsm-image.component";
import { useTranslation } from "renderer/hooks/use-translation.hook";
@@ -6,71 +6,91 @@ import { useClickOutside } from "renderer/hooks/use-click-outside.hook";
import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
import { getCorrectTextColor } from "renderer/helpers/correct-text-color";
type BsmButtonType = "primary"|"secondary"|"success"|"cancel"|"error";
type BsmButtonType = "primary" | "secondary" | "success" | "cancel" | "error";
type Props = {
className?: string,
style?: CSSProperties,
imgClassName?: string,
iconClassName?: string,
icon?: BsmIconType,
image?: string,
text?: string,
type?: string,
active?: boolean,
withBar?: boolean,
disabled?: boolean,
onClickOutside?: React.ComponentProps<"div">["onClick"],
onClick?: React.ComponentProps<"div">["onClick"],
typeColor?:BsmButtonType,
color?: string,
title?: string,
iconColor?: string,
textClassName?: string
}
export function BsmButton({className, style, imgClassName, iconClassName, icon, image, text, type, active, withBar = true, disabled, onClickOutside, onClick, typeColor, color, title, iconColor, textClassName}: Props) {
className?: string;
style?: CSSProperties;
imgClassName?: string;
iconClassName?: string;
icon?: BsmIconType;
image?: string;
text?: string;
type?: string;
active?: boolean;
withBar?: boolean;
disabled?: boolean;
onClickOutside?: React.ComponentProps<"div">["onClick"];
onClick?: React.ComponentProps<"div">["onClick"];
typeColor?: BsmButtonType;
color?: string;
title?: string;
iconColor?: string;
textClassName?: string;
};
export function BsmButton({ className, style, imgClassName, iconClassName, icon, image, text, type, active, withBar = true, disabled, onClickOutside, onClick, typeColor, color, title, iconColor, textClassName }: Props) {
const t = useTranslation();
const {firstColor, secondColor} = useThemeColor();
const { firstColor, secondColor } = useThemeColor();
const ref = useRef(null);
useClickOutside(ref, onClickOutside);
const primaryColor = (() => {
if(typeColor === "primary"){ return firstColor; }
if(typeColor === "secondary"){ return secondColor; }
if (typeColor === "primary") {
return firstColor;
}
if (typeColor === "secondary") {
return secondColor;
}
return undefined;
})();
const textColor = (() => {
if(primaryColor){
return getCorrectTextColor(primaryColor);
if (primaryColor) {
return getCorrectTextColor(primaryColor);
}
return typeColor ? "white" : undefined;
})();
const renderTypeColor = (() => {
if(!typeColor){ return `bg-light-main-color-2 dark:bg-main-color-2 ${(!withBar && !disabled) && "hover:brightness-125"}`; }
if(typeColor === "cancel"){ return "bg-gray-500"; }
if(typeColor === "error"){ return "bg-red-500"; }
if(typeColor === "success"){ return "bg-green-500"; }
if (!typeColor) {
return `bg-light-main-color-2 dark:bg-main-color-2 ${!withBar && !disabled && "hover:brightness-125"}`;
}
if (typeColor === "cancel") {
return "bg-gray-500";
}
if (typeColor === "error") {
return "bg-red-500";
}
if (typeColor === "success") {
return "bg-green-500";
}
return "";
})();
const handleClick = (e: MouseEvent<HTMLDivElement>) => !disabled && onClick?.(e);
return (
<div ref={ref} onClick={handleClick} title={t(title)} className={`${className} overflow-hidden cursor-pointer group ${(!withBar && !disabled && (!!typeColor || !!color)) && "hover:brightness-[1.15]"} ${disabled && "brightness-75 cursor-not-allowed"} ${renderTypeColor}`} style={{...style, backgroundColor: primaryColor || color}}>
{ image && <BsmImage image={image} className={imgClassName}/> }
{ icon && <BsmIcon icon={icon} className={iconClassName ?? "h-full w-full text-gray-800 dark:text-white"} style={{color: iconColor || textColor}}/> }
{text && (type === "submit" ? <button type="submit" className={textClassName || "h-full w-full"} style={{...(!!textColor && {color: textColor})}}>{t(text)}</button> : <span className={textClassName} style={{...(!!textColor && {color: `${textColor}`})}}>{t(text)}</span>)}
{ withBar && (
<div className="absolute bottom-0 left-0 w-full h-1 bg-current" style={{color: secondColor}}>
<div className="absolute top-0 left-0 h-full w-full bg-current brightness-50"/>
<div className={`absolute top-0 left-0 h-full w-full bg-inherit -translate-x-full group-hover:translate-x-0 transition-transform shadow-center shadow-current ${active && "translate-x-0"}`}/>
<div ref={ref} onClick={handleClick} title={t(title)} className={`${className} overflow-hidden cursor-pointer group ${!withBar && !disabled && (!!typeColor || !!color) && "hover:brightness-[1.15]"} ${disabled && "brightness-75 cursor-not-allowed"} ${renderTypeColor}`} style={{ ...style, backgroundColor: primaryColor || color }}>
{image && <BsmImage image={image} className={imgClassName} />}
{icon && <BsmIcon icon={icon} className={iconClassName ?? "h-full w-full text-gray-800 dark:text-white"} style={{ color: iconColor || textColor }} />}
{text &&
(type === "submit" ? (
<button type="submit" className={textClassName || "h-full w-full"} style={{ ...(!!textColor && { color: textColor }) }}>
{t(text)}
</button>
) : (
<span className={textClassName} style={{ ...(!!textColor && { color: `${textColor}` }) }}>
{t(text)}
</span>
))}
{withBar && (
<div className="absolute bottom-0 left-0 w-full h-1 bg-current" style={{ color: secondColor }}>
<div className="absolute top-0 left-0 h-full w-full bg-current brightness-50" />
<div className={`absolute top-0 left-0 h-full w-full bg-inherit -translate-x-full group-hover:translate-x-0 transition-transform shadow-center shadow-current ${active && "translate-x-0"}`} />
</div>
)}
</div>
)
);
}
@@ -1,30 +1,37 @@
import { BsmIcon } from "../svgs/bsm-icon.component"
import { BsmIcon } from "../svgs/bsm-icon.component";
import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
import { getCorrectTextColor } from "renderer/helpers/correct-text-color"
import { getCorrectTextColor } from "renderer/helpers/correct-text-color";
import { GlowEffect } from "./glow-effect.component";
import { motion } from "framer-motion";
import { useState } from "react";
type Props = {className?:string, checked?: boolean, onChange?: (val: boolean) => void, disabled?: boolean}
export function BsmCheckbox({className, checked, onChange, disabled} : Props) {
type Props = { className?: string; checked?: boolean; onChange?: (val: boolean) => void; disabled?: boolean };
export function BsmCheckbox({ className, checked, onChange, disabled }: Props) {
const [hovered, setHovered] = useState(false);
const checkedColor = useThemeColor("first-color");
const iconColor = checkedColor && getCorrectTextColor(checkedColor);
const handleClick = () => {
if(disabled){ return; }
if (disabled) {
return;
}
onChange?.(!checked);
}
};
return (
<motion.div className={`${className} group-one`} onHoverStart={() => setHovered(true)} onHoverEnd={() => setHovered(false)}>
<GlowEffect visible={!disabled && hovered} className="!w-[calc(100%+6px)] !h-[calc(100%+6px)] !-top-[3px] !-left-[3px]"/>
<GlowEffect visible={!disabled && hovered} className="!w-[calc(100%+6px)] !h-[calc(100%+6px)] !-top-[3px] !-left-[3px]" />
<span className={`w-full h-full flex items-center justify-center rounded-md border-2 border-current overflow-hidden bg-light-main-color-3 dark:bg-main-color-1 ${disabled ? "opacity-30 cursor-not-allowed" : "cursor-pointer"}`} onClickCapture={e => {e.stopPropagation(); handleClick()}}>
<BsmIcon className="w-full h-full" icon="check" style={{color: iconColor, backgroundColor: checkedColor, visibility: checked ? "visible" : "hidden"}}/>
<span
className={`w-full h-full flex items-center justify-center rounded-md border-2 border-current overflow-hidden bg-light-main-color-3 dark:bg-main-color-1 ${disabled ? "opacity-30 cursor-not-allowed" : "cursor-pointer"}`}
onClickCapture={e => {
e.stopPropagation();
handleClick();
}}
>
<BsmIcon className="w-full h-full" icon="check" style={{ color: iconColor, backgroundColor: checkedColor, visibility: checked ? "visible" : "hidden" }} />
</span>
</motion.div>
)
);
}
@@ -1,74 +1,81 @@
import { forwardRef, useImperativeHandle, useRef, useState } from "react"
import { BsmIconType, BsmIcon } from "../svgs/bsm-icon.component"
import { BsmButton } from "./bsm-button.component"
import { useTranslation } from "renderer/hooks/use-translation.hook"
import { AnimatePresence } from "framer-motion"
import { useClickOutside } from "renderer/hooks/use-click-outside.hook"
import { forwardRef, useImperativeHandle, useRef, useState } from "react";
import { BsmIconType, BsmIcon } from "../svgs/bsm-icon.component";
import { BsmButton } from "./bsm-button.component";
import { useTranslation } from "renderer/hooks/use-translation.hook";
import { AnimatePresence } from "framer-motion";
import { useClickOutside } from "renderer/hooks/use-click-outside.hook";
export interface DropDownItem {text: string, icon?: BsmIconType, onClick?: () => void}
type Props = {
className?: string,
items?: DropDownItem[],
align?: "left"|"right"|"center",
withBar?: boolean,
icon?: BsmIconType,
buttonClassName?: string,
menuTranslationY?: string|number
children?: JSX.Element,
text?: string,
export interface DropDownItem {
text: string;
icon?: BsmIconType;
onClick?: () => void;
}
export const BsmDropdownButton = forwardRef(({className, items, align, withBar = true, icon = "settings", buttonClassName, menuTranslationY, children, text}: Props, fowardRed) => {
type Props = {
className?: string;
items?: DropDownItem[];
align?: "left" | "right" | "center";
withBar?: boolean;
icon?: BsmIconType;
buttonClassName?: string;
menuTranslationY?: string | number;
children?: JSX.Element;
text?: string;
};
const [expanded, setExpanded] = useState(false)
const t = useTranslation();
const ref = useRef(fowardRed)
useClickOutside(ref, () => setExpanded(false));
export const BsmDropdownButton = forwardRef(({ className, items, align, withBar = true, icon = "settings", buttonClassName, menuTranslationY, children, text }: Props, fowardRed) => {
const [expanded, setExpanded] = useState(false);
const t = useTranslation();
const ref = useRef(fowardRed);
useClickOutside(ref, () => setExpanded(false));
useImperativeHandle(fowardRed, () => ({
close(){
setExpanded(() => false);
},
open(){
setExpanded(() => true);
useImperativeHandle(
fowardRed,
() => ({
close() {
setExpanded(() => false);
},
open() {
setExpanded(() => true);
},
}),
[]
);
const defaultButtonClassName = "relative z-[1] p-1 rounded-md text-inherit w-full h-full shadow-md shadow-black";
const handleClickOutside = () => {
if (children) {
return;
}
}),
[],
)
const defaultButtonClassName = "relative z-[1] p-1 rounded-md text-inherit w-full h-full shadow-md shadow-black"
const handleClickOutside = () => {
if(children){ return; }
setExpanded(false);
}
};
const alignClass = (() => {
if(align === "center"){ return "right-1/2 origin-top-right translate-x-[50%]" }
if(align === "left"){ return "left-0 origin-top-left"; }
const alignClass = (() => {
if (align === "center") {
return "right-1/2 origin-top-right translate-x-[50%]";
}
if (align === "left") {
return "left-0 origin-top-left";
}
return "right-0 origin-top-right";
})()
})();
return (
<div ref={ref as unknown as React.LegacyRef<HTMLDivElement>} className={className}>
<BsmButton onClick={() => setExpanded(!expanded)} className={buttonClassName ?? defaultButtonClassName} icon={icon} active={expanded} onClickOutside={handleClickOutside} withBar={withBar} text={text}/>
<div className={`py-1 w-fit absolute cursor-pointer top-[calc(100%-4px)] rounded-md bg-inherit text-sm text-gray-800 dark:text-gray-200 shadow-md shadow-black transition-[scale] ease-in-out ${alignClass}`} style={{scale: expanded ? "1" : "0", translate: `0 ${menuTranslationY}`}}>
{ items?.map((i) => i && (
<div key={crypto.randomUUID()} onClick={() => i.onClick?.()} className="flex w-full px-3 py-2 hover:backdrop-brightness-150">
{i.icon && <BsmIcon icon={i.icon} className="h-5 w-5 mr-1 text-inherit"/>}
<span className="w-max">{t(i.text)}</span>
</div>
))}
</div>
{!!children && (
<AnimatePresence>
{expanded && (
children
return (
<div ref={ref as unknown as React.LegacyRef<HTMLDivElement>} className={className}>
<BsmButton onClick={() => setExpanded(!expanded)} className={buttonClassName ?? defaultButtonClassName} icon={icon} active={expanded} onClickOutside={handleClickOutside} withBar={withBar} text={text} />
<div className={`py-1 w-fit absolute cursor-pointer top-[calc(100%-4px)] rounded-md bg-inherit text-sm text-gray-800 dark:text-gray-200 shadow-md shadow-black transition-[scale] ease-in-out ${alignClass}`} style={{ scale: expanded ? "1" : "0", translate: `0 ${menuTranslationY}` }}>
{items?.map(
i =>
i && (
<div key={crypto.randomUUID()} onClick={() => i.onClick?.()} className="flex w-full px-3 py-2 hover:backdrop-brightness-150">
{i.icon && <BsmIcon icon={i.icon} className="h-5 w-5 mr-1 text-inherit" />}
<span className="w-max">{t(i.text)}</span>
</div>
)
)}
</AnimatePresence>
)}
</div>
)
})
</div>
{!!children && <AnimatePresence>{expanded && children}</AnimatePresence>}
</div>
);
});
@@ -1,41 +1,38 @@
import { CSSProperties, forwardRef, SyntheticEvent, useState } from "react";
type Props = {
className?: string,
image: string,
errorImage?: string,
placeholder?: string,
loading?: "lazy"|"eager",
style?: CSSProperties
title?: string,
onClick?: (e: MouseEvent) => void
}
export const BsmImage = forwardRef(({className, image, errorImage, placeholder, loading, style, title, onClick}: Props, ref) => {
className?: string;
image: string;
errorImage?: string;
placeholder?: string;
loading?: "lazy" | "eager";
style?: CSSProperties;
title?: string;
onClick?: (e: MouseEvent) => void;
};
export const BsmImage = forwardRef(({ className, image, errorImage, placeholder, loading, style, title, onClick }: Props, ref) => {
const [isLoaded, setIsLoaded] = useState(false);
image = image || (placeholder||errorImage);
image = image || placeholder || errorImage;
const styles: CSSProperties = (() => {
return {
...style,
...(!isLoaded && {backgroundImage: `url(${placeholder})`}),
...(!isLoaded && {backgroundSize: "cover"}),
...(!isLoaded && {backgroundPosition: "center"}),
}
...(!isLoaded && { backgroundImage: `url(${placeholder})` }),
...(!isLoaded && { backgroundSize: "cover" }),
...(!isLoaded && { backgroundPosition: "center" }),
};
})();
const handleError = (e: SyntheticEvent<HTMLImageElement, Event>) => {
e.currentTarget.onerror = null;
e.currentTarget.src = errorImage || "";
}
};
const handleLoaded = () => {
setIsLoaded(() => true);
}
};
return (
<img ref={ref} title={title} className={className} src={image} loading={loading} onLoad={handleLoaded} onError={handleError} style={styles} onClick={(e) => onClick?.(e)} alt=" " decoding="async"/>
)
})
return <img ref={ref} title={title} className={className} src={image} loading={loading} onLoad={handleLoaded} onError={handleError} style={styles} onClick={e => onClick?.(e)} alt=" " decoding="async" />;
});
@@ -1,24 +1,34 @@
import { LinkOpenerService } from "renderer/services/link-opener.service"
import { LinkOpenerService } from "renderer/services/link-opener.service";
type Props = {
className?: string,
href?: string,
internal?: boolean
children?: React.ReactNode,
style?: React.CSSProperties
}
export function BsmLink({className, href, children, style, internal}: Props) {
className?: string;
href?: string;
internal?: boolean;
children?: React.ReactNode;
style?: React.CSSProperties;
};
export function BsmLink({ className, href, children, style, internal }: Props) {
const linkOpener = LinkOpenerService.getInstance();
const openLink = () => {
if(!href){ return; }
if (!href) {
return;
}
linkOpener.open(href, internal);
}
};
return (
// eslint-disable-next-line jsx-a11y/anchor-is-valid -- Will be reworked later
<a className={`${className} ${href && "cursor-pointer"}`} onClick={e => {e.stopPropagation(); openLink()}} style={style}>{children}</a>
)
<a
className={`${className} ${href && "cursor-pointer"}`}
onClick={e => {
e.stopPropagation();
openLink();
}}
style={style}
>
{children}
</a>
);
}
@@ -1,46 +1,45 @@
import { getTrackBackground, Range } from "react-range"
import { getCorrectTextColor } from "renderer/helpers/correct-text-color"
import { ThemeColor, useThemeColor } from "renderer/hooks/use-theme-color.hook"
import { getTrackBackground, Range } from "react-range";
import { getCorrectTextColor } from "renderer/helpers/correct-text-color";
import { ThemeColor, useThemeColor } from "renderer/hooks/use-theme-color.hook";
type Props = {
colorType?: ThemeColor
values: number[],
onChange?: (values: number[]) => void,
onFinalChange?: (values: number[]) => void,
min: number,
max: number,
step?: number,
renderLabel?: (value: number) => JSX.Element,
colors?: string[]
}
export function BsmRange({colorType = "first-color", values, onChange, onFinalChange, min, max, renderLabel, step = 1, colors} : Props) {
colorType?: ThemeColor;
values: number[];
onChange?: (values: number[]) => void;
onFinalChange?: (values: number[]) => void;
min: number;
max: number;
step?: number;
renderLabel?: (value: number) => JSX.Element;
colors?: string[];
};
export function BsmRange({ colorType = "first-color", values, onChange, onFinalChange, min, max, renderLabel, step = 1, colors }: Props) {
const color = useThemeColor(colorType);
const labelTextColor = color && getCorrectTextColor(color);
return (
<Range
<Range
values={values}
min={min}
max={max}
step={step}
onChange={(v) => onChange?.(v)}
onFinalChange={(v) => onFinalChange?.(v)}
renderTrack={({props, children}) => (
onChange={v => onChange?.(v)}
onFinalChange={v => onFinalChange?.(v)}
renderTrack={({ props, children }) => (
<div
onMouseDown={props.onMouseDown}
onTouchStart={props.onTouchStart}
className="w-full rounded-full h-1"
{...props}
style={{
...props.style,
background: getTrackBackground({
values,
colors: colors ?? ["#ccc", color, "#ccc"],
min,
max
}),
...props.style,
background: getTrackBackground({
values,
colors: colors ?? ["#ccc", color, "#ccc"],
min,
max,
}),
}}
>
{children}
@@ -60,5 +59,5 @@ export function BsmRange({colorType = "first-color", values, onChange, onFinalCh
</div>
)}
/>
)
);
}
@@ -1,32 +1,33 @@
import equal from "fast-deep-equal";
import { ComponentProps } from "react"
import { useTranslation } from "renderer/hooks/use-translation.hook"
import { ComponentProps } from "react";
import { useTranslation } from "renderer/hooks/use-translation.hook";
type Props<T> = Omit<ComponentProps<"select">, "onChange"> & {
options?: BsmSelectOption<T>[],
selected?: T,
onChange?: (value: T) => void,
}
options?: BsmSelectOption<T>[];
selected?: T;
onChange?: (value: T) => void;
};
export function BsmSelect<T = unknown>(props: Props<T>) {
const t = useTranslation();
const handleChange: ComponentProps<"select">["onChange"] = (e) => {
const handleChange: ComponentProps<"select">["onChange"] = e => {
e.preventDefault();
props.onChange?.(props.options?.[parseInt(e.target.value)]?.value);
}
};
return (
<select {...props} onChange={handleChange} defaultValue={props.options?.findIndex(opt => equal(opt.value, props.selected))}>
{props.options?.map((option, index) => (
<option key={JSON.stringify(option)} value={index}>{t(option.text)}</option>
<option key={JSON.stringify(option)} value={index}>
{t(option.text)}
</option>
))}
</select>
)
);
}
export interface BsmSelectOption<T>{
text: string,
value: T
export interface BsmSelectOption<T> {
text: string;
value: T;
}
@@ -1,14 +1,10 @@
import { AnimatePresence, motion } from "framer-motion"
import { AnimatePresence, motion } from "framer-motion";
type Props = {
visible?: boolean,
className?: string
}
visible?: boolean;
className?: string;
};
export function GlowEffect({visible, className}: Props) {
return (
<AnimatePresence>
{visible && <motion.div transition={{duration: .1}} initial={{opacity: 0}} animate={{opacity: 1}} exit={{opacity: 0}} className={`${className} glow-on-hover`}/>}
</AnimatePresence>
)
export function GlowEffect({ visible, className }: Props) {
return <AnimatePresence>{visible && <motion.div transition={{ duration: 0.1 }} initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className={`${className} glow-on-hover`} />}</AnimatePresence>;
}
@@ -1,12 +1,11 @@
import { AnimatePresence, motion } from "framer-motion";
import { useRef } from "react";
import { useClickOutside } from "renderer/hooks/use-click-outside.hook";
import { useObservable } from "renderer/hooks/use-observable.hook"
import { useObservable } from "renderer/hooks/use-observable.hook";
import { LinkOpenerService } from "renderer/services/link-opener.service";
export function BsmIframeView() {
const linkService = LinkOpenerService.getInstance()
const linkService = LinkOpenerService.getInstance();
const iframeUrl = useObservable(linkService.iframeLink$);
const ref = useRef(null);
@@ -16,13 +15,12 @@ export function BsmIframeView() {
<AnimatePresence>
{iframeUrl && (
<div className="top-0 absolute w-screen h-screen flex content-center items-center justify-center z-[150]">
<motion.span className="absolute w-full h-full bg-black top-0 right-0" initial={{opacity: 0}} animate={{opacity: .60}} exit={{opacity: 0}} transition={{duration: .2}}/>
<motion.div ref={ref} className="z-[1] w-[calc(100vw-250px)] h-[calc(100vh-250px)] shadow-black shadow-md rounded-md overflow-hidden bg-black" initial={{y: "100vh"}} animate={{y: 0}} exit={{y: "100vh"}}>
<iframe className="w-full h-full" src={iframeUrl}/>
<motion.span className="absolute w-full h-full bg-black top-0 right-0" initial={{ opacity: 0 }} animate={{ opacity: 0.6 }} exit={{ opacity: 0 }} transition={{ duration: 0.2 }} />
<motion.div ref={ref} className="z-[1] w-[calc(100vw-250px)] h-[calc(100vh-250px)] shadow-black shadow-md rounded-md overflow-hidden bg-black" initial={{ y: "100vh" }} animate={{ y: 0 }} exit={{ y: "100vh" }}>
<iframe className="w-full h-full" src={iframeUrl} />
</motion.div>
</div>
)}
</AnimatePresence>
)
);
}
@@ -3,15 +3,14 @@ import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
import { useTranslation } from "renderer/hooks/use-translation.hook";
type Props = {
tabIndex: number
tabsText: string[],
onTabChange: (index: number) => void,
className?: string,
renderTab?: (props: DetailedHTMLProps<React.HTMLAttributes<any>, any>, text: string, index?: number) => JSX.Element
}
tabIndex: number;
tabsText: string[];
onTabChange: (index: number) => void;
className?: string;
renderTab?: (props: DetailedHTMLProps<React.HTMLAttributes<any>, any>, text: string, index?: number) => JSX.Element;
};
export function TabNavBar(props: Props) {
const currentIndex = props.tabIndex ?? 0;
const t = useTranslation();
@@ -19,26 +18,25 @@ export function TabNavBar(props: Props) {
const selectTab = (index: number) => {
props.onTabChange(index);
}
};
return (
<nav className={`relative h-8 shrink-0 cursor-pointer rounded-md overflow-hidden shadow-md shadow-black bg-light-main-color-2 dark:bg-main-color-2 ${props.className}`}>
<div className="absolute w-full h-1 bottom-0" style={{color: secondColor}}>
<div className="absolute w-full h-1 bottom-0" style={{ color: secondColor }}>
<span className="absolute h-full w-full bg-current brightness-50" />
<span className="absolute h-full block bg-current transition-transform duration-300 shadow-center shadow-current" style={{transform: `translate(${currentIndex * 100}%, 0)`, width: `calc(100% / ${props.tabsText.length})`}}/>
<span className="absolute h-full block bg-current transition-transform duration-300 shadow-center shadow-current" style={{ transform: `translate(${currentIndex * 100}%, 0)`, width: `calc(100% / ${props.tabsText.length})` }} />
</div>
<ul className="grid" style={{gridTemplateColumns: `repeat(${props.tabsText.length}, minmax(0, 1fr))`}}>
{props.tabsText.map((text, index) => (
props.renderTab ? (
<Fragment key={text}>
{props.renderTab({onClick: () => selectTab(index)}, t(text), index)}
</Fragment>
) : (
<li className="px-4 h-full text-center text-gray-800 dark:text-gray-200 text-lg font-bold hover:backdrop-brightness-75" key={text} onClick={() => selectTab(index)}>{t(text)}</li>
)
))}
<ul className="grid" style={{ gridTemplateColumns: `repeat(${props.tabsText.length}, minmax(0, 1fr))` }}>
{props.tabsText.map((text, index) =>
props.renderTab ? (
<Fragment key={text}>{props.renderTab({ onClick: () => selectTab(index) }, t(text), index)}</Fragment>
) : (
<li className="px-4 h-full text-center text-gray-800 dark:text-gray-200 text-lg font-bold hover:backdrop-brightness-75" key={text} onClick={() => selectTab(index)}>
{t(text)}
</li>
)
)}
</ul>
</nav>
)
);
}