Spaces:
Running
Running
import classNames from "classnames"; | |
import { useState } from "react"; | |
import { | |
faChevronDown, | |
faChevronRight, | |
faTrash, | |
faCaretDown, | |
faCaretUp, | |
} from "@fortawesome/free-solid-svg-icons"; | |
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | |
import { ColorPicker } from "components/color-picker"; | |
import { Range } from "components/range"; | |
import { UploadImage } from "@/components/upload"; | |
import { Switch } from "@/components/switch"; | |
import { login, useUser } from "@/utils/auth"; | |
import { Premium } from "@/components/premium"; | |
import { PremiumOverlay } from "@/components/premium/overlay"; | |
import { FormattedMessage, useIntl } from "react-intl"; | |
import { Label } from "@/components/label"; | |
export const ShapeSelected = ({ | |
shape, | |
handleChange, | |
onDelete, | |
}: { | |
shape: any; | |
handleChange: (s: any) => void; | |
onDelete: () => void; | |
}) => { | |
const { user } = useUser(); | |
const intl = useIntl(); | |
const [open, setOpen] = useState(true); | |
return ( | |
<div | |
className={classNames( | |
"mt-5 bg-dark-600 w-full rounded-lg pl-4 py-4 pr-6 cursor-pointer transition-all border-2 border-dark-600 duration-200 hover:border-blue", | |
{ | |
"border-blue": open, | |
} | |
)} | |
> | |
<div | |
className="tracking-wider flex items-center justify-between gap-4" | |
onClick={() => setOpen(!open)} | |
> | |
<p className="text-white font-semibold"> | |
<FormattedMessage id="iconsEditor.editor.shape.update.title" /> | |
</p> | |
<div className="flex items-center justify-end gap-4"> | |
<div | |
className="bg-danger bg-opacity-60 rounded-lg text-white hover:bg-opacity-100 cursor-pointer w-8 h-8 flex items-center justify-center" | |
onClick={(e: any) => { | |
e.preventDefault(); | |
e.stopPropagation(); | |
onDelete(); | |
}} | |
> | |
<FontAwesomeIcon icon={faTrash} className="w-4" /> | |
</div> | |
<div className="w-4 flex items-center justify-end"> | |
<FontAwesomeIcon | |
icon={open ? faChevronDown : faChevronRight} | |
className="text-dark-100 transition-all duration-200" | |
/> | |
</div> | |
</div> | |
</div> | |
{open && ( | |
<div className="border-t border-dark-400 pt-3 mt-4 grid grid-cols-2 gap-4"> | |
<div className="w-full col-span-2"> | |
<Label className="!mb-2"> | |
<FormattedMessage id="iconsEditor.editor.customisation.rotation" /> | |
</Label> | |
<div className="flex items-center gap-3 w-full"> | |
<p className="font-semibold uppercase text-dark-200 text-xs">Z</p> | |
<Range | |
value={shape?.position?.angle ?? 0} | |
max={360} | |
onChange={(value) => { | |
const newShape = { | |
...shape, | |
position: { ...shape.position, angle: Number(value) }, | |
}; | |
handleChange(newShape); | |
}} | |
/> | |
<input | |
type="number" | |
className="w-full bg-dark-500 rounded px-2 py-2 text-sm text-white placeholder-dark-200 outline-none border-none" | |
placeholder={intl.formatMessage({ | |
id: "iconsEditor.editor.customisation.angle", | |
})} | |
value={shape?.position?.angle} | |
onChange={({ target }) => { | |
const newShape = { | |
...shape, | |
position: { | |
...shape.position, | |
angle: target.value | |
? Number(target.value) > 360 | |
? 360 | |
: Number(target.value) | |
: undefined, | |
}, | |
}; | |
handleChange(newShape); | |
}} | |
/> | |
</div> | |
</div> | |
{shape?.component === "Square" && ( | |
<div className="w-full col-span-2"> | |
<Label className="!mb-2"> | |
<FormattedMessage id="iconsEditor.editor.customisation.radius" /> | |
</Label> | |
<div className="flex items-center gap-3 w-full"> | |
<p className="font-semibold uppercase text-dark-200 text-xs"> | |
Z | |
</p> | |
<Range | |
value={shape?.radius ?? 0} | |
max={120} | |
onChange={(value) => { | |
const newShape = { | |
...shape, | |
radius: Number(value), | |
}; | |
handleChange(newShape); | |
}} | |
/> | |
<input | |
type="number" | |
className="w-full bg-dark-500 rounded px-2 py-2 text-sm text-white placeholder-dark-200 outline-none border-none" | |
placeholder={intl.formatMessage({ | |
id: "iconsEditor.editor.customisation.angle", | |
})} | |
value={shape?.radius} | |
onChange={({ target }) => { | |
const newShape = { | |
...shape, | |
radius: Number(target.value), | |
}; | |
handleChange(newShape); | |
}} | |
/> | |
</div> | |
</div> | |
)} | |
<div className="col-span-2"> | |
<div className="flex items-center justify-start gap-3 mb-2.5 "> | |
<Label className=""> | |
<FormattedMessage | |
id="iconsEditor.editor.customisation.gradientColor" | |
values={{ | |
span: (t) => ( | |
<span className="text-xs opacity-40">{t}</span> | |
), | |
}} | |
/> | |
</Label> | |
<Switch | |
value={!shape?.transparency} | |
onChange={(transparency: boolean) => { | |
const newShape = { | |
...shape, | |
transparency: !transparency, | |
}; | |
handleChange(newShape); | |
}} | |
/> | |
</div> | |
<ColorPicker | |
value={shape?.stringColor ?? shape?.colour} | |
data={shape} | |
onChange={(c: any, datas) => { | |
let newShape = { ...shape, stringColor: c }; | |
if (c.includes("gradient")) { | |
const { colors, degrees } = datas; | |
const gradientType = c?.startsWith("linear") | |
? "linearGradient" | |
: "radialGradient"; | |
const angle = c?.startsWith("linear") | |
? c?.replace("linear-gradient(", "")?.split("deg")?.[0] | |
: 90; | |
newShape["gradient"] = { | |
...newShape.gradient, | |
enabled: true, | |
colours: colors, | |
angle, | |
type: gradientType, | |
}; | |
} else { | |
newShape = { | |
...newShape, | |
colour: c, | |
gradient: { | |
...shape?.gradient, | |
enabled: false, | |
}, | |
}; | |
} | |
handleChange(newShape); | |
}} | |
/> | |
</div> | |
<div className="col-span-2 grid grid-cols-2 gap-4 relative"> | |
<div className="col-span-2"> | |
<div className="flex items-center justify-start gap-3 mb-2.5 "> | |
<Label className=""> | |
<FormattedMessage id="iconsEditor.editor.customisation.backgroundImage" /> | |
</Label> | |
<Switch | |
value={shape?.image?.enabled} | |
onChange={(enabled: boolean) => { | |
const newShape = { | |
...shape, | |
image: { | |
...shape.image, | |
enabled, | |
}, | |
}; | |
handleChange(newShape); | |
}} | |
/> | |
</div> | |
{shape?.image?.enabled && ( | |
<UploadImage | |
values={shape?.image?.urls} | |
onChange={(urls: string) => { | |
const newShape = { | |
...shape, | |
image: { | |
...shape.image, | |
urls, | |
}, | |
}; | |
handleChange(newShape); | |
}} | |
/> | |
)} | |
</div> | |
<div> | |
<Label className="!mb-2.5"> | |
<FormattedMessage id="iconsEditor.editor.customisation.border" /> | |
</Label> | |
<div className="flex items-start justify-start gap-5"> | |
<div className="w-full"> | |
<p className="font-semibold uppercase text-dark-200 text-xs mb-2"> | |
<FormattedMessage id="iconsEditor.editor.customisation.width" /> | |
</p> | |
<input | |
type="number" | |
className="bg-dark-500 w-full rounded px-4 py-2 text-sm text-white placeholder-dark-200 outline-none border-none" | |
placeholder={ | |
intl.formatMessage({ | |
id: "iconsEditor.editor.customisation.width", | |
}) + "...px" | |
} | |
min={0} | |
value={shape?.border?.width} | |
onChange={({ target }) => { | |
const newShape = { | |
...shape, | |
border: { | |
...shape.border, | |
width: target?.value | |
? Number(target.value) | |
: undefined, | |
}, | |
}; | |
handleChange(newShape); | |
}} | |
/> | |
</div> | |
<div> | |
<p className="font-semibold uppercase text-dark-200 text-xs mb-2"> | |
<FormattedMessage id="iconsEditor.editor.customisation.color" /> | |
</p> | |
<ColorPicker | |
value={shape?.border?.colour} | |
gradients={false} | |
onChange={(c: any) => { | |
const newShape = { | |
...shape, | |
border: { | |
...shape.border, | |
colour: c, | |
}, | |
}; | |
handleChange(newShape); | |
}} | |
/> | |
</div> | |
</div> | |
</div> | |
<PremiumOverlay /> | |
</div> | |
</div> | |
)} | |
</div> | |
); | |
}; | |