File manager - Edit - /var/www/payraty/helpdesk/common/resources/client/background-selector/gradient-background-tab.tsx
Back
import {Trans} from '@common/i18n/trans'; import {DialogTrigger} from '@common/ui/overlays/dialog/dialog-trigger'; import {GradientIcon} from '@common/icons/material/Gradient'; import {Dialog} from '@common/ui/overlays/dialog/dialog'; import {DialogHeader} from '@common/ui/overlays/dialog/dialog-header'; import {DialogBody} from '@common/ui/overlays/dialog/dialog-body'; import {DialogFooter} from '@common/ui/overlays/dialog/dialog-footer'; import {Button} from '@common/ui/buttons/button'; import {useDialogContext} from '@common/ui/overlays/dialog/dialog-context'; import {useCallback, useState} from 'react'; import clsx from 'clsx'; import {ColorPickerDialog} from '@common/ui/color-picker/color-picker-dialog'; import {IconButton} from '@common/ui/buttons/icon-button'; import {ArrowDownwardIcon} from '@common/icons/material/ArrowDownward'; import {ArrowForwardIcon} from '@common/icons/material/ArrowForward'; import {Tooltip} from '@common/ui/tooltip/tooltip'; import {ArrowUpwardIcon} from '@common/icons/material/ArrowUpward'; import { BaseGradientBg, GradientBackgrounds, } from '@common/background-selector/gradient-backgrounds'; import {BackgroundSelectorButton} from '@common/background-selector/background-selector-button'; import {BgSelectorTabProps} from '@common/background-selector/bg-selector-tab-props'; import {BackgroundSelectorConfig} from '@common/background-selector/background-selector-config'; export function GradientBackgroundTab({ value, onChange, className, isInsideDialog, }: BgSelectorTabProps<BackgroundSelectorConfig>) { return ( <div className={className}> <CustomGradientButton value={value} onChange={onChange} isInsideDialog={isInsideDialog} /> {GradientBackgrounds.map(gradient => ( <BackgroundSelectorButton key={gradient.backgroundImage} label={gradient.label && <Trans {...gradient.label} />} isActive={value?.id === gradient.id} style={{backgroundImage: gradient.backgroundImage}} onClick={() => { onChange?.({ ...BaseGradientBg, ...gradient, }); }} /> ))} </div> ); } function CustomGradientButton({ value, onChange, isInsideDialog, }: BgSelectorTabProps<BackgroundSelectorConfig>) { const isCustomGradient = value?.id === BaseGradientBg.id; return ( <DialogTrigger type="popover" value={value} onValueChange={newValue => onChange?.(newValue)} alwaysReturnCurrentValueOnClose={isInsideDialog} onOpenChange={isOpen => { // on dialog open set default gradient as active, if no other gradient is selected if (isOpen && !value) { onChange?.(GradientBackgrounds[0]); } }} onClose={gradient => onChange?.(gradient)} > <BackgroundSelectorButton label={<Trans {...BaseGradientBg.label} />} className="border-2 border-dashed" style={{ backgroundImage: isCustomGradient ? value?.backgroundImage : undefined, }} > <span className="inline-block rounded bg-black/20 p-10 text-white"> <GradientIcon size="lg" /> </span> </BackgroundSelectorButton> <CustomGradientDialog hideFooter={isInsideDialog} /> </DialogTrigger> ); } interface CustomGradientState { colorOne: string; colorTwo: string; angle: string; } interface CustomGradientDialogProps { hideFooter?: boolean; } function CustomGradientDialog({hideFooter}: CustomGradientDialogProps) { const { close, value: dialogValue, setValue, } = useDialogContext<BackgroundSelectorConfig>(); const [state, setLocalState] = useState<CustomGradientState>(() => { const parts = dialogValue?.backgroundImage?.match(/\(([0-9]+deg),.?(.+?),.?(.+?)\)/) || []; return { angle: parts[1] || '45deg', colorOne: parts[2] || '#ff9a9e', colorTwo: parts[3] || '#fad0c4', }; }); const buildGradientBackground = (s: CustomGradientState) => { return { ...BaseGradientBg, backgroundImage: `linear-gradient(${s.angle}, ${s.colorOne}, ${s.colorTwo})`, }; }; const setState = useCallback( (newValues: Partial<CustomGradientState>) => { const newState = { ...state, ...newValues, }; setLocalState(newState); setValue(buildGradientBackground(newState)); }, [state, setValue], ); return ( <Dialog size="sm"> <DialogHeader> <Trans message="Custom gradient" /> </DialogHeader> <DialogBody> <div className="mb-6"> <Trans message="Colors" /> </div> <div className="mb-20 flex h-40 items-stretch"> <ColorPickerButton className="rounded-input" value={state.colorOne} onChange={value => setState({colorOne: value})} /> <div className="flex-auto border-y border-[#c3cbdc]" style={{ backgroundImage: buildGradientBackground(state).backgroundImage, }} /> <ColorPickerButton className="rounded-r-input" value={state.colorTwo} onChange={value => setState({colorTwo: value})} /> </div> <div className="mb-6"> <Trans message="Direction" /> </div> <DirectionButtons value={state.angle} onChange={value => setState({angle: value})} /> </DialogBody> {!hideFooter && ( <DialogFooter dividerTop> <Button onClick={() => close()}> <Trans message="Cancel" /> </Button> <Button variant="flat" color="primary" onClick={() => close(buildGradientBackground(state))} > <Trans message="Apply" /> </Button> </DialogFooter> )} </Dialog> ); } interface ColorPickerButtonProps { className: string; value: string; onChange: (value: string) => void; } function ColorPickerButton({ className, value, onChange, }: ColorPickerButtonProps) { return ( <DialogTrigger type="popover" value={value} onValueChange={onChange} alwaysReturnCurrentValueOnClose > <Tooltip label={<Trans message="Click to change color" />}> <button type="button" className={clsx( 'w-40 flex-shrink-0 border border-[#c3cbdc]', className, )} style={{backgroundColor: value}} /> </Tooltip> <ColorPickerDialog hideFooter /> </DialogTrigger> ); } interface DirectionButtonsProps { value: string; onChange: (value: string) => void; } function DirectionButtons({value, onChange}: DirectionButtonsProps) { const activeStyle = 'text-primary border-primary'; return ( <div className="flex flex-wrap items-center gap-8 text-muted"> <IconButton variant="outline" className={value === '0deg' ? activeStyle : undefined} onClick={() => onChange('0deg')} > <ArrowUpwardIcon /> </IconButton> <IconButton variant="outline" className={value === '180deg' ? activeStyle : undefined} onClick={() => onChange('180deg')} > <ArrowDownwardIcon /> </IconButton> <IconButton variant="outline" className={value === '90deg' ? activeStyle : undefined} onClick={() => onChange('90deg')} > <ArrowForwardIcon /> </IconButton> <IconButton variant="outline" className={value === '135deg' ? activeStyle : undefined} onClick={() => onChange('135deg')} > <ArrowDownwardIcon className="-rotate-45" /> </IconButton> <IconButton variant="outline" className={value === '225deg' ? activeStyle : undefined} onClick={() => onChange('225deg')} > <ArrowDownwardIcon className="rotate-45" /> </IconButton> <IconButton variant="outline" className={value === '45deg' ? activeStyle : undefined} onClick={() => onChange('45deg')} > <ArrowUpwardIcon className="rotate-45" /> </IconButton> <IconButton variant="outline" className={value === '325deg' ? activeStyle : undefined} onClick={() => onChange('325deg')} > <ArrowUpwardIcon className="-rotate-45" /> </IconButton> </div> ); }
| ver. 1.4 |
Github
|
.
| PHP 8.3.30 | Generation time: 1.19 |
proxy
|
phpinfo
|
Settings