Fix the about page image display
This commit is contained in:
@ -5,6 +5,7 @@ import { saveAboutMeAction } from "@/actions/about/saveAbout";
|
|||||||
import { BasicBlocksKit } from "@/components/editor/plugins/basic-blocks-kit";
|
import { BasicBlocksKit } from "@/components/editor/plugins/basic-blocks-kit";
|
||||||
import { BasicMarksKit } from "@/components/editor/plugins/basic-marks-kit";
|
import { BasicMarksKit } from "@/components/editor/plugins/basic-marks-kit";
|
||||||
import { CodeBlockKit } from "@/components/editor/plugins/code-block-kit";
|
import { CodeBlockKit } from "@/components/editor/plugins/code-block-kit";
|
||||||
|
import { ImageKit } from "@/components/editor/plugins/image-kit";
|
||||||
import { ListKit } from "@/components/editor/plugins/list-kit";
|
import { ListKit } from "@/components/editor/plugins/list-kit";
|
||||||
import { MarkdownKit } from "@/components/editor/plugins/markdown-kit";
|
import { MarkdownKit } from "@/components/editor/plugins/markdown-kit";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@ -43,6 +44,7 @@ export default function AboutEditor({ markdown }: { markdown: string | null }) {
|
|||||||
plugins: [
|
plugins: [
|
||||||
...BasicBlocksKit,
|
...BasicBlocksKit,
|
||||||
...CodeBlockKit,
|
...CodeBlockKit,
|
||||||
|
...ImageKit,
|
||||||
...ListKit,
|
...ListKit,
|
||||||
...BasicMarksKit,
|
...BasicMarksKit,
|
||||||
...MarkdownKit,
|
...MarkdownKit,
|
||||||
|
|||||||
15
src/components/editor/plugins/image-kit.tsx
Normal file
15
src/components/editor/plugins/image-kit.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { createPlatePlugin } from 'platejs/react';
|
||||||
|
|
||||||
|
import { ImageElement } from '@/components/ui/image-node';
|
||||||
|
|
||||||
|
// Minimal image plugin to render markdown images.
|
||||||
|
export const ImageKit = [
|
||||||
|
createPlatePlugin({
|
||||||
|
key: 'img',
|
||||||
|
node: {
|
||||||
|
isElement: true,
|
||||||
|
},
|
||||||
|
}).withComponent(ImageElement),
|
||||||
|
];
|
||||||
76
src/components/ui/image-node.tsx
Normal file
76
src/components/ui/image-node.tsx
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import type { PlateElementProps } from 'platejs/react';
|
||||||
|
|
||||||
|
import { PlateElement, useEditorRef, useFocused, useReadOnly, useSelected, useElement } from 'platejs/react';
|
||||||
|
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
|
type ImageElementData = {
|
||||||
|
url?: string;
|
||||||
|
src?: string;
|
||||||
|
alt?: string;
|
||||||
|
altText?: string;
|
||||||
|
caption?: { text: string }[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ImageElement(props: PlateElementProps) {
|
||||||
|
const editor = useEditorRef();
|
||||||
|
const element = useElement<ImageElementData>();
|
||||||
|
const readOnly = useReadOnly();
|
||||||
|
const selected = useSelected();
|
||||||
|
const focused = useFocused();
|
||||||
|
const data = element ?? (props.element as ImageElementData);
|
||||||
|
const src = data.url ?? data.src;
|
||||||
|
const captionText =
|
||||||
|
data.caption?.map((c) => c.text).join('') ?? data.alt ?? data.altText ?? '';
|
||||||
|
const showCaptionEditor = !readOnly;
|
||||||
|
const path = showCaptionEditor ? editor.api.findPath(element) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PlateElement {...props} className={cn('my-4')}>
|
||||||
|
<figure className="w-full">
|
||||||
|
{src ? (
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
alt={captionText}
|
||||||
|
className="max-w-full rounded-md border border-border"
|
||||||
|
loading="lazy"
|
||||||
|
contentEditable={false}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="text-sm text-muted-foreground">Missing image source</div>
|
||||||
|
)}
|
||||||
|
<figcaption
|
||||||
|
className="mt-2"
|
||||||
|
contentEditable={false}
|
||||||
|
onMouseDown={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{showCaptionEditor ? (
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={captionText}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (!path) return;
|
||||||
|
editor.tf.setNodes<ImageElementData>(
|
||||||
|
{ caption: [{ text: e.target.value }] },
|
||||||
|
{ at: path }
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
placeholder="Add caption / alt text"
|
||||||
|
className="w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground"
|
||||||
|
onMouseDown={(e) => e.stopPropagation()}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
onFocus={(e) => e.stopPropagation()}
|
||||||
|
/>
|
||||||
|
) : captionText ? (
|
||||||
|
<div className="text-xs text-muted-foreground">{captionText}</div>
|
||||||
|
) : null}
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
{props.children}
|
||||||
|
</PlateElement>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user