Skip to content

Commit

Permalink
rework to use javascript dom query selector
Browse files Browse the repository at this point in the history
  • Loading branch information
rebeccahongsf committed Oct 9, 2024
1 parent 9fb8cb1 commit 765c5fd
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 40 deletions.
2 changes: 1 addition & 1 deletion src/components/paragraph/stanford-wysiwyg.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type Props = HTMLAttributes<HTMLDivElement> & {

const StanfordWysiwyg = ({text, ...props}: Props) => {
return (
<div className="centered relative lg:max-w-[980px]" {...props}>
<div className="wysiwyg centered relative lg:max-w-[980px]" {...props}>
{text && <>{formatHtml(text)}</>}
</div>
)
Expand Down
64 changes: 25 additions & 39 deletions src/components/patterns/on-the-page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
"use client"

import React, {useState, useEffect, useMemo} from "react"
import parse from "html-react-parser"
import React, {useState, useEffect} from "react"
import {NodeStanfordPage} from "@/lib/gql/__generated__/drupal.d"
import {ParagraphStanfordWysiwyg} from "@/lib/gql/__generated__/drupal.d"
import {twMerge} from "tailwind-merge"
import DrupalLink from "./elements/drupal-link"

Expand All @@ -13,62 +11,50 @@ interface Heading {
}

const OnThePageLink = ({node}: {node: NodeStanfordPage}) => {
const [headings, setHeadings] = useState<Heading[]>([])
const [activeHeading, setActiveHeading] = useState<string>("")
const relLinkHeading = node.sulRelLinksHeading
const relLinks = node.sulRelLinks

const headings = useMemo(() => {
const content =
node?.suPageComponents &&
node?.suPageComponents
.filter((item): item is ParagraphStanfordWysiwyg => item.__typename === "ParagraphStanfordWysiwyg")
.map(item => item.suWysiwygText && item.suWysiwygText.processed)
.join(" ")
useEffect(() => {
const wysiwygContainers: NodeListOf<Element> = document.querySelectorAll(".wysiwyg")

const parsedContent = parse(content ?? "")
const headingsArr: Heading[] = []
const allHeadings: Heading[] = []

React.Children.forEach(parsedContent, child => {
if (React.isValidElement(child) && child.type === "h2") {
const element = child as React.ReactElement
const text = element.props.children
wysiwygContainers.forEach((container, containerIndex) => {
const h2Elements: HTMLHeadingElement[] = Array.from(container.querySelectorAll("h2"))

if (typeof text === "string") {
const id = text.toLowerCase().replace(/\s+/g, "-")
headingsArr.push({text, id})
}
}
h2Elements.forEach((heading, headingIndex) => {
const id = `${heading.textContent?.trim().toLowerCase().replace(/\s+/g, "-")}-${containerIndex}-${headingIndex}`
heading.setAttribute("id", id)
allHeadings.push({text: heading.textContent || "", id})
})
})

return headingsArr
}, [node])
setHeadings(allHeadings)

useEffect(() => {
const options: IntersectionObserverInit = {
root: null,
rootMargin: "0px",
threshold: 0.5,
}

const observer = new IntersectionObserver(entries => {
const observerCallback: IntersectionObserverCallback = entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
if (entry.isIntersecting && entry.intersectionRatio > 0) {
setActiveHeading(entry.target.id)
}
})
}, options)
}

const observer = new IntersectionObserver(observerCallback, {
rootMargin: "-10px 0px 0px 0px",
threshold: 0,
})

headings.forEach(({id}) => {
const headingElement = document.getElementById(id)
if (headingElement) {
observer.observe(headingElement)
}
wysiwygContainers.forEach(container => {
const h2Elements = container.querySelectorAll("h2")
h2Elements.forEach(heading => observer.observe(heading))
})

return () => {
observer.disconnect()
}
}, [headings])
}, [])

return (
<div className="sticky top-0 h-fit max-w-300 bg-fog-light px-24 pb-40 pt-16">
Expand Down

0 comments on commit 765c5fd

Please sign in to comment.