From cd027940b8750da114b2c164e6f19c92b2112386 Mon Sep 17 00:00:00 2001 From: Rodrigo Pombo Date: Thu, 26 Dec 2024 17:10:24 +0100 Subject: [PATCH 1/2] Split focus annotation example --- apps/web/content/docs/code/focus.mdx | 31 +++++++------ apps/web/demos/focus/code.tsx | 65 +++------------------------ apps/web/demos/focus/focus.client.tsx | 41 +++++++++++++++++ apps/web/demos/focus/focus.tsx | 17 +++++++ 4 files changed, 80 insertions(+), 74 deletions(-) create mode 100644 apps/web/demos/focus/focus.client.tsx create mode 100644 apps/web/demos/focus/focus.tsx diff --git a/apps/web/content/docs/code/focus.mdx b/apps/web/content/docs/code/focus.mdx index 93f74254..f2c1c166 100644 --- a/apps/web/content/docs/code/focus.mdx +++ b/apps/web/content/docs/code/focus.mdx @@ -20,25 +20,14 @@ We need two things: - Get a `ref` of the `pre` element, and scroll it if needed ```tsx focus.tsx -c -"use client" - -import { - AnnotationHandler, - InnerPre, - getPreRef, - InnerLine, -} from "codehike/code" -import React, { useLayoutEffect, useRef } from "react" // !fold[/className="(.*?)"/gm] +import { AnnotationHandler, InnerLine } from "codehike/code" +import { PreWithFocus } from "./focus.client" export const focus: AnnotationHandler = { name: "focus", onlyIfAnnotated: true, - PreWithRef: (props) => { - const ref = getPreRef(props) - useScrollToFocus(ref) - return - }, + PreWithRef: PreWithFocus, Line: (props) => ( ), } +``` + +```tsx focus.client.tsx -c +// !fold[/className="(.*?)"/gm] +"use client" + +import React, { useLayoutEffect, useRef } from "react" +import { AnnotationHandler, InnerPre, getPreRef } from "codehike/code" + +export const PreWithFocus: AnnotationHandler["PreWithRef"] = (props) => { + const ref = getPreRef(props) + useScrollToFocus(ref) + return +} function useScrollToFocus(ref: React.RefObject) { const firstRender = useRef(true) diff --git a/apps/web/demos/focus/code.tsx b/apps/web/demos/focus/code.tsx index d357c6fe..b579cfc9 100644 --- a/apps/web/demos/focus/code.tsx +++ b/apps/web/demos/focus/code.tsx @@ -1,14 +1,8 @@ "use client" -import { - HighlightedCode, - Pre, - AnnotationHandler, - InnerPre, - getPreRef, - InnerLine, -} from "codehike/code" -import React, { useLayoutEffect, useRef, useState } from "react" +import { HighlightedCode, Pre } from "codehike/code" +import React, { useState } from "react" +import { focus } from "./focus" const ranges = { lorem: { fromLineNumber: 1, toLineNumber: 5 }, @@ -42,14 +36,14 @@ export function CodeContainer({ code }: { code: HighlightedCode }) { {" "} @@ -57,52 +51,3 @@ export function CodeContainer({ code }: { code: HighlightedCode }) { ) } - -const focus: AnnotationHandler = { - name: "focus", - PreWithRef: (props) => { - const ref = getPreRef(props) - useScrollToFocus(ref) - return - }, - Line: (props) => ( - - ), - AnnotatedLine: ({ annotation, ...props }) => ( - - ), -} - -function useScrollToFocus(ref: React.RefObject) { - const firstRender = useRef(true) - useLayoutEffect(() => { - if (ref.current) { - // find all descendants whith data-focus="true" - const focusedElements = ref.current.querySelectorAll( - "[data-focus=true]", - ) as NodeListOf - - // find top and bottom of the focused elements - const containerRect = ref.current.getBoundingClientRect() - let top = Infinity - let bottom = -Infinity - focusedElements.forEach((el) => { - const rect = el.getBoundingClientRect() - top = Math.min(top, rect.top - containerRect.top) - bottom = Math.max(bottom, rect.bottom - containerRect.top) - }) - - // scroll to the focused elements if any part of them is not visible - if (bottom > containerRect.height || top < 0) { - ref.current.scrollTo({ - top: ref.current.scrollTop + top - 10, - behavior: firstRender.current ? "instant" : "smooth", - }) - } - firstRender.current = false - } - }) -} diff --git a/apps/web/demos/focus/focus.client.tsx b/apps/web/demos/focus/focus.client.tsx new file mode 100644 index 00000000..d768737c --- /dev/null +++ b/apps/web/demos/focus/focus.client.tsx @@ -0,0 +1,41 @@ +"use client" + +import React, { useLayoutEffect, useRef } from "react" +import { AnnotationHandler, InnerPre, getPreRef } from "codehike/code" + +export const PreWithFocus: AnnotationHandler["PreWithRef"] = (props) => { + const ref = getPreRef(props) + useScrollToFocus(ref) + return +} + +function useScrollToFocus(ref: React.RefObject) { + const firstRender = useRef(true) + useLayoutEffect(() => { + if (ref.current) { + // find all descendants whith data-focus="true" + const focusedElements = ref.current.querySelectorAll( + "[data-focus=true]", + ) as NodeListOf + + // find top and bottom of the focused elements + const containerRect = ref.current.getBoundingClientRect() + let top = Infinity + let bottom = -Infinity + focusedElements.forEach((el) => { + const rect = el.getBoundingClientRect() + top = Math.min(top, rect.top - containerRect.top) + bottom = Math.max(bottom, rect.bottom - containerRect.top) + }) + + // scroll to the focused elements if any part of them is not visible + if (bottom > containerRect.height || top < 0) { + ref.current.scrollTo({ + top: ref.current.scrollTop + top - 10, + behavior: firstRender.current ? "instant" : "smooth", + }) + } + firstRender.current = false + } + }) +} diff --git a/apps/web/demos/focus/focus.tsx b/apps/web/demos/focus/focus.tsx new file mode 100644 index 00000000..b5b3ecea --- /dev/null +++ b/apps/web/demos/focus/focus.tsx @@ -0,0 +1,17 @@ +import { AnnotationHandler, InnerLine } from "codehike/code" +import { PreWithFocus } from "./focus.client" + +export const focus: AnnotationHandler = { + name: "focus", + onlyIfAnnotated: true, + PreWithRef: PreWithFocus, + Line: (props) => ( + + ), + AnnotatedLine: ({ annotation, ...props }) => ( + + ), +} From 00782d2dac79661fec37596bf4c4a345457dfea2 Mon Sep 17 00:00:00 2001 From: Ryan Berdeen Date: Tue, 31 Dec 2024 00:51:37 -0500 Subject: [PATCH 2/2] headigns --- apps/web/content/docs/concepts/blocks.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/content/docs/concepts/blocks.mdx b/apps/web/content/docs/concepts/blocks.mdx index b7efc677..5035e24e 100644 --- a/apps/web/content/docs/concepts/blocks.mdx +++ b/apps/web/content/docs/concepts/blocks.mdx @@ -218,7 +218,7 @@ The same applies to images, codeblocks, and paragraphs. ## Nesting -You can use headigns with different levels to create nested blocks. +You can use headings with different levels to create nested blocks.