From e78f45ebb90ef75819c8ce35b689194a34ef1ebb Mon Sep 17 00:00:00 2001 From: John <75003086+ZYJLiu@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:05:28 -0500 Subject: [PATCH] Docs UI update (#3) * markdownsteps, add lightmode color to scss * markdowntabs, add tabs/tab component for docs * markdownaccordion, add accordion component for docs * update docs scrollbar, display onhover only * markdownpre, code ui update and add lightmode * add lightmode to copytoclipboard and move svgs * fix doc toc parsing bug * update toc edit page / scroll to top * reorder docs secondary nav and add stack exchange * update svg paths with /@@ * update contentApi regex * tsignore --- package.json | 2 + public/src/img/icons/Copy.inline.svg | 12 ++ public/src/img/icons/CopyConfirm.inline.svg | 12 ++ public/src/img/icons/FileDiff.inline.svg | 14 ++ public/src/img/icons/Rust.inline.svg | 14 ++ public/src/img/icons/Terminal.inline.svg | 13 ++ public/src/img/icons/Typescript.inline.svg | 5 + .../DevelopersContentPage.module.scss | 36 +++++ .../DevelopersContentPage.tsx | 16 +-- .../DevelopersContentPage/TableOfContents.tsx | 51 +++++-- .../DevelopersNav/DevelopersNav.jsx | 54 ++++--- .../MarkdownRenderer/MarkdownRenderer.tsx | 8 ++ .../CopyToClipBoardButton.module.scss | 26 +++- .../components/CopyToClipBoardButton.tsx | 39 +---- .../components/MarkdownAccordion.module.scss | 105 ++++++++++++++ .../components/MarkdownAccordion.tsx | 75 ++++++++++ .../components/MarkdownPre.module.scss | 95 ++++++++----- .../components/MarkdownPre.tsx | 36 ++++- .../components/MarkdownSteps.module.scss | 19 ++- .../components/MarkdownTabs.module.scss | 56 ++++++++ .../components/MarkdownTabs.tsx | 122 ++++++++++++++++ .../MarkdownRenderer/components/index.ts | 2 + src/pages/docs/[[...slug]].tsx | 15 +- src/pages/docs/rpc/[[...slug]].tsx | 13 +- src/utils/contentApi.ts | 30 ++-- src/utils/markdown.ts | 8 +- yarn.lock | 134 ++++++++++++++++++ 27 files changed, 850 insertions(+), 162 deletions(-) create mode 100644 public/src/img/icons/Copy.inline.svg create mode 100644 public/src/img/icons/CopyConfirm.inline.svg create mode 100644 public/src/img/icons/FileDiff.inline.svg create mode 100644 public/src/img/icons/Rust.inline.svg create mode 100644 public/src/img/icons/Terminal.inline.svg create mode 100644 public/src/img/icons/Typescript.inline.svg create mode 100644 src/components/shared/MarkdownRenderer/components/MarkdownAccordion.module.scss create mode 100644 src/components/shared/MarkdownRenderer/components/MarkdownAccordion.tsx create mode 100644 src/components/shared/MarkdownRenderer/components/MarkdownTabs.module.scss create mode 100644 src/components/shared/MarkdownRenderer/components/MarkdownTabs.tsx diff --git a/package.json b/package.json index b92f8ba2c..c0caac73c 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "@builder.io/react": "^3.2.6", "@docsearch/react": "^3.6.0", "@mdx-js/react": "^3.0.1", + "@radix-ui/react-accordion": "^1.2.0", + "@radix-ui/react-tabs": "^1.1.0", "@shikijs/transformers": "^1.6.0", "@sindresorhus/slugify": "^2.2.1", "@solana-foundation/solana-lib": "^2.39.0", diff --git a/public/src/img/icons/Copy.inline.svg b/public/src/img/icons/Copy.inline.svg new file mode 100644 index 000000000..b52f3a555 --- /dev/null +++ b/public/src/img/icons/Copy.inline.svg @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/public/src/img/icons/CopyConfirm.inline.svg b/public/src/img/icons/CopyConfirm.inline.svg new file mode 100644 index 000000000..4572ea5bf --- /dev/null +++ b/public/src/img/icons/CopyConfirm.inline.svg @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/public/src/img/icons/FileDiff.inline.svg b/public/src/img/icons/FileDiff.inline.svg new file mode 100644 index 000000000..763df2e22 --- /dev/null +++ b/public/src/img/icons/FileDiff.inline.svg @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/public/src/img/icons/Rust.inline.svg b/public/src/img/icons/Rust.inline.svg new file mode 100644 index 000000000..42de76f4d --- /dev/null +++ b/public/src/img/icons/Rust.inline.svg @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/public/src/img/icons/Terminal.inline.svg b/public/src/img/icons/Terminal.inline.svg new file mode 100644 index 000000000..6d4159641 --- /dev/null +++ b/public/src/img/icons/Terminal.inline.svg @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/public/src/img/icons/Typescript.inline.svg b/public/src/img/icons/Typescript.inline.svg new file mode 100644 index 000000000..7f495f32e --- /dev/null +++ b/public/src/img/icons/Typescript.inline.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss b/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss index 45ec7d291..a292535f3 100644 --- a/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss +++ b/src/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss @@ -38,6 +38,16 @@ background: var(--scrollbar-thumb-hover); } + @mixin custom-scrollbar { + scrollbar-width: thin; + scrollbar-color: transparent transparent; + transition: scrollbar-color 0.2s ease; + + &:hover { + scrollbar-color: var(--scrollbar-thumb) transparent; + } + } + > * + * { margin-top: 1.5rem; } @@ -343,6 +353,7 @@ max-height: calc(100vh - 8rem); overflow-y: auto; overflow-x: hidden; + @include custom-scrollbar; } @media (max-width: 992px) { @@ -389,6 +400,7 @@ order: 3 !important; position: sticky !important; max-width: 248px; + @include custom-scrollbar; } @media (max-width: 992px) { @@ -541,4 +553,28 @@ } } } + + .scroll-to-top { + opacity: 0; + visibility: hidden; + transition: + opacity 0.2s ease, + visibility 0.2s ease; + + &.show { + opacity: 1; + visibility: visible; + } + } + + .toc-action-item { + justify-content: flex-start; + gap: 0.7rem; + padding: 0.5rem 1rem; + color: inherit; + } + + .toc-action-item:hover { + background-color: transparent; + } } diff --git a/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx b/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx index 0542a32d9..64a10a6f0 100644 --- a/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx +++ b/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx @@ -5,14 +5,9 @@ import styles from "./DevelopersContentPage.module.scss"; import { FormattedDate } from "@/components/SolFormattedMessage"; import MarkdownRenderer from "@/components/shared/MarkdownRenderer/MarkdownRenderer"; import Link from "next/link"; -import ContentApi from "@/utils/contentApi"; import Image from "next/image"; - import defaultImg from "@@/public/social/solana.jpg"; import blurImage from "@@/public/img/blurImage.png"; -import ArrowLeft from "@@/public/src/img/icons/ArrowLeft.inline.svg"; - -import GithubIcon from "@@/public/src/img/footer/github.inline.svg"; import SocialShareButtons from "@/components/sharedPageSections/SocialShareButtons"; import { config } from "src/config"; import { useRouter } from "next/router"; @@ -156,17 +151,8 @@ export default memo(function DevelopersContentPage({ !!showSidebar && styles["developers-content-page__sidebar__active"] } + githubPath={record._raw.sourceFilePath} /> - - - - {t("shared.general.edit-page")} - - diff --git a/src/components/developers/DevelopersContentPage/TableOfContents.tsx b/src/components/developers/DevelopersContentPage/TableOfContents.tsx index b0d7b0b00..18a1bec1f 100644 --- a/src/components/developers/DevelopersContentPage/TableOfContents.tsx +++ b/src/components/developers/DevelopersContentPage/TableOfContents.tsx @@ -1,10 +1,11 @@ -import { memo } from "react"; +import { memo, useEffect, useState } from "react"; import classNames from "classnames"; import styles from "./DevelopersContentPage.module.scss"; import Link from "next/link"; import ContentApi from "@/utils/contentApi"; import { TOC_HEADING_SIZE } from "@/constants/developerContentConfig"; import ArrowLeft from "@@/public/src/img/icons/ArrowLeft.inline.svg"; +import GithubIcon from "@@/public/src/img/footer/github.inline.svg"; import { useTranslation } from "next-i18next"; type TableOfContentsProps = { @@ -18,6 +19,8 @@ type TableOfContentsProps = { content: string; /** the current router's path */ currentPath: string; + /** the path to the github repo */ + githubPath: string; }; /** @@ -31,6 +34,7 @@ export const TableOfContents = memo( content = "", className = "", currentPath = "", + githubPath = "", }: TableOfContentsProps) => { const { t } = useTranslation("common"); @@ -42,6 +46,21 @@ export const TableOfContents = memo( // show nothing if we are unable to parse the TOC // if (!toc || toc?.length <= 0) return <>; + const [showScrollToTop, setShowScrollToTop] = useState(false); + + useEffect(() => { + const checkScroll = () => { + setShowScrollToTop(window.scrollY > window.innerHeight); + }; + + window.addEventListener("scroll", checkScroll); + return () => window.removeEventListener("scroll", checkScroll); + }, []); + + const scrollToTop = () => { + window.scrollTo({ top: 0, behavior: "smooth" }); + }; + return (
{!!title &&
{title}
} @@ -69,17 +88,27 @@ export const TableOfContents = memo( ))} - - typeof window != "undefined" && - window.scrollTo({ top: 0, behavior: "instant" }) - } - className={styles["developers-content-page__simpleButton"]} +
  • + + + {t("shared.general.edit-page")} + +
  • + +
  • - - {t("shared.general.scroll-to-top")} - + +
  • ); }, diff --git a/src/components/developers/DevelopersNav/DevelopersNav.jsx b/src/components/developers/DevelopersNav/DevelopersNav.jsx index ee5654c4e..45b71227b 100644 --- a/src/components/developers/DevelopersNav/DevelopersNav.jsx +++ b/src/components/developers/DevelopersNav/DevelopersNav.jsx @@ -1,11 +1,12 @@ import styles from "./DevelopersNav.module.scss"; import Link from "@/utils/Link"; -import DocsIcon from "../../../../public/src/img/developers/docs.inline.svg"; -import RpcApiIcon from "../../../../public/src/img/developers/api.inline.svg"; -import CookbookIcon from "../../../../public/src/img/developers/cookbook.inline.svg"; -import GuidesIcon from "../../../../public/src/img/developers/guides.inline.svg"; -import TerminologyIcon from "../../../../public/src/img/developers/terminology.inline.svg"; -import CoursesIcon from "../../../../public/src/img/developers/courses.inline.svg"; +import DocsIcon from "@@/public/src/img/developers/docs.inline.svg"; +import RpcApiIcon from "@@/public/src/img/developers/api.inline.svg"; +import CookbookIcon from "@@/public/src/img/developers/cookbook.inline.svg"; +import GuidesIcon from "@@/public/src/img/developers/guides.inline.svg"; +import TerminologyIcon from "@@/public/src/img/developers/terminology.inline.svg"; +import CoursesIcon from "@@/public/src/img/developers/courses.inline.svg"; +import StackExchangeIcon from "@@/assets/developers/stackexchange.inline.svg"; import { useTranslation } from "next-i18next"; export default function DevelopersNav({ containerClassName }) { @@ -27,20 +28,6 @@ export default function DevelopersNav({ containerClassName }) { {t("developers.nav.documentation")} - - - {t("developers.nav.rpc")} - - - - - {t("developers.nav.cookbook")} - - {t("developers.nav.guides")} + + + + {t("developers.nav.cookbook")} + + {t("developers.nav.terminology")} + + + {t("developers.nav.rpc")} + + + + Stack Exchange + diff --git a/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx b/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx index fa10da874..92792e670 100644 --- a/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx +++ b/src/components/shared/MarkdownRenderer/MarkdownRenderer.tsx @@ -16,6 +16,10 @@ import { MarkdownPre, MarkdownImage, MarkdownSteps, + MarkdownTabs, + MarkdownTab, + MarkdownAccordion, + MarkdownAccordionItem, } from "./components"; /** @@ -223,6 +227,10 @@ const DEFAULT_COMPONENTS: MDXRemoteProps["components"] = { Callout: MarkdownCallout, Embed: MarkdownEmbed, Steps: MarkdownSteps, + Tabs: MarkdownTabs, + Tab: MarkdownTab, + Accordion: MarkdownAccordion, + AccordionItem: MarkdownAccordionItem, }; type MarkdownRendererProps = { diff --git a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.module.scss b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.module.scss index f7e53ac10..e01f2ca21 100644 --- a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.module.scss +++ b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.module.scss @@ -7,10 +7,28 @@ border-radius: 0.4rem; color: #adbac7; background-color: #1b1f25; + transition: + color 0.2s, + background-color 0.2s, + border-color 0.2s; + + &:hover { + color: #fff; + background-color: #2d333b; + border-color: #838383 !important; + } } -.button:hover { - color: #fff; - background-color: #1b1f25; - border-color: #838383 !important; +:global(.light) { + .button { + color: #24292e; + background-color: #f6f8fa; + border-color: #d1d5da !important; + + &:hover { + color: #24292e; + background-color: #e1e4e8; + border-color: #b1b5ba !important; + } + } } diff --git a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx index 7c6ced35b..0ba1adab7 100644 --- a/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx +++ b/src/components/shared/MarkdownRenderer/components/CopyToClipBoardButton.tsx @@ -1,8 +1,9 @@ -"use client"; - import styles from "./CopyToClipBoardButton.module.scss"; import { useCallback, useEffect, useRef, useState } from "react"; +import CopyIcon from "@@/public/src/img/icons/Copy.inline.svg"; +import CopyConfirmIcon from "@@/public/src/img/icons/CopyConfirm.inline.svg"; + export function CopyToClipBoardButton() { const btnRef = useRef(null); const [isCopied, setIsCopied] = useState(false); @@ -35,37 +36,7 @@ export function CopyToClipBoardButton() { } }, [btnRef]); - const IconToUse = isCopied ? ( - - - - ) : ( - - - - ); + const IconToUse = isCopied ? CopyConfirmIcon : CopyIcon; return ( ); } diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.module.scss b/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.module.scss new file mode 100644 index 000000000..895606742 --- /dev/null +++ b/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.module.scss @@ -0,0 +1,105 @@ +.root { + --accordion-border-color: #414141; + --accordion-bg-color: #171717; + --accordion-text-color: #a0a0a0; + --accordion-text-active-color: #ffffff; + --accordion-content-bg-color: #0e0e0e; + + border-radius: 0.5rem; + width: 100%; + border: 1px solid var(--accordion-border-color); + overflow: hidden; + position: relative; + + h3 { + all: unset; + } +} + +.item { + border-bottom: 1px solid var(--accordion-border-color); + margin-bottom: 0px !important; + + &:last-child { + border-bottom: none; + } +} + +.trigger { + background-color: var(--accordion-bg-color); + color: var(--accordion-text-color); + padding: 0.75rem 1rem; + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 16px; + line-height: 1; + border: none; + transition: + background-color 0.2s ease, + color 0.2s ease; + + &[data-state="open"] { + color: var(--accordion-text-active-color); + } +} + +.chevron { + width: 1.5rem; + height: 1.5rem; + transition: transform 0.2s ease; + + [data-state="open"] > & { + transform: rotate(180deg); + } +} + +.content { + background-color: var(--accordion-content-bg-color); + overflow: hidden; + transition: + height 0.3s ease, + opacity 0.3s ease; + border-top: 1px solid var(--accordion-border-color); + + &[data-state="open"] { + animation: slideDown 300ms cubic-bezier(0.87, 0, 0.13, 1); + } + + &[data-state="closed"] { + animation: slideUp 300ms cubic-bezier(0.87, 0, 0.13, 1); + } +} + +.content-inner { + padding: 0.75rem 1rem; + font-size: 1.25rem; + padding-bottom: 0; +} + +:global(.light) .root { + --accordion-border-color: #e0e0e0; + --accordion-bg-color: #f5f5f5; + --accordion-text-color: #666666; + --accordion-text-active-color: #333333; + --accordion-content-bg-color: #ffffff; +} + +@keyframes slideDown { + from { + height: 0; + } + to { + height: var(--radix-accordion-content-height); + } +} + +@keyframes slideUp { + from { + height: var(--radix-accordion-content-height); + } + to { + height: 0; + } +} diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.tsx b/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.tsx new file mode 100644 index 000000000..63730fa2f --- /dev/null +++ b/src/components/shared/MarkdownRenderer/components/MarkdownAccordion.tsx @@ -0,0 +1,75 @@ +import React, { ReactNode, useRef, useEffect } from "react"; +import * as AccordionPrimitive from "@radix-ui/react-accordion"; +import styles from "./MarkdownAccordion.module.scss"; +import AngleDownIcon from "../../../../../public/src/img/icons/Angle-down.inline.svg"; + +interface MarkdownAccordionProps { + children: ReactNode; +} + +export function MarkdownAccordion({ + children, + ...props +}: MarkdownAccordionProps) { + return ( + + {children} + + ); +} + +interface MarkdownAccordionItemProps { + title: string; + value?: string; + children: ReactNode; +} + +export function MarkdownAccordionItem({ + title, + value, + children, +}: MarkdownAccordionItemProps) { + const itemId = value ? value : title.toLowerCase().replace(/\s+/g, "-"); + const contentRef = useRef(null); + + // css for radixui data-state attribute (sometimes) doesn't render on change + // this seems to cause rerender and apply the correct state + useEffect(() => { + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if ( + mutation.type === "attributes" && + mutation.attributeName === "data-state" + ) { + const element = mutation.target as HTMLElement; + const newState = element.getAttribute("data-state"); + console.log(newState); + } + }); + }); + + if (contentRef.current) { + observer.observe(contentRef.current, { attributes: true }); + } + + return () => observer.disconnect(); + }, []); + + return ( + + + + {title} + + + + +
    {children}
    +
    +
    + ); +} diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownPre.module.scss b/src/components/shared/MarkdownRenderer/components/MarkdownPre.module.scss index 2d8bf9165..966e1cd17 100644 --- a/src/components/shared/MarkdownRenderer/components/MarkdownPre.module.scss +++ b/src/components/shared/MarkdownRenderer/components/MarkdownPre.module.scss @@ -1,24 +1,52 @@ .wrapper { + --wrapper-border-color: #414141; + --wrapper-bg-color: #0e0e0e; + --header-bg-color: #171717; + --header-text-color: #ededed; + --highlighted-line-bg: #081c2e; + --highlighted-chars-bg: rgba(138, 208, 255, 0.1); + --highlighted-chars-border: var(--bs-link-color); + --diff-add-bg: rgba(44, 246, 75, 0.25); + --diff-remove-bg: rgba(246, 44, 61, 0.25); + overflow: clip; position: relative; border-radius: 0.4rem; - border: 1px solid #414141 !important; + border: 1px solid var(--wrapper-border-color) !important; .header { + display: flex; + align-items: center; + gap: 0.75rem; line-height: 1; font-size: 16px; - background-color: #414141; + background-color: var(--header-bg-color); + border-bottom: 1px solid var(--wrapper-border-color) !important; margin-bottom: 0 !important; - color: #ededed; - padding: 0.8rem; - /* border-bottom: 1px solid #414141 !important; */ + color: var(--header-text-color); + padding: 0.75rem 1rem; font-family: monospace; + + .icon { + width: 1.5rem; + height: 1.5rem; + } + + span { + padding-top: 2px; + } } .copy-button { position: absolute; - top: 4px; - right: 5px; + top: 0.5rem; + right: 0.5rem; + opacity: 0; + transition: opacity 0.2s ease-in-out; + } + + &:hover .copy-button { + opacity: 1; } & > pre { @@ -27,39 +55,24 @@ position: static; padding: 0.5rem 0; margin-bottom: 0 !important; + background-color: var(--wrapper-bg-color) !important; & code > * { padding: 0.06rem 3rem 0.06rem 0.75rem; } - } - // line numbers via css - // :global(code) { - // counter-reset: line; - // } - // :global(code > [data-line]::before) { - // counter-increment: line; - // content: counter(line); - - // /* Other styling */ - // display: inline-block; - // width: 1rem; - // margin-right: 1rem; - // text-align: right; - // color: gray; - // } + & span { + color: var(--shiki-dark); + } + } :global([data-highlighted-line]) { - // background-color: red; - // background-color: rgba(0, 0, 0, 0.3); - // background-color: rgba(146, 76, 189, 0.5); - background-color: rgba(138, 208, 255, 0.1); + background-color: var(--highlighted-line-bg); } :global([data-highlighted-chars]) { - // background-color: rgba(146, 76, 189, 0.7); - background-color: rgba(138, 208, 255, 0.1); - border-bottom: 1px solid var(--bs-link-color); + background-color: var(--highlighted-chars-bg); + border-bottom: 1px solid var(--highlighted-chars-border); border-radius: 0.25rem; padding: 0.1rem 0.4rem; } @@ -69,16 +82,34 @@ } :global(.diff.add) { - background-color: rgba(44, 246, 75, 0.25); + background-color: var(--diff-add-bg); &::before { content: "+"; } } :global(.diff.remove) { - background-color: rgba(246, 44, 61, 0.25); + background-color: var(--diff-remove-bg); &::before { content: "-"; } } } + +:global(.light) .wrapper { + --wrapper-border-color: #e0e0e0; + --wrapper-bg-color: #f6f6f6; + --header-bg-color: #f5f5f5; + --header-text-color: #333333; + --highlighted-line-bg: #e6f7ff; + --highlighted-chars-bg: rgba(3, 102, 214, 0.1); + --highlighted-chars-border: #0366d6; + --diff-add-bg: rgba(46, 160, 67, 0.15); + --diff-remove-bg: rgba(248, 81, 73, 0.15); + + & > pre { + & span { + color: var(--shiki-light); + } + } +} diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx b/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx index 26783c096..8be8d0f99 100644 --- a/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx +++ b/src/components/shared/MarkdownRenderer/components/MarkdownPre.tsx @@ -1,6 +1,12 @@ +import React from "react"; import styles from "./MarkdownPre.module.scss"; import { CopyToClipBoardButton } from "./CopyToClipBoardButton"; +import RustIcon from "@@/public/src/img/icons/Rust.inline.svg"; +import TypescriptIcon from "@@/public/src/img/icons/Typescript.inline.svg"; +import TerminalIcon from "@@/public/src/img/icons/Terminal.inline.svg"; +import FileDiffIcon from "@@/public/src/img/icons/FileDiff.inline.svg"; + /** * Listing of the supported custom metadata that can be attached to parsed components via `attachMetadata` */ @@ -10,14 +16,40 @@ export type CustomPreMetadataProps = { showLineNumbers?: boolean; }; +const languageIcons: Record>> = { + typescript: TypescriptIcon, + javascript: TypescriptIcon, + ts: TypescriptIcon, + js: TypescriptIcon, + rust: RustIcon, + rs: RustIcon, + sh: TerminalIcon, + shell: TerminalIcon, + bash: TerminalIcon, + diff: FileDiffIcon, +}; + +const getIconForLanguage = ( + language: string | undefined, +): React.FC> | undefined => { + if (!language) return undefined; + return languageIcons[language]; +}; + export function MarkdownPre({ children, ...props }: React.ComponentProps<"pre"> & CustomPreMetadataProps) { + const language = props["data-language"]; + const Icon = getIconForLanguage(language); + return (
    - {!!props.filename && ( -
    {props.filename}
    + {(Icon || props.filename) && ( +
    + {Icon && } + {props.filename} +
    )}
             {children}
    diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownSteps.module.scss b/src/components/shared/MarkdownRenderer/components/MarkdownSteps.module.scss
    index 4925a455d..1ca453fe4 100644
    --- a/src/components/shared/MarkdownRenderer/components/MarkdownSteps.module.scss
    +++ b/src/components/shared/MarkdownRenderer/components/MarkdownSteps.module.scss
    @@ -1,7 +1,12 @@
     .markdown-steps {
    +  --steps-border-color: #414141;
    +  --steps-number-border: #414141;
    +  --steps-number-bg: #121212;
    +  --steps-number-color: #fafafa;
    +
       margin-left: 1rem;
       padding-left: 1.5rem;
    -  border-left: 1px solid #414141;
    +  border-left: 1px solid var(--steps-border-color);
       counter-reset: step;
     
       h3 {
    @@ -21,8 +26,9 @@
           width: 33px;
           height: 33px;
           left: -41px;
    -      border: 1px solid #414141;
    -      background-color: #121212;
    +      border: 1px solid var(--steps-number-border);
    +      background-color: var(--steps-number-bg);
    +      color: var(--steps-number-color);
           border-radius: 50%;
           font-size: 1rem;
           font-weight: normal;
    @@ -32,3 +38,10 @@
         }
       }
     }
    +
    +:global(.light) .markdown-steps {
    +  --steps-border-color: #e0e0e0;
    +  --steps-number-border: #e0e0e0;
    +  --steps-number-bg: #ffffff;
    +  --steps-number-color: #333333;
    +}
    diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownTabs.module.scss b/src/components/shared/MarkdownRenderer/components/MarkdownTabs.module.scss
    new file mode 100644
    index 000000000..f853b6710
    --- /dev/null
    +++ b/src/components/shared/MarkdownRenderer/components/MarkdownTabs.module.scss
    @@ -0,0 +1,56 @@
    +.markdown-tabs {
    +  --tabs-border-color: #414141;
    +  --tabs-bg-color: #1a1a1a;
    +  --tabs-text-color: #a0a0a0;
    +  --tabs-text-hover-color: #ffffff;
    +  --tabs-active-color: #ffffff;
    +
    +  margin: 1rem 0;
    +  border: 1px solid var(--tabs-border-color);
    +  border-radius: 0.5rem;
    +  overflow: hidden;
    +}
    +
    +.markdown-tabs-list {
    +  display: flex;
    +  overflow-x: auto;
    +  background-color: var(--tabs-bg-color);
    +  border-bottom: 1px solid var(--tabs-border-color);
    +}
    +
    +.markdown-tabs-trigger {
    +  padding: 0.5rem 1rem;
    +  font-size: 0.875rem;
    +  font-weight: 500;
    +  color: var(--tabs-text-color);
    +  background-color: transparent;
    +  border: none;
    +  border-bottom: 2px solid transparent;
    +  cursor: pointer;
    +  transition:
    +    color 0.2s,
    +    border-color 0.2s;
    +
    +  &:hover {
    +    color: var(--tabs-text-hover-color);
    +  }
    +
    +  &.active {
    +    color: var(--tabs-active-color);
    +    border-bottom-color: var(--tabs-active-color);
    +  }
    +}
    +
    +.markdown-tabs-content {
    +  padding-left: 1rem;
    +  padding-right: 1rem;
    +  font-size: 1rem;
    +}
    +
    +:global(.light) .markdown-tabs {
    +  --tabs-border-color: #e0e0e0;
    +  --tabs-bg-color: #f5f5f5;
    +  --tabs-text-color: #666666;
    +  --tabs-text-hover-color: #333333;
    +  --tabs-active-color: #333333;
    +}
    diff --git a/src/components/shared/MarkdownRenderer/components/MarkdownTabs.tsx b/src/components/shared/MarkdownRenderer/components/MarkdownTabs.tsx
    new file mode 100644
    index 000000000..96dc94de5
    --- /dev/null
    +++ b/src/components/shared/MarkdownRenderer/components/MarkdownTabs.tsx
    @@ -0,0 +1,122 @@
    +import React, {
    +  ReactNode,
    +  useState,
    +  useCallback,
    +  useMemo,
    +  useLayoutEffect,
    +} from "react";
    +import * as TabsPrimitive from "@radix-ui/react-tabs";
    +import styles from "./MarkdownTabs.module.scss";
    +
    +interface MarkdownTabsProps {
    +  children: ReactNode;
    +  items?: string[];
    +  defaultIndex?: number;
    +  groupId?: string;
    +  persist?: boolean;
    +}
    +
    +type ChangeListener = (_v: string) => void;
    +const listeners = new Map();
    +
    +export function MarkdownTabs({
    +  children,
    +  items = [],
    +  defaultIndex = 0,
    +  groupId,
    +  persist = false,
    +  ...props
    +}: MarkdownTabsProps) {
    +  const values = useMemo(() => items.map((item) => toValue(item)), [items]);
    +  const [value, setValue] = useState(values[defaultIndex]);
    +
    +  useLayoutEffect(() => {
    +    if (!groupId) return;
    +
    +    const onUpdate: ChangeListener = (v) => {
    +      if (values.includes(v)) setValue(v);
    +    };
    +
    +    const previous = persist
    +      ? localStorage.getItem(groupId)
    +      : sessionStorage.getItem(groupId);
    +
    +    if (previous) onUpdate(previous);
    +    addChangeListener(groupId, onUpdate);
    +    return () => {
    +      removeChangeListener(groupId, onUpdate);
    +    };
    +  }, [groupId, persist, values]);
    +
    +  const onValueChange = useCallback(
    +    (v: string) => {
    +      if (groupId) {
    +        update(groupId, v, persist);
    +      } else {
    +        setValue(v);
    +      }
    +    },
    +    [groupId, persist],
    +  );
    +
    +  return (
    +    
    +      
    +        {values.map((v, i) => (
    +          
    +            {items[i]}
    +          
    +        ))}
    +      
    +      {children}
    +    
    +  );
    +}
    +
    +export function MarkdownTab({
    +  value,
    +  ...props
    +}: TabsPrimitive.TabsContentProps) {
    +  return (
    +    
    +  );
    +}
    +
    +function addChangeListener(groupId: string, listener: ChangeListener): void {
    +  const list = listeners.get(groupId) ?? [];
    +  list.push(listener);
    +  listeners.set(groupId, list);
    +}
    +
    +function removeChangeListener(groupId: string, listener: ChangeListener): void {
    +  const list = listeners.get(groupId) ?? [];
    +  listeners.set(
    +    groupId,
    +    list.filter((item) => item !== listener),
    +  );
    +}
    +
    +function update(groupId: string, v: string, persist: boolean): void {
    +  listeners.get(groupId)?.forEach((item) => item(v));
    +  if (persist) localStorage.setItem(groupId, v);
    +  else sessionStorage.setItem(groupId, v);
    +}
    +
    +function toValue(v: string): string {
    +  return v.toLowerCase().replace(/\s/, "-");
    +}
    diff --git a/src/components/shared/MarkdownRenderer/components/index.ts b/src/components/shared/MarkdownRenderer/components/index.ts
    index f487ccfc5..5f519ab0f 100644
    --- a/src/components/shared/MarkdownRenderer/components/index.ts
    +++ b/src/components/shared/MarkdownRenderer/components/index.ts
    @@ -6,4 +6,6 @@ export * from "./MarkdownEmbed";
     export * from "./MarkdownPre";
     export * from "./MarkdownImage";
     export * from "./MarkdownSteps";
    +export * from "./MarkdownTabs";
    +export * from "./MarkdownAccordion";
     export * from "./CopyToClipBoardButton";
    diff --git a/src/pages/docs/[[...slug]].tsx b/src/pages/docs/[[...slug]].tsx
    index b6e9c8180..ca7f5cf8d 100644
    --- a/src/pages/docs/[[...slug]].tsx
    +++ b/src/pages/docs/[[...slug]].tsx
    @@ -14,8 +14,6 @@ import MarkdownRenderer from "@/components/shared/MarkdownRenderer/MarkdownRende
     import Link from "next/link";
     import { useRouter } from "next/router";
     
    -import ArrowLeft from "@@/public/src/img/icons/ArrowLeft.inline.svg";
    -import GithubIcon from "@@/public/src/img/footer/github.inline.svg";
     import DocsNavSidebar from "@/components/developers/DocsNavSidebar";
     import { InferGetStaticPropsType } from "next";
     import { SidebarToggleButton } from "@/components/developers/DevelopersContentPage/SidebarToggleButton";
    @@ -75,19 +73,8 @@ export default function DeveloperDocs({
                       title={t("shared.general.toc")}
                       currentPath={router.asPath}
                       content={record.body}
    +                  githubPath={record._raw.sourceFilePath}
                     />
    -
    -                
    -                  
    -                  {t("shared.general.edit-page")}
    -                  
    -                
                   
    - - - - {t("shared.general.edit-page")} - - )} diff --git a/src/utils/contentApi.ts b/src/utils/contentApi.ts index c457bd316..a173bab9c 100644 --- a/src/utils/contentApi.ts +++ b/src/utils/contentApi.ts @@ -353,7 +353,8 @@ export default class ContentApi { // we remove any special characters from the end of the label // to make it look cleaner in the UI - label = label.split(/[\v{L|N}]*$/)[0]; + // @ts-ignore + label = label.replace(/[^\p{L}\p{N}]+$/u, ""); // if (!duplicator.has(label)) { // duplicator.set(label, 0); @@ -380,18 +381,21 @@ export default class ContentApi { */ static slugify(url: string): string { try { - return url - .toString() - .normalize("NFD") - .replace(/[\u0300-\u036f]/g, "") - .toLowerCase() - .trim() - .replace(/\s+/g, "-") - .replace(/\./g, "") - .replace(/[[\v{L|N}]*]+/g, "-") - .replace(/^-/g, "") - .replace(/-$/g, "") - .replace(/--+/g, "-"); + return ( + url + .toString() + .normalize("NFD") + .replace(/[\u0300-\u036f]/g, "") + .toLowerCase() + .trim() + .replace(/\s+/g, "-") + .replace(/\./g, "") + // @ts-ignore + .replace(/[^\p{L}\p{N}]+/gu, "-") + .replace(/^-/g, "") + .replace(/-$/g, "") + .replace(/--+/g, "-") + ); } catch (err) { console.error("[slugify error]", err); return "#err"; diff --git a/src/utils/markdown.ts b/src/utils/markdown.ts index 426398a8c..ba9d97431 100644 --- a/src/utils/markdown.ts +++ b/src/utils/markdown.ts @@ -5,7 +5,8 @@ import rehypePrettyCode, { Options as RehypePrettyCodeOptions, } from "rehype-pretty-code"; import { transformerNotationDiff } from "@shikijs/transformers"; -import codeTheme from "shiki/themes/github-dark-dimmed.mjs"; +import darkTheme from "shiki/themes/github-dark-dimmed.mjs"; +import lightTheme from "shiki/themes/github-light.mjs"; // import codeTheme from "shiki/themes/rose-pine-moon.mjs"; // import codeTheme from "shiki/themes/andromeeda.mjs"; @@ -116,7 +117,10 @@ export const rehypePluginConfig: import("unified").PluggableList = [ defaultLang: { block: "text", }, - theme: codeTheme, + theme: { + dark: darkTheme, + light: lightTheme, + }, transformers: [transformerNotationDiff()], } as RehypePrettyCodeOptions, // rehypeSanitize, diff --git a/yarn.lock b/yarn.lock index 09c0729d6..d6a3bab61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1279,6 +1279,26 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/primitive@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" + integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== + +"@radix-ui/react-accordion@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-accordion/-/react-accordion-1.2.0.tgz#aed0770fcb16285db992d81873ccd7a014c7f17d" + integrity sha512-HJOzSX8dQqtsp/3jVxCU3CXEONF7/2jlGAB28oX8TTw1Dz8JYbEI1UcL8355PuLBE41/IRRMvCw7VkiK/jcUOQ== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collapsible" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-arrow@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d" @@ -1287,6 +1307,30 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" +"@radix-ui/react-collapsible@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.0.tgz#4d49ddcc7b7d38f6c82f1fd29674f6fab5353e77" + integrity sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-collection@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz#f18af78e46454a2360d103c2251773028b7724ed" + integrity sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-compose-refs@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989" @@ -1294,6 +1338,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-compose-refs@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" + integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw== + "@radix-ui/react-context@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" @@ -1301,6 +1350,16 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-context@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8" + integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A== + +"@radix-ui/react-direction@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" + integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== + "@radix-ui/react-dismissable-layer@1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz#883a48f5f938fa679427aa17fcba70c5494c6978" @@ -1321,6 +1380,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.1" +"@radix-ui/react-id@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-popper@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.2.tgz#4c0b96fcd188dc1f334e02dba2d538973ad842e9" @@ -1355,6 +1421,14 @@ "@radix-ui/react-compose-refs" "1.0.1" "@radix-ui/react-use-layout-effect" "1.0.1" +"@radix-ui/react-presence@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.0.tgz#227d84d20ca6bfe7da97104b1a8b48a833bfb478" + integrity sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-primitive@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" @@ -1363,6 +1437,28 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "1.0.2" +"@radix-ui/react-primitive@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884" + integrity sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw== + dependencies: + "@radix-ui/react-slot" "1.1.0" + +"@radix-ui/react-roving-focus@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz#b30c59daf7e714c748805bfe11c76f96caaac35e" + integrity sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-slot@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" @@ -1371,6 +1467,27 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-compose-refs" "1.0.1" +"@radix-ui/react-slot@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" + integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + +"@radix-ui/react-tabs@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.1.0.tgz#0a6db1caed56776a1176aae68532060e301cc1c0" + integrity sha512-bZgOKB/LtZIij75FSuPzyEti/XBhJH52ExgtdVqjCIh+Nx/FW+LhnbXtbCzIi34ccyMsyOja8T0thCzoHFXNKA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-roving-focus" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-tooltip@^1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.0.6.tgz#87a7786cd9f2b4de957ac645afae1575339c58b0" @@ -1397,6 +1514,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== + "@radix-ui/react-use-controllable-state@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286" @@ -1405,6 +1527,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-callback-ref" "1.0.1" +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755" @@ -1420,6 +1549,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== + "@radix-ui/react-use-rect@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz#fde50b3bb9fd08f4a1cd204572e5943c244fcec2"