docs: rework docs site to have different sections (#2686)
This PR starts putting in place the high-level changes we want to make to the docs site. - It makes separate sections for Reference and Examples and Community. - Gets rid of the secondary sidebar and integrates it into the main sidebar. - Groups the reference articles by type. - Pulls in the examples alongside code and a live playground so people don't have to visit examples.tldraw.com separately. <img width="1458" alt="Screenshot 2024-01-30 at 09 43 46" src="https://github.com/tldraw/tldraw/assets/469604/4f5aa339-3a69-4d9b-9b9f-dfdddea623e8"> Again, this is the top-level changes and there's more to be done for the next PR(s): - create quick start page - clean up installation page - add accordion to Examples page prbly - put fun stuff in header (from footer) - landing page - something for landing page of API - search cmd-k and border - cleanup _sidebarReferenceContentLinks - external links _blank - address potential skew issue with code examples - have a link to other examples (next.js, etc.) ### Change Type - [x] `documentation` — Changes to the documentation only[^2] ### Test Plan 1. Make sure examples work! ### Release Notes - Rework our docs site to pull together the examples app and reference section more cohesively. --------- Co-authored-by: Taha <98838967+Taha-Hassan-Git@users.noreply.github.com> Co-authored-by: Steve Ruiz <steveruizok@gmail.com> Co-authored-by: Mitja Bezenšek <mitja.bezensek@gmail.com> Co-authored-by: alex <alex@dytry.ch> Co-authored-by: Lu Wilson <l2wilson94@gmail.com> Co-authored-by: Dan Groshev <git@dgroshev.com>
This commit is contained in:
parent
a43b172b64
commit
3ae48af67c
68 changed files with 94415 additions and 92577 deletions
2
apps/docs/.gitignore
vendored
2
apps/docs/.gitignore
vendored
|
@ -1,4 +1,4 @@
|
||||||
content/gen
|
content/reference
|
||||||
api-content.json
|
api-content.json
|
||||||
content.db
|
content.db
|
||||||
.env
|
.env
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
content.db
|
content.db
|
||||||
node_modules
|
node_modules
|
||||||
utils/vector-db/index.json
|
utils/vector-db/index.json
|
||||||
**/*.api.json
|
|
|
@ -25,8 +25,7 @@ The files are also provided in this repo.
|
||||||
|
|
||||||
You can build the markdown and API content using the following scripts:
|
You can build the markdown and API content using the following scripts:
|
||||||
|
|
||||||
- `yarn refresh-all` to reset the database, generate the markdown from the API docs, and populate the database with articles from both the regular content and the generated API content
|
- `yarn refresh-everything` to reset the database, generate the markdown from the API docs, and populate the database with articles from both the regular content and the generated API content
|
||||||
- `yarn refresh-api-content` to refresh just the API content
|
|
||||||
- `yarn refresh-content` to generate just the regular content
|
- `yarn refresh-content` to generate just the regular content
|
||||||
|
|
||||||
# Content
|
# Content
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
@ -80,12 +80,12 @@ export async function GET(req: NextRequest) {
|
||||||
const { category, section, article, heading, score } = result
|
const { category, section, article, heading, score } = result
|
||||||
const isUncategorized = category.id === section.id + '_ucg'
|
const isUncategorized = category.id === section.id + '_ucg'
|
||||||
if (BANNED_HEADINGS.some((h) => heading.slug.endsWith(h))) continue
|
if (BANNED_HEADINGS.some((h) => heading.slug.endsWith(h))) continue
|
||||||
results[section.id === 'gen' ? 'apiDocs' : 'articles'].push({
|
results[section.id === 'reference' ? 'apiDocs' : 'articles'].push({
|
||||||
id: result.id,
|
id: result.id,
|
||||||
type: 'heading',
|
type: 'heading',
|
||||||
subtitle: isUncategorized ? section.title : `${section.title} / ${category.title}`,
|
subtitle: isUncategorized ? section.title : `${section.title} / ${category.title}`,
|
||||||
title:
|
title:
|
||||||
section.id === 'gen'
|
section.id === 'reference'
|
||||||
? article.title + '.' + heading.title
|
? article.title + '.' + heading.title
|
||||||
: article.title + ': ' + heading.title,
|
: article.title + ': ' + heading.title,
|
||||||
url: isUncategorized
|
url: isUncategorized
|
||||||
|
@ -115,7 +115,7 @@ export async function GET(req: NextRequest) {
|
||||||
article.sectionId
|
article.sectionId
|
||||||
)
|
)
|
||||||
const isUncategorized = category.id === section.id + '_ucg'
|
const isUncategorized = category.id === section.id + '_ucg'
|
||||||
results[section.id === 'gen' ? 'apiDocs' : 'articles'].push({
|
results[section.id === 'reference' ? 'apiDocs' : 'articles'].push({
|
||||||
id: article.id,
|
id: article.id,
|
||||||
type: 'article',
|
type: 'article',
|
||||||
subtitle: isUncategorized ? section.title : `${section.title} / ${category.title}`,
|
subtitle: isUncategorized ? section.title : `${section.title} / ${category.title}`,
|
||||||
|
|
|
@ -61,7 +61,7 @@ export async function GET(req: NextRequest) {
|
||||||
|
|
||||||
await searchForArticle.all(query).then(async (queryResults) => {
|
await searchForArticle.all(query).then(async (queryResults) => {
|
||||||
for (const article of queryResults) {
|
for (const article of queryResults) {
|
||||||
const isApiDoc = article.sectionId === 'gen'
|
const isApiDoc = article.sectionId === 'reference'
|
||||||
const section = await db.getSection(article.sectionId)
|
const section = await db.getSection(article.sectionId)
|
||||||
const category = await db.getCategory(article.categoryId)
|
const category = await db.getCategory(article.categoryId)
|
||||||
const isUncategorized = category.id === section.id + '_ucg'
|
const isUncategorized = category.id === section.id + '_ucg'
|
||||||
|
@ -95,7 +95,7 @@ export async function GET(req: NextRequest) {
|
||||||
if (BANNED_HEADINGS.some((h) => heading.slug.endsWith(h))) continue
|
if (BANNED_HEADINGS.some((h) => heading.slug.endsWith(h))) continue
|
||||||
const article = await db.getArticle(heading.articleId)
|
const article = await db.getArticle(heading.articleId)
|
||||||
|
|
||||||
const isApiDoc = article.sectionId === 'gen'
|
const isApiDoc = article.sectionId === 'reference'
|
||||||
const section = await db.getSection(article.sectionId)
|
const section = await db.getSection(article.sectionId)
|
||||||
const category = await db.getCategory(article.categoryId)
|
const category = await db.getCategory(article.categoryId)
|
||||||
const isUncategorized = category.id === section.id + '_ucg'
|
const isUncategorized = category.id === section.id + '_ucg'
|
||||||
|
@ -105,7 +105,7 @@ export async function GET(req: NextRequest) {
|
||||||
type: 'heading',
|
type: 'heading',
|
||||||
subtitle: isUncategorized ? section.title : `${section.title} / ${category.title}`,
|
subtitle: isUncategorized ? section.title : `${section.title} / ${category.title}`,
|
||||||
title:
|
title:
|
||||||
section.id === 'gen'
|
section.id === 'reference'
|
||||||
? article.title + '.' + heading.title
|
? article.title + '.' + heading.title
|
||||||
: article.title + ': ' + heading.title,
|
: article.title + ': ' + heading.title,
|
||||||
url: isUncategorized
|
url: isUncategorized
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default async function ClaPage() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header activeId={null} />
|
<Header />
|
||||||
<Sidebar {...sidebar} />
|
<Sidebar {...sidebar} />
|
||||||
<main className="article">
|
<main className="article">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default async function LicensePage() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header activeId={null} />
|
<Header />
|
||||||
<Sidebar {...sidebar} />
|
<Sidebar {...sidebar} />
|
||||||
<main className="article">
|
<main className="article">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default async function NotFound() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header activeId={null} />
|
<Header />
|
||||||
<Sidebar {...sidebar} />
|
<Sidebar {...sidebar} />
|
||||||
<main className="article">
|
<main className="article">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { notFound } from 'next/navigation'
|
||||||
|
|
||||||
export default async function HomePage() {
|
export default async function HomePage() {
|
||||||
const db = await getDb()
|
const db = await getDb()
|
||||||
const article = await db.db.get(`SELECT * FROM articles WHERE articles.path = ?`, `/introduction`)
|
const article = await db.db.get(`SELECT * FROM articles WHERE articles.path = ?`, `/quick-start`)
|
||||||
if (article) return <ArticleDocsPage article={article} />
|
if (article) return <ArticleDocsPage article={article} />
|
||||||
throw notFound()
|
throw notFound()
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,8 @@ export default async function SearchResultsPage({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header activeId={null} searchQuery={query} searchType={type} />
|
<Header searchQuery={query} searchType={type} />
|
||||||
<Sidebar {...sidebar} />
|
<Sidebar {...sidebar} searchQuery={query} searchType={type} />
|
||||||
<main className="article list">
|
<main className="article list">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<h2>{`Found ${
|
<h2>{`Found ${
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { getDb } from '@/utils/ContentDatabase'
|
||||||
import { ArticleDetails } from './ArticleDetails'
|
import { ArticleDetails } from './ArticleDetails'
|
||||||
import { ArticleNavLinks } from './ArticleNavLinks'
|
import { ArticleNavLinks } from './ArticleNavLinks'
|
||||||
import { Breadcrumb } from './Breadcrumb'
|
import { Breadcrumb } from './Breadcrumb'
|
||||||
|
import ExampleCodeBlock from './ExampleCodeBlock'
|
||||||
import { Header } from './Header'
|
import { Header } from './Header'
|
||||||
import { HeadingLinks } from './HeadingLinks'
|
|
||||||
import { Mdx } from './Mdx'
|
import { Mdx } from './Mdx'
|
||||||
import { Sidebar } from './Sidebar'
|
import { Sidebar } from './Sidebar'
|
||||||
import { Image } from './mdx-components/generic'
|
import { Image } from './mdx-components/generic'
|
||||||
|
@ -21,23 +21,34 @@ export async function ArticleDocsPage({ article }: { article: Article }) {
|
||||||
articleId: article.id,
|
articleId: article.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
const isGenerated = article.sectionId === 'gen'
|
const isGenerated = article.sectionId === 'reference'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header activeId={article.id} />
|
<Header sectionId={section.id} />
|
||||||
<Sidebar {...sidebar} />
|
<Sidebar headings={headings} {...sidebar} />
|
||||||
<main className={`article${isGenerated ? ' article__api-docs' : ''}`}>
|
<main
|
||||||
|
className={`article${isGenerated ? ' article__api-docs' : ''}${article.componentCode ? ' article__example' : ''}`}
|
||||||
|
>
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<Breadcrumb section={section} category={category} />
|
<Breadcrumb section={section} category={category} />
|
||||||
<h1>{article.title}</h1>
|
<h1>{article.title}</h1>
|
||||||
</div>
|
</div>
|
||||||
{article.hero && <Image alt="hero" title={article.title} src={`images/${article.hero}`} />}
|
{article.hero && <Image alt="hero" title={article.title} src={`images/${article.hero}`} />}
|
||||||
{article.content && <Mdx content={article.content} />}
|
{article.content && <Mdx content={article.content} />}
|
||||||
|
{article.componentCode && (
|
||||||
|
<ExampleCodeBlock
|
||||||
|
articleId={article.id}
|
||||||
|
files={{
|
||||||
|
'App.tsx': article.componentCode,
|
||||||
|
...(article.componentCodeFiles ? JSON.parse(article.componentCodeFiles) : null),
|
||||||
|
}}
|
||||||
|
activeFile={'App.tsx'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{isGenerated ? null : <ArticleDetails article={article} />}
|
{isGenerated ? null : <ArticleDetails article={article} />}
|
||||||
{links && <ArticleNavLinks links={links} />}
|
{links && <ArticleNavLinks links={links} />}
|
||||||
</main>
|
</main>
|
||||||
{headings.length > 0 ? <HeadingLinks article={article} headingLinks={headings} /> : null}
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ export async function CategoryDocsPage({ category }: { category: Category }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header activeId={category.id} />
|
<Header sectionId={section.id} />
|
||||||
<Sidebar {...sidebar} />
|
<Sidebar {...sidebar} />
|
||||||
<main className={'article'}>
|
<main className={'article'}>
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
|
@ -23,9 +23,11 @@ export async function CategoryDocsPage({ category }: { category: Category }) {
|
||||||
{articles.length > 0 && (
|
{articles.length > 0 && (
|
||||||
<ul>
|
<ul>
|
||||||
{articles.map((article) => (
|
{articles.map((article) => (
|
||||||
<Link key={article.id} href={`/${section.id}/${category.id}/${article.id}`}>
|
<li>
|
||||||
<li>{article.title}</li>
|
<Link key={article.id} href={`/${section.id}/${category.id}/${article.id}`}>
|
||||||
</Link>
|
{article.title}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
|
|
52
apps/docs/components/ExampleCodeBlock.tsx
Normal file
52
apps/docs/components/ExampleCodeBlock.tsx
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { SandpackCodeEditor, SandpackFiles, SandpackProvider } from '@codesandbox/sandpack-react'
|
||||||
|
import { useTheme } from 'next-themes'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
export default function ExampleCodeBlock({
|
||||||
|
articleId,
|
||||||
|
files = {},
|
||||||
|
activeFile,
|
||||||
|
}: {
|
||||||
|
articleId: string
|
||||||
|
activeFile: string
|
||||||
|
files: SandpackFiles
|
||||||
|
}) {
|
||||||
|
const [isClientSide, setIsClientSide] = useState(false)
|
||||||
|
const { theme } = useTheme()
|
||||||
|
useEffect(() => setIsClientSide(true), [])
|
||||||
|
const SERVER =
|
||||||
|
process.env.NODE_ENV === 'development' ? 'http://localhost:5420' : 'https://examples.tldraw.com'
|
||||||
|
|
||||||
|
// This is to avoid hydration mismatch between the server and the client because of the useTheme.
|
||||||
|
if (!isClientSide) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<iframe
|
||||||
|
src={`${SERVER}/${articleId}/full`}
|
||||||
|
style={{ border: 0, height: '50vh', width: '100%' }}
|
||||||
|
/>
|
||||||
|
<SandpackProvider
|
||||||
|
key={`sandpack-${theme}-${activeFile}`}
|
||||||
|
template="react-ts"
|
||||||
|
options={{ activeFile }}
|
||||||
|
customSetup={{
|
||||||
|
dependencies: {
|
||||||
|
'@tldraw/assets': 'latest',
|
||||||
|
'@tldraw/tldraw': 'latest',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
files={{
|
||||||
|
...files,
|
||||||
|
}}
|
||||||
|
theme={theme === 'dark' ? 'dark' : 'light'}
|
||||||
|
>
|
||||||
|
<SandpackCodeEditor readOnly />
|
||||||
|
</SandpackProvider>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ export function Footer() {
|
||||||
WebkitMask: `url(/tldraw-icon.svg) center 100% / 100% no-repeat`,
|
WebkitMask: `url(/tldraw-icon.svg) center 100% / 100% no-repeat`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<p>tldraw © 2024</p>
|
<p>tldraw © {new Date().getFullYear()}</p>
|
||||||
</a>
|
</a>
|
||||||
<div className="footer__socials">
|
<div className="footer__socials">
|
||||||
<a
|
<a
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import * as NavigationMenu from '@radix-ui/react-navigation-menu'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { Icon } from './Icon'
|
import { Icon } from './Icon'
|
||||||
|
import { Chevron } from './Icons'
|
||||||
import { Search } from './Search'
|
import { Search } from './Search'
|
||||||
import { ThemeSwitcher } from './ThemeSwitcher'
|
import { ThemeSwitcher } from './ThemeSwitcher'
|
||||||
|
|
||||||
export function Header({
|
export function Header({
|
||||||
activeId,
|
|
||||||
searchQuery,
|
searchQuery,
|
||||||
searchType,
|
searchType,
|
||||||
|
sectionId,
|
||||||
}: {
|
}: {
|
||||||
activeId: string | null
|
|
||||||
searchQuery?: string
|
searchQuery?: string
|
||||||
searchType?: string
|
searchType?: string
|
||||||
|
sectionId?: string
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="layout__header">
|
<div className="layout__header">
|
||||||
<Link href="/">
|
<Link href="/quick-start">
|
||||||
<div
|
<div
|
||||||
className="lockup"
|
className="lockup"
|
||||||
style={{
|
style={{
|
||||||
|
@ -23,14 +27,16 @@ export function Header({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<Search activeId={activeId} prevQuery={searchQuery} prevType={searchType} />
|
<Search prevQuery={searchQuery} prevType={searchType} />
|
||||||
<div className="layout__header__socials">
|
<div className="layout__header__sections_and_socials">
|
||||||
|
<SectionLinks sectionId={sectionId} />
|
||||||
|
<ThemeSwitcher />
|
||||||
<a
|
<a
|
||||||
href="https://twitter.com/tldraw"
|
href="https://discord.com/invite/SBBEVCA4PG"
|
||||||
className="sidebar__button icon-button"
|
className="sidebar__button icon-button"
|
||||||
title="twitter"
|
title="discord"
|
||||||
>
|
>
|
||||||
<Icon icon="twitter" />
|
<Icon icon="discord" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/tldraw/tldraw"
|
href="https://github.com/tldraw/tldraw"
|
||||||
|
@ -39,15 +45,84 @@ export function Header({
|
||||||
>
|
>
|
||||||
<Icon icon="github" />
|
<Icon icon="github" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
|
||||||
href="https://discord.com/invite/SBBEVCA4PG"
|
|
||||||
className="sidebar__button icon-button"
|
|
||||||
title="discord"
|
|
||||||
>
|
|
||||||
<Icon icon="discord" />
|
|
||||||
</a>
|
|
||||||
<ThemeSwitcher />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SectionLinks({ sectionId }: { sectionId?: string | null }) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<a
|
||||||
|
href="/quick-start"
|
||||||
|
title="Learn"
|
||||||
|
data-active={!['reference', 'examples'].includes(sectionId || '')}
|
||||||
|
className="layout_header__section"
|
||||||
|
>
|
||||||
|
Learn
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="/reference/editor/Editor"
|
||||||
|
title="Reference"
|
||||||
|
data-active={sectionId === 'reference'}
|
||||||
|
className="layout_header__section"
|
||||||
|
>
|
||||||
|
Reference
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="/examples/basic/develop"
|
||||||
|
title="Examples"
|
||||||
|
data-active={sectionId === 'examples'}
|
||||||
|
className="layout_header__section"
|
||||||
|
>
|
||||||
|
Examples
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<NavigationMenu.Root className="NavigationMenuRoot">
|
||||||
|
<NavigationMenu.List className="NavigationMenuList">
|
||||||
|
<NavigationMenu.Item>
|
||||||
|
<NavigationMenu.Trigger
|
||||||
|
className="NavigationMenuTrigger"
|
||||||
|
onPointerMove={(event) => event.preventDefault()}
|
||||||
|
onPointerLeave={(event) => event.preventDefault()}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Community <Chevron className="CaretDown" aria-hidden />
|
||||||
|
</span>
|
||||||
|
</NavigationMenu.Trigger>
|
||||||
|
<NavigationMenu.Content
|
||||||
|
className="NavigationMenuContent"
|
||||||
|
onPointerMove={(event) => event.preventDefault()}
|
||||||
|
onPointerLeave={(event) => event.preventDefault()}
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<NavigationMenu.Link asChild>
|
||||||
|
<a href="/community/contributing">Contributing</a>
|
||||||
|
</NavigationMenu.Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<NavigationMenu.Link asChild>
|
||||||
|
<a href="/community/translations">Translations</a>
|
||||||
|
</NavigationMenu.Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<NavigationMenu.Link asChild>
|
||||||
|
<a href="/community/license">License</a>
|
||||||
|
</NavigationMenu.Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<NavigationMenu.Link asChild>
|
||||||
|
<a href="https://discord.com/invite/SBBEVCA4PG" target="_blank">
|
||||||
|
Discord
|
||||||
|
</a>
|
||||||
|
</NavigationMenu.Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</NavigationMenu.Content>
|
||||||
|
</NavigationMenu.Item>
|
||||||
|
</NavigationMenu.List>
|
||||||
|
</NavigationMenu.Root>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
/* eslint-disable no-useless-escape */
|
|
||||||
import { Article, ArticleHeadings } from '@/types/content-types'
|
|
||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
export function HeadingLinks({
|
|
||||||
article,
|
|
||||||
headingLinks,
|
|
||||||
}: {
|
|
||||||
article: Article
|
|
||||||
headingLinks: ArticleHeadings
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<nav className="layout__headings">
|
|
||||||
<ul className="sidebar__list sidebar__sections__list" key={article.id}>
|
|
||||||
<li className="sidebar__section">
|
|
||||||
<div className="sidebar__section__title" data-active={false}>
|
|
||||||
On this page
|
|
||||||
</div>
|
|
||||||
<ul className="sidebar__list">
|
|
||||||
{headingLinks
|
|
||||||
.filter((heading) => heading.level < 4)
|
|
||||||
.map((heading) => (
|
|
||||||
<li className="sidebar__article" key={heading.slug}>
|
|
||||||
<Link href={`#${heading.slug}`} className="sidebar__link">
|
|
||||||
{heading.level > 2 ? (
|
|
||||||
<span className="sidebar__link__indent">{'– '}</span>
|
|
||||||
) : null}
|
|
||||||
<span className="sidebar__link__title">
|
|
||||||
{heading.isCode ? (
|
|
||||||
<code>{heading.title.replace(/\[([^\]]+)\]\([^\)]+\)/g, '$1')}</code>
|
|
||||||
) : (
|
|
||||||
heading.title.replace(/\[([^\]]+)\]\([^\)]+\)/g, '$1')
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
)
|
|
||||||
}
|
|
22
apps/docs/components/Icons.tsx
Normal file
22
apps/docs/components/Icons.tsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import classNames from 'classnames'
|
||||||
|
|
||||||
|
export function Chevron({ className }: { className?: string }) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={classNames('accordion__trigger__chevron', className)}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M4 6L8 10L12 6"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
|
@ -9,7 +9,6 @@ export function Search({
|
||||||
prevType = 'n',
|
prevType = 'n',
|
||||||
prevQuery = '',
|
prevQuery = '',
|
||||||
}: {
|
}: {
|
||||||
activeId: string | null
|
|
||||||
prevType?: string
|
prevType?: string
|
||||||
prevQuery?: string
|
prevQuery?: string
|
||||||
}) {
|
}) {
|
||||||
|
|
|
@ -1,65 +1,21 @@
|
||||||
import { Article, Category, Section } from '@/types/content-types'
|
import { Section } from '@/types/content-types'
|
||||||
import { getDb } from '@/utils/ContentDatabase'
|
import { getDb } from '@/utils/ContentDatabase'
|
||||||
import Link from 'next/link'
|
|
||||||
import { Header } from './Header'
|
import { Header } from './Header'
|
||||||
import { Sidebar } from './Sidebar'
|
import { Sidebar } from './Sidebar'
|
||||||
|
|
||||||
export async function SectionDocsPage({ section }: { section: Section }) {
|
export async function SectionDocsPage({ section }: { section: Section }) {
|
||||||
const db = await getDb()
|
const db = await getDb()
|
||||||
|
|
||||||
const sidebar = await db.getSidebarContentList({ sectionId: section.id })
|
const sidebar = await db.getSidebarContentList({ sectionId: section.id })
|
||||||
|
|
||||||
const categories = [] as Category[]
|
|
||||||
const articles: Article[] = []
|
|
||||||
|
|
||||||
const sectionCategories = await db.getCategoriesForSection(section.id)
|
|
||||||
|
|
||||||
for (const category of sectionCategories) {
|
|
||||||
if (category.id === section.id + '_ucg') {
|
|
||||||
const categoryArticles = await db.getCategoryArticles(section.id, category.id)
|
|
||||||
for (const article of categoryArticles) {
|
|
||||||
articles.push(article)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the count of articles for this category is greater than zero...
|
|
||||||
const articleCount = await db.getCategoryArticlesCount(section.id, category.id)
|
|
||||||
|
|
||||||
if (articleCount > 0) {
|
|
||||||
categories.push(category)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header activeId={section.id} />
|
<Header sectionId={section.id} />
|
||||||
<Sidebar {...sidebar} />
|
<Sidebar {...sidebar} />
|
||||||
<main className="article">
|
<main className="article">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<h1>{section.title}</h1>
|
<h1>{section.title}</h1>
|
||||||
</div>
|
</div>
|
||||||
{articles.length > 0 && (
|
Choose your adventure on the left.
|
||||||
<ul>
|
|
||||||
{articles.map((articleLink) => {
|
|
||||||
return (
|
|
||||||
<Link key={articleLink.id} href={articleLink.path!}>
|
|
||||||
<li>{articleLink.title}</li>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
)}
|
|
||||||
{categories.length > 0 && (
|
|
||||||
<ul>
|
|
||||||
{categories.map((category) =>
|
|
||||||
category.id === 'ucg' ? null : (
|
|
||||||
<Link key={category.id} href={`/${section.id}/${category.id}`}>
|
|
||||||
{category.id === 'ucg' ? null : <li>{category.title}</li>}
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
)}
|
|
||||||
</main>
|
</main>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,65 +1,97 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
ArticleHeadings,
|
||||||
SidebarContentArticleLink,
|
SidebarContentArticleLink,
|
||||||
SidebarContentCategoryLink,
|
SidebarContentCategoryLink,
|
||||||
SidebarContentLink,
|
SidebarContentLink,
|
||||||
SidebarContentList,
|
SidebarContentList,
|
||||||
SidebarContentSectionLink,
|
SidebarContentSectionLink,
|
||||||
} from '@/types/content-types'
|
} from '@/types/content-types'
|
||||||
|
import * as Accordion from '@radix-ui/react-accordion'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { usePathname } from 'next/navigation'
|
import { usePathname } from 'next/navigation'
|
||||||
import { createContext, useContext, useEffect } from 'react'
|
import { createContext, useContext, useEffect } from 'react'
|
||||||
|
import { SectionLinks } from './Header'
|
||||||
|
import { Chevron } from './Icons'
|
||||||
import { Search } from './Search'
|
import { Search } from './Search'
|
||||||
import { SidebarCloseButton } from './SidebarCloseButton'
|
import { SidebarCloseButton } from './SidebarCloseButton'
|
||||||
import { ToggleMenuButton } from './ToggleMenuButton'
|
import { ToggleMenuButton } from './ToggleMenuButton'
|
||||||
|
|
||||||
type SidebarProps = SidebarContentList
|
type SidebarProps = SidebarContentList
|
||||||
|
|
||||||
const activeLinkContext = createContext<string | null>(null)
|
const linkContext = createContext<{
|
||||||
|
activeId: string | null
|
||||||
|
articleId: string | null
|
||||||
|
categoryId: string | null
|
||||||
|
sectionId: string | null
|
||||||
|
} | null>(null)
|
||||||
|
|
||||||
export function Sidebar({ links, sectionId, categoryId, articleId }: SidebarProps) {
|
export function Sidebar({
|
||||||
|
headings,
|
||||||
|
links,
|
||||||
|
sectionId,
|
||||||
|
categoryId,
|
||||||
|
articleId,
|
||||||
|
searchQuery,
|
||||||
|
searchType,
|
||||||
|
}: SidebarProps) {
|
||||||
const activeId = articleId ?? categoryId ?? sectionId
|
const activeId = articleId ?? categoryId ?? sectionId
|
||||||
|
|
||||||
const pathName = usePathname()
|
const pathName = usePathname()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.body.classList.remove('sidebar-open')
|
document.body.classList.remove('sidebar-open')
|
||||||
|
|
||||||
|
document.querySelector('.sidebar [data-active=true]')?.scrollIntoView({ block: 'center' })
|
||||||
|
|
||||||
|
// XXX(mime): scrolling the sidebar into position also scrolls the page to the wrong
|
||||||
|
// spot. this compensates for that but, ugh.
|
||||||
|
document.documentElement.scrollTop = 0
|
||||||
}, [pathName])
|
}, [pathName])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<activeLinkContext.Provider value={activeId}>
|
<linkContext.Provider value={{ activeId, articleId, categoryId, sectionId }}>
|
||||||
<div className="sidebar" onScroll={(e) => e.stopPropagation()}>
|
<div className="sidebar" onScroll={(e) => e.stopPropagation()}>
|
||||||
<Search activeId={activeId} />
|
<Search prevQuery={searchQuery} prevType={searchType} />
|
||||||
<SidebarLinks links={links} />
|
<div className="sidebar__section__links">
|
||||||
|
<SectionLinks sectionId={sectionId} />
|
||||||
|
</div>
|
||||||
|
<SidebarLinks headings={headings} links={links} />
|
||||||
<SidebarCloseButton />
|
<SidebarCloseButton />
|
||||||
</div>
|
</div>
|
||||||
<ToggleMenuButton />
|
<ToggleMenuButton />
|
||||||
</activeLinkContext.Provider>
|
</linkContext.Provider>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SidebarLinks({ links }: { links: SidebarContentLink[] }) {
|
export function SidebarLinks({
|
||||||
|
headings,
|
||||||
|
links,
|
||||||
|
}: {
|
||||||
|
headings?: ArticleHeadings
|
||||||
|
links: SidebarContentLink[]
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<nav className="sidebar__nav">
|
<nav className="sidebar__nav">
|
||||||
<ul className="sidebar__list sidebar__sections__list">
|
<ul className="sidebar__list sidebar__sections__list">
|
||||||
{links.map((link) => (
|
{links.map((link) => (
|
||||||
<SidebarLink key={link.url} {...link} />
|
<SidebarLink key={link.url} headings={headings} {...link} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarLink(props: SidebarContentLink) {
|
function SidebarLink({ headings, ...props }: SidebarContentLink & { headings?: ArticleHeadings }) {
|
||||||
switch (props.type) {
|
switch (props.type) {
|
||||||
case 'section': {
|
case 'section': {
|
||||||
return <SidebarSection {...props} />
|
return <SidebarSection headings={headings} {...props} />
|
||||||
}
|
}
|
||||||
case 'article': {
|
case 'article': {
|
||||||
return <SidebarArticle {...props} />
|
return <SidebarArticle headings={headings} {...props} />
|
||||||
}
|
}
|
||||||
case 'category': {
|
case 'category': {
|
||||||
return <SidebarCategory {...props} />
|
return <SidebarCategory {...props} />
|
||||||
|
@ -67,19 +99,19 @@ function SidebarLink(props: SidebarContentLink) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarSection({ title, children }: SidebarContentSectionLink) {
|
function SidebarSection({
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
headings,
|
||||||
|
}: SidebarContentSectionLink & { headings?: ArticleHeadings }) {
|
||||||
if (children.length === 0) return null
|
if (children.length === 0) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className="sidebar__section">
|
<li className="sidebar__section">
|
||||||
{title && (
|
{title && <span className="sidebar__section__title">{title}</span>}
|
||||||
<Link href={children[0].url} title={title} className="sidebar__section__title">
|
|
||||||
{title}
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
<ul className="sidebar__list">
|
<ul className="sidebar__list">
|
||||||
{children.map((link) => (
|
{children.map((link) => (
|
||||||
<SidebarLink key={link.url} {...link} />
|
<SidebarLink key={link.url} headings={headings} {...link} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
@ -87,33 +119,102 @@ function SidebarSection({ title, children }: SidebarContentSectionLink) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarCategory({ title, children }: SidebarContentCategoryLink) {
|
function SidebarCategory({ title, children }: SidebarContentCategoryLink) {
|
||||||
|
const linkCtx = useContext(linkContext)
|
||||||
if (children.length === 0) return null
|
if (children.length === 0) return null
|
||||||
|
const hasGroups = children.some((child) => !!(child as SidebarContentArticleLink).groupId)
|
||||||
|
const activeArticle = children.find(
|
||||||
|
(child) => (child as SidebarContentArticleLink).articleId === linkCtx?.articleId
|
||||||
|
)
|
||||||
|
const activeGroup = activeArticle && (activeArticle as SidebarContentArticleLink).groupId
|
||||||
|
const groups = ['Class', 'Function', 'Variable', 'Interface', 'Enum', 'TypeAlias', 'Namespace']
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className="sidebar__category">
|
<li className="sidebar__category">
|
||||||
<Link href={children[0].url} title={title} className="sidebar__link">
|
{hasGroups ? (
|
||||||
{title}
|
<>
|
||||||
</Link>
|
<span className="sidebar__link">{title}</span>
|
||||||
<ul className="sidebar__list">
|
<Accordion.Root
|
||||||
{children.map((link) => (
|
type="multiple"
|
||||||
<SidebarLink key={link.url} {...link} />
|
defaultValue={[`${linkCtx?.categoryId}-${activeGroup}-${linkCtx?.articleId}`]}
|
||||||
))}
|
>
|
||||||
</ul>
|
{groups.map((group) => {
|
||||||
|
const articles = children.filter(
|
||||||
|
(child) => (child as SidebarContentArticleLink).groupId === group
|
||||||
|
)
|
||||||
|
if (articles.length === 0) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion.Item
|
||||||
|
key={group}
|
||||||
|
value={`${linkCtx?.categoryId}-${group}-${linkCtx?.articleId}`}
|
||||||
|
>
|
||||||
|
<Accordion.Trigger
|
||||||
|
className="sidebar__section__group__title"
|
||||||
|
style={{ marginLeft: '8px', paddingRight: '8px' }}
|
||||||
|
>
|
||||||
|
{group}
|
||||||
|
<Chevron />
|
||||||
|
</Accordion.Trigger>
|
||||||
|
<Accordion.Content>
|
||||||
|
<ul className="sidebar__list" style={{ paddingLeft: '8px' }}>
|
||||||
|
{articles.map((link) => (
|
||||||
|
<SidebarLink key={link.url} {...link} />
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</Accordion.Content>
|
||||||
|
</Accordion.Item>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Accordion.Root>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Link href={children[0].url} title={title} className="sidebar__link">
|
||||||
|
{title}
|
||||||
|
</Link>
|
||||||
|
<ul className="sidebar__list">
|
||||||
|
{children.map((link) => (
|
||||||
|
<SidebarLink key={link.url} {...link} />
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<hr />
|
<hr />
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarArticle({ title, url, articleId }: SidebarContentArticleLink) {
|
function SidebarArticle({
|
||||||
const isActive = useContext(activeLinkContext) === articleId
|
title,
|
||||||
|
url,
|
||||||
|
articleId,
|
||||||
|
headings,
|
||||||
|
}: SidebarContentArticleLink & { headings?: ArticleHeadings }) {
|
||||||
|
const isActive = useContext(linkContext)?.activeId === articleId
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className="sidebar__article">
|
<li className="sidebar__article">
|
||||||
<Link href={url}>
|
<Link href={url} className="sidebar__link" data-active={isActive}>
|
||||||
<div className="sidebar__link" data-active={isActive}>
|
{title}
|
||||||
{title}
|
|
||||||
</div>
|
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
{isActive && (
|
||||||
|
<ul className="sidebar__list">
|
||||||
|
{headings
|
||||||
|
?.filter((heading) => heading.level < 3)
|
||||||
|
.map((heading) => (
|
||||||
|
<li key={heading.slug}>
|
||||||
|
<Link href={`#${heading.slug}`} className="sidebar__link">
|
||||||
|
{heading.isCode ? (
|
||||||
|
<code>{heading.title.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')}</code>
|
||||||
|
) : (
|
||||||
|
heading.title.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
title: Examples
|
|
||||||
status: published
|
|
||||||
author: steveruizok
|
|
||||||
date: 10/11/2023
|
|
||||||
order: 3
|
|
||||||
---
|
|
||||||
|
|
||||||
Here's a [very simple sandbox](https://codesandbox.io/s/tldraw-example-canary-2lrzmy) showing the tldraw component.
|
|
||||||
|
|
||||||
<Embed src="https://codesandbox.io/embed/2lrzmy?view=Editor+%2B+Preview&module=%2Fsrc%2Fapp.tsx" />
|
|
||||||
|
|
||||||
You can also find simple [framework-specific examples](https://github.com/tldraw/examples). For a multiplayer example using a collaboration backend, see our [Yjs example](https://github.com/tldraw/tldraw-yjs-example).
|
|
||||||
|
|
||||||
For more specific examples of how to use the tldraw component, check out the [tldraw repository's examples app](https://github.com/tldraw/tldraw/blob/main/apps/examples/src). The [tldraw repo](https://github.com/tldraw/tldraw) has more information about running the examples locally.
|
|
|
@ -31,3 +31,169 @@ yarn add @tldraw/tldraw@canary
|
||||||
```bash
|
```bash
|
||||||
npm install @tldraw/tldraw@canary
|
npm install @tldraw/tldraw@canary
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
You can use the [Tldraw](?) component inside of any React component.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { Tldraw } from '@tldraw/tldraw'
|
||||||
|
import '@tldraw/tldraw/tldraw.css'
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
return (
|
||||||
|
<div style={{ position: 'fixed', inset: 0 }}>
|
||||||
|
<Tldraw />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Wrapper
|
||||||
|
|
||||||
|
It's important that the [Tldraw](?) component is wrapped in a parent container that has an explicit size. Its height and width are set to `100%`, so it will fill its parent container.
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
In addition to the [Tldraw](?) component itself, you should also import the `tldraw.css` file from the `@tldraw/tldraw` package.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import '@tldraw/tldraw/tldraw.css'
|
||||||
|
```
|
||||||
|
|
||||||
|
You can alternatively import this file inside of another CSS file using the `@import` syntax.
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import url('@tldraw/tldraw/tldraw.css');
|
||||||
|
```
|
||||||
|
|
||||||
|
If you'd like to deeply change the way that tldraw looks, you can copy the `tldraw.css` file into a new CSS file, make your changes, and import that instead.
|
||||||
|
|
||||||
|
### Fonts
|
||||||
|
|
||||||
|
We also use Inter as the default tldraw font. You can import this font however you like (or use a different font!) but here's the CSS import from Google fonts that we use:
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap');
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTML
|
||||||
|
|
||||||
|
If you're using the [Tldraw](?) component in a full-screen app, you probably also want to update your `index.html`'s meta viewport element as shown below.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||||
|
```
|
||||||
|
|
||||||
|
This may not be critical to [Tldraw](?) performing correctly, however some features (such as safe area positioning) will only work correctly if these viewport options are set.
|
||||||
|
|
||||||
|
## Server Rendering
|
||||||
|
|
||||||
|
The [Tldraw](?) component can't be server-rendered. If you're using the component in a server-rendered framework (such as Next.js) then you need to import it dynamically.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const Tldraw = dynamic(async () => (await import('@tldraw/tldraw')).Tldraw, { ssr: false })
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using a bundler
|
||||||
|
|
||||||
|
If you're using a bundler like webpack or rollup, you can import the assets directly from the `@tldraw/assets` package. Here you can use `getAssetUrlsByMetaUrl` helper function:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getAssetUrlsByMetaUrl } from '@tldraw/assets/urls'
|
||||||
|
|
||||||
|
const assetUrls = getAssetUrlsByMetaUrl()
|
||||||
|
|
||||||
|
<Tldraw assetUrls={assetUrls} />
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage in Frameworks
|
||||||
|
|
||||||
|
Visit our [framework examples repository](https://github.com/tldraw/examples) to see examples of tldraw being used in various frameworks.
|
||||||
|
|
||||||
|
## Static Assets
|
||||||
|
|
||||||
|
In order to use the [Tldraw](?) component, the app must be able to find certain assets. These are contained in the `embed-icons`, `fonts`, `icons`, and `translations` folders. We offer a few different ways of making these assets available to your app.
|
||||||
|
|
||||||
|
### Using a public CDN
|
||||||
|
|
||||||
|
By default we serve these assets from a [public CDN called unpkg](https://unpkg.com/browse/@tldraw/assets@2.0.0-alpha.12/), so everything should work out of the box and is a good way to get started.
|
||||||
|
|
||||||
|
If you would like to customize some of the assets you can pass the customizations to our [Tldraw](?) component. For example, to use a custom icon for the `hand` tool you can do the following:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const assetUrls = {
|
||||||
|
icons: {
|
||||||
|
'tool-hand': './custom-tool-hand.svg',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
<Tldraw assetUrls={assetUrls} />
|
||||||
|
```
|
||||||
|
|
||||||
|
This will use the custom icon for the `hand` tool and the default assets for everything else.
|
||||||
|
|
||||||
|
### Self-hosting static assets
|
||||||
|
|
||||||
|
If you want more flexibility you can also host these assets yourself:
|
||||||
|
|
||||||
|
1. Download the `embed-icons`, `fonts`, `icons`, and `translations` folders from the [assets folder](https://github.com/tldraw/tldraw/tree/main/assets) of the tldraw repository.
|
||||||
|
2. Place the folders in your project's public path.
|
||||||
|
3. Pass `assetUrls` prop to our `<Tldraw/>` component to let the component know where the assets live.
|
||||||
|
|
||||||
|
You can use our `getAssetUrls` helper function from the `@tldraw/assets` package to generate these urls for you.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getAssetUrls } from '@tldraw/assets/selfHosted'
|
||||||
|
|
||||||
|
const assetUrls = getAssetUrls()
|
||||||
|
|
||||||
|
<Tldraw assetUrls={assetUrls} />
|
||||||
|
```
|
||||||
|
|
||||||
|
While these files must be available, you can overwrite the individual files: for example, by placing different icons under the same name or modifying / adding translations.
|
||||||
|
|
||||||
|
If you use a CDN for hosting these files you can specify the base url of your assets. To recreate the above option of serving the assets from unpkg you would do the following:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const assetUrls = getAssetUrls({
|
||||||
|
baseUrl: 'https://unpkg.com/@tldraw/assets@2.0.0-alpha.12/',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Subcomponents
|
||||||
|
|
||||||
|
The [Tldraw](?) component combines two lower-level components: [TldrawEditor](?) and [TldrawUi](?). If you want to have more granular control, you can use those lower-level components directly. See [this example](https://github.com/tldraw/tldraw/blob/main/apps/examples/src/examples/ExplodedExample.tsx) for reference.
|
||||||
|
|
||||||
|
### Customize the default components
|
||||||
|
|
||||||
|
You can customize the appearance of the tldraw editor using the [Tldraw](?) (or [TldrawEditor](?) component's `components` prop.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
<Tldraw
|
||||||
|
components={{
|
||||||
|
Background: YourCustomBackground,
|
||||||
|
SvgDefs: YourCustomSvgDefs,
|
||||||
|
Brush: YourCustomBrush,
|
||||||
|
ZoomBrush: YourCustomBrush,
|
||||||
|
CollaboratorBrush: YourCustomBrush,
|
||||||
|
Cursor: YourCustomCursor,
|
||||||
|
CollaboratorCursor: YourCustomCursor,
|
||||||
|
CollaboratorHint: YourCustomCollaboratorHint,
|
||||||
|
CollaboratorShapeIndicator: YourCustomdicator,
|
||||||
|
Grid: YourCustomGrid,
|
||||||
|
Scribble: YourCustomScribble,
|
||||||
|
SnapLine: YourCustomSnapLine,
|
||||||
|
Handles: YourCustomHandles,
|
||||||
|
Handle: YourCustomHandle,
|
||||||
|
CollaboratorScribble: YourCustomScribble,
|
||||||
|
ErrorFallback: YourCustomErrorFallback,
|
||||||
|
ShapeErrorFallback: YourCustomShapeErrorFallback,
|
||||||
|
ShapeIndicatorErrorFallback: YourCustomShapeIndicatorErrorFallback,
|
||||||
|
Spinner: YourCustomSpinner,
|
||||||
|
SelectionBackground: YourCustomSelectionBackground,
|
||||||
|
SelectionForeground: YourCustomSelectionForeground,
|
||||||
|
HoveredShapeIndicator: YourCustomHoveredShapeIndicator,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
|
@ -6,7 +6,7 @@ date: 3/22/2023
|
||||||
order: 0
|
order: 0
|
||||||
---
|
---
|
||||||
|
|
||||||
Welcome to the developer docs for tldraw, a React library for creating whiteboards and other infinite canvas experiences. These docs are for the 2.0 version which is currently in alpha.
|
Welcome to the developer docs for tldraw, a React library for creating whiteboards and other infinite canvas experiences. These docs are for the 2.0 version which is currently in beta.
|
||||||
|
|
||||||
<a className="hero__images" href="https://examples.tldraw.com">
|
<a className="hero__images" href="https://examples.tldraw.com">
|
||||||
<img src={'/images/hero_light.png'} alt="tldraw demo" className="article__image hero__light" />
|
<img src={'/images/hero_light.png'} alt="tldraw demo" className="article__image hero__light" />
|
||||||
|
@ -31,7 +31,7 @@ If you want to go even deeper, you can use the [TldrawEditor](?) component as a
|
||||||
|
|
||||||
In addition to the docs on this website, we provide [many examples](https://github.com/tldraw/tldraw/tree/main/apps/examples/src/examples) in the tldraw repo that demonstrate different ways of using the tldraw library. You can view them running [here](https://examples.tldraw.com/); or else you can clone the tldraw repo and start a local development server to see them in action.
|
In addition to the docs on this website, we provide [many examples](https://github.com/tldraw/tldraw/tree/main/apps/examples/src/examples) in the tldraw repo that demonstrate different ways of using the tldraw library. You can view them running [here](https://examples.tldraw.com/); or else you can clone the tldraw repo and start a local development server to see them in action.
|
||||||
|
|
||||||
You can ask questions and get help on our [Discord](https://discord.gg/JMbeb96jsh) channel or in our Github [issues](https://github.com/tldraw/tldraw/issues).
|
You can ask questions and get help on our [Discord](https://discord.com/invite/SBBEVCA4PG) channel or in our Github [issues](https://github.com/tldraw/tldraw/issues).
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
|
@ -1,171 +0,0 @@
|
||||||
---
|
|
||||||
title: Usage
|
|
||||||
status: published
|
|
||||||
author: steveruizok
|
|
||||||
date: 3/22/2023
|
|
||||||
order: 2
|
|
||||||
---
|
|
||||||
|
|
||||||
You can use the [Tldraw](?) component inside of any React component.
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { Tldraw } from '@tldraw/tldraw'
|
|
||||||
import '@tldraw/tldraw/tldraw.css'
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
return (
|
|
||||||
<div style={{ position: 'fixed', inset: 0 }}>
|
|
||||||
<Tldraw />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Wrapper
|
|
||||||
|
|
||||||
It's important that the [Tldraw](?) component is wrapped in a parent container that has an explicit size. Its height and width are set to `100%`, so it will fill its parent container.
|
|
||||||
|
|
||||||
### CSS
|
|
||||||
|
|
||||||
In addition to the [Tldraw](?) component itself, you should also import the `tldraw.css` file from the `@tldraw/tldraw` package.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import '@tldraw/tldraw/tldraw.css'
|
|
||||||
```
|
|
||||||
|
|
||||||
You can alternatively import this file inside of another CSS file using the `@import` syntax.
|
|
||||||
|
|
||||||
```css
|
|
||||||
@import url('@tldraw/tldraw/tldraw.css');
|
|
||||||
```
|
|
||||||
|
|
||||||
If you'd like to deeply change the way that tldraw looks, you can copy the `tldraw.css` file into a new CSS file, make your changes, and import that instead.
|
|
||||||
|
|
||||||
### Fonts
|
|
||||||
|
|
||||||
We also use Inter as the default tldraw font. You can import this font however you like (or use a different font!) but here's the CSS import from Google fonts that we use:
|
|
||||||
|
|
||||||
```css
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap');
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML
|
|
||||||
|
|
||||||
If you're using the [Tldraw](?) component in a full-screen app, you probably also want to update your `index.html`'s meta viewport element as shown below.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
||||||
```
|
|
||||||
|
|
||||||
This may not be critical to [Tldraw](?) performing correctly, however some features (such as safe area positioning) will only work correctly if these viewport options are set.
|
|
||||||
|
|
||||||
## Server Rendering
|
|
||||||
|
|
||||||
The [Tldraw](?) component can't be server-rendered. If you're using the component in a server-rendered framework (such as Next.js) then you need to import it dynamically.
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
const Tldraw = dynamic(async () => (await import('@tldraw/tldraw')).Tldraw, { ssr: false })
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using a bundler
|
|
||||||
|
|
||||||
If you're using a bundler like webpack or rollup, you can import the assets directly from the `@tldraw/assets` package. Here you can use `getAssetUrlsByMetaUrl` helper function:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
import { getAssetUrlsByMetaUrl } from '@tldraw/assets/urls'
|
|
||||||
|
|
||||||
const assetUrls = getAssetUrlsByMetaUrl()
|
|
||||||
|
|
||||||
<Tldraw assetUrls={assetUrls} />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage in Frameworks
|
|
||||||
|
|
||||||
Visit our [framework examples repository](https://github.com/tldraw/examples) to see examples of tldraw being used in various frameworks.
|
|
||||||
|
|
||||||
## Static Assets
|
|
||||||
|
|
||||||
In order to use the [Tldraw](?) component, the app must be able to find certain assets. These are contained in the `embed-icons`, `fonts`, `icons`, and `translations` folders. We offer a few different ways of making these assets available to your app.
|
|
||||||
|
|
||||||
### Using a public CDN
|
|
||||||
|
|
||||||
By default we serve these assets from a [public CDN called unpkg](https://unpkg.com/browse/@tldraw/assets@2.0.0-alpha.12/), so everything should work out of the box and is a good way to get started.
|
|
||||||
|
|
||||||
If you would like to customize some of the assets you can pass the customizations to our [Tldraw](?) component. For example, to use a custom icon for the `hand` tool you can do the following:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const assetUrls = {
|
|
||||||
icons: {
|
|
||||||
'tool-hand': './custom-tool-hand.svg',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
<Tldraw assetUrls={assetUrls} />
|
|
||||||
```
|
|
||||||
|
|
||||||
This will use the custom icon for the `hand` tool and the default assets for everything else.
|
|
||||||
|
|
||||||
### Self-hosting static assets
|
|
||||||
|
|
||||||
If you want more flexibility you can also host these assets yourself:
|
|
||||||
|
|
||||||
1. Download the `embed-icons`, `fonts`, `icons`, and `translations` folders from the [assets folder](https://github.com/tldraw/tldraw/tree/main/assets) of the tldraw repository.
|
|
||||||
2. Place the folders in your project's public path.
|
|
||||||
3. Pass `assetUrls` prop to our `<Tldraw/>` component to let the component know where the assets live.
|
|
||||||
|
|
||||||
You can use our `getAssetUrls` helper function from the `@tldraw/assets` package to generate these urls for you.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
import { getAssetUrls } from '@tldraw/assets/selfHosted'
|
|
||||||
|
|
||||||
const assetUrls = getAssetUrls()
|
|
||||||
|
|
||||||
<Tldraw assetUrls={assetUrls} />
|
|
||||||
```
|
|
||||||
|
|
||||||
While these files must be available, you can overwrite the individual files: for example, by placing different icons under the same name or modifying / adding translations.
|
|
||||||
|
|
||||||
If you use a CDN for hosting these files you can specify the base url of your assets. To recreate the above option of serving the assets from unpkg you would do the following:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const assetUrls = getAssetUrls({
|
|
||||||
baseUrl: 'https://unpkg.com/@tldraw/assets@2.0.0-alpha.12/',
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## Subcomponents
|
|
||||||
|
|
||||||
The [Tldraw](?) component combines two lower-level components: [TldrawEditor](?) and [TldrawUi](?). If you want to have more granular control, you can use those lower-level components directly. See [this example](https://github.com/tldraw/tldraw/blob/main/apps/examples/src/examples/ExplodedExample.tsx) for reference.
|
|
||||||
|
|
||||||
### Customize the default components
|
|
||||||
|
|
||||||
You can customize the appearance of the tldraw editor using the [Tldraw](?) (or [TldrawEditor](?) component's `components` prop.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
<Tldraw
|
|
||||||
components={{
|
|
||||||
Background: YourCustomBackground,
|
|
||||||
SvgDefs: YourCustomSvgDefs,
|
|
||||||
Brush: YourCustomBrush,
|
|
||||||
ZoomBrush: YourCustomBrush,
|
|
||||||
CollaboratorBrush: YourCustomBrush,
|
|
||||||
Cursor: YourCustomCursor,
|
|
||||||
CollaboratorCursor: YourCustomCursor,
|
|
||||||
CollaboratorHint: YourCustomCollaboratorHint,
|
|
||||||
CollaboratorShapeIndicator: YourCustomdicator,
|
|
||||||
Grid: YourCustomGrid,
|
|
||||||
Scribble: YourCustomScribble,
|
|
||||||
SnapLine: YourCustomSnapLine,
|
|
||||||
Handles: YourCustomHandles,
|
|
||||||
Handle: YourCustomHandle,
|
|
||||||
CollaboratorScribble: YourCustomScribble,
|
|
||||||
ErrorFallback: YourCustomErrorFallback,
|
|
||||||
ShapeErrorFallback: YourCustomShapeErrorFallback,
|
|
||||||
ShapeIndicatorErrorFallback: YourCustomShapeIndicatorErrorFallback,
|
|
||||||
Spinner: YourCustomSpinner,
|
|
||||||
SelectionBackground: YourCustomSelectionBackground,
|
|
||||||
SelectionForeground: YourCustomSelectionForeground,
|
|
||||||
HoveredShapeIndicator: YourCustomHoveredShapeIndicator,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
```
|
|
|
@ -8,3 +8,4 @@ status: published
|
||||||
---
|
---
|
||||||
|
|
||||||
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.12)
|
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.12)
|
||||||
|
|
||||||
|
|
|
@ -296,6 +296,8 @@ n/a
|
||||||
|
|
||||||
#### Select locked shapes on long press ([#1529](https://github.com/tldraw/tldraw/pull/1529))
|
#### Select locked shapes on long press ([#1529](https://github.com/tldraw/tldraw/pull/1529))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### highlighter fixes ([#1530](https://github.com/tldraw/tldraw/pull/1530))
|
#### highlighter fixes ([#1530](https://github.com/tldraw/tldraw/pull/1530))
|
||||||
|
|
||||||
[aq bug fixes]
|
[aq bug fixes]
|
||||||
|
@ -453,8 +455,8 @@ Highlighter pen is here! 🎉🎉🎉
|
||||||
|
|
||||||
#### Update docs links + guides + build ([#1422](https://github.com/tldraw/tldraw/pull/1422))
|
#### Update docs links + guides + build ([#1422](https://github.com/tldraw/tldraw/pull/1422))
|
||||||
|
|
||||||
- [docs] Updated guides to get assets from the new `tldraw/tldraw` repo instead of the old `tldraw/tldraw-examples`.
|
* [docs] Updated guides to get assets from the new `tldraw/tldraw` repo instead of the old `tldraw/tldraw-examples`.
|
||||||
- [docs] Updated an old CodeSandbox link to the new StackBlitz.
|
* [docs] Updated an old CodeSandbox link to the new StackBlitz.
|
||||||
|
|
||||||
#### Create @tldraw/indices package ([#1426](https://github.com/tldraw/tldraw/pull/1426))
|
#### Create @tldraw/indices package ([#1426](https://github.com/tldraw/tldraw/pull/1426))
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ status: published
|
||||||
|
|
||||||
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.14)
|
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.14)
|
||||||
|
|
||||||
|
|
||||||
#### Disable styles panel button on mobile when using the laser tool. ([#1704](https://github.com/tldraw/tldraw/pull/1704))
|
#### Disable styles panel button on mobile when using the laser tool. ([#1704](https://github.com/tldraw/tldraw/pull/1704))
|
||||||
|
|
||||||
- Disable the styles panel button for laser tool on mobile.
|
- Disable the styles panel button for laser tool on mobile.
|
||||||
|
|
|
@ -9,6 +9,7 @@ status: published
|
||||||
|
|
||||||
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.15)
|
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.15)
|
||||||
|
|
||||||
|
|
||||||
#### frame label fix ([#2016](https://github.com/tldraw/tldraw/pull/2016))
|
#### frame label fix ([#2016](https://github.com/tldraw/tldraw/pull/2016))
|
||||||
|
|
||||||
- Add a brief release note for your PR here.
|
- Add a brief release note for your PR here.
|
||||||
|
@ -35,14 +36,8 @@ This pr add the custom defined shapes that's being passed to Tldraw
|
||||||
|
|
||||||
Before/After
|
Before/After
|
||||||
|
|
||||||
<img
|
<img width="300" src="https://github.com/tldraw/tldraw/assets/98838967/91ea55c8-0fcc-4f73-b61e-565829a5f25e" />
|
||||||
width="300"
|
<img width="300" src="https://github.com/tldraw/tldraw/assets/98838967/ee4070fe-e236-4818-8fb4-43520210102b" />
|
||||||
src="https://github.com/tldraw/tldraw/assets/98838967/91ea55c8-0fcc-4f73-b61e-565829a5f25e"
|
|
||||||
/>
|
|
||||||
<img
|
|
||||||
width="300"
|
|
||||||
src="https://github.com/tldraw/tldraw/assets/98838967/ee4070fe-e236-4818-8fb4-43520210102b"
|
|
||||||
/>
|
|
||||||
|
|
||||||
#### [fix] pinch events ([#1979](https://github.com/tldraw/tldraw/pull/1979))
|
#### [fix] pinch events ([#1979](https://github.com/tldraw/tldraw/pull/1979))
|
||||||
|
|
||||||
|
@ -54,14 +49,8 @@ Before/After
|
||||||
|
|
||||||
Before/After
|
Before/After
|
||||||
|
|
||||||
<image
|
<image width="350" src="https://github.com/tldraw/tldraw/assets/98838967/320171b4-61e0-4a41-b8d3-830bd90bea65" />
|
||||||
width="350"
|
<image width="350" src="https://github.com/tldraw/tldraw/assets/98838967/b42d7156-0ce9-4894-9692-9338dc931b79" />
|
||||||
src="https://github.com/tldraw/tldraw/assets/98838967/320171b4-61e0-4a41-b8d3-830bd90bea65"
|
|
||||||
/>
|
|
||||||
<image
|
|
||||||
width="350"
|
|
||||||
src="https://github.com/tldraw/tldraw/assets/98838967/b42d7156-0ce9-4894-9692-9338dc931b79"
|
|
||||||
/>
|
|
||||||
|
|
||||||
#### Remove focus management ([#1953](https://github.com/tldraw/tldraw/pull/1953))
|
#### Remove focus management ([#1953](https://github.com/tldraw/tldraw/pull/1953))
|
||||||
|
|
||||||
|
@ -82,14 +71,8 @@ Before/After
|
||||||
|
|
||||||
Before & After:
|
Before & After:
|
||||||
|
|
||||||
<image
|
<image width="250" src="https://github.com/tldraw/tldraw/assets/98838967/e0ca7d54-506f-4014-b65a-6b61a98e3665" />
|
||||||
width="250"
|
<image width="250" src="https://github.com/tldraw/tldraw/assets/98838967/90c9fa12-1bcb-430d-80c7-97e1faacea16" />
|
||||||
src="https://github.com/tldraw/tldraw/assets/98838967/e0ca7d54-506f-4014-b65a-6b61a98e3665"
|
|
||||||
/>
|
|
||||||
<image
|
|
||||||
width="250"
|
|
||||||
src="https://github.com/tldraw/tldraw/assets/98838967/90c9fa12-1bcb-430d-80c7-97e1faacea16"
|
|
||||||
/>
|
|
||||||
|
|
||||||
#### Allow right clicking selection backgrounds ([#1968](https://github.com/tldraw/tldraw/pull/1968))
|
#### Allow right clicking selection backgrounds ([#1968](https://github.com/tldraw/tldraw/pull/1968))
|
||||||
|
|
||||||
|
@ -105,7 +88,7 @@ Before & After:
|
||||||
|
|
||||||
#### Lokalise: Translations update ([#1964](https://github.com/tldraw/tldraw/pull/1964))
|
#### Lokalise: Translations update ([#1964](https://github.com/tldraw/tldraw/pull/1964))
|
||||||
|
|
||||||
- Updated community translations for German and Galician
|
* Updated community translations for German and Galician
|
||||||
|
|
||||||
#### [improvement] improve arrows (for real) ([#1957](https://github.com/tldraw/tldraw/pull/1957))
|
#### [improvement] improve arrows (for real) ([#1957](https://github.com/tldraw/tldraw/pull/1957))
|
||||||
|
|
||||||
|
@ -149,7 +132,7 @@ Before & After:
|
||||||
|
|
||||||
#### :recycle: fix: editing is not terminated after the conversion is confirmed. ([#1885](https://github.com/tldraw/tldraw/pull/1885))
|
#### :recycle: fix: editing is not terminated after the conversion is confirmed. ([#1885](https://github.com/tldraw/tldraw/pull/1885))
|
||||||
|
|
||||||
- fix: editing is not terminated after the conversion is confirmed.
|
- fix: editing is not terminated after the conversion is confirmed.
|
||||||
|
|
||||||
#### Update community translations ([#1889](https://github.com/tldraw/tldraw/pull/1889))
|
#### Update community translations ([#1889](https://github.com/tldraw/tldraw/pull/1889))
|
||||||
|
|
||||||
|
@ -467,17 +450,10 @@ Removed a feature to reset the viewport back to a shape that is being edited.
|
||||||
- `@tldraw/editor`, `@tldraw/store`, `@tldraw/tldraw`, `@tldraw/tlschema`
|
- `@tldraw/editor`, `@tldraw/store`, `@tldraw/tldraw`, `@tldraw/tlschema`
|
||||||
- Migrate snapshot [#1843](https://github.com/tldraw/tldraw/pull/1843) ([@steveruizok](https://github.com/steveruizok))
|
- Migrate snapshot [#1843](https://github.com/tldraw/tldraw/pull/1843) ([@steveruizok](https://github.com/steveruizok))
|
||||||
- `@tldraw/tldraw`
|
- `@tldraw/tldraw`
|
||||||
|
- export asset stuff [#1829](https://github.com/tldraw/tldraw/pull/1829) ([@steveruizok](https://github.com/steveruizok))
|
||||||
- export asset stuff [#1829](https://github.com/tldraw/tldraw/pull/1829) ([@steveruizok](https://github.com/steveruizok)
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
- [feature] Asset props [#1824](https://github.com/tldraw/tldraw/pull/1824) ([@steveruizok](https://github.com/steveruizok))
|
- [feature] Asset props [#1824](https://github.com/tldraw/tldraw/pull/1824) ([@steveruizok](https://github.com/steveruizok))
|
||||||
- [feature] unlock all action [#1820](https://github.com/tldraw/tldraw/pull/1820) ([@steveruizok](https://github.com/steveruizok))
|
- [feature] unlock all action [#1820](https://github.com/tldraw/tldraw/pull/1820) ([@steveruizok](https://github.com/steveruizok))
|
||||||
- export `UiEventsProvider` [#1774](https://github.com/tldraw/tldraw/pull/1774) ([@steveruizok](https://github.com/steveruizok)
|
- export `UiEventsProvider` [#1774](https://github.com/tldraw/tldraw/pull/1774) ([@steveruizok](https://github.com/steveruizok))
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
- `@tldraw/editor`
|
- `@tldraw/editor`
|
||||||
- Add className as prop to Canvas [#1827](https://github.com/tldraw/tldraw/pull/1827) ([@steveruizok](https://github.com/steveruizok))
|
- Add className as prop to Canvas [#1827](https://github.com/tldraw/tldraw/pull/1827) ([@steveruizok](https://github.com/steveruizok))
|
||||||
- refactor `parentsToChildrenWithIndexes` [#1764](https://github.com/tldraw/tldraw/pull/1764) ([@steveruizok](https://github.com/steveruizok))
|
- refactor `parentsToChildrenWithIndexes` [#1764](https://github.com/tldraw/tldraw/pull/1764) ([@steveruizok](https://github.com/steveruizok))
|
||||||
|
|
|
@ -9,6 +9,7 @@ status: published
|
||||||
|
|
||||||
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.16)
|
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.16)
|
||||||
|
|
||||||
|
|
||||||
#### Fix shape opacity when erasing ([#2055](https://github.com/tldraw/tldraw/pull/2055))
|
#### Fix shape opacity when erasing ([#2055](https://github.com/tldraw/tldraw/pull/2055))
|
||||||
|
|
||||||
- Fixes opacity of shapes while erasing in a group or frame.
|
- Fixes opacity of shapes while erasing in a group or frame.
|
||||||
|
@ -23,15 +24,9 @@ status: published
|
||||||
|
|
||||||
Before/after:
|
Before/after:
|
||||||
|
|
||||||
<image
|
<image width="250" src="https://github.com/tldraw/tldraw/assets/98838967/763a93eb-ffaa-405c-9255-e68ba88ed9a2" />
|
||||||
width="250"
|
|
||||||
src="https://github.com/tldraw/tldraw/assets/98838967/763a93eb-ffaa-405c-9255-e68ba88ed9a2"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<image
|
<image width="250" src="https://github.com/tldraw/tldraw/assets/98838967/dc9d3f77-c1c5-40f2-a9fe-10c723b6a21c" />
|
||||||
width="250"
|
|
||||||
src="https://github.com/tldraw/tldraw/assets/98838967/dc9d3f77-c1c5-40f2-a9fe-10c723b6a21c"
|
|
||||||
/>
|
|
||||||
|
|
||||||
#### fix: proper label for opacity tooltip on hover ([#2044](https://github.com/tldraw/tldraw/pull/2044))
|
#### fix: proper label for opacity tooltip on hover ([#2044](https://github.com/tldraw/tldraw/pull/2044))
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ status: published
|
||||||
|
|
||||||
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.17)
|
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.17)
|
||||||
|
|
||||||
|
|
||||||
#### Firefox, Touch: Fix not being able to open style dropdowns ([#2092](https://github.com/tldraw/tldraw/pull/2092))
|
#### Firefox, Touch: Fix not being able to open style dropdowns ([#2092](https://github.com/tldraw/tldraw/pull/2092))
|
||||||
|
|
||||||
- Firefox Mobile: Fixed a bug where you couldn't open some style dropdown options.
|
- Firefox Mobile: Fixed a bug where you couldn't open some style dropdown options.
|
||||||
|
@ -48,8 +49,8 @@ status: published
|
||||||
#### [fix] locked shape of opacity problem with eraser.pointing ([#2073](https://github.com/tldraw/tldraw/pull/2073))
|
#### [fix] locked shape of opacity problem with eraser.pointing ([#2073](https://github.com/tldraw/tldraw/pull/2073))
|
||||||
|
|
||||||
- locked shape of opacity problem with eraser.pointing
|
- locked shape of opacity problem with eraser.pointing
|
||||||
Before/after:
|
Before/after:
|
||||||
![A](https://github.com/tldraw/tldraw/assets/59823089/7483506c-72ac-45cc-93aa-f2a794ea8ff0) ![B](https://github.com/tldraw/tldraw/assets/59823089/ef0f988c-83f5-46a2-b891-0a391bca2f87)
|
![A](https://github.com/tldraw/tldraw/assets/59823089/7483506c-72ac-45cc-93aa-f2a794ea8ff0) ![B](https://github.com/tldraw/tldraw/assets/59823089/ef0f988c-83f5-46a2-b891-0a391bca2f87)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ status: published
|
||||||
|
|
||||||
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.18)
|
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.18)
|
||||||
|
|
||||||
|
|
||||||
#### Fix an error when using context menu. ([#2186](https://github.com/tldraw/tldraw/pull/2186))
|
#### Fix an error when using context menu. ([#2186](https://github.com/tldraw/tldraw/pull/2186))
|
||||||
|
|
||||||
- Fixes the console error when opening the context menu for the first time.
|
- Fixes the console error when opening the context menu for the first time.
|
||||||
|
|
|
@ -9,6 +9,7 @@ status: published
|
||||||
|
|
||||||
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.19)
|
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-alpha.19)
|
||||||
|
|
||||||
|
|
||||||
#### zoom to affected shapes after undo/redo ([#2293](https://github.com/tldraw/tldraw/pull/2293))
|
#### zoom to affected shapes after undo/redo ([#2293](https://github.com/tldraw/tldraw/pull/2293))
|
||||||
|
|
||||||
- Make sure affected shapes are visible after undo/redo
|
- Make sure affected shapes are visible after undo/redo
|
||||||
|
|
|
@ -9,6 +9,7 @@ status: published
|
||||||
|
|
||||||
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-beta.1)
|
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-beta.1)
|
||||||
|
|
||||||
|
|
||||||
#### add speech bubble example ([#2362](https://github.com/tldraw/tldraw/pull/2362))
|
#### add speech bubble example ([#2362](https://github.com/tldraw/tldraw/pull/2362))
|
||||||
|
|
||||||
- Add an example for making a custom shape with handles, this one is a speech bubble with a movable tail.
|
- Add an example for making a custom shape with handles, this one is a speech bubble with a movable tail.
|
||||||
|
|
|
@ -9,6 +9,7 @@ status: published
|
||||||
|
|
||||||
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-beta.2)
|
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0-beta.2)
|
||||||
|
|
||||||
|
|
||||||
#### Fix validation when pasting images. ([#2436](https://github.com/tldraw/tldraw/pull/2436))
|
#### Fix validation when pasting images. ([#2436](https://github.com/tldraw/tldraw/pull/2436))
|
||||||
|
|
||||||
- Fixes url validations.
|
- Fixes url validations.
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "getting-started",
|
"id": "getting-started",
|
||||||
"title": "Getting Started",
|
"title": "Get Started",
|
||||||
"description": "Introduction articles for tldraw.",
|
"description": "Introduction articles for tldraw.",
|
||||||
"categories": [],
|
"categories": [],
|
||||||
"sidebar_behavior": "show-links"
|
"sidebar_behavior": "show-links"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "docs",
|
"id": "docs",
|
||||||
"title": "Documentation",
|
"title": "Learn tldraw",
|
||||||
"description": "Developer documentation for tldraw.",
|
"description": "Developer documentation for tldraw.",
|
||||||
"categories": [],
|
"categories": [],
|
||||||
"sidebar_behavior": "show-links"
|
"sidebar_behavior": "show-links"
|
||||||
|
@ -18,10 +18,10 @@
|
||||||
"title": "Community",
|
"title": "Community",
|
||||||
"description": "Guides for contributing to tldraw's open source project.",
|
"description": "Guides for contributing to tldraw's open source project.",
|
||||||
"categories": [],
|
"categories": [],
|
||||||
"sidebar_behavior": "show-links"
|
"sidebar_behavior": "hidden"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "gen",
|
"id": "reference",
|
||||||
"title": "API Reference",
|
"title": "API Reference",
|
||||||
"description": "Reference for the tldraw package's APIs (generated).",
|
"description": "Reference for the tldraw package's APIs (generated).",
|
||||||
"categories": [
|
"categories": [
|
||||||
|
@ -201,6 +201,6 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sidebar_behavior": "show-title"
|
"sidebar_behavior": "reference"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -16,7 +16,13 @@ const nextConfig = {
|
||||||
{
|
{
|
||||||
// For reverse compatibility with old links
|
// For reverse compatibility with old links
|
||||||
source: '/docs/introduction',
|
source: '/docs/introduction',
|
||||||
destination: '/introduction',
|
destination: '/quick-start',
|
||||||
|
permanent: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// For reverse compatibility with old links
|
||||||
|
source: '/introduction',
|
||||||
|
destination: '/quick-start',
|
||||||
permanent: true,
|
permanent: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -31,30 +37,6 @@ const nextConfig = {
|
||||||
destination: '/usage',
|
destination: '/usage',
|
||||||
permanent: true,
|
permanent: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
// For reverse compatibility with old links
|
|
||||||
source: '/docs/introduction',
|
|
||||||
destination: '/introduction',
|
|
||||||
permanent: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// For reverse compatibility with old links
|
|
||||||
source: '/docs/installation',
|
|
||||||
destination: '/installation',
|
|
||||||
permanent: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// For reverse compatibility with old links
|
|
||||||
source: '/docs/usage',
|
|
||||||
destination: '/usage',
|
|
||||||
permanent: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// To reflect that these are at the top level of the sidebar
|
|
||||||
source: '/getting-started/:childId',
|
|
||||||
destination: '/:childId',
|
|
||||||
permanent: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
// To reflect that these are at the top level of the sidebar
|
// To reflect that these are at the top level of the sidebar
|
||||||
source: '/getting-started/:childId',
|
source: '/getting-started/:childId',
|
||||||
|
|
|
@ -37,19 +37,24 @@
|
||||||
"create-api-markdown": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/create-api-markdown.ts",
|
"create-api-markdown": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/create-api-markdown.ts",
|
||||||
"refresh-content": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/refresh-content.ts",
|
"refresh-content": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/refresh-content.ts",
|
||||||
"refresh-embeddings": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/refresh-embeddings.ts",
|
"refresh-embeddings": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/refresh-embeddings.ts",
|
||||||
"refresh-everything": "yarn fetch-api-source && yarn fetch-releases && yarn create-api-markdown && yarn refresh-content && yarn refresh-embeddings",
|
"refresh-everything": "yarn fetch-api-source && yarn fetch-releases && yarn create-api-markdown && yarn refresh-content && yarn refresh-embeddings && yarn format",
|
||||||
"clean": "rm -rf node_modules .yarn",
|
"clean": "rm -rf node_modules .yarn",
|
||||||
|
"format": "yarn run -T prettier --write .",
|
||||||
"watch-content": "tsx ./watcher.ts"
|
"watch-content": "tsx ./watcher.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@codesandbox/sandpack-react": "^2.11.3",
|
||||||
"@microsoft/api-extractor-model": "^7.26.4",
|
"@microsoft/api-extractor-model": "^7.26.4",
|
||||||
"@microsoft/tsdoc": "^0.14.2",
|
"@microsoft/tsdoc": "^0.14.2",
|
||||||
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
|
"@radix-ui/react-navigation-menu": "^1.1.4",
|
||||||
"@types/broken-link-checker": "^0.7.1",
|
"@types/broken-link-checker": "^0.7.1",
|
||||||
"@types/node": "^18.7.3",
|
"@types/node": "^18.7.3",
|
||||||
"@types/sqlite3": "^3.1.9",
|
"@types/sqlite3": "^3.1.9",
|
||||||
"@types/ws": "^8.5.9",
|
"@types/ws": "^8.5.9",
|
||||||
"@vercel/analytics": "^1.1.1",
|
"@vercel/analytics": "^1.1.1",
|
||||||
"broken-link-checker": "^0.7.8",
|
"broken-link-checker": "^0.7.8",
|
||||||
|
"classnames": "^2.3.2",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^8.2.2",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"eslint": "^8.37.0",
|
"eslint": "^8.37.0",
|
||||||
|
|
|
@ -65,6 +65,8 @@ export async function connect(opts = {} as { reset?: boolean }) {
|
||||||
status TEXT NOT NULL,
|
status TEXT NOT NULL,
|
||||||
date TEXT,
|
date TEXT,
|
||||||
sourceUrl TEXT,
|
sourceUrl TEXT,
|
||||||
|
componentCode TEXT,
|
||||||
|
componentCodeFiles TEXT,
|
||||||
keywords TEXT,
|
keywords TEXT,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
path TEXT,
|
path TEXT,
|
||||||
|
|
|
@ -8,17 +8,17 @@ import { getApiMarkdown } from './getApiMarkdown'
|
||||||
|
|
||||||
export async function createApiMarkdown() {
|
export async function createApiMarkdown() {
|
||||||
const apiInputSection: InputSection = {
|
const apiInputSection: InputSection = {
|
||||||
id: 'gen' as string,
|
id: 'reference' as string,
|
||||||
title: 'API Reference',
|
title: 'API Reference',
|
||||||
description: "Reference for the tldraw package's APIs (generated).",
|
description: "Reference for the tldraw package's APIs (generated).",
|
||||||
categories: [],
|
categories: [],
|
||||||
sidebar_behavior: 'show-title',
|
sidebar_behavior: 'reference',
|
||||||
}
|
}
|
||||||
|
|
||||||
const addedCategories = new Set<string>()
|
const addedCategories = new Set<string>()
|
||||||
|
|
||||||
const INPUT_DIR = path.join(process.cwd(), 'api')
|
const INPUT_DIR = path.join(process.cwd(), 'api')
|
||||||
const OUTPUT_DIR = path.join(CONTENT_DIR, 'gen')
|
const OUTPUT_DIR = path.join(CONTENT_DIR, 'reference')
|
||||||
|
|
||||||
if (fs.existsSync(OUTPUT_DIR)) {
|
if (fs.existsSync(OUTPUT_DIR)) {
|
||||||
fs.rmSync(OUTPUT_DIR, { recursive: true })
|
fs.rmSync(OUTPUT_DIR, { recursive: true })
|
||||||
|
@ -85,7 +85,7 @@ export async function createApiMarkdown() {
|
||||||
const sectionsJsonPath = path.join(CONTENT_DIR, 'sections.json')
|
const sectionsJsonPath = path.join(CONTENT_DIR, 'sections.json')
|
||||||
const sectionsJson = JSON.parse(fs.readFileSync(sectionsJsonPath, 'utf8')) as InputSection[]
|
const sectionsJson = JSON.parse(fs.readFileSync(sectionsJsonPath, 'utf8')) as InputSection[]
|
||||||
sectionsJson.splice(
|
sectionsJson.splice(
|
||||||
sectionsJson.findIndex((s) => s.id === 'gen'),
|
sectionsJson.findIndex((s) => s.id === 'reference'),
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
sectionsJson.push(apiInputSection)
|
sectionsJson.push(apiInputSection)
|
||||||
|
|
|
@ -11,8 +11,8 @@ export async function generateApiContent(): Promise<GeneratedContent> {
|
||||||
const sections = require(path.join(CONTENT_DIRECTORY, 'sections.json')) as InputSection[]
|
const sections = require(path.join(CONTENT_DIRECTORY, 'sections.json')) as InputSection[]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const inputApiSection = sections.find((s) => s.id === 'gen')
|
const inputApiSection = sections.find((s) => s.id === 'reference')
|
||||||
if (!inputApiSection) throw new Error(`Could not find section with id 'gen'`)
|
if (!inputApiSection) throw new Error(`Could not find section with id 'reference'`)
|
||||||
const outputApiSection = generateSection(inputApiSection, articles, 999999) // always at the end!
|
const outputApiSection = generateSection(inputApiSection, articles, 999999) // always at the end!
|
||||||
const contentComplete = { sections: [outputApiSection], articles }
|
const contentComplete = { sections: [outputApiSection], articles }
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ export async function generateContent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < sections.length; i++) {
|
for (let i = 0; i < sections.length; i++) {
|
||||||
if (sections[i].id === 'gen') continue
|
if (sections[i].id === 'reference') continue
|
||||||
result.sections.push(generateSection(sections[i], result.articles, i))
|
result.sections.push(generateSection(sections[i], result.articles, i))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
apps/docs/scripts/functions/generateExamplesContent.ts
Normal file
34
apps/docs/scripts/functions/generateExamplesContent.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import { Articles, GeneratedContent, InputSection } from '../../types/content-types'
|
||||||
|
import { generateSection } from './generateSection'
|
||||||
|
|
||||||
|
const { log: nicelog } = console
|
||||||
|
|
||||||
|
const section: InputSection = {
|
||||||
|
id: 'examples',
|
||||||
|
title: 'Examples',
|
||||||
|
description: 'Code recipes for bending tldraw to your will.',
|
||||||
|
categories: [
|
||||||
|
{ id: 'basic', title: 'Getting Started', description: '', groups: [] },
|
||||||
|
{ id: 'ui', title: 'UI/Theming', description: '', groups: [] },
|
||||||
|
{ id: 'shapes/tools', title: 'Shapes & Tools', description: '', groups: [] },
|
||||||
|
{ id: 'data/assets', title: 'Data & Assets', description: '', groups: [] },
|
||||||
|
{ id: 'editor-api', title: 'Editor API', description: '', groups: [] },
|
||||||
|
{ id: 'collaboration', title: 'Collaboration', description: '', groups: [] },
|
||||||
|
],
|
||||||
|
sidebar_behavior: 'show-links',
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateExamplesContent(): Promise<GeneratedContent> {
|
||||||
|
const articles: Articles = {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const outputExamplesSection = generateSection(section, articles, 0)
|
||||||
|
const contentComplete = { sections: [outputExamplesSection], articles }
|
||||||
|
|
||||||
|
return contentComplete
|
||||||
|
} catch (error) {
|
||||||
|
nicelog(`x Could not generate Examples content`)
|
||||||
|
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,21 +21,29 @@ export function generateSection(section: InputSection, articles: Articles, index
|
||||||
)
|
)
|
||||||
|
|
||||||
// The file directory for this section
|
// The file directory for this section
|
||||||
const dir = path.join(CONTENT_DIR, section.id)
|
const isExamples = section.id === 'examples'
|
||||||
|
const dir = isExamples
|
||||||
|
? path.join(process.cwd(), '..', 'examples', 'src', 'examples')
|
||||||
|
: path.join(CONTENT_DIR, section.id)
|
||||||
const files = fs.readdirSync(dir, { withFileTypes: false })
|
const files = fs.readdirSync(dir, { withFileTypes: false })
|
||||||
|
|
||||||
const isGenerated = section.id === 'gen'
|
const isGenerated = section.id === 'reference'
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const filename = file.toString()
|
const filename = file.toString()
|
||||||
const fileContent = fs.readFileSync(path.join(dir, filename)).toString()
|
const pathname = isExamples ? path.join(dir, filename, 'README.md') : path.join(dir, filename)
|
||||||
|
const fileContent = fs.readFileSync(pathname).toString()
|
||||||
const extension = path.extname(filename)
|
const extension = path.extname(filename)
|
||||||
const articleId = filename.replace(extension, '')
|
const articleId = filename.replace(extension, '')
|
||||||
|
|
||||||
const parsed = matter({ content: fileContent }, {})
|
const parsed = matter({ content: fileContent }, {})
|
||||||
|
|
||||||
// If we're in prod and the article isn't published, skip it
|
// If we're in prod and the article isn't published, skip it
|
||||||
if (process.env.NODE_ENV !== 'development' && parsed.data.status !== 'published') {
|
if (
|
||||||
|
process.env.NODE_ENV !== 'development' &&
|
||||||
|
!isExamples &&
|
||||||
|
parsed.data.status !== 'published'
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +56,38 @@ export function generateSection(section: InputSection, articles: Articles, index
|
||||||
|
|
||||||
const isUncategorized = categoryId === section.id + '_ucg'
|
const isUncategorized = categoryId === section.id + '_ucg'
|
||||||
const isIndex = articleId === section.id
|
const isIndex = articleId === section.id
|
||||||
|
const componentCode = parsed.data.component
|
||||||
|
? fs
|
||||||
|
.readFileSync(
|
||||||
|
path.join(
|
||||||
|
dir,
|
||||||
|
filename,
|
||||||
|
`${parsed.data.component}${parsed.data.component.endsWith('.tsx') ? '' : '.tsx'}`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.toString()
|
||||||
|
: null
|
||||||
|
const componentCodeFiles: { [key: string]: string } = {}
|
||||||
|
if (parsed.data.component) {
|
||||||
|
const exampleParentDirectory = path.join(dir, filename)
|
||||||
|
const codeFilenames = fs.readdirSync(exampleParentDirectory, {
|
||||||
|
withFileTypes: true,
|
||||||
|
recursive: true,
|
||||||
|
})
|
||||||
|
codeFilenames
|
||||||
|
.filter(
|
||||||
|
(file) =>
|
||||||
|
!file.isDirectory() &&
|
||||||
|
file.name !== 'README.md' &&
|
||||||
|
file.name.replace('.tsx', '') !==
|
||||||
|
parsed.data.component.replace('./', '').replace('.tsx', '')
|
||||||
|
)
|
||||||
|
.forEach((file) => {
|
||||||
|
componentCodeFiles[file.name] = fs
|
||||||
|
.readFileSync(path.join(file.path, file.name))
|
||||||
|
.toString()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const article: Article = {
|
const article: Article = {
|
||||||
id: articleId,
|
id: articleId,
|
||||||
|
@ -55,7 +95,7 @@ export function generateSection(section: InputSection, articles: Articles, index
|
||||||
sectionIndex: 0,
|
sectionIndex: 0,
|
||||||
groupIndex: -1,
|
groupIndex: -1,
|
||||||
groupId: parsed.data.group ?? null,
|
groupId: parsed.data.group ?? null,
|
||||||
categoryIndex: parsed.data.order ?? -1,
|
categoryIndex: parsed.data.order ?? parsed.data.priority ?? -1,
|
||||||
sectionId: section.id,
|
sectionId: section.id,
|
||||||
author,
|
author,
|
||||||
categoryId,
|
categoryId,
|
||||||
|
@ -68,6 +108,8 @@ export function generateSection(section: InputSection, articles: Articles, index
|
||||||
sourceUrl: isGenerated // if it's a generated API doc, then we don't have a link
|
sourceUrl: isGenerated // if it's a generated API doc, then we don't have a link
|
||||||
? parsed.data.sourceUrl ?? null
|
? parsed.data.sourceUrl ?? null
|
||||||
: `${section.id}/${articleId}${extension}`,
|
: `${section.id}/${articleId}${extension}`,
|
||||||
|
componentCode,
|
||||||
|
componentCodeFiles: componentCode ? JSON.stringify(componentCodeFiles) : null,
|
||||||
content: parsed.content,
|
content: parsed.content,
|
||||||
path:
|
path:
|
||||||
section.id === 'getting-started'
|
section.id === 'getting-started'
|
||||||
|
@ -166,14 +208,10 @@ export function generateSection(section: InputSection, articles: Articles, index
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortArticles = (articleA: Article, articleB: Article) => {
|
const sortArticles = (articleA: Article, articleB: Article) => {
|
||||||
const { categoryIndex: categoryIndexA, date: dateA = '01/01/1970' } = articleA
|
const { categoryIndex: categoryIndexA, title: titleA } = articleA
|
||||||
const { categoryIndex: categoryIndexB, date: dateB = '01/01/1970' } = articleB
|
const { categoryIndex: categoryIndexB, title: titleB } = articleB
|
||||||
|
|
||||||
return categoryIndexA === categoryIndexB
|
return categoryIndexA === categoryIndexB
|
||||||
? new Date(dateB!).getTime() > new Date(dateA!).getTime()
|
? titleA.localeCompare(titleB)
|
||||||
? 1
|
: categoryIndexA - categoryIndexB
|
||||||
: -1
|
|
||||||
: categoryIndexA < categoryIndexB
|
|
||||||
? -1
|
|
||||||
: 1
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { nicelog } from '@/utils/nicelog'
|
||||||
import { connect } from './connect'
|
import { connect } from './connect'
|
||||||
import { generateApiContent } from './generateApiContent'
|
import { generateApiContent } from './generateApiContent'
|
||||||
import { generateContent } from './generateContent'
|
import { generateContent } from './generateContent'
|
||||||
|
import { generateExamplesContent } from './generateExamplesContent'
|
||||||
|
|
||||||
export async function refreshContent(opts = {} as { silent: boolean }) {
|
export async function refreshContent(opts = {} as { silent: boolean }) {
|
||||||
if (!opts.silent) nicelog('◦ Resetting database...')
|
if (!opts.silent) nicelog('◦ Resetting database...')
|
||||||
|
@ -16,6 +17,9 @@ export async function refreshContent(opts = {} as { silent: boolean }) {
|
||||||
if (!opts.silent) nicelog('◦ Generating / adding regular content to db...')
|
if (!opts.silent) nicelog('◦ Generating / adding regular content to db...')
|
||||||
await addContentToDb(db, await generateContent())
|
await addContentToDb(db, await generateContent())
|
||||||
|
|
||||||
|
if (!opts.silent) nicelog('◦ Generating / adding Examples content to db...')
|
||||||
|
await addContentToDb(db, await generateExamplesContent())
|
||||||
|
|
||||||
if (!opts.silent) nicelog('◦ Generating / adding API content to db...')
|
if (!opts.silent) nicelog('◦ Generating / adding API content to db...')
|
||||||
await addContentToDb(db, await generateApiContent())
|
await addContentToDb(db, await generateApiContent())
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
/* Light theme */
|
/* Light theme */
|
||||||
--color-text: #1d1d1d;
|
--color-text: #1d1d1d;
|
||||||
|
--color-text-secondary: #999;
|
||||||
--color-background: #ffffff;
|
--color-background: #ffffff;
|
||||||
--color-contrast: #ffffff;
|
--color-contrast: #ffffff;
|
||||||
--color-accent: #2f80ed;
|
--color-accent: #2f80ed;
|
||||||
|
@ -46,6 +47,7 @@
|
||||||
[data-theme='dark'] {
|
[data-theme='dark'] {
|
||||||
/* Dark theme */
|
/* Dark theme */
|
||||||
--color-text: #fafafa;
|
--color-text: #fafafa;
|
||||||
|
--color-text-secondary: #999;
|
||||||
--color-background: hsl(240, 5%, 8%);
|
--color-background: hsl(240, 5%, 8%);
|
||||||
--color-contrast: #000;
|
--color-contrast: #000;
|
||||||
--color-accent: #74b0ff;
|
--color-accent: #74b0ff;
|
||||||
|
@ -129,7 +131,7 @@ body {
|
||||||
top: 0px;
|
top: 0px;
|
||||||
display: grid;
|
display: grid;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
grid-template-columns: 264px 1fr auto;
|
grid-template-columns: auto 1fr auto;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -145,12 +147,34 @@ body {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout__header__socials {
|
.layout__header__sections_and_socials {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layout_header__section {
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 0 4px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text);
|
||||||
|
background-color: transparent;
|
||||||
|
transition: background-color 0.12s ease-in-out;
|
||||||
|
transition-delay: 0.1s;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_header__section[data-active='true'] {
|
||||||
|
background-color: var(--color-tint-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
.layout_header__section:not([data-active='true']):hover {
|
||||||
|
background-color: var(--color-tint-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.icon-button {
|
.icon-button {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -170,7 +194,7 @@ body {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
content: '';
|
content: '';
|
||||||
inset: 4px;
|
inset: 0;
|
||||||
background-color: var(--bg);
|
background-color: var(--bg);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
transition: background-color 0.1s ease-in-out;
|
transition: background-color 0.1s ease-in-out;
|
||||||
|
@ -209,7 +233,7 @@ body {
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: calc(100vh - 64px);
|
min-height: calc(100vh - 64px);
|
||||||
padding: 24px 0px 96px 0px;
|
padding: 0px 0px 96px 0px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: visible;
|
overflow-y: visible;
|
||||||
|
@ -444,6 +468,10 @@ body {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.article.article__example pre {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.article__api-docs pre {
|
.article__api-docs pre {
|
||||||
margin: 24px 0px;
|
margin: 24px 0px;
|
||||||
}
|
}
|
||||||
|
@ -491,6 +519,10 @@ body {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.article.article__example hr {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.article table {
|
.article table {
|
||||||
margin: 20px 0px;
|
margin: 20px 0px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -734,7 +766,7 @@ body {
|
||||||
align-self: start;
|
align-self: start;
|
||||||
top: 72px;
|
top: 72px;
|
||||||
margin-left: -12px;
|
margin-left: -12px;
|
||||||
padding: 24px 12px 120px 28px;
|
padding: 0px 12px 120px 28px;
|
||||||
width: calc(100% + 24px);
|
width: calc(100% + 24px);
|
||||||
max-height: calc(100vh);
|
max-height: calc(100vh);
|
||||||
z-index: 800;
|
z-index: 800;
|
||||||
|
@ -742,10 +774,10 @@ body {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar a {
|
.sidebar a,
|
||||||
color: inherit;
|
.sidebar .sidebar__link {
|
||||||
|
font-weight: bold;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar hr {
|
.sidebar hr {
|
||||||
|
@ -757,22 +789,32 @@ body {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar__section__links {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar__list {
|
.sidebar__list {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__list li .sidebar__article {
|
.sidebar__list li .sidebar__article,
|
||||||
height: 44px;
|
.sidebar__list li .sidebar__article li {
|
||||||
margin-top: -6px;
|
margin-top: -6px;
|
||||||
margin-bottom: -6px;
|
margin-bottom: -6px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar__list li .sidebar__category li a,
|
||||||
|
.sidebar__list li .sidebar__article li a {
|
||||||
|
padding-left: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar__link {
|
.sidebar__link {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 40px;
|
padding: 6px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
@ -815,33 +857,51 @@ body {
|
||||||
|
|
||||||
.sidebar__section__title {
|
.sidebar__section__title {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: bold;
|
font-weight: normal;
|
||||||
color: var(--color-text);
|
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
color: var(--color-text);
|
color: var(--color-text-secondary);
|
||||||
|
text-transform: uppercase;
|
||||||
--bg: transparent;
|
--bg: transparent;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__sections__list > *:nth-last-of-type(n + 2) .sidebar__list {
|
.sidebar__section__group__title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
position: relative;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
white-space: nowrap;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__sections__list > *:nth-last-of-type(n + 2) > .sidebar__list {
|
||||||
padding-bottom: 12px;
|
padding-bottom: 12px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
border-bottom: 1px solid var(--color-tint-2);
|
border-bottom: 1px solid var(--color-tint-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
.sidebar__link:hover {
|
a.sidebar__link:hover {
|
||||||
|
cursor: pointer;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
transition: background-color 0.12s ease-in-out;
|
transition: background-color 0.12s ease-in-out;
|
||||||
transition-delay: 0.1s;
|
transition-delay: 0.1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__link:not([data-active='true']):hover {
|
a.sidebar__link:not([data-active='true']):hover {
|
||||||
--bg: var(--color-tint-1);
|
--bg: var(--color-tint-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1073,6 +1133,23 @@ body {
|
||||||
grid-gap: 40px;
|
grid-gap: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layout__header .layout__header__sections_and_socials .layout_header__section,
|
||||||
|
.layout__header .layout__header__sections_and_socials .NavigationMenuRoot {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__section__links {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 16px 0;
|
||||||
|
border-top: 1px solid var(--color-accent);
|
||||||
|
border-bottom: 1px solid var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.NavigationMenuTrigger {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.menu__button {
|
.menu__button {
|
||||||
display: flex;
|
display: flex;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
@ -1257,3 +1334,93 @@ html[data-theme='light'] .hero__dark {
|
||||||
margin: 0px -16px;
|
margin: 0px -16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------- Menus ------------------ */
|
||||||
|
|
||||||
|
.NavigationMenuRoot {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.NavigationMenuList {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.NavigationMenuTrigger {
|
||||||
|
outline: none;
|
||||||
|
user-select: none;
|
||||||
|
border: 0;
|
||||||
|
background: none;
|
||||||
|
background-color: transparent;
|
||||||
|
transition: background-color 0.12s ease-in-out;
|
||||||
|
transition-delay: 0.1s;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0 4px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
height: 44px;
|
||||||
|
line-height: 22px;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.NavigationMenuTrigger span {
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
.NavigationMenuTrigger:hover {
|
||||||
|
background-color: var(--color-tint-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.NavigationMenuContent {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: calc(100% + 4px);
|
||||||
|
left: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: var(--color-background);
|
||||||
|
box-shadow: var(--shadow-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.NavigationMenuContent li {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.NavigationMenuContent li a {
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--color-text);
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
.NavigationMenuContent li a:hover {
|
||||||
|
background-color: var(--color-tint-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.NavigationMenuViewport {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: var(--radix-navigation-menu-viewport-height);
|
||||||
|
}
|
||||||
|
@media only screen and (min-width: 600px) {
|
||||||
|
.NavigationMenuViewport {
|
||||||
|
width: var(--radix-navigation-menu-viewport-width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.CaretDown {
|
||||||
|
position: relative;
|
||||||
|
top: 3px;
|
||||||
|
transition: transform 250ms ease;
|
||||||
|
}
|
||||||
|
[data-state='open'] > .CaretDown {
|
||||||
|
transform: rotate(-180deg);
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ export type InputSection = {
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
categories: InputCategory[]
|
categories: InputCategory[]
|
||||||
sidebar_behavior: 'show-links' | 'show-title'
|
sidebar_behavior: 'show-links' | 'show-title' | 'hidden' | 'reference'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InputGroup = {
|
export type InputGroup = {
|
||||||
|
@ -55,7 +55,7 @@ export interface Section extends ContentPage {
|
||||||
/** An array of this section's categories. */
|
/** An array of this section's categories. */
|
||||||
categories: Category[]
|
categories: Category[]
|
||||||
/** How the section should appear in the sidebar. */
|
/** How the section should appear in the sidebar. */
|
||||||
sidebar_behavior: 'show-links' | 'show-title'
|
sidebar_behavior: 'show-links' | 'show-title' | 'hidden' | 'reference'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Category extends ContentPage {
|
export interface Category extends ContentPage {
|
||||||
|
@ -104,6 +104,10 @@ export interface Article extends ContentPage {
|
||||||
keywords: string[]
|
keywords: string[]
|
||||||
/** The URL where the article's source can be found. */
|
/** The URL where the article's source can be found. */
|
||||||
sourceUrl: string | null
|
sourceUrl: string | null
|
||||||
|
/** The article's code example (optional). */
|
||||||
|
componentCode: string | null
|
||||||
|
/** The article's code example files, JSON stringified (optional). */
|
||||||
|
componentCodeFiles: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ArticleStatus {
|
export enum ArticleStatus {
|
||||||
|
@ -155,7 +159,8 @@ export interface SidebarContentCategoryLink extends BaseSidebarLink {
|
||||||
|
|
||||||
export interface SidebarContentArticleLink extends BaseSidebarLink {
|
export interface SidebarContentArticleLink extends BaseSidebarLink {
|
||||||
type: 'article'
|
type: 'article'
|
||||||
articleId: string
|
articleId: string | null
|
||||||
|
groupId: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SidebarContentLink =
|
export type SidebarContentLink =
|
||||||
|
@ -164,10 +169,14 @@ export type SidebarContentLink =
|
||||||
| SidebarContentArticleLink
|
| SidebarContentArticleLink
|
||||||
|
|
||||||
export type SidebarContentList = {
|
export type SidebarContentList = {
|
||||||
|
headings?: ArticleHeadings
|
||||||
sectionId: string | null
|
sectionId: string | null
|
||||||
categoryId: string | null
|
categoryId: string | null
|
||||||
articleId: string | null
|
articleId: string | null
|
||||||
links: SidebarContentLink[]
|
links: SidebarContentLink[]
|
||||||
|
activeId?: string | null
|
||||||
|
searchQuery?: string
|
||||||
|
searchType?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- Finished / generated content ---------- */
|
/* ---------- Finished / generated content ---------- */
|
||||||
|
|
|
@ -141,7 +141,10 @@ export class ContentDatabase {
|
||||||
return { prev: prev ?? null, next: next ?? null }
|
return { prev: prev ?? null, next: next ?? null }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(mime): make this more generic, not per docs area
|
||||||
private _sidebarContentLinks: SidebarContentLink[] | undefined
|
private _sidebarContentLinks: SidebarContentLink[] | undefined
|
||||||
|
private _sidebarReferenceContentLinks: SidebarContentLink[] | undefined
|
||||||
|
private _sidebarExamplesContentLinks: SidebarContentLink[] | undefined
|
||||||
|
|
||||||
async getSidebarContentList({
|
async getSidebarContentList({
|
||||||
sectionId,
|
sectionId,
|
||||||
|
@ -154,9 +157,15 @@ export class ContentDatabase {
|
||||||
}): Promise<SidebarContentList> {
|
}): Promise<SidebarContentList> {
|
||||||
let links: SidebarContentLink[]
|
let links: SidebarContentLink[]
|
||||||
|
|
||||||
if (this._sidebarContentLinks && process.env.NODE_ENV !== 'development') {
|
const cachedLinks =
|
||||||
|
sectionId === 'examples'
|
||||||
|
? this._sidebarExamplesContentLinks
|
||||||
|
: sectionId === 'reference'
|
||||||
|
? this._sidebarReferenceContentLinks
|
||||||
|
: this._sidebarContentLinks
|
||||||
|
if (cachedLinks && process.env.NODE_ENV !== 'development') {
|
||||||
// Use the previously cached sidebar links
|
// Use the previously cached sidebar links
|
||||||
links = this._sidebarContentLinks
|
links = cachedLinks
|
||||||
} else {
|
} else {
|
||||||
// Generate sidebar links and cache them
|
// Generate sidebar links and cache them
|
||||||
links = []
|
links = []
|
||||||
|
@ -168,12 +177,31 @@ export class ContentDatabase {
|
||||||
|
|
||||||
const children: SidebarContentLink[] = []
|
const children: SidebarContentLink[] = []
|
||||||
|
|
||||||
|
if (section.sidebar_behavior === 'hidden') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(sectionId === 'reference' && section.id !== 'reference') ||
|
||||||
|
(sectionId !== 'reference' && section.id === 'reference')
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(sectionId === 'examples' && section.id !== 'examples') ||
|
||||||
|
(sectionId !== 'examples' && section.id === 'examples')
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (section.sidebar_behavior === 'show-title') {
|
if (section.sidebar_behavior === 'show-title') {
|
||||||
links.push({
|
links.push({
|
||||||
type: 'article',
|
type: 'article',
|
||||||
title: section.title,
|
title: section.title,
|
||||||
url: section.path,
|
url: section.path,
|
||||||
articleId: section.id,
|
articleId: section.id,
|
||||||
|
groupId: null,
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -204,6 +232,7 @@ export class ContentDatabase {
|
||||||
articleId: article.id,
|
articleId: article.id,
|
||||||
title: article.title,
|
title: article.title,
|
||||||
url: article.path,
|
url: article.path,
|
||||||
|
groupId: article.groupId,
|
||||||
}
|
}
|
||||||
|
|
||||||
ucg.push(sidebarArticleLink)
|
ucg.push(sidebarArticleLink)
|
||||||
|
@ -228,6 +257,7 @@ export class ContentDatabase {
|
||||||
const sidebarArticleLink: SidebarContentArticleLink = {
|
const sidebarArticleLink: SidebarContentArticleLink = {
|
||||||
type: 'article' as const,
|
type: 'article' as const,
|
||||||
articleId: article.id,
|
articleId: article.id,
|
||||||
|
groupId: article.groupId,
|
||||||
title: article.title,
|
title: article.title,
|
||||||
url: article.path,
|
url: article.path,
|
||||||
}
|
}
|
||||||
|
@ -244,7 +274,14 @@ export class ContentDatabase {
|
||||||
links.push({ type: 'section', title: section.title, url: section.path, children })
|
links.push({ type: 'section', title: section.title, url: section.path, children })
|
||||||
|
|
||||||
// Cache the links structure for next time
|
// Cache the links structure for next time
|
||||||
this._sidebarContentLinks = links
|
if (sectionId === 'examples') {
|
||||||
|
this._sidebarExamplesContentLinks = links
|
||||||
|
}
|
||||||
|
if (sectionId === 'reference') {
|
||||||
|
this._sidebarReferenceContentLinks = links
|
||||||
|
} else {
|
||||||
|
this._sidebarContentLinks = links
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ export class ContentVectorDatabase {
|
||||||
// This is the content that we'll create the embedding for
|
// This is the content that we'll create the embedding for
|
||||||
let contentToVectorize: string
|
let contentToVectorize: string
|
||||||
|
|
||||||
if (article.sectionId === 'gen') {
|
if (article.sectionId === 'reference') {
|
||||||
// For API docs, we'll just use the title, description, and members as the content.
|
// For API docs, we'll just use the title, description, and members as the content.
|
||||||
// We'll also add a note that the content was generated from the API docs, hopefully
|
// We'll also add a note that the content was generated from the API docs, hopefully
|
||||||
// so that the embedding better reflects searches for api docs.
|
// so that the embedding better reflects searches for api docs.
|
||||||
|
@ -217,8 +217,8 @@ export async function getVectorDb(
|
||||||
INCLUDE_API_CONTENT && INCLUDE_CONTENT
|
INCLUDE_API_CONTENT && INCLUDE_CONTENT
|
||||||
? await db.all('SELECT * FROM articles')
|
? await db.all('SELECT * FROM articles')
|
||||||
: INCLUDE_API_CONTENT
|
: INCLUDE_API_CONTENT
|
||||||
? await db.all('SELECT * FROM articles WHERE articles.sectionId = ?', 'gen')
|
? await db.all('SELECT * FROM articles WHERE articles.sectionId = ?', 'reference')
|
||||||
: await db.all('SELECT * FROM articles WHERE articles.sectionId != ?', 'gen')
|
: await db.all('SELECT * FROM articles WHERE articles.sectionId != ?', 'reference')
|
||||||
|
|
||||||
nicelog(`Adding articles to index`)
|
nicelog(`Adding articles to index`)
|
||||||
const max = Math.min(articles.length, MAX_ARTICLES)
|
const max = Math.min(articles.length, MAX_ARTICLES)
|
||||||
|
|
|
@ -35,10 +35,12 @@ export async function addContentToDb(
|
||||||
status,
|
status,
|
||||||
date,
|
date,
|
||||||
sourceUrl,
|
sourceUrl,
|
||||||
|
componentCode,
|
||||||
|
componentCodeFiles,
|
||||||
keywords,
|
keywords,
|
||||||
content,
|
content,
|
||||||
path
|
path
|
||||||
) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||||
)
|
)
|
||||||
|
|
||||||
for (let i = 0; i < content.sections.length; i++) {
|
for (let i = 0; i < content.sections.length; i++) {
|
||||||
|
@ -46,7 +48,7 @@ export async function addContentToDb(
|
||||||
try {
|
try {
|
||||||
await sectionInsert.run(
|
await sectionInsert.run(
|
||||||
section.id,
|
section.id,
|
||||||
section.id === 'gen' ? 99999 : i,
|
section.id === 'reference' ? 99999 : i,
|
||||||
section.title,
|
section.title,
|
||||||
section.description,
|
section.description,
|
||||||
section.path,
|
section.path,
|
||||||
|
@ -92,6 +94,8 @@ export async function addContentToDb(
|
||||||
article.status,
|
article.status,
|
||||||
article.date,
|
article.date,
|
||||||
article.sourceUrl,
|
article.sourceUrl,
|
||||||
|
article.componentCode,
|
||||||
|
article.componentCodeFiles,
|
||||||
article.keywords.join(', '),
|
article.keywords.join(', '),
|
||||||
article.content,
|
article.content,
|
||||||
article.path
|
article.path
|
||||||
|
|
|
@ -6,7 +6,10 @@ import sqlite3 from 'sqlite3'
|
||||||
export async function autoLinkDocs(db: Database<sqlite3.Database, sqlite3.Statement>) {
|
export async function autoLinkDocs(db: Database<sqlite3.Database, sqlite3.Statement>) {
|
||||||
// replace [TLEditor](?) with [TLEditor](/gen/editor/TLEditor)?
|
// replace [TLEditor](?) with [TLEditor](/gen/editor/TLEditor)?
|
||||||
// not sure how we would get there but finding an article with the same title
|
// not sure how we would get there but finding an article with the same title
|
||||||
const articles = await db.all('SELECT id, content FROM articles WHERE sectionId != ?', 'gen')
|
const articles = await db.all(
|
||||||
|
'SELECT id, content FROM articles WHERE sectionId != ?',
|
||||||
|
'reference'
|
||||||
|
)
|
||||||
await Promise.all(articles.map((a) => autoLinkDocsForArticle(db, a)))
|
await Promise.all(articles.map((a) => autoLinkDocsForArticle(db, a)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +33,7 @@ export async function autoLinkDocsForArticle(
|
||||||
const article = await db.get(
|
const article = await db.get(
|
||||||
'SELECT id, sectionId, categoryId FROM articles WHERE title = ? AND sectionId = ?',
|
'SELECT id, sectionId, categoryId FROM articles WHERE title = ? AND sectionId = ?',
|
||||||
title,
|
title,
|
||||||
'gen'
|
'reference'
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!article) throw Error(`Could not find article for ${_title} (${title})`)
|
if (!article) throw Error(`Could not find article for ${_title} (${title})`)
|
||||||
|
|
|
@ -13,7 +13,7 @@ export type Example = {
|
||||||
loadComponent: () => Promise<ComponentType>
|
loadComponent: () => Promise<ComponentType>
|
||||||
}
|
}
|
||||||
|
|
||||||
type Category = 'basic' | 'editor' | 'ui' | 'collaboration' | 'data/assets' | 'shapes/tools'
|
type Category = 'basic' | 'editor-api' | 'ui' | 'collaboration' | 'data/assets' | 'shapes/tools'
|
||||||
|
|
||||||
const getExamplesForCategory = (category: Category) =>
|
const getExamplesForCategory = (category: Category) =>
|
||||||
(Object.values(import.meta.glob('./examples/*/README.md', { eager: true })) as Example[])
|
(Object.values(import.meta.glob('./examples/*/README.md', { eager: true })) as Example[])
|
||||||
|
@ -28,7 +28,7 @@ const categories: Record<Category, string> = {
|
||||||
ui: 'UI/Theming',
|
ui: 'UI/Theming',
|
||||||
'shapes/tools': 'Shapes & Tools',
|
'shapes/tools': 'Shapes & Tools',
|
||||||
'data/assets': 'Data & Assets',
|
'data/assets': 'Data & Assets',
|
||||||
editor: 'Editor API',
|
'editor-api': 'Editor API',
|
||||||
collaboration: 'Collaboration',
|
collaboration: 'Collaboration',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: Editor API
|
title: Editor API
|
||||||
component: ./APIExample.tsx
|
component: ./APIExample.tsx
|
||||||
category: editor
|
category: editor-api
|
||||||
priority: 1
|
priority: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: Canvas events
|
title: Canvas events
|
||||||
component: ./CanvasEventsExample.tsx
|
component: ./CanvasEventsExample.tsx
|
||||||
category: editor
|
category: editor-api
|
||||||
priority: 2
|
priority: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: Context Toolbar
|
title: Context Toolbar
|
||||||
component: ./ContextToolbar.tsx
|
component: ./ContextToolbar.tsx
|
||||||
category: UI
|
category: ui
|
||||||
priority: 2
|
priority: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: Sublibraries
|
title: Sublibraries
|
||||||
component: ./ExplodedExample.tsx
|
component: ./ExplodedExample.tsx
|
||||||
category: editor
|
category: editor-api
|
||||||
priority: 3
|
priority: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
title: Floaty window
|
title: Floaty window
|
||||||
hide: true
|
hide: true
|
||||||
component: ./FloatyExample.tsx
|
component: ./FloatyExample.tsx
|
||||||
category: UI
|
category: ui
|
||||||
priority: 3
|
priority: 3
|
||||||
---
|
---
|
||||||
|
|
|
@ -5,4 +5,4 @@ category: basic
|
||||||
priority: 3
|
priority: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
Use multiple <Tldraw/> components on the same page.
|
Use multiple `<Tldraw/>` components on the same page.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: Minimal
|
title: Minimal
|
||||||
component: ./OnlyEditor.tsx
|
component: ./OnlyEditor.tsx
|
||||||
category: editor
|
category: editor-api
|
||||||
priority: 3
|
priority: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: Snapshots
|
title: Snapshots
|
||||||
component: ./SnapshotExample.tsx
|
component: ./SnapshotExample.tsx
|
||||||
category: editor
|
category: editor-api
|
||||||
priority: 1
|
priority: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: Store events
|
title: Store events
|
||||||
component: ./StoreEventsExample.tsx
|
component: ./StoreEventsExample.tsx
|
||||||
category: editor
|
category: editor-api
|
||||||
priority: 2
|
priority: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: UI events
|
title: UI events
|
||||||
component: ./UiEventsExample.tsx
|
component: ./UiEventsExample.tsx
|
||||||
category: editor
|
category: editor-api
|
||||||
priority: 2
|
priority: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
12
apps/examples/src/examples/yjs/README.md
Normal file
12
apps/examples/src/examples/yjs/README.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
title: YJS
|
||||||
|
component: ./YjsExample.tsx
|
||||||
|
category: collaboration
|
||||||
|
priority: 2
|
||||||
|
---
|
||||||
|
|
||||||
|
TODOTODO
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
TODOTODO
|
497
yarn.lock
497
yarn.lock
|
@ -2356,6 +2356,177 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@codemirror/autocomplete@npm:^6.0.0, @codemirror/autocomplete@npm:^6.4.0":
|
||||||
|
version: 6.12.0
|
||||||
|
resolution: "@codemirror/autocomplete@npm:6.12.0"
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/language": "npm:^6.0.0"
|
||||||
|
"@codemirror/state": "npm:^6.0.0"
|
||||||
|
"@codemirror/view": "npm:^6.17.0"
|
||||||
|
"@lezer/common": "npm:^1.0.0"
|
||||||
|
peerDependencies:
|
||||||
|
"@codemirror/language": ^6.0.0
|
||||||
|
"@codemirror/state": ^6.0.0
|
||||||
|
"@codemirror/view": ^6.0.0
|
||||||
|
"@lezer/common": ^1.0.0
|
||||||
|
checksum: d01fa7e5b965285e7c26116c716c2f85d8fc4810f69abb9432dd97d60bf3a05cac547fe9dc6eaf8c7723a8621c017ff41a0b5df0e635c5a7cc37b041c7676ce8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codemirror/commands@npm:^6.1.3":
|
||||||
|
version: 6.3.3
|
||||||
|
resolution: "@codemirror/commands@npm:6.3.3"
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/language": "npm:^6.0.0"
|
||||||
|
"@codemirror/state": "npm:^6.4.0"
|
||||||
|
"@codemirror/view": "npm:^6.0.0"
|
||||||
|
"@lezer/common": "npm:^1.1.0"
|
||||||
|
checksum: 4b398b102d6afcbf0e0018b426287a7458867497811c9155790a3cc679b880765cd756bdb96bf35abc28fecb85c0938e618d39469ce8bc0724d4dea5d88f6ac2
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codemirror/lang-css@npm:^6.0.0, @codemirror/lang-css@npm:^6.0.1":
|
||||||
|
version: 6.2.1
|
||||||
|
resolution: "@codemirror/lang-css@npm:6.2.1"
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete": "npm:^6.0.0"
|
||||||
|
"@codemirror/language": "npm:^6.0.0"
|
||||||
|
"@codemirror/state": "npm:^6.0.0"
|
||||||
|
"@lezer/common": "npm:^1.0.2"
|
||||||
|
"@lezer/css": "npm:^1.0.0"
|
||||||
|
checksum: 03c9111904850127ad69658e5e6f5d61bacc0d56e080aab17bedbc99fced10810f9930454aee812f138767ee9e65efae246301c49db55294c2a67ccf75b28731
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codemirror/lang-html@npm:^6.4.0":
|
||||||
|
version: 6.4.8
|
||||||
|
resolution: "@codemirror/lang-html@npm:6.4.8"
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete": "npm:^6.0.0"
|
||||||
|
"@codemirror/lang-css": "npm:^6.0.0"
|
||||||
|
"@codemirror/lang-javascript": "npm:^6.0.0"
|
||||||
|
"@codemirror/language": "npm:^6.4.0"
|
||||||
|
"@codemirror/state": "npm:^6.0.0"
|
||||||
|
"@codemirror/view": "npm:^6.17.0"
|
||||||
|
"@lezer/common": "npm:^1.0.0"
|
||||||
|
"@lezer/css": "npm:^1.1.0"
|
||||||
|
"@lezer/html": "npm:^1.3.0"
|
||||||
|
checksum: 92928806ee7d2ff570b279a6527b65fa61be44fd1b409529aead08d9d2bed0c2408efaaeb2638929ecbcd5894868312a870d24da46679bab3d136342b25a8f93
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codemirror/lang-javascript@npm:^6.0.0, @codemirror/lang-javascript@npm:^6.1.2":
|
||||||
|
version: 6.2.1
|
||||||
|
resolution: "@codemirror/lang-javascript@npm:6.2.1"
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete": "npm:^6.0.0"
|
||||||
|
"@codemirror/language": "npm:^6.6.0"
|
||||||
|
"@codemirror/lint": "npm:^6.0.0"
|
||||||
|
"@codemirror/state": "npm:^6.0.0"
|
||||||
|
"@codemirror/view": "npm:^6.17.0"
|
||||||
|
"@lezer/common": "npm:^1.0.0"
|
||||||
|
"@lezer/javascript": "npm:^1.0.0"
|
||||||
|
checksum: edc874d7c0563aeb50c720e3c9cb4928f08263ae2b26f72e49d58c57ed75cfbd2f4ef9f704f15747087989b37d249cbb17e9833c5281d992ab33120bd910887b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codemirror/language@npm:^6.0.0, @codemirror/language@npm:^6.3.2, @codemirror/language@npm:^6.4.0, @codemirror/language@npm:^6.6.0":
|
||||||
|
version: 6.10.0
|
||||||
|
resolution: "@codemirror/language@npm:6.10.0"
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state": "npm:^6.0.0"
|
||||||
|
"@codemirror/view": "npm:^6.23.0"
|
||||||
|
"@lezer/common": "npm:^1.1.0"
|
||||||
|
"@lezer/highlight": "npm:^1.0.0"
|
||||||
|
"@lezer/lr": "npm:^1.0.0"
|
||||||
|
style-mod: "npm:^4.0.0"
|
||||||
|
checksum: 674f87a5f7cae19a5e0cbdd0e06beade7f3694809cc30b31939aa04790dd43008942e3cd3b537ba5729fd14fed81c8ff62b7dcf51800db815cbf8d19d1d6a763
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codemirror/lint@npm:^6.0.0":
|
||||||
|
version: 6.4.2
|
||||||
|
resolution: "@codemirror/lint@npm:6.4.2"
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state": "npm:^6.0.0"
|
||||||
|
"@codemirror/view": "npm:^6.0.0"
|
||||||
|
crelt: "npm:^1.0.5"
|
||||||
|
checksum: 5e48e4f654c0890fe226fd84dca7fcea716dc72939eb2583151cc8cb6342187a0744b8bffc10b14ad8d8e67d96549c32b054926411c3a5b65de107388cb7ff6b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.2.0, @codemirror/state@npm:^6.4.0":
|
||||||
|
version: 6.4.0
|
||||||
|
resolution: "@codemirror/state@npm:6.4.0"
|
||||||
|
checksum: d9129c456d1589ca376594620bad10c51d3dcdb57950f34637cea0e2ea073a695d426dc1cfc9b909b07365c236a6312da1eaf740c384c853009742493b8c9935
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0, @codemirror/view@npm:^6.7.1":
|
||||||
|
version: 6.23.1
|
||||||
|
resolution: "@codemirror/view@npm:6.23.1"
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state": "npm:^6.4.0"
|
||||||
|
style-mod: "npm:^4.1.0"
|
||||||
|
w3c-keyname: "npm:^2.2.4"
|
||||||
|
checksum: 42e6b73bcad6bf5d2e9578c54d166c63c4b1c7c7c7806b6f6b4bead8683dc7fcca52201a02a1f9b8ccf120a4ad87e7dcd68f09d9d3e416304dad41a75e20da82
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codesandbox/nodebox@npm:0.1.8":
|
||||||
|
version: 0.1.8
|
||||||
|
resolution: "@codesandbox/nodebox@npm:0.1.8"
|
||||||
|
dependencies:
|
||||||
|
outvariant: "npm:^1.4.0"
|
||||||
|
strict-event-emitter: "npm:^0.4.3"
|
||||||
|
checksum: 3de00d306ae0236524c436b8640c442a4541f0eb696820aa5f6fc66018dc66431d8d78edd9305986aa2877befca292a3906bb4c6af2ecba5f15dbd587d1c916d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codesandbox/sandpack-client@npm:^2.11.2":
|
||||||
|
version: 2.11.2
|
||||||
|
resolution: "@codesandbox/sandpack-client@npm:2.11.2"
|
||||||
|
dependencies:
|
||||||
|
"@codesandbox/nodebox": "npm:0.1.8"
|
||||||
|
buffer: "npm:^6.0.3"
|
||||||
|
dequal: "npm:^2.0.2"
|
||||||
|
outvariant: "npm:1.4.0"
|
||||||
|
static-browser-server: "npm:1.0.3"
|
||||||
|
checksum: 70f97d27414755b564e929c3a824a4811f3664c268f54f98ea5e003f4ffc8f36111d79d819e77390a5c1d43805ae5779e8100df2fa5f7c900c40e2882890e888
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@codesandbox/sandpack-react@npm:^2.11.3":
|
||||||
|
version: 2.11.3
|
||||||
|
resolution: "@codesandbox/sandpack-react@npm:2.11.3"
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete": "npm:^6.4.0"
|
||||||
|
"@codemirror/commands": "npm:^6.1.3"
|
||||||
|
"@codemirror/lang-css": "npm:^6.0.1"
|
||||||
|
"@codemirror/lang-html": "npm:^6.4.0"
|
||||||
|
"@codemirror/lang-javascript": "npm:^6.1.2"
|
||||||
|
"@codemirror/language": "npm:^6.3.2"
|
||||||
|
"@codemirror/state": "npm:^6.2.0"
|
||||||
|
"@codemirror/view": "npm:^6.7.1"
|
||||||
|
"@codesandbox/sandpack-client": "npm:^2.11.2"
|
||||||
|
"@lezer/highlight": "npm:^1.1.3"
|
||||||
|
"@react-hook/intersection-observer": "npm:^3.1.1"
|
||||||
|
"@stitches/core": "npm:^1.2.6"
|
||||||
|
anser: "npm:^2.1.1"
|
||||||
|
clean-set: "npm:^1.1.2"
|
||||||
|
codesandbox-import-util-types: "npm:^2.2.3"
|
||||||
|
dequal: "npm:^2.0.2"
|
||||||
|
escape-carriage: "npm:^1.3.1"
|
||||||
|
lz-string: "npm:^1.4.4"
|
||||||
|
react-devtools-inline: "npm:4.4.0"
|
||||||
|
react-is: "npm:^17.0.2"
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8.0 || ^17 || ^18
|
||||||
|
react-dom: ^16.8.0 || ^17 || ^18
|
||||||
|
checksum: c78fb334a003df1c2398c04ae988259a61626865ac25f3bf2c1f46ac72d83f03d01aa6e2adcf2ab81ff781b8bf1caa8551f1a2c2ceca53f2eb78bb4f3604ea3c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@cspotcode/source-map-support@npm:^0.8.0":
|
"@cspotcode/source-map-support@npm:^0.8.0":
|
||||||
version: 0.8.1
|
version: 0.8.1
|
||||||
resolution: "@cspotcode/source-map-support@npm:0.8.1"
|
resolution: "@cspotcode/source-map-support@npm:0.8.1"
|
||||||
|
@ -3761,6 +3932,64 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.0.2, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.2.0":
|
||||||
|
version: 1.2.1
|
||||||
|
resolution: "@lezer/common@npm:1.2.1"
|
||||||
|
checksum: b362ed2e97664e4b36b3dbff49b52d1bfc5accc0152b577fefd46e585d012ff685d1fd336d75d80066e01c0505b1135d4cf69be5e330b5bfec2e2650c437bcae
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@lezer/css@npm:^1.0.0, @lezer/css@npm:^1.1.0":
|
||||||
|
version: 1.1.7
|
||||||
|
resolution: "@lezer/css@npm:1.1.7"
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common": "npm:^1.2.0"
|
||||||
|
"@lezer/highlight": "npm:^1.0.0"
|
||||||
|
"@lezer/lr": "npm:^1.0.0"
|
||||||
|
checksum: cffa5f0c65c622af3df294d6697d88ee1b5ce445250b0b95576b7c1c9dfaa1513ca34fde514507662c7d6fb9a17a33f5372d01685fe0925ea3021d86da5fa222
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@lezer/highlight@npm:^1.0.0, @lezer/highlight@npm:^1.1.3":
|
||||||
|
version: 1.2.0
|
||||||
|
resolution: "@lezer/highlight@npm:1.2.0"
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common": "npm:^1.0.0"
|
||||||
|
checksum: 14a80cbfb0cd1ce716decb4f3a045d42e7146f539cfd483b62ce46c4586a26d2f4fbdc35ace1cad81645304be4d30eafb95a2b057c34dfd471d56c7fbd82df3a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@lezer/html@npm:^1.3.0":
|
||||||
|
version: 1.3.8
|
||||||
|
resolution: "@lezer/html@npm:1.3.8"
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common": "npm:^1.2.0"
|
||||||
|
"@lezer/highlight": "npm:^1.0.0"
|
||||||
|
"@lezer/lr": "npm:^1.0.0"
|
||||||
|
checksum: 34eb58de4bf8fba49f84d8552fd6487bd981be5f8abd702cda517acdd89dee3dd33fec5a34349431d9357fe72512d4385bdec7617079a0c748b92c2e68b66e94
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@lezer/javascript@npm:^1.0.0":
|
||||||
|
version: 1.4.13
|
||||||
|
resolution: "@lezer/javascript@npm:1.4.13"
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common": "npm:^1.2.0"
|
||||||
|
"@lezer/highlight": "npm:^1.1.3"
|
||||||
|
"@lezer/lr": "npm:^1.3.0"
|
||||||
|
checksum: 2ebdfae4968e7d0ff1a6b21b13b511cfcc78ee08f548de0133d5dc6fa4e45f089ef35368ff82ab4370f22881768958e70d3d2d5c662784add0170a0fc48c9be0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@lezer/lr@npm:^1.0.0, @lezer/lr@npm:^1.3.0":
|
||||||
|
version: 1.4.0
|
||||||
|
resolution: "@lezer/lr@npm:1.4.0"
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common": "npm:^1.0.0"
|
||||||
|
checksum: 7391d0d08e54cd9e4f4d46e6ee6aa81fbaf079b22ed9c13d01fc9928e0ffd16d0c2d21b2cedd55675ad6c687277db28349ea8db81c9c69222cd7e7c40edd026e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@mapbox/node-pre-gyp@npm:^1.0.5":
|
"@mapbox/node-pre-gyp@npm:^1.0.5":
|
||||||
version: 1.0.11
|
version: 1.0.11
|
||||||
resolution: "@mapbox/node-pre-gyp@npm:1.0.11"
|
resolution: "@mapbox/node-pre-gyp@npm:1.0.11"
|
||||||
|
@ -4521,6 +4750,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@open-draft/deferred-promise@npm:^2.1.0":
|
||||||
|
version: 2.2.0
|
||||||
|
resolution: "@open-draft/deferred-promise@npm:2.2.0"
|
||||||
|
checksum: bc3bb1668a555bb87b33383cafcf207d9561e17d2ca0d9e61b7ce88e82b66e36a333d3676c1d39eb5848022c03c8145331fcdc828ba297f88cb1de9c5cef6c19
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@peculiar/asn1-schema@npm:^2.3.6":
|
"@peculiar/asn1-schema@npm:^2.3.6":
|
||||||
version: 2.3.8
|
version: 2.3.8
|
||||||
resolution: "@peculiar/asn1-schema@npm:2.3.8"
|
resolution: "@peculiar/asn1-schema@npm:2.3.8"
|
||||||
|
@ -5002,6 +5238,39 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@radix-ui/react-navigation-menu@npm:^1.1.4":
|
||||||
|
version: 1.1.4
|
||||||
|
resolution: "@radix-ui/react-navigation-menu@npm:1.1.4"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": "npm:^7.13.10"
|
||||||
|
"@radix-ui/primitive": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-collection": "npm:1.0.3"
|
||||||
|
"@radix-ui/react-compose-refs": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-context": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-direction": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-dismissable-layer": "npm:1.0.5"
|
||||||
|
"@radix-ui/react-id": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-presence": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-primitive": "npm:1.0.3"
|
||||||
|
"@radix-ui/react-use-callback-ref": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-use-controllable-state": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-use-layout-effect": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-use-previous": "npm:1.0.1"
|
||||||
|
"@radix-ui/react-visually-hidden": "npm:1.0.3"
|
||||||
|
peerDependencies:
|
||||||
|
"@types/react": "*"
|
||||||
|
"@types/react-dom": "*"
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@types/react":
|
||||||
|
optional: true
|
||||||
|
"@types/react-dom":
|
||||||
|
optional: true
|
||||||
|
checksum: ae502c3757a1a0417209a76def7fd43088d3414658b8acc2010a1c68c3f737fdd20f601eed384ddc0fdb55404f6299ae1dd23e1ae28b7e902595d98b97699825
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@radix-ui/react-popover@npm:^1.0.7":
|
"@radix-ui/react-popover@npm:^1.0.7":
|
||||||
version: 1.0.7
|
version: 1.0.7
|
||||||
resolution: "@radix-ui/react-popover@npm:1.0.7"
|
resolution: "@radix-ui/react-popover@npm:1.0.7"
|
||||||
|
@ -5458,6 +5727,27 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@react-hook/intersection-observer@npm:^3.1.1":
|
||||||
|
version: 3.1.1
|
||||||
|
resolution: "@react-hook/intersection-observer@npm:3.1.1"
|
||||||
|
dependencies:
|
||||||
|
"@react-hook/passive-layout-effect": "npm:^1.2.0"
|
||||||
|
intersection-observer: "npm:^0.10.0"
|
||||||
|
peerDependencies:
|
||||||
|
react: ">=16.8"
|
||||||
|
checksum: dc11695baa03765d53a23753c261f74dd0f226b9abd5bf3019d87c4f5e43da1919d81b8b902cd03d08f21f6484eb66a64139307bc84b379a95b2e3b9947e935f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@react-hook/passive-layout-effect@npm:^1.2.0":
|
||||||
|
version: 1.2.1
|
||||||
|
resolution: "@react-hook/passive-layout-effect@npm:1.2.1"
|
||||||
|
peerDependencies:
|
||||||
|
react: ">=16.8"
|
||||||
|
checksum: 217cb8aa90fb8e677672319a9a466d7752890cf4357c76df000b207696e9cc717cf2ee88080671cc9dae238a82f92093ab4f61ab2f6032d2a8db958fc7d99b5d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@remix-run/dev@npm:@vercel/remix-run-dev@1.15.0":
|
"@remix-run/dev@npm:@vercel/remix-run-dev@1.15.0":
|
||||||
version: 1.15.0
|
version: 1.15.0
|
||||||
resolution: "@vercel/remix-run-dev@npm:1.15.0"
|
resolution: "@vercel/remix-run-dev@npm:1.15.0"
|
||||||
|
@ -6611,6 +6901,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@stitches/core@npm:^1.2.6":
|
||||||
|
version: 1.2.8
|
||||||
|
resolution: "@stitches/core@npm:1.2.8"
|
||||||
|
checksum: bdee1772f033b20bfb1081a3bb8c3e85f2a44f381379d4c2ae21408336025e2d2578f79eec74db26824b852ebcc72de3edfc8c51418608f189aa5ffc26df667a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@supabase/auth-helpers-remix@npm:^0.2.2":
|
"@supabase/auth-helpers-remix@npm:^0.2.2":
|
||||||
version: 0.2.6
|
version: 0.2.6
|
||||||
resolution: "@supabase/auth-helpers-remix@npm:0.2.6"
|
resolution: "@supabase/auth-helpers-remix@npm:0.2.6"
|
||||||
|
@ -6939,14 +7236,18 @@ __metadata:
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@tldraw/docs@workspace:apps/docs"
|
resolution: "@tldraw/docs@workspace:apps/docs"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@codesandbox/sandpack-react": "npm:^2.11.3"
|
||||||
"@microsoft/api-extractor-model": "npm:^7.26.4"
|
"@microsoft/api-extractor-model": "npm:^7.26.4"
|
||||||
"@microsoft/tsdoc": "npm:^0.14.2"
|
"@microsoft/tsdoc": "npm:^0.14.2"
|
||||||
|
"@radix-ui/react-accordion": "npm:^1.1.2"
|
||||||
|
"@radix-ui/react-navigation-menu": "npm:^1.1.4"
|
||||||
"@types/broken-link-checker": "npm:^0.7.1"
|
"@types/broken-link-checker": "npm:^0.7.1"
|
||||||
"@types/node": "npm:^18.7.3"
|
"@types/node": "npm:^18.7.3"
|
||||||
"@types/sqlite3": "npm:^3.1.9"
|
"@types/sqlite3": "npm:^3.1.9"
|
||||||
"@types/ws": "npm:^8.5.9"
|
"@types/ws": "npm:^8.5.9"
|
||||||
"@vercel/analytics": "npm:^1.1.1"
|
"@vercel/analytics": "npm:^1.1.1"
|
||||||
broken-link-checker: "npm:^0.7.8"
|
broken-link-checker: "npm:^0.7.8"
|
||||||
|
classnames: "npm:^2.3.2"
|
||||||
concurrently: "npm:^8.2.2"
|
concurrently: "npm:^8.2.2"
|
||||||
dotenv: "npm:^16.3.1"
|
dotenv: "npm:^16.3.1"
|
||||||
eslint: "npm:^8.37.0"
|
eslint: "npm:^8.37.0"
|
||||||
|
@ -8964,6 +9265,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"anser@npm:^2.1.1":
|
||||||
|
version: 2.1.1
|
||||||
|
resolution: "anser@npm:2.1.1"
|
||||||
|
checksum: 7cf63f2ac34a77a410da37bd7748f9d4f1b077763b51e5eadf7b355211050e12cabbb405268cc033f6351e1e60cc00ca18431a240053ffc94c12f0c758e1e66d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"ansi-colors@npm:4.1.1":
|
"ansi-colors@npm:4.1.1":
|
||||||
version: 4.1.1
|
version: 4.1.1
|
||||||
resolution: "ansi-colors@npm:4.1.1"
|
resolution: "ansi-colors@npm:4.1.1"
|
||||||
|
@ -9988,6 +10296,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"buffer@npm:^6.0.3":
|
||||||
|
version: 6.0.3
|
||||||
|
resolution: "buffer@npm:6.0.3"
|
||||||
|
dependencies:
|
||||||
|
base64-js: "npm:^1.3.1"
|
||||||
|
ieee754: "npm:^1.2.1"
|
||||||
|
checksum: b6bc68237ebf29bdacae48ce60e5e28fc53ae886301f2ad9496618efac49427ed79096750033e7eab1897a4f26ae374ace49106a5758f38fb70c78c9fda2c3b1
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"busboy@npm:1.6.0":
|
"busboy@npm:1.6.0":
|
||||||
version: 1.6.0
|
version: 1.6.0
|
||||||
resolution: "busboy@npm:1.6.0"
|
resolution: "busboy@npm:1.6.0"
|
||||||
|
@ -10403,6 +10721,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"clean-set@npm:^1.1.2":
|
||||||
|
version: 1.1.2
|
||||||
|
resolution: "clean-set@npm:1.1.2"
|
||||||
|
checksum: b460b59c82a11945052b59efa1d51405c0ba11d227f2c2140e9f7803d702b4a36354bfee0077d46a758979891aa4322211ce392c86961f11bf57e2ff774d5506
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"clean-stack@npm:^2.0.0":
|
"clean-stack@npm:^2.0.0":
|
||||||
version: 2.2.0
|
version: 2.2.0
|
||||||
resolution: "clean-stack@npm:2.2.0"
|
resolution: "clean-stack@npm:2.2.0"
|
||||||
|
@ -10542,6 +10867,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"codesandbox-import-util-types@npm:^2.2.3":
|
||||||
|
version: 2.3.0
|
||||||
|
resolution: "codesandbox-import-util-types@npm:2.3.0"
|
||||||
|
checksum: 6cbb7050fb8bd822b4bf101792052a0d8a602bb2f85bb6f9422f9b1d11d170926c44af6f73e98fbb259792a45908ff4dc122123bec86d58176f6dadfc2f01f03
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"collect-v8-coverage@npm:^1.0.0":
|
"collect-v8-coverage@npm:^1.0.0":
|
||||||
version: 1.0.2
|
version: 1.0.2
|
||||||
resolution: "collect-v8-coverage@npm:1.0.2"
|
resolution: "collect-v8-coverage@npm:1.0.2"
|
||||||
|
@ -10911,6 +11243,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"crelt@npm:^1.0.5":
|
||||||
|
version: 1.0.6
|
||||||
|
resolution: "crelt@npm:1.0.6"
|
||||||
|
checksum: 5ed326ca6bd243b1dba6b943f665b21c2c04be03271824bc48f20dba324b0f8233e221f8c67312526d24af2b1243c023dc05a41bd8bd05d1a479fd2c72fb39c3
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"cross-env@npm:^7.0.3":
|
"cross-env@npm:^7.0.3":
|
||||||
version: 7.0.3
|
version: 7.0.3
|
||||||
resolution: "cross-env@npm:7.0.3"
|
resolution: "cross-env@npm:7.0.3"
|
||||||
|
@ -11061,6 +11400,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"d@npm:1, d@npm:^1.0.1":
|
||||||
|
version: 1.0.1
|
||||||
|
resolution: "d@npm:1.0.1"
|
||||||
|
dependencies:
|
||||||
|
es5-ext: "npm:^0.10.50"
|
||||||
|
type: "npm:^1.0.1"
|
||||||
|
checksum: 1296e3f92e646895681c1cb564abd0eb23c29db7d62c5120a279e84e98915499a477808e9580760f09e3744c0ed7ac8f7cff98d096ba9770754f6ef0f1c97983
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"damerau-levenshtein@npm:^1.0.8":
|
"damerau-levenshtein@npm:^1.0.8":
|
||||||
version: 1.0.8
|
version: 1.0.8
|
||||||
resolution: "damerau-levenshtein@npm:1.0.8"
|
resolution: "damerau-levenshtein@npm:1.0.8"
|
||||||
|
@ -11350,7 +11699,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"dequal@npm:^2.0.0, dequal@npm:^2.0.3":
|
"dequal@npm:^2.0.0, dequal@npm:^2.0.2, dequal@npm:^2.0.3":
|
||||||
version: 2.0.3
|
version: 2.0.3
|
||||||
resolution: "dequal@npm:2.0.3"
|
resolution: "dequal@npm:2.0.3"
|
||||||
checksum: 6ff05a7561f33603df87c45e389c9ac0a95e3c056be3da1a0c4702149e3a7f6fe5ffbb294478687ba51a9e95f3a60e8b6b9005993acd79c292c7d15f71964b6b
|
checksum: 6ff05a7561f33603df87c45e389c9ac0a95e3c056be3da1a0c4702149e3a7f6fe5ffbb294478687ba51a9e95f3a60e8b6b9005993acd79c292c7d15f71964b6b
|
||||||
|
@ -11626,10 +11975,10 @@ __metadata:
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"dotenv@npm:^16.0.0, dotenv@npm:^16.3.1":
|
"dotenv@npm:^16.0.0, dotenv@npm:^16.0.3, dotenv@npm:^16.3.1":
|
||||||
version: 16.3.1
|
version: 16.4.1
|
||||||
resolution: "dotenv@npm:16.3.1"
|
resolution: "dotenv@npm:16.4.1"
|
||||||
checksum: dbb778237ef8750e9e3cd1473d3c8eaa9cc3600e33a75c0e36415d0fa0848197f56c3800f77924c70e7828f0b03896818cd52f785b07b9ad4d88dba73fbba83f
|
checksum: 8da20250633703686961004df3ea81b1f81e16fbe873372050676f54ca4053172d0589aae902e683eb575884d56b6bc89fe48bbac5e1e0bef606a061389ca33c
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -12038,6 +12387,38 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.50":
|
||||||
|
version: 0.10.62
|
||||||
|
resolution: "es5-ext@npm:0.10.62"
|
||||||
|
dependencies:
|
||||||
|
es6-iterator: "npm:^2.0.3"
|
||||||
|
es6-symbol: "npm:^3.1.3"
|
||||||
|
next-tick: "npm:^1.1.0"
|
||||||
|
checksum: 3f6a3bcdb7ff82aaf65265799729828023c687a2645da04005b8f1dc6676a0c41fd06571b2517f89dcf143e0268d3d9ef0fdfd536ab74580083204c688d6fb45
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"es6-iterator@npm:^2.0.3":
|
||||||
|
version: 2.0.3
|
||||||
|
resolution: "es6-iterator@npm:2.0.3"
|
||||||
|
dependencies:
|
||||||
|
d: "npm:1"
|
||||||
|
es5-ext: "npm:^0.10.35"
|
||||||
|
es6-symbol: "npm:^3.1.1"
|
||||||
|
checksum: dbadecf3d0e467692815c2b438dfa99e5a97cbbecf4a58720adcb467a04220e0e36282399ba297911fd472c50ae4158fffba7ed0b7d4273fe322b69d03f9e3a5
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"es6-symbol@npm:^3, es6-symbol@npm:^3.1.1, es6-symbol@npm:^3.1.3":
|
||||||
|
version: 3.1.3
|
||||||
|
resolution: "es6-symbol@npm:3.1.3"
|
||||||
|
dependencies:
|
||||||
|
d: "npm:^1.0.1"
|
||||||
|
ext: "npm:^1.1.2"
|
||||||
|
checksum: b404e5ecae1a076058aa2ba2568d87e2cb4490cb1130784b84e7b4c09c570b487d4f58ed685a08db8d350bd4916500dd3d623b26e6b3520841d30d2ebb152f8d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"esbuild-android-64@npm:0.14.47":
|
"esbuild-android-64@npm:0.14.47":
|
||||||
version: 0.14.47
|
version: 0.14.47
|
||||||
resolution: "esbuild-android-64@npm:0.14.47"
|
resolution: "esbuild-android-64@npm:0.14.47"
|
||||||
|
@ -12644,6 +13025,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"escape-carriage@npm:^1.3.1":
|
||||||
|
version: 1.3.1
|
||||||
|
resolution: "escape-carriage@npm:1.3.1"
|
||||||
|
checksum: 6d7613a5875977b04eb4651f3fa14eb8f54c72aa198b603c823502fcfef9f5969afc4c76d27b2f2fc008d88764fbf4c3a6e04d549d6134e2ff7f705c99e3ddb9
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"escape-html@npm:~1.0.3":
|
"escape-html@npm:~1.0.3":
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
resolution: "escape-html@npm:1.0.3"
|
resolution: "escape-html@npm:1.0.3"
|
||||||
|
@ -13325,6 +13713,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"ext@npm:^1.1.2":
|
||||||
|
version: 1.7.0
|
||||||
|
resolution: "ext@npm:1.7.0"
|
||||||
|
dependencies:
|
||||||
|
type: "npm:^2.7.2"
|
||||||
|
checksum: 666a135980b002df0e75c8ac6c389140cdc59ac953db62770479ee2856d58ce69d2f845e5f2586716350b725400f6945e51e9159573158c39f369984c72dcd84
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"extend-shallow@npm:^2.0.1":
|
"extend-shallow@npm:^2.0.1":
|
||||||
version: 2.0.1
|
version: 2.0.1
|
||||||
resolution: "extend-shallow@npm:2.0.1"
|
resolution: "extend-shallow@npm:2.0.1"
|
||||||
|
@ -15020,7 +15417,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ieee754@npm:^1.1.13, ieee754@npm:^1.1.4":
|
"ieee754@npm:^1.1.13, ieee754@npm:^1.1.4, ieee754@npm:^1.2.1":
|
||||||
version: 1.2.1
|
version: 1.2.1
|
||||||
resolution: "ieee754@npm:1.2.1"
|
resolution: "ieee754@npm:1.2.1"
|
||||||
checksum: d9f2557a59036f16c282aaeb107832dc957a93d73397d89bbad4eb1130560560eb695060145e8e6b3b498b15ab95510226649a0b8f52ae06583575419fe10fc4
|
checksum: d9f2557a59036f16c282aaeb107832dc957a93d73397d89bbad4eb1130560560eb695060145e8e6b3b498b15ab95510226649a0b8f52ae06583575419fe10fc4
|
||||||
|
@ -15181,6 +15578,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"intersection-observer@npm:^0.10.0":
|
||||||
|
version: 0.10.0
|
||||||
|
resolution: "intersection-observer@npm:0.10.0"
|
||||||
|
checksum: d9ffce291459a2c4ada9e45f23ef805361691f93e9a41a2afe801d29e6c9b1d0054f7faddafd79ecc341d7008e1f921a2e67cadeae9692d9831af903f23fc644
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"invariant@npm:^2.2.4":
|
"invariant@npm:^2.2.4":
|
||||||
version: 2.2.4
|
version: 2.2.4
|
||||||
resolution: "invariant@npm:2.2.4"
|
resolution: "invariant@npm:2.2.4"
|
||||||
|
@ -18405,7 +18809,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"mime-db@npm:1.52.0":
|
"mime-db@npm:1.52.0, mime-db@npm:^1.52.0":
|
||||||
version: 1.52.0
|
version: 1.52.0
|
||||||
resolution: "mime-db@npm:1.52.0"
|
resolution: "mime-db@npm:1.52.0"
|
||||||
checksum: 54bb60bf39e6f8689f6622784e668a3d7f8bed6b0d886f5c3c446cb3284be28b30bf707ed05d0fe44a036f8469976b2629bbea182684977b084de9da274694d7
|
checksum: 54bb60bf39e6f8689f6622784e668a3d7f8bed6b0d886f5c3c446cb3284be28b30bf707ed05d0fe44a036f8469976b2629bbea182684977b084de9da274694d7
|
||||||
|
@ -18902,6 +19306,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"next-tick@npm:^1.1.0":
|
||||||
|
version: 1.1.0
|
||||||
|
resolution: "next-tick@npm:1.1.0"
|
||||||
|
checksum: 83b5cf36027a53ee6d8b7f9c0782f2ba87f4858d977342bfc3c20c21629290a2111f8374d13a81221179603ffc4364f38374b5655d17b6a8f8a8c77bdea4fe8b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"next@npm:^14.0.4":
|
"next@npm:^14.0.4":
|
||||||
version: 14.0.4
|
version: 14.0.4
|
||||||
resolution: "next@npm:14.0.4"
|
resolution: "next@npm:14.0.4"
|
||||||
|
@ -19530,6 +19941,20 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"outvariant@npm:1.4.0":
|
||||||
|
version: 1.4.0
|
||||||
|
resolution: "outvariant@npm:1.4.0"
|
||||||
|
checksum: 07b9bcb9b3a2ff1b3db02af6b07d70e663082b30ddc08ff475d7c85fc623fdcc4433a4ab5b88f6902b62dbb284eef1be386aa537e14cef0519fad887ec483054
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"outvariant@npm:^1.3.0, outvariant@npm:^1.4.0":
|
||||||
|
version: 1.4.2
|
||||||
|
resolution: "outvariant@npm:1.4.2"
|
||||||
|
checksum: f16ba035fb65d1cbe7d2e06693dd42183c46bc8456713d9ddb5182d067defa7d78217edab0a2d3e173d3bacd627b2bd692195c7087c225b82548fbf52c677b38
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"p-cancelable@npm:^2.0.0":
|
"p-cancelable@npm:^2.0.0":
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
resolution: "p-cancelable@npm:2.1.1"
|
resolution: "p-cancelable@npm:2.1.1"
|
||||||
|
@ -20638,6 +21063,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"react-devtools-inline@npm:4.4.0":
|
||||||
|
version: 4.4.0
|
||||||
|
resolution: "react-devtools-inline@npm:4.4.0"
|
||||||
|
dependencies:
|
||||||
|
es6-symbol: "npm:^3"
|
||||||
|
checksum: 316a03bd21eb34f511e74e4e969e6a7d75d299800a4158ff59081457f024dc3aebc0c471938fd7e1c4676823fdcb546ca0d7c2d7ab74e34a9c1bdac31f2284b2
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"react-dom@npm:^18.2.0":
|
"react-dom@npm:^18.2.0":
|
||||||
version: 18.2.0
|
version: 18.2.0
|
||||||
resolution: "react-dom@npm:18.2.0"
|
resolution: "react-dom@npm:18.2.0"
|
||||||
|
@ -20697,7 +21131,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-is@npm:^17.0.1":
|
"react-is@npm:^17.0.1, react-is@npm:^17.0.2":
|
||||||
version: 17.0.2
|
version: 17.0.2
|
||||||
resolution: "react-is@npm:17.0.2"
|
resolution: "react-is@npm:17.0.2"
|
||||||
checksum: 73b36281e58eeb27c9cc6031301b6ae19ecdc9f18ae2d518bdb39b0ac564e65c5779405d623f1df9abf378a13858b79442480244bd579968afc1faf9a2ce5e05
|
checksum: 73b36281e58eeb27c9cc6031301b6ae19ecdc9f18ae2d518bdb39b0ac564e65c5779405d623f1df9abf378a13858b79442480244bd579968afc1faf9a2ce5e05
|
||||||
|
@ -22421,6 +22855,18 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"static-browser-server@npm:1.0.3":
|
||||||
|
version: 1.0.3
|
||||||
|
resolution: "static-browser-server@npm:1.0.3"
|
||||||
|
dependencies:
|
||||||
|
"@open-draft/deferred-promise": "npm:^2.1.0"
|
||||||
|
dotenv: "npm:^16.0.3"
|
||||||
|
mime-db: "npm:^1.52.0"
|
||||||
|
outvariant: "npm:^1.3.0"
|
||||||
|
checksum: d047c6c8a667a054db23c3d9770cf5e9d558694f052be81886f606ccc1c6dab034eb1fc5b35d1e3bf23a8dc6ca6f9cd7e4349bfb7b5cad1c2af13058c32dea86
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"statuses@npm:2.0.1":
|
"statuses@npm:2.0.1":
|
||||||
version: 2.0.1
|
version: 2.0.1
|
||||||
resolution: "statuses@npm:2.0.1"
|
resolution: "statuses@npm:2.0.1"
|
||||||
|
@ -22494,6 +22940,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"strict-event-emitter@npm:^0.4.3":
|
||||||
|
version: 0.4.6
|
||||||
|
resolution: "strict-event-emitter@npm:0.4.6"
|
||||||
|
checksum: abdbf59b6c45b599cc2f227fa473765d1510d155ebd22533e8ecb06110dfacb2ff07aece7fd528dde2b4f9e379d60f2687eee8af3fa2877c3ed88ee5b7ed2707
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"string-argv@npm:0.3.2, string-argv@npm:~0.3.1":
|
"string-argv@npm:0.3.2, string-argv@npm:~0.3.1":
|
||||||
version: 0.3.2
|
version: 0.3.2
|
||||||
resolution: "string-argv@npm:0.3.2"
|
resolution: "string-argv@npm:0.3.2"
|
||||||
|
@ -22759,6 +23212,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"style-mod@npm:^4.0.0, style-mod@npm:^4.1.0":
|
||||||
|
version: 4.1.0
|
||||||
|
resolution: "style-mod@npm:4.1.0"
|
||||||
|
checksum: e0bf199d699f15d382c31ae7f18b1508f426b35346002dd1b9072db2cd32fdb0ba3ce7a4629e2fa867a79ffe4830ebf11cb9bce6500815f6a0534fac763e94f4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"style-to-object@npm:^0.4.1":
|
"style-to-object@npm:^0.4.1":
|
||||||
version: 0.4.4
|
version: 0.4.4
|
||||||
resolution: "style-to-object@npm:0.4.4"
|
resolution: "style-to-object@npm:0.4.4"
|
||||||
|
@ -23585,6 +24045,20 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"type@npm:^1.0.1":
|
||||||
|
version: 1.2.0
|
||||||
|
resolution: "type@npm:1.2.0"
|
||||||
|
checksum: b4d4b27d1926028be45fc5baaca205896e2a1fe9e5d24dc892046256efbe88de6acd0149e7353cd24dad596e1483e48ec60b0912aa47ca078d68cdd198b09885
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"type@npm:^2.7.2":
|
||||||
|
version: 2.7.2
|
||||||
|
resolution: "type@npm:2.7.2"
|
||||||
|
checksum: 602f1b369fba60687fa4d0af6fcfb814075bcaf9ed3a87637fb384d9ff849e2ad15bc244a431f341374562e51a76c159527ffdb1f1f24b0f1f988f35a301c41d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"typed-array-buffer@npm:^1.0.0":
|
"typed-array-buffer@npm:^1.0.0":
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
resolution: "typed-array-buffer@npm:1.0.0"
|
resolution: "typed-array-buffer@npm:1.0.0"
|
||||||
|
@ -24601,6 +25075,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"w3c-keyname@npm:^2.2.4":
|
||||||
|
version: 2.2.8
|
||||||
|
resolution: "w3c-keyname@npm:2.2.8"
|
||||||
|
checksum: 95bafa4c04fa2f685a86ca1000069c1ec43ace1f8776c10f226a73296caeddd83f893db885c2c220ebeb6c52d424e3b54d7c0c1e963bbf204038ff1a944fbb07
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"w3c-xmlserializer@npm:^4.0.0":
|
"w3c-xmlserializer@npm:^4.0.0":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "w3c-xmlserializer@npm:4.0.0"
|
resolution: "w3c-xmlserializer@npm:4.0.0"
|
||||||
|
|
Loading…
Reference in a new issue