mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-24 11:01:54 +00:00
Use simple markdown
This commit is contained in:
parent
48dcacc7ce
commit
57ae64d44a
79 changed files with 32 additions and 15209 deletions
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
32
docs/.gitignore
vendored
32
docs/.gitignore
vendored
|
@ -1,32 +0,0 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
|
@ -1 +0,0 @@
|
|||
.next
|
|
@ -1,5 +0,0 @@
|
|||
# Zed Internal Docs
|
||||
|
||||
## Template: Protocol
|
||||
|
||||
Protocol is a [Tailwind UI](https://tailwindui.com) site template built using [Tailwind CSS](https://tailwindcss.com) and [Next.js](https://nextjs.org).
|
|
@ -1,30 +1,30 @@
|
|||
export const description = 'Get your machine set up for the first time'
|
||||
# Building Zed
|
||||
|
||||
# Setup
|
||||
How to build Zed from source for the first time.
|
||||
|
||||
## Getting Zed to build
|
||||
## Process
|
||||
|
||||
Expect this to take 30min to an hour! Some of these steps will take quite a while based on your connection speed, and how long your first build will be.
|
||||
|
||||
1. Install the [GitHub CLI](https://cli.github.com/):
|
||||
- `brew install gh`
|
||||
2. Clone the `zed` repo
|
||||
1. Clone the `zed` repo
|
||||
- `gh repo clone zed-industries/zed`
|
||||
3. Install Xcode from the macOS App Store
|
||||
4. Install [Postgres](https://postgresapp.com)
|
||||
5. Install rust/rustup
|
||||
1. Install Xcode from the macOS App Store
|
||||
1. Install [Postgres](https://postgresapp.com)
|
||||
1. Install rust/rustup
|
||||
- `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
|
||||
6. Install the wasm toolchain
|
||||
1. Install the wasm toolchain
|
||||
- `rustup target add wasm32-wasi`
|
||||
7. Generate an GitHub API Key
|
||||
1. Generate an GitHub API Key
|
||||
- Go to https://github.com/settings/tokens and Generate new token
|
||||
- GitHub currently provides two kinds of tokens:
|
||||
- Classic Tokens, where only `repo` (Full control of private repositories) OAuth scope has to be selected
|
||||
Unfortunately, unselecting `repo` scope and selecting every its inner scope instead does not allow the token users to read from private repositories
|
||||
- (not applicable) Fine-grained Tokens, at the moment of writing, did not allow any kind of access of non-owned private repos
|
||||
- Keep the token in the browser tab/editor for the next two steps
|
||||
8. Open Postgres.app
|
||||
9. From `./path/to/zed/`:
|
||||
1. Open Postgres.app
|
||||
1. From `./path/to/zed/`:
|
||||
- Run:
|
||||
- `GITHUB_TOKEN={yourGithubAPIToken} script/bootstrap`
|
||||
- Replace `{yourGithubAPIToken}` with the API token you generated above.
|
||||
|
@ -42,7 +42,7 @@ Expect this to take 30min to an hour! Some of these steps will take quite a whil
|
|||
- Replace `{username}` with your home folder name (usually your login name)
|
||||
- `echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/{username}/.zprofile`
|
||||
- `eval "$(/opt/homebrew/bin/brew shellenv)"`
|
||||
10. To run the Zed app:
|
||||
1. To run the Zed app:
|
||||
- If you are working on zed:
|
||||
- `cargo run`
|
||||
- If you are just using the latest version, but not working on zed:
|
|
@ -1,10 +1,4 @@
|
|||
export const description = 'Welcome to Zed!'
|
||||
|
||||
# Welcome to Zed
|
||||
|
||||
Welcome! These internal docs are a work in progress. You can contribute to them by submitting a PR directly!
|
||||
|
||||
## Getting Started
|
||||
# Company & Vision
|
||||
|
||||
## Vision
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
export const description = 'A list of useful design tools.'
|
||||
|
||||
# Design Tools
|
||||
# Design Tools & Links
|
||||
|
||||
Generally useful tools and resources for design.
|
||||
|
12
docs/index.md
Normal file
12
docs/index.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Welcome to Zed
|
||||
|
||||
Welcome! These internal docs are a work in progress. You can contribute to them by submitting a PR directly!
|
||||
|
||||
## Contents
|
||||
|
||||
- [The Company](./company-and-vision.md)
|
||||
- [Tools We Use](./tools.md)
|
||||
- [Building Zed](./building-zed.md)
|
||||
- [Reloease Process](./release-process.md)
|
||||
- [Backend Development](./backend-development.md)
|
||||
- [Design Tools & Links](design-tools.md)
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import nextMDX from '@next/mdx'
|
||||
import { remarkPlugins } from './src/mdx/remark.mjs'
|
||||
import { rehypePlugins } from './src/mdx/rehype.mjs'
|
||||
import { recmaPlugins } from './src/mdx/recma.mjs'
|
||||
|
||||
const withMDX = nextMDX({
|
||||
options: {
|
||||
remarkPlugins,
|
||||
rehypePlugins,
|
||||
recmaPlugins,
|
||||
providerImportSource: '@mdx-js/react',
|
||||
},
|
||||
})
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'mdx'],
|
||||
experimental: {
|
||||
scrollRestoration: true,
|
||||
},
|
||||
}
|
||||
|
||||
export default withMDX(nextConfig)
|
11975
docs/package-lock.json
generated
11975
docs/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,51 +0,0 @@
|
|||
{
|
||||
"name": "zed-internal-docs",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"browserslist": "defaults, not ie <= 11",
|
||||
"dependencies": {
|
||||
"@algolia/autocomplete-core": "^1.7.3",
|
||||
"@headlessui/react": "^1.7.13",
|
||||
"@mdx-js/loader": "^2.1.5",
|
||||
"@mdx-js/react": "^2.1.5",
|
||||
"@next/mdx": "^13.0.3",
|
||||
"@sindresorhus/slugify": "^2.1.1",
|
||||
"@tailwindcss/typography": "^0.5.8",
|
||||
"acorn": "^8.8.1",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"clsx": "^1.2.0",
|
||||
"fast-glob": "^3.2.12",
|
||||
"focus-visible": "^5.2.0",
|
||||
"framer-motion": "7.8.1",
|
||||
"mdast-util-to-string": "^3.2.0",
|
||||
"mdx-annotations": "^0.1.1",
|
||||
"next": "13.4.2",
|
||||
"postcss-focus-visible": "^6.0.4",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-highlight-words": "^0.20.0",
|
||||
"recma-nextjs-static-props": "^1.0.0",
|
||||
"rehype-mdx-title": "^2.0.0",
|
||||
"remark": "^14.0.2",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-mdx": "^2.3.0",
|
||||
"shiki": "^0.11.1",
|
||||
"simple-functional-loader": "^1.2.1",
|
||||
"tailwindcss": "^3.3.0",
|
||||
"unist-util-filter": "^4.0.1",
|
||||
"unist-util-visit": "^4.1.1",
|
||||
"zustand": "^4.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-next": "13.0.2",
|
||||
"prettier": "^2.8.7",
|
||||
"prettier-plugin-tailwindcss": "^0.2.6"
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
'postcss-focus-visible': {
|
||||
replaceWith: '[data-focus-visible-added]',
|
||||
},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = {
|
||||
singleQuote: true,
|
||||
semi: false,
|
||||
plugins: [require('prettier-plugin-tailwindcss')],
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
|
@ -1,7 +1,7 @@
|
|||
export const description = 'The process to create and ship a Zed release'
|
||||
|
||||
# Zed's Release Process
|
||||
|
||||
The process to create and ship a Zed release
|
||||
|
||||
## Overview
|
||||
|
||||
### Release Channels
|
||||
|
@ -79,9 +79,9 @@ This means that when releasing a new version of Zed that has changes to the RPC
|
|||
1. Deploying the server is a two-step process that begins with pushing a tag. 1. Check out the commit you'd like to deploy. Often it will be the head of `main`, but could be on any branch.
|
||||
1. Run the following script, which will bump the version of the `collab` crate and create a new tag. The script takes an argument `minor` or `patch`, to indicate how to increment the version. If you're releasing new features, use `minor`. If it's just a bugfix, use `patch`
|
||||
|
||||
```
|
||||
script/bump-collab-version patch
|
||||
```
|
||||
```
|
||||
script/bump-collab-version patch
|
||||
```
|
||||
|
||||
1. This script will make local changes only, and print out a shell command that you can use to push the branch and tag.
|
||||
1. Pushing the new tag will trigger a CI build that, when finished will upload a new versioned docker image to the DigitalOcean docker registry.
|
|
@ -1,62 +0,0 @@
|
|||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
|
||||
function ArrowIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" {...props}>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m11.5 6.5 3 3.5m0 0-3 3.5m3-3.5h-9"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
const variantStyles = {
|
||||
primary:
|
||||
'rounded-full bg-zinc-900 py-1 px-3 text-white hover:bg-zinc-700 dark:bg-emerald-400/10 dark:text-emerald-400 dark:ring-1 dark:ring-inset dark:ring-emerald-400/20 dark:hover:bg-emerald-400/10 dark:hover:text-emerald-300 dark:hover:ring-emerald-300',
|
||||
secondary:
|
||||
'rounded-full bg-zinc-100 py-1 px-3 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-800/40 dark:text-zinc-400 dark:ring-1 dark:ring-inset dark:ring-zinc-800 dark:hover:bg-zinc-800 dark:hover:text-zinc-300',
|
||||
filled:
|
||||
'rounded-full bg-zinc-900 py-1 px-3 text-white hover:bg-zinc-700 dark:bg-emerald-500 dark:text-white dark:hover:bg-emerald-400',
|
||||
outline:
|
||||
'rounded-full py-1 px-3 text-zinc-700 ring-1 ring-inset ring-zinc-900/10 hover:bg-zinc-900/2.5 hover:text-zinc-900 dark:text-zinc-400 dark:ring-white/10 dark:hover:bg-white/5 dark:hover:text-white',
|
||||
text: 'text-emerald-500 hover:text-emerald-600 dark:text-emerald-400 dark:hover:text-emerald-500',
|
||||
}
|
||||
|
||||
export function Button({
|
||||
variant = 'primary',
|
||||
className,
|
||||
children,
|
||||
arrow,
|
||||
...props
|
||||
}) {
|
||||
let Component = props.href ? Link : 'button'
|
||||
|
||||
className = clsx(
|
||||
'inline-flex gap-0.5 justify-center overflow-hidden text-sm font-medium transition',
|
||||
variantStyles[variant],
|
||||
className
|
||||
)
|
||||
|
||||
let arrowIcon = (
|
||||
<ArrowIcon
|
||||
className={clsx(
|
||||
'mt-0.5 h-5 w-5',
|
||||
variant === 'text' && 'relative top-px',
|
||||
arrow === 'left' && '-ml-1 rotate-180',
|
||||
arrow === 'right' && '-mr-1'
|
||||
)}
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
<Component className={className} {...props}>
|
||||
{arrow === 'left' && arrowIcon}
|
||||
{children}
|
||||
{arrow === 'right' && arrowIcon}
|
||||
</Component>
|
||||
)
|
||||
}
|
|
@ -1,297 +0,0 @@
|
|||
import {
|
||||
Children,
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { Tab } from '@headlessui/react'
|
||||
import clsx from 'clsx'
|
||||
import { create } from 'zustand'
|
||||
|
||||
import { Tag } from '@/components/Tag'
|
||||
|
||||
const languageNames = {
|
||||
js: 'JavaScript',
|
||||
ts: 'TypeScript',
|
||||
javascript: 'JavaScript',
|
||||
typescript: 'TypeScript',
|
||||
php: 'PHP',
|
||||
python: 'Python',
|
||||
ruby: 'Ruby',
|
||||
go: 'Go',
|
||||
}
|
||||
|
||||
function getPanelTitle({ title, language }) {
|
||||
return title ?? languageNames[language] ?? 'Code'
|
||||
}
|
||||
|
||||
function ClipboardIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeWidth="0"
|
||||
d="M5.5 13.5v-5a2 2 0 0 1 2-2l.447-.894A2 2 0 0 1 9.737 4.5h.527a2 2 0 0 1 1.789 1.106l.447.894a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinejoin="round"
|
||||
d="M12.5 6.5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2m5 0-.447-.894a2 2 0 0 0-1.79-1.106h-.527a2 2 0 0 0-1.789 1.106L7.5 6.5m5 0-1 1h-3l-1-1"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function CopyButton({ code }) {
|
||||
let [copyCount, setCopyCount] = useState(0)
|
||||
let copied = copyCount > 0
|
||||
|
||||
useEffect(() => {
|
||||
if (copyCount > 0) {
|
||||
let timeout = setTimeout(() => setCopyCount(0), 1000)
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
}, [copyCount])
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={clsx(
|
||||
'group/button absolute right-4 top-3.5 overflow-hidden rounded-full py-1 pl-2 pr-3 text-2xs font-medium opacity-0 backdrop-blur transition focus:opacity-100 group-hover:opacity-100',
|
||||
copied
|
||||
? 'bg-emerald-400/10 ring-1 ring-inset ring-emerald-400/20'
|
||||
: 'bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5'
|
||||
)}
|
||||
onClick={() => {
|
||||
window.navigator.clipboard.writeText(code).then(() => {
|
||||
setCopyCount((count) => count + 1)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<span
|
||||
aria-hidden={copied}
|
||||
className={clsx(
|
||||
'pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300',
|
||||
copied && '-translate-y-1.5 opacity-0'
|
||||
)}
|
||||
>
|
||||
<ClipboardIcon className="h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" />
|
||||
Copy
|
||||
</span>
|
||||
<span
|
||||
aria-hidden={!copied}
|
||||
className={clsx(
|
||||
'pointer-events-none absolute inset-0 flex items-center justify-center text-emerald-400 transition duration-300',
|
||||
!copied && 'translate-y-1.5 opacity-0'
|
||||
)}
|
||||
>
|
||||
Copied!
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
function CodePanelHeader({ tag, label }) {
|
||||
if (!tag && !label) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-9 items-center gap-2 border-y border-b-white/7.5 border-t-transparent bg-white/2.5 bg-zinc-900 px-4 dark:border-b-white/5 dark:bg-white/1">
|
||||
{tag && (
|
||||
<div className="dark flex">
|
||||
<Tag variant="small">{tag}</Tag>
|
||||
</div>
|
||||
)}
|
||||
{tag && label && (
|
||||
<span className="h-0.5 w-0.5 rounded-full bg-zinc-500" />
|
||||
)}
|
||||
{label && (
|
||||
<span className="font-mono text-xs text-zinc-400">{label}</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function CodePanel({ tag, label, code, children }) {
|
||||
let child = Children.only(children)
|
||||
|
||||
return (
|
||||
<div className="group dark:bg-white/2.5">
|
||||
<CodePanelHeader
|
||||
tag={child.props.tag ?? tag}
|
||||
label={child.props.label ?? label}
|
||||
/>
|
||||
<div className="relative">
|
||||
<pre className="overflow-x-auto p-4 text-xs text-white">{children}</pre>
|
||||
<CopyButton code={child.props.code ?? code} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function CodeGroupHeader({ title, children, selectedIndex }) {
|
||||
let hasTabs = Children.count(children) > 1
|
||||
|
||||
if (!title && !hasTabs) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-[calc(theme(spacing.12)+1px)] flex-wrap items-start gap-x-4 border-b border-zinc-700 bg-zinc-800 px-4 dark:border-zinc-800 dark:bg-transparent">
|
||||
{title && (
|
||||
<h3 className="mr-auto pt-3 text-xs font-semibold text-white">
|
||||
{title}
|
||||
</h3>
|
||||
)}
|
||||
{hasTabs && (
|
||||
<Tab.List className="-mb-px flex gap-4 text-xs font-medium">
|
||||
{Children.map(children, (child, childIndex) => (
|
||||
<Tab
|
||||
className={clsx(
|
||||
'border-b py-3 transition focus:[&:not(:focus-visible)]:outline-none',
|
||||
childIndex === selectedIndex
|
||||
? 'border-emerald-500 text-emerald-400'
|
||||
: 'border-transparent text-zinc-400 hover:text-zinc-300'
|
||||
)}
|
||||
>
|
||||
{getPanelTitle(child.props)}
|
||||
</Tab>
|
||||
))}
|
||||
</Tab.List>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function CodeGroupPanels({ children, ...props }) {
|
||||
let hasTabs = Children.count(children) > 1
|
||||
|
||||
if (hasTabs) {
|
||||
return (
|
||||
<Tab.Panels>
|
||||
{Children.map(children, (child) => (
|
||||
<Tab.Panel>
|
||||
<CodePanel {...props}>{child}</CodePanel>
|
||||
</Tab.Panel>
|
||||
))}
|
||||
</Tab.Panels>
|
||||
)
|
||||
}
|
||||
|
||||
return <CodePanel {...props}>{children}</CodePanel>
|
||||
}
|
||||
|
||||
function usePreventLayoutShift() {
|
||||
let positionRef = useRef()
|
||||
let rafRef = useRef()
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
window.cancelAnimationFrame(rafRef.current)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return {
|
||||
positionRef,
|
||||
preventLayoutShift(callback) {
|
||||
let initialTop = positionRef.current.getBoundingClientRect().top
|
||||
|
||||
callback()
|
||||
|
||||
rafRef.current = window.requestAnimationFrame(() => {
|
||||
let newTop = positionRef.current.getBoundingClientRect().top
|
||||
window.scrollBy(0, newTop - initialTop)
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const usePreferredLanguageStore = create((set) => ({
|
||||
preferredLanguages: [],
|
||||
addPreferredLanguage: (language) =>
|
||||
set((state) => ({
|
||||
preferredLanguages: [
|
||||
...state.preferredLanguages.filter(
|
||||
(preferredLanguage) => preferredLanguage !== language
|
||||
),
|
||||
language,
|
||||
],
|
||||
})),
|
||||
}))
|
||||
|
||||
function useTabGroupProps(availableLanguages) {
|
||||
let { preferredLanguages, addPreferredLanguage } = usePreferredLanguageStore()
|
||||
let [selectedIndex, setSelectedIndex] = useState(0)
|
||||
let activeLanguage = [...availableLanguages].sort(
|
||||
(a, z) => preferredLanguages.indexOf(z) - preferredLanguages.indexOf(a)
|
||||
)[0]
|
||||
let languageIndex = availableLanguages.indexOf(activeLanguage)
|
||||
let newSelectedIndex = languageIndex === -1 ? selectedIndex : languageIndex
|
||||
if (newSelectedIndex !== selectedIndex) {
|
||||
setSelectedIndex(newSelectedIndex)
|
||||
}
|
||||
|
||||
let { positionRef, preventLayoutShift } = usePreventLayoutShift()
|
||||
|
||||
return {
|
||||
as: 'div',
|
||||
ref: positionRef,
|
||||
selectedIndex,
|
||||
onChange: (newSelectedIndex) => {
|
||||
preventLayoutShift(() =>
|
||||
addPreferredLanguage(availableLanguages[newSelectedIndex])
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const CodeGroupContext = createContext(false)
|
||||
|
||||
export function CodeGroup({ children, title, ...props }) {
|
||||
let languages = Children.map(children, (child) => getPanelTitle(child.props))
|
||||
let tabGroupProps = useTabGroupProps(languages)
|
||||
let hasTabs = Children.count(children) > 1
|
||||
let Container = hasTabs ? Tab.Group : 'div'
|
||||
let containerProps = hasTabs ? tabGroupProps : {}
|
||||
let headerProps = hasTabs
|
||||
? { selectedIndex: tabGroupProps.selectedIndex }
|
||||
: {}
|
||||
|
||||
return (
|
||||
<CodeGroupContext.Provider value={true}>
|
||||
<Container
|
||||
{...containerProps}
|
||||
className="not-prose my-6 overflow-hidden rounded-2xl bg-zinc-900 shadow-md dark:ring-1 dark:ring-white/10"
|
||||
>
|
||||
<CodeGroupHeader title={title} {...headerProps}>
|
||||
{children}
|
||||
</CodeGroupHeader>
|
||||
<CodeGroupPanels {...props}>{children}</CodeGroupPanels>
|
||||
</Container>
|
||||
</CodeGroupContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function Code({ children, ...props }) {
|
||||
let isGrouped = useContext(CodeGroupContext)
|
||||
|
||||
if (isGrouped) {
|
||||
return <code {...props} dangerouslySetInnerHTML={{ __html: children }} />
|
||||
}
|
||||
|
||||
return <code {...props}>{children}</code>
|
||||
}
|
||||
|
||||
export function Pre({ children, ...props }) {
|
||||
let isGrouped = useContext(CodeGroupContext)
|
||||
|
||||
if (isGrouped) {
|
||||
return children
|
||||
}
|
||||
|
||||
return <CodeGroup {...props}>{children}</CodeGroup>
|
||||
}
|
|
@ -1,228 +0,0 @@
|
|||
import { forwardRef, Fragment, useState } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
import { Button } from '@/components/Button'
|
||||
import { navigation } from '@/components/Navigation'
|
||||
|
||||
function CheckIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<circle cx="10" cy="10" r="10" strokeWidth="0" />
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="m6.75 10.813 2.438 2.437c1.218-4.469 4.062-6.5 4.062-6.5"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function FeedbackButton(props) {
|
||||
return (
|
||||
<button
|
||||
type="submit"
|
||||
className="px-3 text-sm font-medium text-zinc-600 transition hover:bg-zinc-900/2.5 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-white/5 dark:hover:text-white"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const FeedbackForm = forwardRef(function FeedbackForm({ onSubmit }, ref) {
|
||||
return (
|
||||
<form
|
||||
ref={ref}
|
||||
onSubmit={onSubmit}
|
||||
className="absolute inset-0 flex items-center justify-center gap-6 md:justify-start"
|
||||
>
|
||||
<p className="text-sm text-zinc-600 dark:text-zinc-400">
|
||||
(Not hooked up) Was this page helpful?
|
||||
</p>
|
||||
<div className="group grid h-8 grid-cols-[1fr,1px,1fr] overflow-hidden rounded-full border border-zinc-900/10 dark:border-white/10">
|
||||
<FeedbackButton data-response="yes">Yes</FeedbackButton>
|
||||
<div className="bg-zinc-900/10 dark:bg-white/10" />
|
||||
<FeedbackButton data-response="no">No</FeedbackButton>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
})
|
||||
|
||||
const FeedbackThanks = forwardRef(function FeedbackThanks(_props, ref) {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="absolute inset-0 flex justify-center md:justify-start"
|
||||
>
|
||||
<div className="flex items-center gap-3 rounded-full bg-emerald-50/50 py-1 pl-1.5 pr-3 text-sm text-emerald-900 ring-1 ring-inset ring-emerald-500/20 dark:bg-emerald-500/5 dark:text-emerald-200 dark:ring-emerald-500/30">
|
||||
<CheckIcon className="h-5 w-5 flex-none fill-emerald-500 stroke-white dark:fill-emerald-200/20 dark:stroke-emerald-200" />
|
||||
(Not hooked up) Thanks for your feedback!
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
function Feedback() {
|
||||
let [submitted, setSubmitted] = useState(false)
|
||||
|
||||
function onSubmit(event) {
|
||||
event.preventDefault()
|
||||
|
||||
// event.nativeEvent.submitter.dataset.response
|
||||
// => "yes" or "no"
|
||||
|
||||
setSubmitted(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative h-8">
|
||||
<Transition
|
||||
show={!submitted}
|
||||
as={Fragment}
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
leave="pointer-events-none duration-300"
|
||||
>
|
||||
<FeedbackForm onSubmit={onSubmit} />
|
||||
</Transition>
|
||||
<Transition
|
||||
show={submitted}
|
||||
as={Fragment}
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
enter="delay-150 duration-300"
|
||||
>
|
||||
<FeedbackThanks />
|
||||
</Transition>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function PageLink({ label, page, previous = false }) {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
href={page.href}
|
||||
aria-label={`${label}: ${page.title}`}
|
||||
variant="secondary"
|
||||
arrow={previous ? 'left' : 'right'}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
<Link
|
||||
href={page.href}
|
||||
tabIndex={-1}
|
||||
aria-hidden="true"
|
||||
className="text-base font-semibold text-zinc-900 transition hover:text-zinc-600 dark:text-white dark:hover:text-zinc-300"
|
||||
>
|
||||
{page.title}
|
||||
</Link>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function PageNavigation() {
|
||||
let router = useRouter()
|
||||
let allPages = navigation.flatMap((group) => group.links)
|
||||
let currentPageIndex = allPages.findIndex(
|
||||
(page) => page.href === router.pathname
|
||||
)
|
||||
|
||||
if (currentPageIndex === -1) {
|
||||
return null
|
||||
}
|
||||
|
||||
let previousPage = allPages[currentPageIndex - 1]
|
||||
let nextPage = allPages[currentPageIndex + 1]
|
||||
|
||||
if (!previousPage && !nextPage) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex">
|
||||
{previousPage && (
|
||||
<div className="flex flex-col items-start gap-3">
|
||||
<PageLink label="Previous" page={previousPage} previous />
|
||||
</div>
|
||||
)}
|
||||
{nextPage && (
|
||||
<div className="ml-auto flex flex-col items-end gap-3">
|
||||
<PageLink label="Next" page={nextPage} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function TwitterIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path d="M16.712 6.652c.01.146.01.29.01.436 0 4.449-3.267 9.579-9.242 9.579v-.003a8.963 8.963 0 0 1-4.98-1.509 6.379 6.379 0 0 0 4.807-1.396c-1.39-.027-2.608-.966-3.035-2.337.487.097.99.077 1.467-.059-1.514-.316-2.606-1.696-2.606-3.3v-.041c.45.26.956.404 1.475.42C3.18 7.454 2.74 5.486 3.602 3.947c1.65 2.104 4.083 3.382 6.695 3.517a3.446 3.446 0 0 1 .94-3.217 3.172 3.172 0 0 1 4.596.148 6.38 6.38 0 0 0 2.063-.817 3.357 3.357 0 0 1-1.428 1.861 6.283 6.283 0 0 0 1.865-.53 6.735 6.735 0 0 1-1.62 1.744Z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function GitHubIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M10 1.667c-4.605 0-8.334 3.823-8.334 8.544 0 3.78 2.385 6.974 5.698 8.106.417.075.573-.182.573-.406 0-.203-.011-.875-.011-1.592-2.093.397-2.635-.522-2.802-1.002-.094-.246-.5-1.005-.854-1.207-.291-.16-.708-.556-.01-.567.656-.01 1.124.62 1.281.876.75 1.292 1.948.93 2.427.705.073-.555.291-.93.531-1.143-1.854-.213-3.791-.95-3.791-4.218 0-.929.322-1.698.854-2.296-.083-.214-.375-1.09.083-2.265 0 0 .698-.224 2.292.876a7.576 7.576 0 0 1 2.083-.288c.709 0 1.417.096 2.084.288 1.593-1.11 2.291-.875 2.291-.875.459 1.174.167 2.05.084 2.263.53.599.854 1.357.854 2.297 0 3.278-1.948 4.005-3.802 4.219.302.266.563.78.563 1.58 0 1.143-.011 2.061-.011 2.35 0 .224.156.491.573.405a8.365 8.365 0 0 0 4.11-3.116 8.707 8.707 0 0 0 1.567-4.99c0-4.721-3.73-8.545-8.334-8.545Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function DiscordIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path d="M16.238 4.515a14.842 14.842 0 0 0-3.664-1.136.055.055 0 0 0-.059.027 10.35 10.35 0 0 0-.456.938 13.702 13.702 0 0 0-4.115 0 9.479 9.479 0 0 0-.464-.938.058.058 0 0 0-.058-.027c-1.266.218-2.497.6-3.664 1.136a.052.052 0 0 0-.024.02C1.4 8.023.76 11.424 1.074 14.782a.062.062 0 0 0 .024.042 14.923 14.923 0 0 0 4.494 2.272.058.058 0 0 0 .064-.02c.346-.473.654-.972.92-1.496a.057.057 0 0 0-.032-.08 9.83 9.83 0 0 1-1.404-.669.058.058 0 0 1-.029-.046.058.058 0 0 1 .023-.05c.094-.07.189-.144.279-.218a.056.056 0 0 1 .058-.008c2.946 1.345 6.135 1.345 9.046 0a.056.056 0 0 1 .059.007c.09.074.184.149.28.22a.058.058 0 0 1 .023.049.059.059 0 0 1-.028.046 9.224 9.224 0 0 1-1.405.669.058.058 0 0 0-.033.033.056.056 0 0 0 .002.047c.27.523.58 1.022.92 1.495a.056.056 0 0 0 .062.021 14.878 14.878 0 0 0 4.502-2.272.055.055 0 0 0 .016-.018.056.056 0 0 0 .008-.023c.375-3.883-.63-7.256-2.662-10.246a.046.046 0 0 0-.023-.021Zm-9.223 8.221c-.887 0-1.618-.814-1.618-1.814s.717-1.814 1.618-1.814c.908 0 1.632.821 1.618 1.814 0 1-.717 1.814-1.618 1.814Zm5.981 0c-.887 0-1.618-.814-1.618-1.814s.717-1.814 1.618-1.814c.908 0 1.632.821 1.618 1.814 0 1-.71 1.814-1.618 1.814Z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function SocialLink({ href, icon: Icon, children }) {
|
||||
return (
|
||||
<Link href={href} className="group">
|
||||
<span className="sr-only">{children}</span>
|
||||
<Icon className="h-5 w-5 fill-zinc-700 transition group-hover:fill-zinc-900 dark:group-hover:fill-zinc-500" />
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
function SmallPrint() {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-between gap-5 border-t border-zinc-900/5 pt-8 dark:border-white/5 sm:flex-row">
|
||||
<p className="text-xs text-zinc-600 dark:text-zinc-400">
|
||||
© Copyright {new Date().getFullYear()}. All rights reserved.
|
||||
</p>
|
||||
<div className="flex gap-4">
|
||||
<SocialLink href="#" icon={TwitterIcon}>
|
||||
Follow us on Twitter
|
||||
</SocialLink>
|
||||
<SocialLink href="#" icon={GitHubIcon}>
|
||||
Follow us on GitHub
|
||||
</SocialLink>
|
||||
<SocialLink href="#" icon={DiscordIcon}>
|
||||
Join our Discord server
|
||||
</SocialLink>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Footer() {
|
||||
let router = useRouter()
|
||||
|
||||
return (
|
||||
<footer className="mx-auto max-w-2xl space-y-10 pb-16 lg:max-w-5xl">
|
||||
<Feedback key={router.pathname} />
|
||||
<PageNavigation />
|
||||
<SmallPrint />
|
||||
</footer>
|
||||
)
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
import { useId } from 'react'
|
||||
|
||||
export function GridPattern({ width, height, x, y, squares, ...props }) {
|
||||
let patternId = useId()
|
||||
|
||||
return (
|
||||
<svg aria-hidden="true" {...props}>
|
||||
<defs>
|
||||
<pattern
|
||||
id={patternId}
|
||||
width={width}
|
||||
height={height}
|
||||
patternUnits="userSpaceOnUse"
|
||||
x={x}
|
||||
y={y}
|
||||
>
|
||||
<path d={`M.5 ${height}V.5H${width}`} fill="none" />
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect
|
||||
width="100%"
|
||||
height="100%"
|
||||
strokeWidth={0}
|
||||
fill={`url(#${patternId})`}
|
||||
/>
|
||||
{squares && (
|
||||
<svg x={x} y={y} className="overflow-visible">
|
||||
{squares.map(([x, y]) => (
|
||||
<rect
|
||||
strokeWidth="0"
|
||||
key={`${x}-${y}`}
|
||||
width={width + 1}
|
||||
height={height + 1}
|
||||
x={x * width}
|
||||
y={y * height}
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
)}
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
import { Button } from '@/components/Button'
|
||||
import { Heading } from '@/components/Heading'
|
||||
|
||||
const guides = [
|
||||
{
|
||||
href: '/authentication',
|
||||
name: 'Authentication',
|
||||
description: 'Learn how to authenticate your API requests.',
|
||||
},
|
||||
{
|
||||
href: '/pagination',
|
||||
name: 'Pagination',
|
||||
description: 'Understand how to work with paginated responses.',
|
||||
},
|
||||
{
|
||||
href: '/errors',
|
||||
name: 'Errors',
|
||||
description:
|
||||
'Read about the different types of errors returned by the API.',
|
||||
},
|
||||
{
|
||||
href: '/webhooks',
|
||||
name: 'Webhooks',
|
||||
description:
|
||||
'Learn how to programmatically configure webhooks for your app.',
|
||||
},
|
||||
]
|
||||
|
||||
export function Guides() {
|
||||
return (
|
||||
<div className="my-16 xl:max-w-none">
|
||||
<Heading level={2} id="guides">
|
||||
Guides
|
||||
</Heading>
|
||||
<div className="not-prose mt-4 grid grid-cols-1 gap-8 border-t border-zinc-900/5 pt-10 dark:border-white/5 sm:grid-cols-2 xl:grid-cols-4">
|
||||
{guides.map((guide) => (
|
||||
<div key={guide.href}>
|
||||
<h3 className="text-sm font-semibold text-zinc-900 dark:text-white">
|
||||
{guide.name}
|
||||
</h3>
|
||||
<p className="mt-1 text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{guide.description}
|
||||
</p>
|
||||
<p className="mt-4">
|
||||
<Button href={guide.href} variant="text" arrow="right">
|
||||
Read more
|
||||
</Button>
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
import { forwardRef } from 'react'
|
||||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
import { motion, useScroll, useTransform } from 'framer-motion'
|
||||
|
||||
import { Button } from '@/components/Button'
|
||||
import { Logo } from '@/components/Logo'
|
||||
import {
|
||||
MobileNavigation,
|
||||
useIsInsideMobileNavigation,
|
||||
} from '@/components/MobileNavigation'
|
||||
import { useMobileNavigationStore } from '@/components/MobileNavigation'
|
||||
import { ModeToggle } from '@/components/ModeToggle'
|
||||
|
||||
function TopLevelNavItem({ href, children }) {
|
||||
return (
|
||||
<li>
|
||||
<Link
|
||||
href={href}
|
||||
className="text-sm leading-5 text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white"
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
export const Header = forwardRef(function Header({ className }, ref) {
|
||||
let { isOpen: mobileNavIsOpen } = useMobileNavigationStore()
|
||||
let isInsideMobileNavigation = useIsInsideMobileNavigation()
|
||||
|
||||
let { scrollY } = useScroll()
|
||||
let bgOpacityLight = useTransform(scrollY, [0, 72], [0.5, 0.9])
|
||||
let bgOpacityDark = useTransform(scrollY, [0, 72], [0.2, 0.8])
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
ref={ref}
|
||||
className={clsx(
|
||||
className,
|
||||
'fixed inset-x-0 top-0 z-50 flex h-14 items-center justify-between gap-12 px-4 transition sm:px-6 lg:left-72 lg:z-30 lg:px-8 xl:left-80',
|
||||
!isInsideMobileNavigation &&
|
||||
'backdrop-blur-sm dark:backdrop-blur lg:left-72 xl:left-80',
|
||||
isInsideMobileNavigation
|
||||
? 'bg-white dark:bg-zinc-900'
|
||||
: 'bg-white/[var(--bg-opacity-light)] dark:bg-zinc-900/[var(--bg-opacity-dark)]'
|
||||
)}
|
||||
style={{
|
||||
'--bg-opacity-light': bgOpacityLight,
|
||||
'--bg-opacity-dark': bgOpacityDark,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
'absolute inset-x-0 top-full h-px transition',
|
||||
(isInsideMobileNavigation || !mobileNavIsOpen) &&
|
||||
'bg-zinc-900/7.5 dark:bg-white/7.5'
|
||||
)}
|
||||
/>
|
||||
<div className="flex items-center gap-5 lg:hidden">
|
||||
<MobileNavigation />
|
||||
<Link href="/" aria-label="Home">
|
||||
<Logo className="h-6" />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex items-center gap-5">
|
||||
<nav className="hidden md:block">
|
||||
<ul role="list" className="flex items-center gap-8">
|
||||
<TopLevelNavItem href="/">API</TopLevelNavItem>
|
||||
<TopLevelNavItem href="#">Documentation</TopLevelNavItem>
|
||||
<TopLevelNavItem href="#">Support</TopLevelNavItem>
|
||||
</ul>
|
||||
</nav>
|
||||
<div className="hidden md:block md:h-5 md:w-px md:bg-zinc-900/10 md:dark:bg-white/15" />
|
||||
<div className="flex gap-4">
|
||||
<ModeToggle />
|
||||
</div>
|
||||
<div className="hidden min-[416px]:contents">
|
||||
<Button href="#">Sign in</Button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
})
|
|
@ -1,102 +0,0 @@
|
|||
import { useEffect, useRef } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { useInView } from 'framer-motion'
|
||||
|
||||
import { useSectionStore } from '@/components/SectionProvider'
|
||||
import { Tag } from '@/components/Tag'
|
||||
import { remToPx } from '@/lib/remToPx'
|
||||
|
||||
function AnchorIcon(props) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
aria-hidden="true"
|
||||
{...props}
|
||||
>
|
||||
<path d="m6.5 11.5-.964-.964a3.535 3.535 0 1 1 5-5l.964.964m2 2 .964.964a3.536 3.536 0 0 1-5 5L8.5 13.5m0-5 3 3" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function Eyebrow({ tag, label }) {
|
||||
if (!tag && !label) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-x-3">
|
||||
{tag && <Tag>{tag}</Tag>}
|
||||
{tag && label && (
|
||||
<span className="h-0.5 w-0.5 rounded-full bg-zinc-300 dark:bg-zinc-600" />
|
||||
)}
|
||||
{label && (
|
||||
<span className="font-mono text-xs text-zinc-400">{label}</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Anchor({ id, inView, children }) {
|
||||
return (
|
||||
<Link
|
||||
href={`#${id}`}
|
||||
className="group text-inherit no-underline hover:text-inherit"
|
||||
>
|
||||
{inView && (
|
||||
<div className="absolute ml-[calc(-1*var(--width))] mt-1 hidden w-[var(--width)] opacity-0 transition [--width:calc(2.625rem+0.5px+50%-min(50%,calc(theme(maxWidth.lg)+theme(spacing.8))))] group-hover:opacity-100 group-focus:opacity-100 md:block lg:z-50 2xl:[--width:theme(spacing.10)]">
|
||||
<div className="group/anchor block h-5 w-5 rounded-lg bg-zinc-50 ring-1 ring-inset ring-zinc-300 transition hover:ring-zinc-500 dark:bg-zinc-800 dark:ring-zinc-700 dark:hover:bg-zinc-700 dark:hover:ring-zinc-600">
|
||||
<AnchorIcon className="h-5 w-5 stroke-zinc-500 transition dark:stroke-zinc-400 dark:group-hover/anchor:stroke-white" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export function Heading({
|
||||
level = 2,
|
||||
children,
|
||||
id,
|
||||
tag,
|
||||
label,
|
||||
anchor = true,
|
||||
...props
|
||||
}) {
|
||||
let Component = `h${level}`
|
||||
let ref = useRef()
|
||||
let registerHeading = useSectionStore((s) => s.registerHeading)
|
||||
|
||||
let inView = useInView(ref, {
|
||||
margin: `${remToPx(-3.5)}px 0px 0px 0px`,
|
||||
amount: 'all',
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (level === 2) {
|
||||
registerHeading({ id, ref, offsetRem: tag || label ? 8 : 6 })
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Eyebrow tag={tag} label={label} />
|
||||
<Component
|
||||
ref={ref}
|
||||
id={anchor ? id : undefined}
|
||||
className={tag || label ? 'mt-2 scroll-mt-32' : 'scroll-mt-24'}
|
||||
{...props}
|
||||
>
|
||||
{anchor ? (
|
||||
<Anchor id={id} inView={inView}>
|
||||
{children}
|
||||
</Anchor>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</Component>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
import { GridPattern } from '@/components/GridPattern'
|
||||
|
||||
export function HeroPattern() {
|
||||
return (
|
||||
<div className="absolute inset-0 -z-10 mx-0 max-w-none overflow-hidden">
|
||||
<div className="absolute left-1/2 top-0 ml-[-38rem] h-[25rem] w-[81.25rem] dark:[mask-image:linear-gradient(white,transparent)]">
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-[#36b49f] to-[#DBFF75] opacity-40 [mask-image:radial-gradient(farthest-side_at_top,white,transparent)] dark:from-[#36b49f]/30 dark:to-[#DBFF75]/30 dark:opacity-100">
|
||||
<GridPattern
|
||||
width={72}
|
||||
height={56}
|
||||
x="-12"
|
||||
y="4"
|
||||
squares={[
|
||||
[4, 3],
|
||||
[2, 1],
|
||||
[7, 3],
|
||||
[10, 6],
|
||||
]}
|
||||
className="absolute inset-x-0 inset-y-[-50%] h-[200%] w-full skew-y-[-18deg] fill-black/40 stroke-black/50 mix-blend-overlay dark:fill-white/2.5 dark:stroke-white/5"
|
||||
/>
|
||||
</div>
|
||||
<svg
|
||||
viewBox="0 0 1113 440"
|
||||
aria-hidden="true"
|
||||
className="absolute left-1/2 top-0 ml-[-19rem] w-[69.5625rem] fill-white blur-[26px] dark:hidden"
|
||||
>
|
||||
<path d="M.016 439.5s-9.5-300 434-300S882.516 20 882.516 20V0h230.004v439.5H.016Z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
import Link from 'next/link'
|
||||
import { motion } from 'framer-motion'
|
||||
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { Header } from '@/components/Header'
|
||||
import { Logo } from '@/components/Logo'
|
||||
import { Navigation } from '@/components/Navigation'
|
||||
import { Prose } from '@/components/Prose'
|
||||
import { SectionProvider } from '@/components/SectionProvider'
|
||||
|
||||
export function Layout({ children, sections = [] }) {
|
||||
return (
|
||||
<SectionProvider sections={sections}>
|
||||
<div className="lg:ml-72 xl:ml-80">
|
||||
<motion.header
|
||||
layoutScroll
|
||||
className="contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex"
|
||||
>
|
||||
<div className="contents lg:pointer-events-auto lg:block lg:w-72 lg:overflow-y-auto lg:border-r lg:border-zinc-900/10 lg:px-6 lg:pb-8 lg:pt-4 lg:dark:border-white/10 xl:w-80">
|
||||
<div className="hidden lg:flex">
|
||||
<Link href="/" aria-label="Home">
|
||||
<Logo className="h-6" />
|
||||
</Link>
|
||||
</div>
|
||||
<Header />
|
||||
<Navigation className="hidden lg:mt-10 lg:block" />
|
||||
</div>
|
||||
</motion.header>
|
||||
<div className="relative px-4 pt-14 sm:px-6 lg:px-8">
|
||||
<main className="py-16">
|
||||
<Prose as="article">{children}</Prose>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
</SectionProvider>
|
||||
)
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
import Image from 'next/image'
|
||||
|
||||
import { Button } from '@/components/Button'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import logoGo from '@/images/logos/go.svg'
|
||||
import logoNode from '@/images/logos/node.svg'
|
||||
import logoPhp from '@/images/logos/php.svg'
|
||||
import logoPython from '@/images/logos/python.svg'
|
||||
import logoRuby from '@/images/logos/ruby.svg'
|
||||
|
||||
const libraries = [
|
||||
{
|
||||
href: '#',
|
||||
name: 'PHP',
|
||||
description:
|
||||
'A popular general-purpose scripting language that is especially suited to web development.',
|
||||
logo: logoPhp,
|
||||
},
|
||||
{
|
||||
href: '#',
|
||||
name: 'Ruby',
|
||||
description:
|
||||
'A dynamic, open source programming language with a focus on simplicity and productivity.',
|
||||
logo: logoRuby,
|
||||
},
|
||||
{
|
||||
href: '#',
|
||||
name: 'Node.js',
|
||||
description:
|
||||
'Node.js® is an open-source, cross-platform JavaScript runtime environment.',
|
||||
logo: logoNode,
|
||||
},
|
||||
{
|
||||
href: '#',
|
||||
name: 'Python',
|
||||
description:
|
||||
'Python is a programming language that lets you work quickly and integrate systems more effectively.',
|
||||
logo: logoPython,
|
||||
},
|
||||
{
|
||||
href: '#',
|
||||
name: 'Go',
|
||||
description:
|
||||
'An open-source programming language supported by Google with built-in concurrency.',
|
||||
logo: logoGo,
|
||||
},
|
||||
]
|
||||
|
||||
export function Libraries() {
|
||||
return (
|
||||
<div className="my-16 xl:max-w-none">
|
||||
<Heading level={2} id="official-libraries">
|
||||
Official libraries
|
||||
</Heading>
|
||||
<div className="not-prose mt-4 grid grid-cols-1 gap-x-6 gap-y-10 border-t border-zinc-900/5 pt-10 dark:border-white/5 sm:grid-cols-2 xl:max-w-none xl:grid-cols-3">
|
||||
{libraries.map((library) => (
|
||||
<div key={library.name} className="flex flex-row-reverse gap-6">
|
||||
<div className="flex-auto">
|
||||
<h3 className="text-sm font-semibold text-zinc-900 dark:text-white">
|
||||
{library.name}
|
||||
</h3>
|
||||
<p className="mt-1 text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{library.description}
|
||||
</p>
|
||||
<p className="mt-4">
|
||||
<Button href={library.href} variant="text" arrow="right">
|
||||
Read more
|
||||
</Button>
|
||||
</p>
|
||||
</div>
|
||||
<Image
|
||||
src={library.logo}
|
||||
alt=""
|
||||
className="h-12 w-12"
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function Logo(props) {
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
<svg aria-hidden="true" {...props} viewBox="0 0 24 24">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M1.34266 1.34265V18.7972H0V1.20839C0 0.541014 0.541015 0 1.20839 0H23.0045C23.7222 0 24.0817 0.867745 23.5742 1.37523L10.5526 14.3968H14.3496V12.7552H15.6923V14.9339C15.6923 15.3788 15.3316 15.7395 14.8867 15.7395H9.20989L6.44591 18.5035H18.5035V8.979H19.8462V18.9062C19.8462 19.4253 19.4254 19.8461 18.9063 19.8461H5.10325L2.29206 22.6573H22.6573V5.20278H24V22.7916C24 23.4589 23.459 23.9999 22.7916 23.9999H0.995475C0.277776 23.9999 -0.0816697 23.1322 0.425834 22.6247C0.425835 22.6247 0.425836 22.6247 0.425838 22.6247L13.4002 9.65033H9.65035V11.2447H8.30769V9.11326C8.30769 8.66835 8.66837 8.30767 9.11329 8.30767H14.7429L17.5541 5.49649H5.4965V15.0209H4.15385V5.09369C4.15385 4.57462 4.57464 4.15384 5.09371 4.15384H18.8968L21.7079 1.34265H1.34266Z"
|
||||
className="fill-zinc-900 dark:fill-white"
|
||||
/>
|
||||
</svg>
|
||||
<div className="font-mono text-sm text-zinc-900 dark:text-white">
|
||||
Zed Internal
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
import { createContext, Fragment, useContext } from 'react'
|
||||
import { Dialog, Transition } from '@headlessui/react'
|
||||
import { motion } from 'framer-motion'
|
||||
import { create } from 'zustand'
|
||||
|
||||
import { Header } from '@/components/Header'
|
||||
import { Navigation } from '@/components/Navigation'
|
||||
|
||||
function MenuIcon(props) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 10 9"
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
aria-hidden="true"
|
||||
{...props}
|
||||
>
|
||||
<path d="M.5 1h9M.5 8h9M.5 4.5h9" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function XIcon(props) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 10 9"
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
aria-hidden="true"
|
||||
{...props}
|
||||
>
|
||||
<path d="m1.5 1 7 7M8.5 1l-7 7" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
const IsInsideMobileNavigationContext = createContext(false)
|
||||
|
||||
export function useIsInsideMobileNavigation() {
|
||||
return useContext(IsInsideMobileNavigationContext)
|
||||
}
|
||||
|
||||
export const useMobileNavigationStore = create((set) => ({
|
||||
isOpen: false,
|
||||
open: () => set({ isOpen: true }),
|
||||
close: () => set({ isOpen: false }),
|
||||
toggle: () => set((state) => ({ isOpen: !state.isOpen })),
|
||||
}))
|
||||
|
||||
export function MobileNavigation() {
|
||||
let isInsideMobileNavigation = useIsInsideMobileNavigation()
|
||||
let { isOpen, toggle, close } = useMobileNavigationStore()
|
||||
let ToggleIcon = isOpen ? XIcon : MenuIcon
|
||||
|
||||
return (
|
||||
<IsInsideMobileNavigationContext.Provider value={true}>
|
||||
<button
|
||||
type="button"
|
||||
className="flex h-6 w-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5"
|
||||
aria-label="Toggle navigation"
|
||||
onClick={toggle}
|
||||
>
|
||||
<ToggleIcon className="w-2.5 stroke-zinc-900 dark:stroke-white" />
|
||||
</button>
|
||||
{!isInsideMobileNavigation && (
|
||||
<Transition.Root show={isOpen} as={Fragment}>
|
||||
<Dialog onClose={close} className="fixed inset-0 z-50 lg:hidden">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="duration-300 ease-out"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="duration-200 ease-in"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 top-14 bg-zinc-400/20 backdrop-blur-sm dark:bg-black/40" />
|
||||
</Transition.Child>
|
||||
|
||||
<Dialog.Panel>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="duration-300 ease-out"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="duration-200 ease-in"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<Header />
|
||||
</Transition.Child>
|
||||
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="duration-500 ease-in-out"
|
||||
enterFrom="-translate-x-full"
|
||||
enterTo="translate-x-0"
|
||||
leave="duration-500 ease-in-out"
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="-translate-x-full"
|
||||
>
|
||||
<motion.div
|
||||
layoutScroll
|
||||
className="fixed bottom-0 left-0 top-14 w-full overflow-y-auto bg-white px-4 pb-4 pt-6 shadow-lg shadow-zinc-900/10 ring-1 ring-zinc-900/7.5 dark:bg-zinc-900 dark:ring-zinc-800 min-[416px]:max-w-sm sm:px-6 sm:pb-10"
|
||||
>
|
||||
<Navigation />
|
||||
</motion.div>
|
||||
</Transition.Child>
|
||||
</Dialog.Panel>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
)}
|
||||
</IsInsideMobileNavigationContext.Provider>
|
||||
)
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
function SunIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" {...props}>
|
||||
<path d="M12.5 10a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z" />
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
d="M10 5.5v-1M13.182 6.818l.707-.707M14.5 10h1M13.182 13.182l.707.707M10 15.5v-1M6.11 13.889l.708-.707M4.5 10h1M6.11 6.111l.708.707"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function MoonIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" {...props}>
|
||||
<path d="M15.224 11.724a5.5 5.5 0 0 1-6.949-6.949 5.5 5.5 0 1 0 6.949 6.949Z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function ModeToggle() {
|
||||
function disableTransitionsTemporarily() {
|
||||
document.documentElement.classList.add('[&_*]:!transition-none')
|
||||
window.setTimeout(() => {
|
||||
document.documentElement.classList.remove('[&_*]:!transition-none')
|
||||
}, 0)
|
||||
}
|
||||
|
||||
function toggleMode() {
|
||||
disableTransitionsTemporarily()
|
||||
|
||||
let darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
let isSystemDarkMode = darkModeMediaQuery.matches
|
||||
let isDarkMode = document.documentElement.classList.toggle('dark')
|
||||
|
||||
if (isDarkMode === isSystemDarkMode) {
|
||||
delete window.localStorage.isDarkMode
|
||||
} else {
|
||||
window.localStorage.isDarkMode = isDarkMode
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="flex h-6 w-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5"
|
||||
aria-label="Toggle dark mode"
|
||||
onClick={toggleMode}
|
||||
>
|
||||
<SunIcon className="h-5 w-5 stroke-zinc-900 dark:hidden" />
|
||||
<MoonIcon className="hidden h-5 w-5 stroke-white dark:block" />
|
||||
</button>
|
||||
)
|
||||
}
|
|
@ -1,230 +0,0 @@
|
|||
import { useRef } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import clsx from 'clsx'
|
||||
import { AnimatePresence, motion, useIsPresent } from 'framer-motion'
|
||||
|
||||
import { Button } from '@/components/Button'
|
||||
import { useIsInsideMobileNavigation } from '@/components/MobileNavigation'
|
||||
import { useSectionStore } from '@/components/SectionProvider'
|
||||
import { Tag } from '@/components/Tag'
|
||||
import { remToPx } from '@/lib/remToPx'
|
||||
|
||||
function useInitialValue(value, condition = true) {
|
||||
let initialValue = useRef(value).current
|
||||
return condition ? initialValue : value
|
||||
}
|
||||
|
||||
function TopLevelNavItem({ href, children }) {
|
||||
return (
|
||||
<li className="md:hidden">
|
||||
<Link
|
||||
href={href}
|
||||
className="block py-1 text-sm text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white"
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
function NavLink({ href, tag, active, isAnchorLink = false, children }) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
aria-current={active ? 'page' : undefined}
|
||||
className={clsx(
|
||||
'flex justify-between gap-2 py-1 pr-3 text-sm transition',
|
||||
isAnchorLink ? 'pl-7' : 'pl-4',
|
||||
active
|
||||
? 'text-zinc-900 dark:text-white'
|
||||
: 'text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white'
|
||||
)}
|
||||
>
|
||||
<span className="truncate">{children}</span>
|
||||
{tag && (
|
||||
<Tag variant="small" color="zinc">
|
||||
{tag}
|
||||
</Tag>
|
||||
)}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
function VisibleSectionHighlight({ group, pathname }) {
|
||||
let [sections, visibleSections] = useInitialValue(
|
||||
[
|
||||
useSectionStore((s) => s.sections),
|
||||
useSectionStore((s) => s.visibleSections),
|
||||
],
|
||||
useIsInsideMobileNavigation()
|
||||
)
|
||||
|
||||
let isPresent = useIsPresent()
|
||||
let firstVisibleSectionIndex = Math.max(
|
||||
0,
|
||||
[{ id: '_top' }, ...sections].findIndex(
|
||||
(section) => section.id === visibleSections[0]
|
||||
)
|
||||
)
|
||||
let itemHeight = remToPx(2)
|
||||
let height = isPresent
|
||||
? Math.max(1, visibleSections.length) * itemHeight
|
||||
: itemHeight
|
||||
let top =
|
||||
group.links.findIndex((link) => link.href === pathname) * itemHeight +
|
||||
firstVisibleSectionIndex * itemHeight
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
layout
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1, transition: { delay: 0.2 } }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="absolute inset-x-0 top-0 bg-zinc-800/2.5 will-change-transform dark:bg-white/2.5"
|
||||
style={{ borderRadius: 8, height, top }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function ActivePageMarker({ group, pathname }) {
|
||||
let itemHeight = remToPx(2)
|
||||
let offset = remToPx(0.25)
|
||||
let activePageIndex = group.links.findIndex((link) => link.href === pathname)
|
||||
let top = offset + activePageIndex * itemHeight
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
layout
|
||||
className="absolute left-2 h-6 w-px bg-emerald-500"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1, transition: { delay: 0.2 } }}
|
||||
exit={{ opacity: 0 }}
|
||||
style={{ top }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function NavigationGroup({ group, className }) {
|
||||
// If this is the mobile navigation then we always render the initial
|
||||
// state, so that the state does not change during the close animation.
|
||||
// The state will still update when we re-open (re-render) the navigation.
|
||||
let isInsideMobileNavigation = useIsInsideMobileNavigation()
|
||||
let [router, sections] = useInitialValue(
|
||||
[useRouter(), useSectionStore((s) => s.sections)],
|
||||
isInsideMobileNavigation
|
||||
)
|
||||
|
||||
let isActiveGroup =
|
||||
group.links.findIndex((link) => link.href === router.pathname) !== -1
|
||||
|
||||
return (
|
||||
<li className={clsx('relative mt-6', className)}>
|
||||
<motion.h2
|
||||
layout="position"
|
||||
className="text-xs font-semibold text-zinc-900 dark:text-white"
|
||||
>
|
||||
{group.title}
|
||||
</motion.h2>
|
||||
<div className="relative mt-3 pl-2">
|
||||
<AnimatePresence initial={!isInsideMobileNavigation}>
|
||||
{isActiveGroup && (
|
||||
<VisibleSectionHighlight group={group} pathname={router.pathname} />
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<motion.div
|
||||
layout
|
||||
className="absolute inset-y-0 left-2 w-px bg-zinc-900/10 dark:bg-white/5"
|
||||
/>
|
||||
<AnimatePresence initial={false}>
|
||||
{isActiveGroup && (
|
||||
<ActivePageMarker group={group} pathname={router.pathname} />
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<ul role="list" className="border-l border-transparent">
|
||||
{group.links.map((link) => (
|
||||
<motion.li key={link.href} layout="position" className="relative">
|
||||
<NavLink href={link.href} active={link.href === router.pathname}>
|
||||
{link.title}
|
||||
</NavLink>
|
||||
<AnimatePresence mode="popLayout" initial={false}>
|
||||
{link.href === router.pathname && sections.length > 0 && (
|
||||
<motion.ul
|
||||
role="list"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
transition: { delay: 0.1 },
|
||||
}}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
transition: { duration: 0.15 },
|
||||
}}
|
||||
>
|
||||
{sections.map((section) => (
|
||||
<li key={section.id}>
|
||||
<NavLink
|
||||
href={`${link.href}#${section.id}`}
|
||||
tag={section.tag}
|
||||
isAnchorLink
|
||||
>
|
||||
{section.title}
|
||||
</NavLink>
|
||||
</li>
|
||||
))}
|
||||
</motion.ul>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
export const navigation = [
|
||||
{
|
||||
title: 'General',
|
||||
links: [
|
||||
{ title: 'Welcome', href: '/' },
|
||||
{ title: 'Tools', href: '/tools' },
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Zed',
|
||||
links: [{ title: 'Release Process', href: '/release-process' },
|
||||
{ title: 'Environment Setup', href: '/setup' },
|
||||
{ title: 'Backend', href: '/backend' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Design',
|
||||
links: [{ title: 'Tools', href: '/design/tools' }],
|
||||
},
|
||||
]
|
||||
|
||||
export function Navigation(props) {
|
||||
return (
|
||||
<nav {...props}>
|
||||
<ul role="list">
|
||||
<TopLevelNavItem href="/">API</TopLevelNavItem>
|
||||
<TopLevelNavItem href="#">Documentation</TopLevelNavItem>
|
||||
<TopLevelNavItem href="#">Support</TopLevelNavItem>
|
||||
{navigation.map((group, groupIndex) => (
|
||||
<NavigationGroup
|
||||
key={group.title}
|
||||
group={group}
|
||||
className={groupIndex === 0 && 'md:mt-0'}
|
||||
/>
|
||||
))}
|
||||
<li className="sticky bottom-0 z-10 mt-6 min-[416px]:hidden">
|
||||
<Button href="#" variant="filled" className="w-full">
|
||||
Sign in
|
||||
</Button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
)
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
import clsx from 'clsx'
|
||||
|
||||
export function Prose({ as: Component = 'div', className, ...props }) {
|
||||
return (
|
||||
<Component
|
||||
className={clsx(className, 'prose dark:prose-invert')}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
import Link from 'next/link'
|
||||
import { motion, useMotionTemplate, useMotionValue } from 'framer-motion'
|
||||
|
||||
import { GridPattern } from '@/components/GridPattern'
|
||||
import { Heading } from '@/components/Heading'
|
||||
import { ChatBubbleIcon } from '@/components/icons/ChatBubbleIcon'
|
||||
import { EnvelopeIcon } from '@/components/icons/EnvelopeIcon'
|
||||
import { UserIcon } from '@/components/icons/UserIcon'
|
||||
import { UsersIcon } from '@/components/icons/UsersIcon'
|
||||
|
||||
const resources = [
|
||||
{
|
||||
href: '/contacts',
|
||||
name: 'Contacts',
|
||||
description:
|
||||
'Learn about the contact model and how to create, retrieve, update, delete, and list contacts.',
|
||||
icon: UserIcon,
|
||||
pattern: {
|
||||
y: 16,
|
||||
squares: [
|
||||
[0, 1],
|
||||
[1, 3],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
href: '/conversations',
|
||||
name: 'Conversations',
|
||||
description:
|
||||
'Learn about the conversation model and how to create, retrieve, update, delete, and list conversations.',
|
||||
icon: ChatBubbleIcon,
|
||||
pattern: {
|
||||
y: -6,
|
||||
squares: [
|
||||
[-1, 2],
|
||||
[1, 3],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
href: '/messages',
|
||||
name: 'Messages',
|
||||
description:
|
||||
'Learn about the message model and how to create, retrieve, update, delete, and list messages.',
|
||||
icon: EnvelopeIcon,
|
||||
pattern: {
|
||||
y: 32,
|
||||
squares: [
|
||||
[0, 2],
|
||||
[1, 4],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
href: '/groups',
|
||||
name: 'Groups',
|
||||
description:
|
||||
'Learn about the group model and how to create, retrieve, update, delete, and list groups.',
|
||||
icon: UsersIcon,
|
||||
pattern: {
|
||||
y: 22,
|
||||
squares: [[0, 1]],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
function ResourceIcon({ icon: Icon }) {
|
||||
return (
|
||||
<div className="flex h-7 w-7 items-center justify-center rounded-full bg-zinc-900/5 ring-1 ring-zinc-900/25 backdrop-blur-[2px] transition duration-300 group-hover:bg-white/50 group-hover:ring-zinc-900/25 dark:bg-white/7.5 dark:ring-white/15 dark:group-hover:bg-emerald-300/10 dark:group-hover:ring-emerald-400">
|
||||
<Icon className="h-5 w-5 fill-zinc-700/10 stroke-zinc-700 transition-colors duration-300 group-hover:stroke-zinc-900 dark:fill-white/10 dark:stroke-zinc-400 dark:group-hover:fill-emerald-300/10 dark:group-hover:stroke-emerald-400" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function ResourcePattern({ mouseX, mouseY, ...gridProps }) {
|
||||
let maskImage = useMotionTemplate`radial-gradient(180px at ${mouseX}px ${mouseY}px, white, transparent)`
|
||||
let style = { maskImage, WebkitMaskImage: maskImage }
|
||||
|
||||
return (
|
||||
<div className="pointer-events-none">
|
||||
<div className="absolute inset-0 rounded-2xl transition duration-300 [mask-image:linear-gradient(white,transparent)] group-hover:opacity-50">
|
||||
<GridPattern
|
||||
width={72}
|
||||
height={56}
|
||||
x="50%"
|
||||
className="absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/[0.02] stroke-black/5 dark:fill-white/1 dark:stroke-white/2.5"
|
||||
{...gridProps}
|
||||
/>
|
||||
</div>
|
||||
<motion.div
|
||||
className="absolute inset-0 rounded-2xl bg-gradient-to-r from-[#D7EDEA] to-[#F4FBDF] opacity-0 transition duration-300 group-hover:opacity-100 dark:from-[#202D2E] dark:to-[#303428]"
|
||||
style={style}
|
||||
/>
|
||||
<motion.div
|
||||
className="absolute inset-0 rounded-2xl opacity-0 mix-blend-overlay transition duration-300 group-hover:opacity-100"
|
||||
style={style}
|
||||
>
|
||||
<GridPattern
|
||||
width={72}
|
||||
height={56}
|
||||
x="50%"
|
||||
className="absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/50 stroke-black/70 dark:fill-white/2.5 dark:stroke-white/10"
|
||||
{...gridProps}
|
||||
/>
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Resource({ resource }) {
|
||||
let mouseX = useMotionValue(0)
|
||||
let mouseY = useMotionValue(0)
|
||||
|
||||
function onMouseMove({ currentTarget, clientX, clientY }) {
|
||||
let { left, top } = currentTarget.getBoundingClientRect()
|
||||
mouseX.set(clientX - left)
|
||||
mouseY.set(clientY - top)
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={resource.href}
|
||||
onMouseMove={onMouseMove}
|
||||
className="group relative flex rounded-2xl bg-zinc-50 transition-shadow hover:shadow-md hover:shadow-zinc-900/5 dark:bg-white/2.5 dark:hover:shadow-black/5"
|
||||
>
|
||||
<ResourcePattern {...resource.pattern} mouseX={mouseX} mouseY={mouseY} />
|
||||
<div className="absolute inset-0 rounded-2xl ring-1 ring-inset ring-zinc-900/7.5 group-hover:ring-zinc-900/10 dark:ring-white/10 dark:group-hover:ring-white/20" />
|
||||
<div className="relative rounded-2xl px-4 pb-4 pt-16">
|
||||
<ResourceIcon icon={resource.icon} />
|
||||
<h3 className="mt-4 text-sm font-semibold leading-7 text-zinc-900 dark:text-white">
|
||||
<Link href={resource.href}>
|
||||
<span className="absolute inset-0 rounded-2xl" />
|
||||
{resource.name}
|
||||
</Link>
|
||||
</h3>
|
||||
<p className="mt-1 text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{resource.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Resources() {
|
||||
return (
|
||||
<div className="my-16 xl:max-w-none">
|
||||
<Heading level={2} id="resources">
|
||||
Resources
|
||||
</Heading>
|
||||
<div className="not-prose mt-4 grid grid-cols-1 gap-8 border-t border-zinc-900/5 pt-10 dark:border-white/5 sm:grid-cols-2 xl:grid-cols-4">
|
||||
{resources.map((resource) => (
|
||||
<Resource key={resource.href} resource={resource} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { createStore, useStore } from 'zustand'
|
||||
|
||||
import { remToPx } from '@/lib/remToPx'
|
||||
|
||||
function createSectionStore(sections) {
|
||||
return createStore((set) => ({
|
||||
sections,
|
||||
visibleSections: [],
|
||||
setVisibleSections: (visibleSections) =>
|
||||
set((state) =>
|
||||
state.visibleSections.join() === visibleSections.join()
|
||||
? {}
|
||||
: { visibleSections }
|
||||
),
|
||||
registerHeading: ({ id, ref, offsetRem }) =>
|
||||
set((state) => {
|
||||
return {
|
||||
sections: state.sections.map((section) => {
|
||||
if (section.id === id) {
|
||||
return {
|
||||
...section,
|
||||
headingRef: ref,
|
||||
offsetRem,
|
||||
}
|
||||
}
|
||||
return section
|
||||
}),
|
||||
}
|
||||
}),
|
||||
}))
|
||||
}
|
||||
|
||||
function useVisibleSections(sectionStore) {
|
||||
let setVisibleSections = useStore(sectionStore, (s) => s.setVisibleSections)
|
||||
let sections = useStore(sectionStore, (s) => s.sections)
|
||||
|
||||
useEffect(() => {
|
||||
function checkVisibleSections() {
|
||||
let { innerHeight, scrollY } = window
|
||||
let newVisibleSections = []
|
||||
|
||||
for (
|
||||
let sectionIndex = 0;
|
||||
sectionIndex < sections.length;
|
||||
sectionIndex++
|
||||
) {
|
||||
let { id, headingRef, offsetRem } = sections[sectionIndex]
|
||||
let offset = remToPx(offsetRem)
|
||||
let top = headingRef.current.getBoundingClientRect().top + scrollY
|
||||
|
||||
if (sectionIndex === 0 && top - offset > scrollY) {
|
||||
newVisibleSections.push('_top')
|
||||
}
|
||||
|
||||
let nextSection = sections[sectionIndex + 1]
|
||||
let bottom =
|
||||
(nextSection?.headingRef.current.getBoundingClientRect().top ??
|
||||
Infinity) +
|
||||
scrollY -
|
||||
remToPx(nextSection?.offsetRem ?? 0)
|
||||
|
||||
if (
|
||||
(top > scrollY && top < scrollY + innerHeight) ||
|
||||
(bottom > scrollY && bottom < scrollY + innerHeight) ||
|
||||
(top <= scrollY && bottom >= scrollY + innerHeight)
|
||||
) {
|
||||
newVisibleSections.push(id)
|
||||
}
|
||||
}
|
||||
|
||||
setVisibleSections(newVisibleSections)
|
||||
}
|
||||
|
||||
let raf = window.requestAnimationFrame(() => checkVisibleSections())
|
||||
window.addEventListener('scroll', checkVisibleSections, { passive: true })
|
||||
window.addEventListener('resize', checkVisibleSections)
|
||||
|
||||
return () => {
|
||||
window.cancelAnimationFrame(raf)
|
||||
window.removeEventListener('scroll', checkVisibleSections)
|
||||
window.removeEventListener('resize', checkVisibleSections)
|
||||
}
|
||||
}, [setVisibleSections, sections])
|
||||
}
|
||||
|
||||
const SectionStoreContext = createContext()
|
||||
|
||||
const useIsomorphicLayoutEffect =
|
||||
typeof window === 'undefined' ? useEffect : useLayoutEffect
|
||||
|
||||
export function SectionProvider({ sections, children }) {
|
||||
let [sectionStore] = useState(() => createSectionStore(sections))
|
||||
|
||||
useVisibleSections(sectionStore)
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
sectionStore.setState({ sections })
|
||||
}, [sectionStore, sections])
|
||||
|
||||
return (
|
||||
<SectionStoreContext.Provider value={sectionStore}>
|
||||
{children}
|
||||
</SectionStoreContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useSectionStore(selector) {
|
||||
let store = useContext(SectionStoreContext)
|
||||
return useStore(store, selector)
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
import clsx from 'clsx'
|
||||
|
||||
const variantStyles = {
|
||||
medium: 'rounded-lg px-1.5 ring-1 ring-inset',
|
||||
}
|
||||
|
||||
const colorStyles = {
|
||||
emerald: {
|
||||
small: 'text-emerald-500 dark:text-emerald-400',
|
||||
medium:
|
||||
'ring-emerald-300 dark:ring-emerald-400/30 bg-emerald-400/10 text-emerald-500 dark:text-emerald-400',
|
||||
},
|
||||
sky: {
|
||||
small: 'text-sky-500',
|
||||
medium:
|
||||
'ring-sky-300 bg-sky-400/10 text-sky-500 dark:ring-sky-400/30 dark:bg-sky-400/10 dark:text-sky-400',
|
||||
},
|
||||
amber: {
|
||||
small: 'text-amber-500',
|
||||
medium:
|
||||
'ring-amber-300 bg-amber-400/10 text-amber-500 dark:ring-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400',
|
||||
},
|
||||
rose: {
|
||||
small: 'text-red-500 dark:text-rose-500',
|
||||
medium:
|
||||
'ring-rose-200 bg-rose-50 text-red-500 dark:ring-rose-500/20 dark:bg-rose-400/10 dark:text-rose-400',
|
||||
},
|
||||
zinc: {
|
||||
small: 'text-zinc-400 dark:text-zinc-500',
|
||||
medium:
|
||||
'ring-zinc-200 bg-zinc-50 text-zinc-500 dark:ring-zinc-500/20 dark:bg-zinc-400/10 dark:text-zinc-400',
|
||||
},
|
||||
}
|
||||
|
||||
const valueColorMap = {
|
||||
get: 'emerald',
|
||||
post: 'sky',
|
||||
put: 'amber',
|
||||
delete: 'rose',
|
||||
}
|
||||
|
||||
export function Tag({
|
||||
children,
|
||||
variant = 'medium',
|
||||
color = valueColorMap[children.toLowerCase()] ?? 'emerald',
|
||||
}) {
|
||||
return (
|
||||
<span
|
||||
className={clsx(
|
||||
'font-mono text-[0.625rem] font-semibold leading-6',
|
||||
variantStyles[variant],
|
||||
colorStyles[color][variant]
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function BellIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M4.438 8.063a5.563 5.563 0 0 1 11.125 0v2.626c0 1.182.34 2.34.982 3.332L17.5 15.5h-15l.955-1.479c.641-.993.982-2.15.982-3.332V8.062Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M7.5 15.5v0a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v0"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
export function BoltIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M4.5 11.5 10 2v5.5a1 1 0 0 0 1 1h4.5L10 18v-5.5a1 1 0 0 0-1-1H4.5Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function BookIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m10 5.5-7.5-3v12l7.5 3m0-12 7.5-3v12l-7.5 3m0-12v12"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m17.5 2.5-7.5 3v12l7.5-3v-12Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
export function CalendarIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M2.5 6.5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-11a2 2 0 0 1-2-2v-9Z"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M2.5 6.5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v2h-15v-2Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M5.5 5.5v-3M14.5 5.5v-3"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
export function CartIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeWidth="0"
|
||||
d="M5.98 11.288 3.5 5.5h14l-2.48 5.788A2 2 0 0 1 13.18 12.5H7.82a2 2 0 0 1-1.838-1.212Z"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m3.5 5.5 2.48 5.788A2 2 0 0 0 7.82 12.5h5.362a2 2 0 0 0 1.839-1.212L17.5 5.5h-14Zm0 0-1-2M6.5 14.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2ZM14.5 14.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function ChatBubbleIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10 16.5c4.142 0 7.5-3.134 7.5-7s-3.358-7-7.5-7c-4.142 0-7.5 3.134-7.5 7 0 1.941.846 3.698 2.214 4.966L3.5 17.5c2.231 0 3.633-.553 4.513-1.248A8.014 8.014 0 0 0 10 16.5Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M7.5 8.5h5M8.5 11.5h3"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function CheckIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10 1.5a8.5 8.5 0 1 1 0 17 8.5 8.5 0 0 1 0-17Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m7.5 10.5 2 2c1-3.5 3-5 3-5"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function ChevronRightLeftIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M1.5 10A6.5 6.5 0 0 1 8 3.5h4a6.5 6.5 0 1 1 0 13H8A6.5 6.5 0 0 1 1.5 10Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m7.5 7.5-3 2.5 3 2.5M12.5 7.5l3 2.5-3 2.5"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function ClipboardIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M3.5 6v10a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-1l-.447.894A2 2 0 0 1 11.263 6H8.737a2 2 0 0 1-1.789-1.106L6.5 4h-1a2 2 0 0 0-2 2Z"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m13.5 4-.447.894A2 2 0 0 1 11.263 6H8.737a2 2 0 0 1-1.789-1.106L6.5 4l.724-1.447A1 1 0 0 1 8.118 2h3.764a1 1 0 0 1 .894.553L13.5 4Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
export function CogIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeWidth="0"
|
||||
fillRule="evenodd"
|
||||
d="M11.063 1.5H8.937l-.14 1.128c-.086.682-.61 1.22-1.246 1.484-.634.264-1.37.247-1.912-.175l-.898-.699-1.503 1.503.699.898c.422.543.44 1.278.175 1.912-.264.635-.802 1.16-1.484 1.245L1.5 8.938v2.124l1.128.142c.682.085 1.22.61 1.484 1.244.264.635.247 1.37-.175 1.913l-.699.898 1.503 1.503.898-.699c.543-.422 1.278-.44 1.912-.175.635.264 1.16.801 1.245 1.484l.142 1.128h2.124l.142-1.128c.085-.683.61-1.22 1.244-1.484.635-.264 1.37-.247 1.913.175l.898.699 1.503-1.503-.699-.898c-.422-.543-.44-1.278-.175-1.913.264-.634.801-1.16 1.484-1.245l1.128-.14V8.937l-1.128-.14c-.683-.086-1.22-.611-1.484-1.246-.264-.634-.247-1.37.175-1.912l.699-.898-1.503-1.503-.898.699c-.543.422-1.278.44-1.913.175-.634-.264-1.16-.802-1.244-1.484L11.062 1.5ZM10 12.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M8.938 1.5h2.124l.142 1.128c.085.682.61 1.22 1.244 1.484v0c.635.264 1.37.247 1.913-.175l.898-.699 1.503 1.503-.699.898c-.422.543-.44 1.278-.175 1.912v0c.264.635.801 1.16 1.484 1.245l1.128.142v2.124l-1.128.142c-.683.085-1.22.61-1.484 1.244v0c-.264.635-.247 1.37.175 1.913l.699.898-1.503 1.503-.898-.699c-.543-.422-1.278-.44-1.913-.175v0c-.634.264-1.16.801-1.245 1.484l-.14 1.128H8.937l-.14-1.128c-.086-.683-.611-1.22-1.246-1.484v0c-.634-.264-1.37-.247-1.912.175l-.898.699-1.503-1.503.699-.898c.422-.543.44-1.278.175-1.913v0c-.264-.634-.802-1.16-1.484-1.245l-1.128-.14V8.937l1.128-.14c.682-.086 1.22-.61 1.484-1.246v0c.264-.634.247-1.37-.175-1.912l-.699-.898 1.503-1.503.898.699c.543.422 1.278.44 1.912.175v0c.635-.264 1.16-.802 1.245-1.484L8.938 1.5Z"
|
||||
/>
|
||||
<circle cx="10" cy="10" r="2.5" fill="none" />
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function CopyIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M14.5 5.5v-1a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h1"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M5.5 7.5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-8a2 2 0 0 1-2-2v-8Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function DocumentIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M3.5 4.5v11a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-8h-5v-5h-6a2 2 0 0 0-2 2Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m11.5 2.5 5 5"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function EnvelopeIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M2.5 5.5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v8a3 3 0 0 1-3 3h-9a3 3 0 0 1-3-3v-8Z"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10 10 4.526 5.256c-.7-.607-.271-1.756.655-1.756h9.638c.926 0 1.355 1.15.655 1.756L10 10Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function FaceSmileIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10 1.5a8.5 8.5 0 1 1 0 17 8.5 8.5 0 0 1 0-17Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M7.5 6.5v2M12.5 6.5v2M5.5 11.5s1 3 4.5 3 4.5-3 4.5-3"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
export function FolderIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M17.5 15.5v-8a2 2 0 0 0-2-2h-2.93a2 2 0 0 1-1.664-.89l-.812-1.22A2 2 0 0 0 8.43 2.5H4.5a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2Z"
|
||||
/>
|
||||
<path
|
||||
strokeWidth="0"
|
||||
d="M8.43 2.5H4.5a2 2 0 0 0-2 2v1h9l-1.406-2.11A2 2 0 0 0 8.43 2.5Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m11.5 5.5-1.406-2.11A2 2 0 0 0 8.43 2.5H4.5a2 2 0 0 0-2 2v1h9Zm0 0h2"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
export function LinkIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m5.056 11.5-1.221-1.222a4.556 4.556 0 0 1 6.443-6.443L11.5 5.056M7.5 7.5l5 5m2.444-4 1.222 1.222a4.556 4.556 0 0 1-6.444 6.444L8.5 14.944"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function ListIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M2.5 4.5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2h-11a2 2 0 0 1-2-2v-11Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M6.5 6.5h7M6.5 13.5h7M6.5 10h7"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
export function MagnifyingGlassIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path strokeWidth="0" d="M2.5 8.5a6 6 0 1 1 12 0 6 6 0 0 1-12 0Z" />
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m13 13 4.5 4.5m-9-3a6 6 0 1 1 0-12 6 6 0 0 1 0 12Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
export function MapPinIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeWidth="0"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M10 2.5A5.5 5.5 0 0 0 4.5 8c0 3.038 5.5 9.5 5.5 9.5s5.5-6.462 5.5-9.5A5.5 5.5 0 0 0 10 2.5Zm0 7a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M4.5 8a5.5 5.5 0 1 1 11 0c0 3.038-5.5 9.5-5.5 9.5S4.5 11.038 4.5 8Z"
|
||||
/>
|
||||
<circle cx="10" cy="8" r="1.5" fill="none" />
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
export function PackageIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeWidth="0"
|
||||
d="m10 9.5-7.5-4v9l7.5 4v-9ZM10 9.5l7.5-4v9l-7.5 4v-9Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m2.5 5.5 7.5 4m-7.5-4v9l7.5 4m-7.5-13 7.5-4 7.5 4m-7.5 4v9m0-9 7.5-4m-7.5 13 7.5-4v-9m-11 6 .028-3.852L13.5 3.5"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function PaperAirplaneIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M17 3L1 9L8 12M17 3L11 19L8 12M17 3L8 12"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M11 19L8 12L17 3L11 19Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
export function PaperClipIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m15.56 7.375-3.678-3.447c-2.032-1.904-5.326-1.904-7.358 0s-2.032 4.99 0 6.895l6.017 5.639c1.477 1.384 3.873 1.384 5.35 0 1.478-1.385 1.478-3.63 0-5.015L10.21 6.122a1.983 1.983 0 0 0-2.676 0 1.695 1.695 0 0 0 0 2.507l4.013 3.76"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function ShapesIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M2.5 7.5v-4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1ZM11.5 16.5v-4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1Z"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m2.5 17.5 3-6 3 6h-6ZM14.5 2.5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
export function ShirtIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M12.5 1.5s0 2-2.5 2-2.5-2-2.5-2h-2L2.207 4.793a1 1 0 0 0 0 1.414L4.5 8.5v10h11v-10l2.293-2.293a1 1 0 0 0 0-1.414L14.5 1.5h-2Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
export function SquaresPlusIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M8.5 4.5v2a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2ZM8.5 13.5v2a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2ZM17.5 4.5v2a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M14.5 11.5v6M17.5 14.5h-6"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
export function TagIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeWidth="0"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M3 8.69499V3H8.69499C9.18447 3 9.65389 3.19444 10 3.54055L16.4594 10C17.1802 10.7207 17.1802 11.8893 16.4594 12.61L12.61 16.4594C11.8893 17.1802 10.7207 17.1802 10 16.4594L3.54055 10C3.19444 9.65389 3 9.18447 3 8.69499ZM7 8.5C7.82843 8.5 8.5 7.82843 8.5 7C8.5 6.17157 7.82843 5.5 7 5.5C6.17157 5.5 5.5 6.17157 5.5 7C5.5 7.82843 6.17157 8.5 7 8.5Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M3 3V8.69499C3 9.18447 3.19444 9.65389 3.54055 10L10 16.4594C10.7207 17.1802 11.8893 17.1802 12.61 16.4594L16.4594 12.61C17.1802 11.8893 17.1802 10.7207 16.4594 10L10 3.54055C9.65389 3.19444 9.18447 3 8.69499 3H3Z"
|
||||
/>
|
||||
<circle cx="7" cy="7" r="1.5" fill="none" />
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
export function UserIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeWidth="0"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M10 .5a9.5 9.5 0 0 1 5.598 17.177C14.466 15.177 12.383 13.5 10 13.5s-4.466 1.677-5.598 4.177A9.5 9.5 0 0 1 10 .5ZM12.5 8a2.5 2.5 0 1 0-5 0 2.5 2.5 0 0 0 5 0Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10 .5a9.5 9.5 0 0 1 5.598 17.177A9.458 9.458 0 0 1 10 19.5a9.458 9.458 0 0 1-5.598-1.823A9.5 9.5 0 0 1 10 .5Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M4.402 17.677C5.534 15.177 7.617 13.5 10 13.5s4.466 1.677 5.598 4.177M10 5.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
export function UsersIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10.046 16H1.955a.458.458 0 0 1-.455-.459C1.5 13.056 3.515 11 6 11h.5"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M7.5 15.454C7.5 12.442 9.988 10 13 10s5.5 2.442 5.5 5.454a.545.545 0 0 1-.546.546H8.045a.545.545 0 0 1-.545-.546Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M6.5 4a2 2 0 1 1 0 4 2 2 0 0 1 0-4Z"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M13 2a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
import Link from 'next/link'
|
||||
import clsx from 'clsx'
|
||||
|
||||
import { Heading } from '@/components/Heading'
|
||||
|
||||
export const a = Link
|
||||
export { Button } from '@/components/Button'
|
||||
export { CodeGroup, Code as code, Pre as pre } from '@/components/Code'
|
||||
|
||||
export const h2 = function H2(props) {
|
||||
return <Heading level={2} {...props} />
|
||||
}
|
||||
|
||||
function InfoIcon(props) {
|
||||
return (
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" {...props}>
|
||||
<circle cx="8" cy="8" r="8" strokeWidth="0" />
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M6.75 7.75h1.5v3.5"
|
||||
/>
|
||||
<circle cx="8" cy="4" r=".5" fill="none" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function Note({ children }) {
|
||||
return (
|
||||
<div className="my-6 flex gap-2.5 rounded-2xl border border-emerald-500/20 bg-emerald-50/50 p-4 leading-6 text-emerald-900 dark:border-emerald-500/30 dark:bg-emerald-500/5 dark:text-emerald-200 dark:[--tw-prose-links-hover:theme(colors.emerald.300)] dark:[--tw-prose-links:theme(colors.white)]">
|
||||
<InfoIcon className="mt-1 h-4 w-4 flex-none fill-emerald-500 stroke-white dark:fill-emerald-200/20 dark:stroke-emerald-200" />
|
||||
<div className="[&>:first-child]:mt-0 [&>:last-child]:mb-0">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Row({ children }) {
|
||||
return (
|
||||
<div className="grid grid-cols-1 items-start gap-x-16 gap-y-10 xl:max-w-none xl:grid-cols-2">
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Col({ children, sticky = false }) {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'[&>:first-child]:mt-0 [&>:last-child]:mb-0',
|
||||
sticky && 'xl:sticky xl:top-24'
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Properties({ children }) {
|
||||
return (
|
||||
<div className="my-6">
|
||||
<ul
|
||||
role="list"
|
||||
className="m-0 max-w-[calc(theme(maxWidth.lg)-theme(spacing.8))] list-none divide-y divide-zinc-900/5 p-0 dark:divide-white/5"
|
||||
>
|
||||
{children}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Property({ name, type, children }) {
|
||||
return (
|
||||
<li className="m-0 px-0 py-4 first:pt-0 last:pb-0">
|
||||
<dl className="m-0 flex flex-wrap items-center gap-x-3 gap-y-2">
|
||||
<dt className="sr-only">Name</dt>
|
||||
<dd>
|
||||
<code>{name}</code>
|
||||
</dd>
|
||||
<dt className="sr-only">Type</dt>
|
||||
<dd className="font-mono text-xs text-zinc-400 dark:text-zinc-500">
|
||||
{type}
|
||||
</dd>
|
||||
<dt className="sr-only">Description</dt>
|
||||
<dd className="w-full flex-none [&>:first-child]:mt-0 [&>:last-child]:mb-0">
|
||||
{children}
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
)
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
|
||||
<g fill="#00ACD7" clip-path="url(#a)">
|
||||
<path fill-rule="evenodd"
|
||||
d="M5.8 19.334c-.08 0-.093-.054-.067-.107l.4-.533a.421.421 0 0 1 .227-.08h6.893c.08 0 .094.053.067.106l-.334.507c-.04.053-.133.12-.2.12L5.8 19.32v.014Zm-2.92 1.773c-.08 0-.093-.04-.053-.107l.4-.52c.04-.053.133-.093.213-.093h8.8c.093 0 .133.053.107.12l-.16.453c-.014.08-.094.134-.174.134H2.88v.013Zm4.68 1.773c-.08 0-.107-.053-.067-.12l.267-.48c.053-.053.133-.12.2-.12h3.866c.08 0 .12.067.12.134l-.04.466c0 .08-.08.134-.133.134L7.56 22.88Zm20.053-3.906-3.24.853c-.293.08-.32.093-.56-.2-.293-.32-.506-.533-.92-.733a3.36 3.36 0 0 0-3.493.293 4.107 4.107 0 0 0-1.973 3.667 3.027 3.027 0 0 0 2.613 3.04c1.306.173 2.413-.294 3.28-1.28l.533-.707H20.12c-.4 0-.507-.267-.373-.587.253-.6.72-1.6.986-2.106a.533.533 0 0 1 .48-.307h7.04c-.04.533-.04 1.04-.12 1.573-.213 1.387-.733 2.667-1.586 3.787a8.053 8.053 0 0 1-5.507 3.28 6.839 6.839 0 0 1-5.2-1.28A6.065 6.065 0 0 1 13.386 24c-.24-2.106.374-4 1.654-5.666A8.573 8.573 0 0 1 20.44 15a6.667 6.667 0 0 1 5.12.934c1.027.666 1.76 1.6 2.253 2.733.107.173.027.267-.2.32v-.013Z"
|
||||
clip-rule="evenodd" />
|
||||
<path
|
||||
d="M34 29.667a7.253 7.253 0 0 1-4.707-1.707 6.066 6.066 0 0 1-2.08-3.733 7.373 7.373 0 0 1 1.56-5.827 8.107 8.107 0 0 1 5.413-3.226 7.173 7.173 0 0 1 5.507.986 6.015 6.015 0 0 1 2.72 4.307 7.467 7.467 0 0 1-2.227 6.547 8.854 8.854 0 0 1-4.626 2.48c-.534.093-1.054.106-1.547.173H34Zm4.613-7.813c-.027-.254-.027-.44-.067-.64a3.186 3.186 0 0 0-3.933-2.547 4.227 4.227 0 0 0-3.387 3.36A3.187 3.187 0 0 0 33 25.68c1.066.454 2.133.4 3.16-.133a4.227 4.227 0 0 0 2.453-3.68v-.013Z" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill="#fff" d="M4 4h40v40H4z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.8 KiB |
|
@ -1,4 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
|
||||
<path fill="#89D42C"
|
||||
d="M23.675 39.82a2.48 2.48 0 0 1-1.19-.313l-3.764-2.236c-.568-.31-.285-.425-.114-.48.765-.256.906-.313 1.698-.765.086-.057.198-.029.284.028l2.888 1.727c.113.057.254.057.34 0l11.296-6.54c.113-.057.17-.17.17-.312v-13.05c0-.143-.057-.256-.17-.313l-11.296-6.51c-.114-.057-.256-.057-.34 0L12.18 17.567c-.114.057-.17.198-.17.311V30.93c0 .114.056.255.17.312l3.087 1.784c1.67.849 2.717-.143 2.717-1.133V19.01a.344.344 0 0 1 .34-.34h1.443a.344.344 0 0 1 .341.34v12.882c0 2.237-1.218 3.539-3.342 3.539-.65 0-1.16 0-2.604-.708l-2.975-1.698A2.39 2.39 0 0 1 10 30.959V17.904c0-.849.452-1.642 1.189-2.066l11.296-6.54a2.527 2.527 0 0 1 2.379 0l11.297 6.54a2.39 2.39 0 0 1 1.188 2.066V30.96c0 .85-.452 1.642-1.188 2.066l-11.297 6.54a2.896 2.896 0 0 1-1.189.256v-.001Zm3.482-8.976c-4.954 0-5.973-2.264-5.973-4.19a.344.344 0 0 1 .34-.34h1.472c.169 0 .311.114.311.284.226 1.5.878 2.236 3.879 2.236 2.378 0 3.397-.538 3.397-1.812 0-.736-.283-1.274-3.992-1.642-3.086-.311-5.012-.99-5.012-3.454 0-2.293 1.926-3.652 5.154-3.652 3.623 0 5.407 1.246 5.634 3.963a.459.459 0 0 1-.086.256c-.056.056-.141.113-.226.113h-1.472a.332.332 0 0 1-.311-.256c-.34-1.555-1.217-2.066-3.539-2.066-2.605 0-2.916.906-2.916 1.585 0 .821.368 1.076 3.878 1.53 3.483.452 5.124 1.104 5.124 3.539-.027 2.491-2.066 3.907-5.662 3.907Z" />
|
||||
</svg>
|
Before Width: | Height: | Size: 1.4 KiB |
|
@ -1,10 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
|
||||
<path fill="#6181B6" fill-rule="evenodd"
|
||||
d="M14.643 21.762h-1.77l-.964 4.965h1.57c1.043 0 1.82-.198 2.33-.59.51-.393.853-1.047 1.03-1.966.173-.882.095-1.503-.232-1.866-.328-.362-.98-.543-1.962-.543h-.002Z"
|
||||
clip-rule="evenodd" />
|
||||
<path fill="#6181B6"
|
||||
d="M24 13.29c-12.426 0-22.5 5.3-22.5 11.835 0 6.535 10.074 11.837 22.5 11.837s22.5-5.3 22.5-11.837S36.426 13.29 24 13.29Zm-6.113 13.971a4.55 4.55 0 0 1-1.718 1.032c-.63.203-1.434.308-2.41.308h-2.215l-.612 3.152H8.346l2.307-11.861h4.968c1.494 0 2.585.391 3.27 1.177.687.785.893 1.88.618 3.285a5.34 5.34 0 0 1-.57 1.588c-.28.493-.634.938-1.053 1.319h.002Zm7.546 1.34 1.018-5.247c.119-.598.073-1.005-.128-1.221-.2-.218-.63-.328-1.288-.328h-2.047l-1.32 6.799h-2.566L21.41 16.74h2.561l-.611 3.155h2.282c1.439 0 2.429.25 2.975.75.546.499.708 1.314.492 2.437l-1.073 5.52h-2.604V28.6Zm14.243-4.245a5.215 5.215 0 0 1-.571 1.586 5.356 5.356 0 0 1-1.051 1.319c-.49.467-1.078.82-1.721 1.032-.63.203-1.434.308-2.41.308H31.71l-.614 3.154h-2.581l2.305-11.862h4.968c1.495 0 2.584.393 3.27 1.177.686.784.895 1.878.62 3.285h-.002Z" />
|
||||
<path fill="#6181B6" fill-rule="evenodd"
|
||||
d="M34.81 21.762h-1.765l-.968 4.965h1.571c1.044 0 1.821-.198 2.33-.59.51-.393.852-1.047 1.032-1.966.172-.882.093-1.503-.234-1.866-.326-.362-.983-.543-1.964-.543h-.002Z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
Before Width: | Height: | Size: 1.4 KiB |
|
@ -1,13 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
|
||||
<g clip-path="url(#a)">
|
||||
<path fill="#3372A7"
|
||||
d="M23.429 9.008c-7.882 0-7.39 3.418-7.39 3.418l.01 3.541h7.52v1.063H13.062s-5.043-.572-5.043 7.38c0 7.954 4.402 7.671 4.402 7.671h2.627v-3.69s-.142-4.402 4.331-4.402h7.46s4.191.068 4.191-4.05v-6.81s.637-4.12-7.6-4.12Zm-4.147 2.382a1.353 1.353 0 1 1 .001 2.706 1.353 1.353 0 0 1-.001-2.706Z" />
|
||||
<path fill="#FFD235"
|
||||
d="M23.653 39.894c7.881 0 7.39-3.418 7.39-3.418l-.01-3.541h-7.52v-1.063H34.02s5.043.572 5.043-7.381-4.402-7.67-4.402-7.67h-2.627v3.69s.142 4.402-4.332 4.402h-7.46s-4.19-.068-4.19 4.05v6.81s-.637 4.12 7.6 4.12Zm4.147-2.381a1.353 1.353 0 1 1-.002-2.707 1.353 1.353 0 0 1 .002 2.706Z" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill="#fff" d="M8 9h31.122v31H8z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 864 B |
|
@ -1,4 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none">
|
||||
<path fill="#D91505"
|
||||
d="M33.735 10.41c3.376.585 4.334 2.893 4.262 5.311l.017-.035-1.519 19.912-19.752 1.352h.017c-1.639-.069-5.294-.218-5.46-5.328l1.83-3.34 3.139 7.331.56 1.306L19.95 26.74l-.032.007.017-.034 10.302 3.29-1.555-6.044-1.101-4.341 9.817-.634-.684-.567-7.048-5.746 4.073-2.272-.004.012v-.001ZM17.01 15.966c3.963-3.932 9.079-6.256 11.044-4.274 1.96 1.98-.118 6.796-4.089 10.726-3.966 3.931-9.02 6.382-10.98 4.405-1.967-1.98.05-6.921 4.02-10.853l.005-.004Z" />
|
||||
</svg>
|
Before Width: | Height: | Size: 561 B |
|
@ -1,8 +0,0 @@
|
|||
export function remToPx(remValue) {
|
||||
let rootFontSize =
|
||||
typeof window === 'undefined'
|
||||
? 16
|
||||
: parseFloat(window.getComputedStyle(document.documentElement).fontSize)
|
||||
|
||||
return parseFloat(remValue) * rootFontSize
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import { mdxAnnotations } from 'mdx-annotations'
|
||||
import recmaNextjsStaticProps from 'recma-nextjs-static-props'
|
||||
|
||||
function recmaRemoveNamedExports() {
|
||||
return (tree) => {
|
||||
tree.body = tree.body.map((node) => {
|
||||
if (node.type === 'ExportNamedDeclaration') {
|
||||
return node.declaration
|
||||
}
|
||||
return node
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const recmaPlugins = [
|
||||
mdxAnnotations.recma,
|
||||
recmaRemoveNamedExports,
|
||||
recmaNextjsStaticProps,
|
||||
]
|
|
@ -1,126 +0,0 @@
|
|||
import { mdxAnnotations } from 'mdx-annotations'
|
||||
import { visit } from 'unist-util-visit'
|
||||
import rehypeMdxTitle from 'rehype-mdx-title'
|
||||
import shiki from 'shiki'
|
||||
import { toString } from 'mdast-util-to-string'
|
||||
import * as acorn from 'acorn'
|
||||
import { slugifyWithCounter } from '@sindresorhus/slugify'
|
||||
|
||||
function rehypeParseCodeBlocks() {
|
||||
return (tree) => {
|
||||
visit(tree, 'element', (node, _nodeIndex, parentNode) => {
|
||||
if (node.tagName === 'code' && node.properties.className) {
|
||||
parentNode.properties.language = node.properties.className[0]?.replace(
|
||||
/^language-/,
|
||||
''
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let highlighter
|
||||
|
||||
function rehypeShiki() {
|
||||
return async (tree) => {
|
||||
highlighter =
|
||||
highlighter ?? (await shiki.getHighlighter({ theme: 'css-variables' }))
|
||||
|
||||
visit(tree, 'element', (node) => {
|
||||
if (node.tagName === 'pre' && node.children[0]?.tagName === 'code') {
|
||||
let codeNode = node.children[0]
|
||||
let textNode = codeNode.children[0]
|
||||
|
||||
node.properties.code = textNode.value
|
||||
|
||||
if (node.properties.language) {
|
||||
let tokens = highlighter.codeToThemedTokens(
|
||||
textNode.value,
|
||||
node.properties.language
|
||||
)
|
||||
|
||||
textNode.value = shiki.renderToHtml(tokens, {
|
||||
elements: {
|
||||
pre: ({ children }) => children,
|
||||
code: ({ children }) => children,
|
||||
line: ({ children }) => `<span>${children}</span>`,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function rehypeSlugify() {
|
||||
return (tree) => {
|
||||
let slugify = slugifyWithCounter()
|
||||
visit(tree, 'element', (node) => {
|
||||
if (node.tagName === 'h2' && !node.properties.id) {
|
||||
node.properties.id = slugify(toString(node))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function rehypeAddMDXExports(getExports) {
|
||||
return (tree) => {
|
||||
let exports = Object.entries(getExports(tree))
|
||||
|
||||
for (let [name, value] of exports) {
|
||||
for (let node of tree.children) {
|
||||
if (
|
||||
node.type === 'mdxjsEsm' &&
|
||||
new RegExp(`export\\s+const\\s+${name}\\s*=`).test(node.value)
|
||||
) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let exportStr = `export const ${name} = ${value}`
|
||||
|
||||
tree.children.push({
|
||||
type: 'mdxjsEsm',
|
||||
value: exportStr,
|
||||
data: {
|
||||
estree: acorn.parse(exportStr, {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 'latest',
|
||||
}),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSections(node) {
|
||||
let sections = []
|
||||
|
||||
for (let child of node.children ?? []) {
|
||||
if (child.type === 'element' && child.tagName === 'h2') {
|
||||
sections.push(`{
|
||||
title: ${JSON.stringify(toString(child))},
|
||||
id: ${JSON.stringify(child.properties.id)},
|
||||
...${child.properties.annotation}
|
||||
}`)
|
||||
} else if (child.children) {
|
||||
sections.push(...getSections(child))
|
||||
}
|
||||
}
|
||||
|
||||
return sections
|
||||
}
|
||||
|
||||
export const rehypePlugins = [
|
||||
mdxAnnotations.rehype,
|
||||
rehypeParseCodeBlocks,
|
||||
rehypeShiki,
|
||||
rehypeSlugify,
|
||||
rehypeMdxTitle,
|
||||
[
|
||||
rehypeAddMDXExports,
|
||||
(tree) => ({
|
||||
sections: `[${getSections(tree).join()}]`,
|
||||
}),
|
||||
],
|
||||
]
|
|
@ -1,4 +0,0 @@
|
|||
import { mdxAnnotations } from 'mdx-annotations'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
|
||||
export const remarkPlugins = [mdxAnnotations.remark, remarkGfm]
|
|
@ -1,39 +0,0 @@
|
|||
import Head from 'next/head'
|
||||
import { Router, useRouter } from 'next/router'
|
||||
import { MDXProvider } from '@mdx-js/react'
|
||||
|
||||
import { Layout } from '@/components/Layout'
|
||||
import * as mdxComponents from '@/components/mdx'
|
||||
import { useMobileNavigationStore } from '@/components/MobileNavigation'
|
||||
|
||||
import '@/styles/tailwind.css'
|
||||
import 'focus-visible'
|
||||
|
||||
function onRouteChange() {
|
||||
useMobileNavigationStore.getState().close()
|
||||
}
|
||||
|
||||
Router.events.on('routeChangeStart', onRouteChange)
|
||||
Router.events.on('hashChangeStart', onRouteChange)
|
||||
|
||||
export default function App({ Component, pageProps }) {
|
||||
let router = useRouter()
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
{router.pathname === '/' ? (
|
||||
<title>Zed Internal Docs</title>
|
||||
) : (
|
||||
<title>{`${pageProps.title} - Zed Internal Docs`}</title>
|
||||
)}
|
||||
<meta name="description" content={pageProps.description} />
|
||||
</Head>
|
||||
<MDXProvider components={mdxComponents}>
|
||||
<Layout {...pageProps}>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</MDXProvider>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
import { Head, Html, Main, NextScript } from 'next/document'
|
||||
|
||||
const modeScript = `
|
||||
let darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
|
||||
updateMode()
|
||||
darkModeMediaQuery.addEventListener('change', updateModeWithoutTransitions)
|
||||
window.addEventListener('storage', updateModeWithoutTransitions)
|
||||
|
||||
function updateMode() {
|
||||
let isSystemDarkMode = darkModeMediaQuery.matches
|
||||
let isDarkMode = window.localStorage.isDarkMode === 'true' || (!('isDarkMode' in window.localStorage) && isSystemDarkMode)
|
||||
|
||||
if (isDarkMode) {
|
||||
document.documentElement.classList.add('dark')
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark')
|
||||
}
|
||||
|
||||
if (isDarkMode === isSystemDarkMode) {
|
||||
delete window.localStorage.isDarkMode
|
||||
}
|
||||
}
|
||||
|
||||
function disableTransitionsTemporarily() {
|
||||
document.documentElement.classList.add('[&_*]:!transition-none')
|
||||
window.setTimeout(() => {
|
||||
document.documentElement.classList.remove('[&_*]:!transition-none')
|
||||
}, 0)
|
||||
}
|
||||
|
||||
function updateModeWithoutTransitions() {
|
||||
disableTransitionsTemporarily()
|
||||
updateMode()
|
||||
}
|
||||
`
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head>
|
||||
<script dangerouslySetInnerHTML={{ __html: modeScript }} />
|
||||
</Head>
|
||||
<body className="bg-white antialiased dark:bg-zinc-900">
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
@layer base {
|
||||
:root {
|
||||
--shiki-color-text: theme('colors.white');
|
||||
--shiki-token-constant: theme('colors.emerald.300');
|
||||
--shiki-token-string: theme('colors.emerald.300');
|
||||
--shiki-token-comment: theme('colors.zinc.500');
|
||||
--shiki-token-keyword: theme('colors.sky.300');
|
||||
--shiki-token-parameter: theme('colors.pink.300');
|
||||
--shiki-token-function: theme('colors.violet.300');
|
||||
--shiki-token-string-expression: theme('colors.emerald.300');
|
||||
--shiki-token-punctuation: theme('colors.zinc.200');
|
||||
}
|
||||
|
||||
[inert] ::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
|
@ -1,42 +0,0 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{js,mjs,jsx,mdx}'],
|
||||
darkMode: 'class',
|
||||
theme: {
|
||||
fontSize: {
|
||||
'2xs': ['0.75rem', { lineHeight: '1.25rem' }],
|
||||
xs: ['0.8125rem', { lineHeight: '1.5rem' }],
|
||||
sm: ['0.875rem', { lineHeight: '1.5rem' }],
|
||||
base: ['1rem', { lineHeight: '1.75rem' }],
|
||||
lg: ['1.125rem', { lineHeight: '1.75rem' }],
|
||||
xl: ['1.25rem', { lineHeight: '1.75rem' }],
|
||||
'2xl': ['1.5rem', { lineHeight: '2rem' }],
|
||||
'3xl': ['1.875rem', { lineHeight: '2.25rem' }],
|
||||
'4xl': ['2.25rem', { lineHeight: '2.5rem' }],
|
||||
'5xl': ['3rem', { lineHeight: '1' }],
|
||||
'6xl': ['3.75rem', { lineHeight: '1' }],
|
||||
'7xl': ['4.5rem', { lineHeight: '1' }],
|
||||
'8xl': ['6rem', { lineHeight: '1' }],
|
||||
'9xl': ['8rem', { lineHeight: '1' }],
|
||||
},
|
||||
typography: require('./typography'),
|
||||
extend: {
|
||||
boxShadow: {
|
||||
glow: '0 0 4px rgb(0 0 0 / 0.1)',
|
||||
},
|
||||
maxWidth: {
|
||||
lg: '33rem',
|
||||
'2xl': '40rem',
|
||||
'3xl': '50rem',
|
||||
'5xl': '66rem',
|
||||
},
|
||||
opacity: {
|
||||
1: '0.01',
|
||||
2.5: '0.025',
|
||||
7.5: '0.075',
|
||||
15: '0.15',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require('@tailwindcss/typography')],
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
export const description = 'Tools to get started at Zed'
|
||||
|
||||
# Tools
|
||||
|
||||
---
|
||||
Tools to get started at Zed
|
||||
|
||||
## Calendar
|
||||
|
|
@ -1,357 +0,0 @@
|
|||
module.exports = ({ theme }) => ({
|
||||
DEFAULT: {
|
||||
css: {
|
||||
'--tw-prose-body': theme('colors.zinc.700'),
|
||||
'--tw-prose-headings': theme('colors.zinc.900'),
|
||||
'--tw-prose-links': theme('colors.emerald.500'),
|
||||
'--tw-prose-links-hover': theme('colors.emerald.600'),
|
||||
'--tw-prose-links-underline': theme('colors.emerald.500 / 0.3'),
|
||||
'--tw-prose-bold': theme('colors.zinc.900'),
|
||||
'--tw-prose-counters': theme('colors.zinc.500'),
|
||||
'--tw-prose-bullets': theme('colors.zinc.300'),
|
||||
'--tw-prose-hr': theme('colors.zinc.900 / 0.05'),
|
||||
'--tw-prose-quotes': theme('colors.zinc.900'),
|
||||
'--tw-prose-quote-borders': theme('colors.zinc.200'),
|
||||
'--tw-prose-captions': theme('colors.zinc.500'),
|
||||
'--tw-prose-code': theme('colors.zinc.900'),
|
||||
'--tw-prose-code-bg': theme('colors.zinc.100'),
|
||||
'--tw-prose-code-ring': theme('colors.zinc.300'),
|
||||
'--tw-prose-th-borders': theme('colors.zinc.300'),
|
||||
'--tw-prose-td-borders': theme('colors.zinc.200'),
|
||||
|
||||
'--tw-prose-invert-body': theme('colors.zinc.400'),
|
||||
'--tw-prose-invert-headings': theme('colors.white'),
|
||||
'--tw-prose-invert-links': theme('colors.emerald.400'),
|
||||
'--tw-prose-invert-links-hover': theme('colors.emerald.500'),
|
||||
'--tw-prose-invert-links-underline': theme('colors.emerald.500 / 0.3'),
|
||||
'--tw-prose-invert-bold': theme('colors.white'),
|
||||
'--tw-prose-invert-counters': theme('colors.zinc.400'),
|
||||
'--tw-prose-invert-bullets': theme('colors.zinc.600'),
|
||||
'--tw-prose-invert-hr': theme('colors.white / 0.05'),
|
||||
'--tw-prose-invert-quotes': theme('colors.zinc.100'),
|
||||
'--tw-prose-invert-quote-borders': theme('colors.zinc.700'),
|
||||
'--tw-prose-invert-captions': theme('colors.zinc.400'),
|
||||
'--tw-prose-invert-code': theme('colors.white'),
|
||||
'--tw-prose-invert-code-bg': theme('colors.zinc.700 / 0.15'),
|
||||
'--tw-prose-invert-code-ring': theme('colors.white / 0.1'),
|
||||
'--tw-prose-invert-th-borders': theme('colors.zinc.600'),
|
||||
'--tw-prose-invert-td-borders': theme('colors.zinc.700'),
|
||||
|
||||
// Base
|
||||
color: 'var(--tw-prose-body)',
|
||||
fontSize: theme('fontSize.sm')[0],
|
||||
lineHeight: theme('lineHeight.7'),
|
||||
|
||||
// Layout
|
||||
'> *': {
|
||||
maxWidth: theme('maxWidth.2xl'),
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
'@screen lg': {
|
||||
maxWidth: theme('maxWidth.3xl'),
|
||||
marginLeft: `calc(50% - min(50%, ${theme('maxWidth.lg')}))`,
|
||||
marginRight: `calc(50% - min(50%, ${theme('maxWidth.lg')}))`,
|
||||
},
|
||||
},
|
||||
|
||||
// Text
|
||||
p: {
|
||||
marginTop: theme('spacing.6'),
|
||||
marginBottom: theme('spacing.6'),
|
||||
},
|
||||
'[class~="lead"]': {
|
||||
fontSize: theme('fontSize.base')[0],
|
||||
...theme('fontSize.base')[1],
|
||||
},
|
||||
|
||||
// Lists
|
||||
ol: {
|
||||
listStyleType: 'decimal',
|
||||
marginTop: theme('spacing.5'),
|
||||
marginBottom: theme('spacing.5'),
|
||||
paddingLeft: '1.625rem',
|
||||
},
|
||||
'ol[type="A"]': {
|
||||
listStyleType: 'upper-alpha',
|
||||
},
|
||||
'ol[type="a"]': {
|
||||
listStyleType: 'lower-alpha',
|
||||
},
|
||||
'ol[type="A" s]': {
|
||||
listStyleType: 'upper-alpha',
|
||||
},
|
||||
'ol[type="a" s]': {
|
||||
listStyleType: 'lower-alpha',
|
||||
},
|
||||
'ol[type="I"]': {
|
||||
listStyleType: 'upper-roman',
|
||||
},
|
||||
'ol[type="i"]': {
|
||||
listStyleType: 'lower-roman',
|
||||
},
|
||||
'ol[type="I" s]': {
|
||||
listStyleType: 'upper-roman',
|
||||
},
|
||||
'ol[type="i" s]': {
|
||||
listStyleType: 'lower-roman',
|
||||
},
|
||||
'ol[type="1"]': {
|
||||
listStyleType: 'decimal',
|
||||
},
|
||||
ul: {
|
||||
listStyleType: 'disc',
|
||||
marginTop: theme('spacing.5'),
|
||||
marginBottom: theme('spacing.5'),
|
||||
paddingLeft: '1.625rem',
|
||||
},
|
||||
li: {
|
||||
marginTop: theme('spacing.2'),
|
||||
marginBottom: theme('spacing.2'),
|
||||
},
|
||||
':is(ol, ul) > li': {
|
||||
paddingLeft: theme('spacing[1.5]'),
|
||||
},
|
||||
'ol > li::marker': {
|
||||
fontWeight: '400',
|
||||
color: 'var(--tw-prose-counters)',
|
||||
},
|
||||
'ul > li::marker': {
|
||||
color: 'var(--tw-prose-bullets)',
|
||||
},
|
||||
'> ul > li p': {
|
||||
marginTop: theme('spacing.3'),
|
||||
marginBottom: theme('spacing.3'),
|
||||
},
|
||||
'> ul > li > *:first-child': {
|
||||
marginTop: theme('spacing.5'),
|
||||
},
|
||||
'> ul > li > *:last-child': {
|
||||
marginBottom: theme('spacing.5'),
|
||||
},
|
||||
'> ol > li > *:first-child': {
|
||||
marginTop: theme('spacing.5'),
|
||||
},
|
||||
'> ol > li > *:last-child': {
|
||||
marginBottom: theme('spacing.5'),
|
||||
},
|
||||
'ul ul, ul ol, ol ul, ol ol': {
|
||||
marginTop: theme('spacing.3'),
|
||||
marginBottom: theme('spacing.3'),
|
||||
},
|
||||
|
||||
// Horizontal rules
|
||||
hr: {
|
||||
borderColor: 'var(--tw-prose-hr)',
|
||||
borderTopWidth: 1,
|
||||
marginTop: theme('spacing.16'),
|
||||
marginBottom: theme('spacing.16'),
|
||||
maxWidth: 'none',
|
||||
marginLeft: `calc(-1 * ${theme('spacing.4')})`,
|
||||
marginRight: `calc(-1 * ${theme('spacing.4')})`,
|
||||
'@screen sm': {
|
||||
marginLeft: `calc(-1 * ${theme('spacing.6')})`,
|
||||
marginRight: `calc(-1 * ${theme('spacing.6')})`,
|
||||
},
|
||||
'@screen lg': {
|
||||
marginLeft: `calc(-1 * ${theme('spacing.8')})`,
|
||||
marginRight: `calc(-1 * ${theme('spacing.8')})`,
|
||||
},
|
||||
},
|
||||
|
||||
// Quotes
|
||||
blockquote: {
|
||||
fontWeight: '500',
|
||||
fontStyle: 'italic',
|
||||
color: 'var(--tw-prose-quotes)',
|
||||
borderLeftWidth: '0.25rem',
|
||||
borderLeftColor: 'var(--tw-prose-quote-borders)',
|
||||
quotes: '"\\201C""\\201D""\\2018""\\2019"',
|
||||
marginTop: theme('spacing.8'),
|
||||
marginBottom: theme('spacing.8'),
|
||||
paddingLeft: theme('spacing.5'),
|
||||
},
|
||||
'blockquote p:first-of-type::before': {
|
||||
content: 'open-quote',
|
||||
},
|
||||
'blockquote p:last-of-type::after': {
|
||||
content: 'close-quote',
|
||||
},
|
||||
|
||||
// Headings
|
||||
h1: {
|
||||
color: 'var(--tw-prose-headings)',
|
||||
fontWeight: '700',
|
||||
fontSize: theme('fontSize.2xl')[0],
|
||||
...theme('fontSize.2xl')[1],
|
||||
marginBottom: theme('spacing.2'),
|
||||
},
|
||||
h2: {
|
||||
color: 'var(--tw-prose-headings)',
|
||||
fontWeight: '600',
|
||||
fontSize: theme('fontSize.lg')[0],
|
||||
...theme('fontSize.lg')[1],
|
||||
marginTop: theme('spacing.16'),
|
||||
marginBottom: theme('spacing.2'),
|
||||
},
|
||||
h3: {
|
||||
color: 'var(--tw-prose-headings)',
|
||||
fontSize: theme('fontSize.base')[0],
|
||||
...theme('fontSize.base')[1],
|
||||
fontWeight: '600',
|
||||
marginTop: theme('spacing.10'),
|
||||
marginBottom: theme('spacing.2'),
|
||||
},
|
||||
|
||||
// Media
|
||||
'img, video, figure': {
|
||||
marginTop: theme('spacing.8'),
|
||||
marginBottom: theme('spacing.8'),
|
||||
},
|
||||
'figure > *': {
|
||||
marginTop: '0',
|
||||
marginBottom: '0',
|
||||
},
|
||||
figcaption: {
|
||||
color: 'var(--tw-prose-captions)',
|
||||
fontSize: theme('fontSize.xs')[0],
|
||||
...theme('fontSize.xs')[1],
|
||||
marginTop: theme('spacing.2'),
|
||||
},
|
||||
|
||||
// Tables
|
||||
table: {
|
||||
width: '100%',
|
||||
tableLayout: 'auto',
|
||||
textAlign: 'left',
|
||||
marginTop: theme('spacing.8'),
|
||||
marginBottom: theme('spacing.8'),
|
||||
lineHeight: theme('lineHeight.6'),
|
||||
},
|
||||
thead: {
|
||||
borderBottomWidth: '1px',
|
||||
borderBottomColor: 'var(--tw-prose-th-borders)',
|
||||
},
|
||||
'thead th': {
|
||||
color: 'var(--tw-prose-headings)',
|
||||
fontWeight: '600',
|
||||
verticalAlign: 'bottom',
|
||||
paddingRight: theme('spacing.2'),
|
||||
paddingBottom: theme('spacing.2'),
|
||||
paddingLeft: theme('spacing.2'),
|
||||
},
|
||||
'thead th:first-child': {
|
||||
paddingLeft: '0',
|
||||
},
|
||||
'thead th:last-child': {
|
||||
paddingRight: '0',
|
||||
},
|
||||
'tbody tr': {
|
||||
borderBottomWidth: '1px',
|
||||
borderBottomColor: 'var(--tw-prose-td-borders)',
|
||||
},
|
||||
'tbody tr:last-child': {
|
||||
borderBottomWidth: '0',
|
||||
},
|
||||
'tbody td': {
|
||||
verticalAlign: 'baseline',
|
||||
},
|
||||
tfoot: {
|
||||
borderTopWidth: '1px',
|
||||
borderTopColor: 'var(--tw-prose-th-borders)',
|
||||
},
|
||||
'tfoot td': {
|
||||
verticalAlign: 'top',
|
||||
},
|
||||
':is(tbody, tfoot) td': {
|
||||
paddingTop: theme('spacing.2'),
|
||||
paddingRight: theme('spacing.2'),
|
||||
paddingBottom: theme('spacing.2'),
|
||||
paddingLeft: theme('spacing.2'),
|
||||
},
|
||||
':is(tbody, tfoot) td:first-child': {
|
||||
paddingLeft: '0',
|
||||
},
|
||||
':is(tbody, tfoot) td:last-child': {
|
||||
paddingRight: '0',
|
||||
},
|
||||
|
||||
// Inline elements
|
||||
a: {
|
||||
color: 'var(--tw-prose-links)',
|
||||
textDecoration: 'underline transparent',
|
||||
fontWeight: '500',
|
||||
transitionProperty: 'color, text-decoration-color',
|
||||
transitionDuration: theme('transitionDuration.DEFAULT'),
|
||||
transitionTimingFunction: theme('transitionTimingFunction.DEFAULT'),
|
||||
'&:hover': {
|
||||
color: 'var(--tw-prose-links-hover)',
|
||||
textDecorationColor: 'var(--tw-prose-links-underline)',
|
||||
},
|
||||
},
|
||||
':is(h1, h2, h3) a': {
|
||||
fontWeight: 'inherit',
|
||||
},
|
||||
strong: {
|
||||
color: 'var(--tw-prose-bold)',
|
||||
fontWeight: '600',
|
||||
},
|
||||
':is(a, blockquote, thead th) strong': {
|
||||
color: 'inherit',
|
||||
},
|
||||
code: {
|
||||
color: 'var(--tw-prose-code)',
|
||||
borderRadius: theme('borderRadius.lg'),
|
||||
paddingTop: theme('padding.1'),
|
||||
paddingRight: theme('padding[1.5]'),
|
||||
paddingBottom: theme('padding.1'),
|
||||
paddingLeft: theme('padding[1.5]'),
|
||||
boxShadow: 'inset 0 0 0 1px var(--tw-prose-code-ring)',
|
||||
backgroundColor: 'var(--tw-prose-code-bg)',
|
||||
fontSize: theme('fontSize.2xs'),
|
||||
},
|
||||
':is(a, h1, h2, h3, blockquote, thead th) code': {
|
||||
color: 'inherit',
|
||||
},
|
||||
'h2 code': {
|
||||
fontSize: theme('fontSize.base')[0],
|
||||
fontWeight: 'inherit',
|
||||
},
|
||||
'h3 code': {
|
||||
fontSize: theme('fontSize.sm')[0],
|
||||
fontWeight: 'inherit',
|
||||
},
|
||||
|
||||
// Overrides
|
||||
':is(h1, h2, h3) + *': {
|
||||
marginTop: '0',
|
||||
},
|
||||
'> :first-child': {
|
||||
marginTop: '0 !important',
|
||||
},
|
||||
'> :last-child': {
|
||||
marginBottom: '0 !important',
|
||||
},
|
||||
},
|
||||
},
|
||||
invert: {
|
||||
css: {
|
||||
'--tw-prose-body': 'var(--tw-prose-invert-body)',
|
||||
'--tw-prose-headings': 'var(--tw-prose-invert-headings)',
|
||||
'--tw-prose-links': 'var(--tw-prose-invert-links)',
|
||||
'--tw-prose-links-hover': 'var(--tw-prose-invert-links-hover)',
|
||||
'--tw-prose-links-underline': 'var(--tw-prose-invert-links-underline)',
|
||||
'--tw-prose-bold': 'var(--tw-prose-invert-bold)',
|
||||
'--tw-prose-counters': 'var(--tw-prose-invert-counters)',
|
||||
'--tw-prose-bullets': 'var(--tw-prose-invert-bullets)',
|
||||
'--tw-prose-hr': 'var(--tw-prose-invert-hr)',
|
||||
'--tw-prose-quotes': 'var(--tw-prose-invert-quotes)',
|
||||
'--tw-prose-quote-borders': 'var(--tw-prose-invert-quote-borders)',
|
||||
'--tw-prose-captions': 'var(--tw-prose-invert-captions)',
|
||||
'--tw-prose-code': 'var(--tw-prose-invert-code)',
|
||||
'--tw-prose-code-bg': 'var(--tw-prose-invert-code-bg)',
|
||||
'--tw-prose-code-ring': 'var(--tw-prose-invert-code-ring)',
|
||||
'--tw-prose-th-borders': 'var(--tw-prose-invert-th-borders)',
|
||||
'--tw-prose-td-borders': 'var(--tw-prose-invert-td-borders)',
|
||||
},
|
||||
},
|
||||
})
|
Loading…
Reference in a new issue