焦点
聚焦代码块。使未聚焦的代码变暗。确保在溢出时聚焦的代码可见。
当您想要根据用户的交互改变代码块焦点时很有用。
content.md
```jsfunction lorem(ipsum, dolor = 1) {const sit = ipsum == null ? 0 : ipsum.sitdolor = sit - amet(dolor)return sit ? consectetur(ipsum) : []}function ipsum(ipsum, dolor = 1) {return dolor}// !focus(1:5)function dolor(ipsum, dolor = 1) {const sit = ipsum == null ? 0 : ipsum.sitdolor = sit - amet(dolor)return sit ? consectetur(ipsum) : []}```
function lorem(ipsum, dolor = 1) {const sit = ipsum == null ? 0 : ipsum.sitdolor = sit - amet(dolor)return sit ? consectetur(ipsum) : []}function ipsum(ipsum, dolor = 1) {return dolor}function dolor(ipsum, dolor = 1) {const sit = ipsum == null ? 0 : ipsum.sitdolor = sit - amet(dolor)return sit ? consectetur(ipsum) : []}
You can also change the focus annotations on a rendered codeblock:
Implementation
我们需要两样东西:
- 为聚焦的行设置
data-focus={true} - 获取
pre元素的ref,并在需要时滚动它
focus.tsx
import { AnnotationHandler, InnerLine } from "codehike/code"import { PreWithFocus } from "./focus.client"export const focus: AnnotationHandler = {name: "focus",onlyIfAnnotated: true,PreWithRef: PreWithFocus,Line: (props) => (<InnerLinemerge={props}className=""/>),AnnotatedLine: ({ annotation, ...props }) => (<InnerLine merge={props} data-focus={true} className="" />),}
focus.client.tsx
"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 <InnerPre merge={props} />}function useScrollToFocus(ref: React.RefObject<HTMLPreElement>) {const firstRender = useRef(true)useLayoutEffect(() => {if (ref.current) {// 查找所有具有 data-focus="true" 的后代元素const focusedElements = ref.current.querySelectorAll("[data-focus=true]",) as NodeListOf<HTMLElement>// 查找聚焦元素的顶部和底部const containerRect = ref.current.getBoundingClientRect()let top = Infinitylet bottom = -InfinityfocusedElements.forEach((el) => {const rect = el.getBoundingClientRect()top = Math.min(top, rect.top - containerRect.top)bottom = Math.max(bottom, rect.bottom - containerRect.top)})// 如果聚焦元素的任何部分不可见,则滚动到聚焦元素if (bottom > containerRect.height || top < 0) {ref.current.scrollTo({top: ref.current.scrollTop + top - 10,behavior: firstRender.current ? "instant" : "smooth",})}firstRender.current = false}})}