Files
contentstack-imagevault/rte/components/ImageEditModal.tsx

237 lines
5.5 KiB
TypeScript

import {
Button,
ButtonGroup,
Field,
FieldLabel,
ModalBody,
ModalFooter,
ModalHeader,
Select,
TextInput,
} from "@contentstack/venus-components"
import React, { ChangeEvent, useEffect, useState } from "react"
import { Path } from "slate"
import type {
IRteElementType,
IRteParam,
} from "@contentstack/app-sdk/dist/src/RTE/types"
import FocalPointPicker from "~/shared-components/FocalPointPicker"
import type { FocalPoint, InsertResponse } from "~/types/imagevault"
enum DropdownValues {
center = "center",
left = "left",
right = "right",
none = "none",
}
type DropDownItem = {
label: string
value: DropdownValues
type: string
}
const dropdownList: DropDownItem[] = [
{
label: "None",
value: DropdownValues.none,
type: "select",
},
{
label: "Center",
value: DropdownValues.center,
type: "select",
},
{
label: "Left",
value: DropdownValues.left,
type: "select",
},
{
label: "Right",
value: DropdownValues.right,
type: "select",
},
]
type ImageEditModalProps = {
element: IRteElementType & {
attrs: InsertResponse
}
rte: IRteParam
closeModal: () => void
path: Path
}
export default function ImageEditModal({
element,
closeModal,
path,
rte,
}: ImageEditModalProps) {
const [alignment, setAlignment] = useState<DropDownItem>({
label: "None",
value: DropdownValues.none,
type: "select",
})
const [altText, setAltText] = useState("")
const [caption, setCaption] = useState("")
const [focalPoint, setFocalPoint] = useState<FocalPoint>({ x: 50, y: 50 })
const assetUrl = element.attrs.MediaConversions[0].Url
useEffect(() => {
if (element.attrs.Metadata && element.attrs.Metadata.length) {
const altText = element.attrs.Metadata.find((meta) =>
meta.Name.includes("AltText_")
)?.Value
const caption = element.attrs.Metadata.find((meta) =>
meta.Name.includes("Title_")
)?.Value
setAltText(altText ?? "")
setCaption(caption ?? "")
}
}, [element.attrs.Metadata])
useEffect(() => {
if (element.attrs.FocalPoint) {
setFocalPoint(element.attrs.FocalPoint)
}
}, [element.attrs.FocalPoint])
function handleSave() {
let newStyle
switch (alignment.value) {
case DropdownValues.center:
case DropdownValues.left:
case DropdownValues.right:
newStyle = {
textAlign: alignment.value,
maxWidth: element.attrs.width
? `${element.attrs.width}px`
: undefined,
}
break
case DropdownValues.none:
default:
newStyle = {}
break
}
const metaData = element.attrs.Metadata ?? []
const newMetadata = metaData.map((meta) => {
if (meta.Name.includes("AltText_")) {
return { ...meta, Value: altText }
}
if (meta.Name.includes("Title_")) {
return { ...meta, Value: caption }
}
return meta
})
rte._adv.Transforms?.setNodes<IRteElementType>(
rte._adv.editor,
{
attrs: {
...element.attrs,
Metadata: newMetadata,
position: alignment.value,
style: { ...element.attrs.style, ...newStyle },
FocalPoint: focalPoint,
},
},
{ at: path }
)
closeModal()
}
function changeFocalPoint(focalPoint: FocalPoint) {
setFocalPoint(focalPoint)
}
return (
<>
<ModalHeader title="Update image" closeModal={closeModal} />
<ModalBody
style={{
display: "grid",
gridTemplateColumns: "1fr minmax(max-content, 250px)",
gap: "1rem",
alignItems: "center",
width: "auto",
maxHeight: "calc(90dvh - 124px)", // 124px is the height of the header and footer
maxWidth: "90dvw",
overflow: "auto",
}}
>
<FocalPointPicker
imageSrc={assetUrl}
focalPoint={focalPoint}
onChange={changeFocalPoint}
/>
<div>
<Field>
<Select
selectLabel="Alignment"
value={alignment}
onChange={(e: DropDownItem) => {
setAlignment(e)
}}
options={dropdownList}
/>
</Field>
<Field>
<FieldLabel htmlFor="alt">Alt text</FieldLabel>
<TextInput
value={altText}
placeholder="Alt text for image"
name="alt"
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setAltText(e.target.value)
}
/>
</Field>
<Field>
<FieldLabel htmlFor="caption">Caption</FieldLabel>
<TextInput
value={caption}
placeholder="Caption for image..."
name="caption"
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setCaption(e.target.value)
}
/>
</Field>
<Field>
<FieldLabel htmlFor="focalPoint">Focal Point</FieldLabel>
<TextInput
value={`X: ${focalPoint.x}, Y: ${focalPoint.y}`}
name="focalPoint"
disabled
/>
</Field>
</div>
</ModalBody>
<ModalFooter>
<ButtonGroup>
<Button onClick={closeModal} buttonType="light">
Cancel
</Button>
<Button onClick={handleSave} icon="SaveWhite">
Save
</Button>
</ButtonGroup>
</ModalFooter>
</>
)
}