add filters panel (partial)

This commit is contained in:
MathieuG-P
2022-11-20 00:54:30 +01:00
parent bbbbf50551
commit f815695298
14 changed files with 275 additions and 150 deletions
@@ -1,16 +1,16 @@
import { BsmIcon, BsmIconType } from "../svgs/bsm-icon.component"
import OutsideClickHandler from 'react-outside-click-handler';
import React, { MutableRefObject, Ref } from "react";
import { useEffect, useRef, CSSProperties } from "react";
import { BsmImage } from "./bsm-image.component";
import { useTranslation } from "renderer/hooks/use-translation.hook";
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"|"success"|"cancel"|"error";
type propsType = {
type Props = {
className?: string,
style?: React.CSSProperties,
style?: CSSProperties,
imgClassName?: string,
iconClassName?: string,
icon?: BsmIconType,
@@ -26,43 +26,43 @@ type propsType = {
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}: propsType) {
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 secondColor = useThemeColor("second-color");
const t = useTranslation();
const secondColor = useThemeColor("second-color");
const ref = useRef(null);
useClickOutside(ref, onClickOutside);
const primaryColor = typeColor === "primary" && useThemeColor("first-color");
const primaryColor = typeColor === "primary" && useThemeColor("first-color");
const textColor = (() => {
if(primaryColor){ return getCorrectTextColor(primaryColor); }
return typeColor ? "white" : undefined;
})();
const textColor = (() => {
if(primaryColor){ return getCorrectTextColor(primaryColor); }
return typeColor ? "white" : undefined;
})();
const renderTypeColor = (() => {
if(typeColor === "primary"){ return ""; }
if(!typeColor){ return `bg-light-main-color-2 dark:bg-main-color-2 ${!withBar && "hover:bg-light-main-color-3 dark:hover:bg-main-color-3"}`; }
if(typeColor === "cancel"){ return "bg-gray-500"; }
if(typeColor === "error"){ return "bg-red-500"; }
if(typeColor === "success"){ return "bg-green-500"; }
return "";
})()
const renderTypeColor = (() => {
if(typeColor === "primary"){ return ""; }
if(!typeColor){ return `bg-light-main-color-2 dark:bg-main-color-2 ${!withBar && "hover:bg-light-main-color-3 dark:hover:bg-main-color-3"}`; }
if(typeColor === "cancel"){ return "bg-gray-500"; }
if(typeColor === "error"){ return "bg-red-500"; }
if(typeColor === "success"){ return "bg-green-500"; }
return "";
})();
return (
<OutsideClickHandler onOutsideClick={e => onClickOutside && onClickOutside(e)}>
<div onClick={onClick} 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}}/> }
{text && (type === "submit" ? <button type="submit" className="w-full h-full" style={{...(!!textColor && {color: textColor})}}>{t(text)}</button> : <span 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>
</OutsideClickHandler>
)
return (
<div ref={ref} onClick={onClick} 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}}/> }
{text && (type === "submit" ? <button type="submit" className={textClassName || "h-full w-full"} style={{...(!!textColor && {color: textColor})}}>{t(text)}</button> : <span 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,31 +1,58 @@
import { useState } from "react"
import { BsmIconType } from "../svgs/bsm-icon.component"
import { useRef, useState } from "react"
import { BsmIconType, BsmIcon } from "../svgs/bsm-icon.component"
import { BsmButton } from "./bsm-button.component"
import { BsmIcon } from "../svgs/bsm-icon.component"
import { useTranslation } from "renderer/hooks/use-translation.hook"
import { AnimatePresence } from "framer-motion"
import { v4 as uuidv4 } from 'uuid';
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", withBar?: boolean, icon?: BsmIconType, buttonClassName?: string, menuTranslationY?: string|number}
type Props = {
className?: string,
items?: DropDownItem[],
align?: "left"|"right",
withBar?: boolean,
icon?: BsmIconType,
buttonClassName?: string,
menuTranslationY?: string|number
children?: JSX.Element,
text?: string,
textClassName?: string
}
export function BsmDropdownButton({className, items, align, withBar = true, icon = "settings", buttonClassName, menuTranslationY}: Props) {
export function BsmDropdownButton({className, items, align, withBar = true, icon = "settings", buttonClassName, menuTranslationY, children, text, textClassName}: Props) {
const [expanded, setExpanded] = useState(false)
const t = useTranslation();
const ref = useRef(null)
useClickOutside(ref, () => setExpanded(false));
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);
}
return (
<div className={`${className}`}>
<BsmButton onClick={() => setExpanded(!expanded)} className={buttonClassName ?? defaultButtonClassName} icon={icon} active={expanded} onClickOutside={() => {setExpanded(false)}} withBar={withBar}/>
<div ref={ref} 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 ${align === "left" ? "left-0 origin-top-left" : "right-0 origin-top-right"}`} style={{scale: expanded ? "1" : "0", translate: `0 ${menuTranslationY}`}}>
{ items?.map((i, index) => !!i &&(
<div key={index} onClick={!!i.onClick ? i.onClick : undefined} 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"></BsmIcon>}
{ items?.map((i) => (
<div key={uuidv4()} 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
)}
</AnimatePresence>
)}
</div>
)
}