Last active
September 18, 2024 15:19
-
-
Save kmelve/850b1b9408f967a4b99b7c3698287750 to your computer and use it in GitHub Desktop.
LinkedIn Embed Input for Sanity Studio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState } from "react" | |
import { TextInput, Stack } from "@sanity/ui" | |
import { set, unset } from "sanity" | |
interface LinkedInEmbed { | |
_key: string | |
_type: string | |
postUrl: string | |
height: number | |
} | |
export const LinkedInEmbedInput = React.forwardRef((props: any, ref) => { | |
const { onChange, value } = props | |
const [embedCode, setEmbedCode] = useState("") | |
const extractLinkedInData = ( | |
html: string | |
): Omit<LinkedInEmbed, "_key" | "_type"> | null => { | |
const parser = new DOMParser() | |
const doc = parser.parseFromString(html, "text/html") | |
const iframe = doc.querySelector("iframe") | |
if (iframe) { | |
const src = iframe.getAttribute("src") | |
const height = iframe.getAttribute("height") | |
if (src && height) { | |
return { | |
postUrl: src, | |
height: parseInt(height, 10), | |
} | |
} | |
} | |
return null | |
} | |
const handleEmbedCodeChange = ( | |
event: React.ChangeEvent<HTMLInputElement> | |
) => { | |
const newEmbedCode = event.target.value | |
setEmbedCode(newEmbedCode) | |
const data = extractLinkedInData(newEmbedCode) | |
if (data) { | |
const fullData: LinkedInEmbed = { | |
_key: value?._key, | |
_type: "linkedInEmbed", | |
...data, | |
} | |
onChange(set(fullData)) | |
} else { | |
onChange(unset()) | |
} | |
} | |
return ( | |
<Stack space={3}> | |
{value.postUrl || value.height ? ( | |
props.renderDefault(props) | |
) : ( | |
<TextInput | |
value={embedCode} | |
onChange={handleEmbedCodeChange} | |
placeholder="Paste LinkedIn embed code here" | |
/> | |
)} | |
</Stack> | |
) | |
}) | |
LinkedInEmbedInput.displayName = "LinkedInEmbedInput" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import styles from "./LinkedInEmbedPreview.module.css" | |
type LinkedInEmbedPreviewProps = { | |
postUrl: string | |
height: number | |
} | |
export const LinkedInEmbedPreview = ({ | |
postUrl, | |
height, | |
}: LinkedInEmbedPreviewProps) => { | |
return postUrl ? ( | |
<iframe | |
className={styles.iframe} | |
src={postUrl} | |
height={height || 500} | |
width="504" | |
frameborder="0" | |
allowfullscreen="" | |
title="Embedded post" | |
></iframe> | |
) : ( | |
<div>🚨 LinkedIn Post URL missing</div> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { CiLinkedin } from "react-icons/ci" | |
import { LinkedInEmbedInput } from "./LinkedInEmbedInput" | |
import { LinkedInEmbedPreview } from "./LinkedInEmbedPreview" | |
export const LinkedInEmbedType = { | |
title: "LinkedIn Embed", | |
icon: ciLinkedIn, | |
type: "object", | |
name: "linkedInEmbed", | |
description: `Paste the LinkedIn embed HTML code here. This field will automatically extract the URL.`, | |
fields: [ | |
{ | |
title: "Post URL", | |
type: "string", | |
name: "postUrl", | |
description: `URL from the LinkedIn embed code "src" attribute`, | |
validation: (Rule) => | |
Rule.custom((value) => { | |
if (!value) return true | |
// Make sure the `src` attribute follows the LinkedIn URL format | |
const linkedinUrlRegex = | |
/^https:\/\/www\.linkedin\.com\/embed\/feed\/update\/urn:li:share:[\w\d-]+$/ | |
if (!linkedinUrlRegex.test(value)) { | |
throw new Error( | |
"Invalid LinkedIn URL: The post URL does not match the LinkedIn embed URL format." | |
) | |
} | |
return true | |
}), | |
}, | |
{ | |
title: "Height", | |
type: "number", | |
name: "height", | |
description: `Height from the iframe’s "height" attribute LinkedIn gives you when you click on "Embed this post"`, | |
validation: (Rule) => Rule.required(), | |
}, | |
], | |
preview: { | |
select: { | |
postUrl: "postUrl", | |
height: "height", | |
}, | |
}, | |
components: { | |
preview: LinkedInEmbedPreview, | |
input: LinkedInEmbedInput, | |
}, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment