Junior Garcia b8e7b94586
🚀 (#4570)
* docs: optimize route higtlight (#4520)

* docs: optimize home display (#4519)

* docs: optimize home display and route highlight

* docs: optimize home display

* fix(alert): propagate className (#4535)

* fix(alert): propagate className

* chore(alert): remove className from alert theme

* fix(avatar): title type in Avatar (#4529)

* fix(avatar): title type in Avatar

* fix(alert): apply isEmpty check on title

* fix(alert): alert interface props type

* refactor: remove unnecessary props types (#4530)

* refactor(docs): remove string type as it is included in ReactNode

* refactor: remove unnecessary types

* feat(changeset): add changeset

* chore: remove changeset

* refactor: remove null since ReactNode unions it already

* fix(input): use onPress for wrapper click focus (#4483)

* fix(input): use onPress for wrapper click focus

* test(input): wrapper click focus test

* chore(changeset): input onPress for wrapper click focus

* chore(changeset): minor wording

* Refactor/rebrand (#4532)

* chore: rebrand in progress

* chore: update docs to use heroui

* chore: components renbranded

* chore: figma moved to the docs files

* fix: posthog config

* fix(docs): extra classname in form example (#4465)

* chore: clean git

* chore: make heroui private

* chore: new logo

* chore: node env var renamed

* chore: public robots txt deleted

* chore: wrangler installed

* chore: wrangler renamed

* chore: cloudlfare workers removed

* chore: force vercel deploy

* refactor: first migration and provider

* refactor: rename nextui plugin

* refactor: rename github site

* refactor: rename CONTRIBUTING

* refactor: rename package name

* refactor: nextjs image hostname

* refactor: mdx repo nextui-org rename frontio-ai

* refactor: nextui.org rename heroui.com

* refactor: add heroui to missing places

* fix: heroui plugin name

* fix: update docs

* docs: nextui to heroui add npmrc pnpm migratation

* chore: rename all packages with new org name

* chore: replace frontio-ai by frontioai

* chore: revert previous changes

* chore: small adjustment

* chore: doc updated

* feat: blog

* chore: avatar updated

* fix: url

* chore: add new ogimage

* fix: ogimage command

* fix: heroui name and storybook welcome page

* fix: og image url

* feat: favicon and icon changed

---------

Co-authored-by: աӄա <wingkwong.code@gmail.com>
Co-authored-by: winches <329487092@qq.com>

* fix: postbuild script

* chore: core package updates

* ci(changesets): version packages (#4569)

Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* feat: contributors added to the blog

---------

Co-authored-by: winches <329487092@qq.com>
Co-authored-by: աӄա <wingkwong.code@gmail.com>
Co-authored-by: Peterl561 <76144929+Peterl561@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-16 16:24:32 -03:00

97 lines
2.7 KiB
TypeScript

"use client";
// Inspired by https://github.dev/modulz/stitches-site code demo
import React from "react";
import rangeParser from "parse-numeric-range";
import CodeBlock, {CodeBlockProps} from "./code-block";
import {CopyButton} from "@/components";
export interface CodeWindowProps extends CodeBlockProps {
showCopy?: boolean;
}
export const CodeWindow: React.FC<CodeWindowProps> = ({highlightLines, showCopy, ...props}) => {
const wrapperRef = React.useRef<HTMLPreElement>(null);
React.useEffect(() => {
const pre = wrapperRef.current;
if (!pre) return;
const PADDING = 15;
let codeInner = pre.querySelector("code") ?? null;
const codeBlockHeight = pre.clientHeight - PADDING * 2;
const lines = pre.querySelectorAll<HTMLElement>(".highlight-line");
if (!highlightLines) {
lines.forEach((line) => {
line.classList.remove("off");
});
if (codeInner) {
codeInner.style.transform = `translate3d(0, 0, 0)`;
}
return;
}
const linesToHighlight = rangeParser(highlightLines);
const firstLineNumber = Math.max(0, linesToHighlight[0] - 1);
const lastLineNumber = Math.min(lines.length - 1, [...linesToHighlight].reverse()[0] - 1);
const firstLine = lines[firstLineNumber];
const lastLine = lines[lastLineNumber];
// Prevent errors in case the right line doesn't exist
if (!firstLine || !lastLine) {
// eslint-disable-next-line no-console
console.warn(`CodeWindow: Error finding the right line`);
return;
}
const linesHeight = lastLine.offsetTop - firstLine.offsetTop;
const maxDistance = (codeInner?.clientHeight || 0) - codeBlockHeight;
const codeFits = linesHeight < codeBlockHeight;
const lastLineIsBelow = lastLine.offsetTop > codeBlockHeight - PADDING;
const lastLineIsAbove = !lastLineIsBelow;
let translateY = 0;
if (codeFits && lastLineIsAbove) {
translateY = 0;
} else if (codeFits && lastLineIsBelow) {
const dist = firstLine.offsetTop - (codeBlockHeight - linesHeight) / 2;
translateY = dist > maxDistance ? maxDistance : dist;
} else {
translateY = firstLine.offsetTop;
}
lines.forEach((line, i) => {
const lineIndex = i + 1;
if (linesToHighlight.includes(lineIndex)) {
line.setAttribute("data-highlighted", "true");
} else {
line.setAttribute("data-highlighted", "false");
}
});
requestAnimationFrame(
() => codeInner && (codeInner.style.transform = `translate3d(0, ${-translateY}px, 0)`),
);
}, [highlightLines]);
return (
<div className="relative">
<CodeBlock ref={wrapperRef} {...props} />
{showCopy && <CopyButton className="top-2 absolute right-2" value={props.value} />}
</div>
);
};