237 lines
5.5 KiB
TypeScript
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>
|
|
</>
|
|
)
|
|
}
|