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 one or more lines are too long
|
@ -427,7 +427,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": "<string>;\n}"
|
"text": "<string>;\n labelPosition: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "T.Validator",
|
||||||
|
"canonicalReference": "@tldraw/validate!Validator:class"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<number>;\n}"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fileUrlPath": "packages/tlschema/src/shapes/TLArrowShape.ts",
|
"fileUrlPath": "packages/tlschema/src/shapes/TLArrowShape.ts",
|
||||||
|
@ -436,7 +445,7 @@
|
||||||
"name": "arrowShapeProps",
|
"name": "arrowShapeProps",
|
||||||
"variableTypeTokenRange": {
|
"variableTypeTokenRange": {
|
||||||
"startIndex": 1,
|
"startIndex": 1,
|
||||||
"endIndex": 42
|
"endIndex": 44
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2688,7 +2697,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": "readonly [{\n readonly locale: \"ar\";\n readonly label: \"عربي\";\n}, {\n readonly locale: \"ca\";\n readonly label: \"Català\";\n}, {\n readonly locale: \"cs\";\n readonly label: \"Čeština\";\n}, {\n readonly locale: \"da\";\n readonly label: \"Danish\";\n}, {\n readonly locale: \"de\";\n readonly label: \"Deutsch\";\n}, {\n readonly locale: \"en\";\n readonly label: \"English\";\n}, {\n readonly locale: \"es\";\n readonly label: \"Español\";\n}, {\n readonly locale: \"fa\";\n readonly label: \"فارسی\";\n}, {\n readonly locale: \"fi\";\n readonly label: \"Suomi\";\n}, {\n readonly locale: \"fr\";\n readonly label: \"Français\";\n}, {\n readonly locale: \"gl\";\n readonly label: \"Galego\";\n}, {\n readonly locale: \"he\";\n readonly label: \"עברית\";\n}, {\n readonly locale: \"it\";\n readonly label: \"Italiano\";\n}, {\n readonly locale: \"ja\";\n readonly label: \"日本語\";\n}, {\n readonly locale: \"ko-kr\";\n readonly label: \"한국어\";\n}, {\n readonly locale: \"ku\";\n readonly label: \"کوردی\";\n}, {\n readonly locale: \"hi-in\";\n readonly label: \"हिन्दी\";\n}, {\n readonly locale: \"hu\";\n readonly label: \"Magyar\";\n}, {\n readonly locale: \"my\";\n readonly label: \"မြန်မာစာ\";\n}, {\n readonly locale: \"ne\";\n readonly label: \"नेपाली\";\n}, {\n readonly locale: \"no\";\n readonly label: \"Norwegian\";\n}, {\n readonly locale: \"pl\";\n readonly label: \"Polski\";\n}, {\n readonly locale: \"pt-br\";\n readonly label: \"Português - Brasil\";\n}, {\n readonly locale: \"pt-pt\";\n readonly label: \"Português - Europeu\";\n}, {\n readonly locale: \"ro\";\n readonly label: \"Română\";\n}, {\n readonly locale: \"ru\";\n readonly label: \"Russian\";\n}, {\n readonly locale: \"sv\";\n readonly label: \"Svenska\";\n}, {\n readonly locale: \"te\";\n readonly label: \"తెలుగు\";\n}, {\n readonly locale: \"th\";\n readonly label: \"ภาษาไทย\";\n}, {\n readonly locale: \"tr\";\n readonly label: \"Türkçe\";\n}, {\n readonly locale: \"uk\";\n readonly label: \"Ukrainian\";\n}, {\n readonly locale: \"vi\";\n readonly label: \"Tiếng Việt\";\n}, {\n readonly locale: \"zh-cn\";\n readonly label: \"简体中文\";\n}, {\n readonly locale: \"zh-tw\";\n readonly label: \"繁體中文 (台灣)\";\n}]"
|
"text": "readonly [{\n readonly locale: \"ca\";\n readonly label: \"Català\";\n}, {\n readonly locale: \"cs\";\n readonly label: \"Čeština\";\n}, {\n readonly locale: \"da\";\n readonly label: \"Danish\";\n}, {\n readonly locale: \"de\";\n readonly label: \"Deutsch\";\n}, {\n readonly locale: \"en\";\n readonly label: \"English\";\n}, {\n readonly locale: \"es\";\n readonly label: \"Español\";\n}, {\n readonly locale: \"fr\";\n readonly label: \"Français\";\n}, {\n readonly locale: \"gl\";\n readonly label: \"Galego\";\n}, {\n readonly locale: \"it\";\n readonly label: \"Italiano\";\n}, {\n readonly locale: \"hu\";\n readonly label: \"Magyar\";\n}, {\n readonly locale: \"no\";\n readonly label: \"Norwegian\";\n}, {\n readonly locale: \"pl\";\n readonly label: \"Polski\";\n}, {\n readonly locale: \"pt-br\";\n readonly label: \"Português - Brasil\";\n}, {\n readonly locale: \"pt-pt\";\n readonly label: \"Português - Europeu\";\n}, {\n readonly locale: \"ro\";\n readonly label: \"Română\";\n}, {\n readonly locale: \"ru\";\n readonly label: \"Russian\";\n}, {\n readonly locale: \"fi\";\n readonly label: \"Suomi\";\n}, {\n readonly locale: \"sv\";\n readonly label: \"Svenska\";\n}, {\n readonly locale: \"vi\";\n readonly label: \"Tiếng Việt\";\n}, {\n readonly locale: \"tr\";\n readonly label: \"Türkçe\";\n}, {\n readonly locale: \"uk\";\n readonly label: \"Ukrainian\";\n}, {\n readonly locale: \"he\";\n readonly label: \"עברית\";\n}, {\n readonly locale: \"ar\";\n readonly label: \"عربي\";\n}, {\n readonly locale: \"fa\";\n readonly label: \"فارسی\";\n}, {\n readonly locale: \"ku\";\n readonly label: \"کوردی\";\n}, {\n readonly locale: \"ne\";\n readonly label: \"नेपाली\";\n}, {\n readonly locale: \"hi-in\";\n readonly label: \"हिन्दी\";\n}, {\n readonly locale: \"te\";\n readonly label: \"తెలుగు\";\n}, {\n readonly locale: \"th\";\n readonly label: \"ภาษาไทย\";\n}, {\n readonly locale: \"my\";\n readonly label: \"မြန်မာစာ\";\n}, {\n readonly locale: \"ko-kr\";\n readonly label: \"한국어\";\n}, {\n readonly locale: \"ja\";\n readonly label: \"日本語\";\n}, {\n readonly locale: \"zh-cn\";\n readonly label: \"简体中文\";\n}, {\n readonly locale: \"zh-tw\";\n readonly label: \"繁體中文 (台灣)\";\n}]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fileUrlPath": "packages/tlschema/src/translations/languages.ts",
|
"fileUrlPath": "packages/tlschema/src/translations/languages.ts",
|
||||||
|
@ -6018,6 +6027,33 @@
|
||||||
"endIndex": 2
|
"endIndex": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"kind": "PropertySignature",
|
||||||
|
"canonicalReference": "@tldraw/tlschema!TLHandle#h:member",
|
||||||
|
"docComment": "",
|
||||||
|
"excerptTokens": [
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "h?: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isReadonly": false,
|
||||||
|
"isOptional": true,
|
||||||
|
"releaseTag": "Public",
|
||||||
|
"name": "h",
|
||||||
|
"propertyTypeTokenRange": {
|
||||||
|
"startIndex": 1,
|
||||||
|
"endIndex": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "PropertySignature",
|
"kind": "PropertySignature",
|
||||||
"canonicalReference": "@tldraw/tlschema!TLHandle#id:member",
|
"canonicalReference": "@tldraw/tlschema!TLHandle#id:member",
|
||||||
|
@ -6100,6 +6136,33 @@
|
||||||
"endIndex": 2
|
"endIndex": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"kind": "PropertySignature",
|
||||||
|
"canonicalReference": "@tldraw/tlschema!TLHandle#w:member",
|
||||||
|
"docComment": "",
|
||||||
|
"excerptTokens": [
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "w?: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isReadonly": false,
|
||||||
|
"isOptional": true,
|
||||||
|
"releaseTag": "Public",
|
||||||
|
"name": "w",
|
||||||
|
"propertyTypeTokenRange": {
|
||||||
|
"startIndex": 1,
|
||||||
|
"endIndex": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "PropertySignature",
|
"kind": "PropertySignature",
|
||||||
"canonicalReference": "@tldraw/tlschema!TLHandle#x:member",
|
"canonicalReference": "@tldraw/tlschema!TLHandle#x:member",
|
||||||
|
@ -6618,6 +6681,42 @@
|
||||||
"endIndex": 2
|
"endIndex": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"kind": "PropertySignature",
|
||||||
|
"canonicalReference": "@tldraw/tlschema!TLInstance#duplicateProps:member",
|
||||||
|
"docComment": "",
|
||||||
|
"excerptTokens": [
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "duplicateProps: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "{\n shapeIds: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLShapeId",
|
||||||
|
"canonicalReference": "@tldraw/tlschema!TLShapeId:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "[];\n offset: {\n x: number;\n y: number;\n };\n } | null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isReadonly": false,
|
||||||
|
"isOptional": false,
|
||||||
|
"releaseTag": "Public",
|
||||||
|
"name": "duplicateProps",
|
||||||
|
"propertyTypeTokenRange": {
|
||||||
|
"startIndex": 1,
|
||||||
|
"endIndex": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "PropertySignature",
|
"kind": "PropertySignature",
|
||||||
"canonicalReference": "@tldraw/tlschema!TLInstance#exportBackground:member",
|
"canonicalReference": "@tldraw/tlschema!TLInstance#exportBackground:member",
|
||||||
|
|
|
@ -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) => (
|
||||||
|
<li>
|
||||||
<Link key={article.id} href={`/${section.id}/${category.id}/${article.id}`}>
|
<Link key={article.id} href={`/${section.id}/${category.id}/${article.id}`}>
|
||||||
<li>{article.title}</li>
|
{article.title}
|
||||||
</Link>
|
</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,10 +119,56 @@ 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">
|
||||||
|
{hasGroups ? (
|
||||||
|
<>
|
||||||
|
<span className="sidebar__link">{title}</span>
|
||||||
|
<Accordion.Root
|
||||||
|
type="multiple"
|
||||||
|
defaultValue={[`${linkCtx?.categoryId}-${activeGroup}-${linkCtx?.articleId}`]}
|
||||||
|
>
|
||||||
|
{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">
|
<Link href={children[0].url} title={title} className="sidebar__link">
|
||||||
{title}
|
{title}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -99,21 +177,44 @@ function SidebarCategory({ title, children }: SidebarContentCategoryLink) {
|
||||||
<SidebarLink key={link.url} {...link} />
|
<SidebarLink key={link.url} {...link} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</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))
|
||||||
|
|
||||||
|
@ -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,9 +274,16 @@ 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
|
||||||
|
if (sectionId === 'examples') {
|
||||||
|
this._sidebarExamplesContentLinks = links
|
||||||
|
}
|
||||||
|
if (sectionId === 'reference') {
|
||||||
|
this._sidebarReferenceContentLinks = links
|
||||||
|
} else {
|
||||||
this._sidebarContentLinks = links
|
this._sidebarContentLinks = links
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sectionId: sectionId ?? null,
|
sectionId: sectionId ?? null,
|
||||||
|
|
|
@ -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