[docs] design shuffle (#2951)
This PR incorporates design tweaks from #2922 without the home page or content changes. These are: - Replacing all `hello@tldraw.com` with `sales@tldraw.com` - Fix mailto links. - Showing the first item in a section on direct routes to the section - Splitting the article page for human-written content from article page for generated content - Splitting the layout for the landing page from the rest of the site (temporarily identical to the regular content) - Removing headings from left sidebar - Restoring headings in right sidebar for human-written pages with > 1 heading link - Styling block quote - Adjusting section link appearance / layout in header / menu - Changing the order of search results to preference docs over examples - Updating copy on events - Removing copy on user interface menus - Adding hero as prop to all articles - Updated icon - Fixing a few broken links - Replaces the sandpack code blocks with hljs code blocks, except in examples. ### Change Type - [x] `documentation` — Changes to the documentation only[^2]
This commit is contained in:
parent
3f5803729d
commit
9a6f4e8c4b
47 changed files with 1587 additions and 1299 deletions
|
@ -138,7 +138,7 @@ Please see our [contributing guide](https://github.com/tldraw/tldraw/blob/main/C
|
||||||
|
|
||||||
The tldraw source code and its distributions are provided under the [tldraw license](https://github.com/tldraw/tldraw/blob/master/LICENSE.md). This license does not permit commercial use.
|
The tldraw source code and its distributions are provided under the [tldraw license](https://github.com/tldraw/tldraw/blob/master/LICENSE.md). This license does not permit commercial use.
|
||||||
|
|
||||||
If you wish to use this project in commercial product, you need to purchase a commercial license. matPlease contact us at [hello@tldraw.com](mailto:hello@tldraw.com) for more inforion about obtaining a commercial license.
|
If you wish to use this project in commercial product, you need to purchase a commercial license. matPlease contact us at [sales@tldraw.com](mailto:sales@tldraw.com) for more inforion about obtaining a commercial license.
|
||||||
|
|
||||||
## Trademarks
|
## Trademarks
|
||||||
|
|
||||||
|
@ -146,4 +146,4 @@ Copyright (c) 2023-present tldraw Inc. The tldraw name and logo are trademarks o
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
Find us on Twitter at [@tldraw](https://twitter.com/tldraw) or email [hello@tldraw.com](mailto://hello@tldraw.com). You can also [join our discord](https://discord.gg/rhsyWMUJxd) for quick help and support.
|
Find us on Twitter at [@tldraw](https://twitter.com/tldraw) or email [sales@tldraw.com](mailto://sales@tldraw.com). You can also [join our discord](https://discord.gg/rhsyWMUJxd) for quick help and support.
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,12 +1,20 @@
|
||||||
import { ArticleDocsPage } from '@/components/ArticleDocsPage'
|
import { ArticleDocsPage } from '@/components/ArticleDocsPage'
|
||||||
|
import { ArticleReferenceDocsPage } from '@/components/ArticleReferenceDocsPage'
|
||||||
import { CategoryDocsPage } from '@/components/CategoryDocsPage'
|
import { CategoryDocsPage } from '@/components/CategoryDocsPage'
|
||||||
import { ExampleDocsPage } from '@/components/ExampleDocsPage'
|
import { ExampleDocsPage } from '@/components/ExampleDocsPage'
|
||||||
import { SectionDocsPage } from '@/components/SectionDocsPage'
|
import { SectionDocsPage } from '@/components/SectionDocsPage'
|
||||||
|
import { Article, Category, Section } from '@/types/content-types'
|
||||||
import { getDb } from '@/utils/ContentDatabase'
|
import { getDb } from '@/utils/ContentDatabase'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { notFound } from 'next/navigation'
|
import { notFound } from 'next/navigation'
|
||||||
|
|
||||||
async function getContentForPath(path: string) {
|
async function getContentForPath(
|
||||||
|
path: string
|
||||||
|
): Promise<
|
||||||
|
| { type: 'section'; section: Section }
|
||||||
|
| { type: 'category'; category: Category }
|
||||||
|
| { type: 'article'; article: Article }
|
||||||
|
> {
|
||||||
const db = await getDb()
|
const db = await getDb()
|
||||||
|
|
||||||
const section = await db.db.get(`SELECT * FROM sections WHERE sections.path = ?`, path)
|
const section = await db.db.get(`SELECT * FROM sections WHERE sections.path = ?`, path)
|
||||||
|
@ -105,6 +113,28 @@ export default async function ContentPage({ params }: { params: { id: string | s
|
||||||
|
|
||||||
switch (content.type) {
|
switch (content.type) {
|
||||||
case 'section': {
|
case 'section': {
|
||||||
|
const db = await getDb()
|
||||||
|
let firstArticleInSection: Article | undefined
|
||||||
|
|
||||||
|
const categories = await db.getCategoriesForSection(content.section.id)
|
||||||
|
|
||||||
|
for (const category of categories) {
|
||||||
|
const articles = await db.getCategoryArticles(content.section.id, category.id)
|
||||||
|
const article = articles[0]
|
||||||
|
if (article) {
|
||||||
|
firstArticleInSection = article
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstArticleInSection) {
|
||||||
|
const article = await db.getArticle(firstArticleInSection.id)
|
||||||
|
if (article?.componentCode) {
|
||||||
|
return <ExampleDocsPage article={article} />
|
||||||
|
}
|
||||||
|
return <ArticleDocsPage article={article} />
|
||||||
|
}
|
||||||
|
|
||||||
return <SectionDocsPage section={content.section} />
|
return <SectionDocsPage section={content.section} />
|
||||||
}
|
}
|
||||||
case 'category': {
|
case 'category': {
|
||||||
|
@ -114,6 +144,11 @@ export default async function ContentPage({ params }: { params: { id: string | s
|
||||||
if (content.article.componentCode) {
|
if (content.article.componentCode) {
|
||||||
return <ExampleDocsPage article={content.article} />
|
return <ExampleDocsPage article={content.article} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (content.article.sectionId === 'reference') {
|
||||||
|
return <ArticleReferenceDocsPage article={content.article} />
|
||||||
|
}
|
||||||
|
|
||||||
return <ArticleDocsPage article={content.article} />
|
return <ArticleDocsPage article={content.article} />
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
|
@ -10,7 +10,7 @@ export default async function ClaPage() {
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
<Sidebar {...sidebar} />
|
<Sidebar {...sidebar} />
|
||||||
<main className="article">
|
<main className="main-content article">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<h1>Contributor License Agreement</h1>
|
<h1>Contributor License Agreement</h1>
|
||||||
</div>
|
</div>
|
10
apps/docs/app/(content)/layout.tsx
Normal file
10
apps/docs/app/(content)/layout.tsx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { Footer } from '@/components/Footer'
|
||||||
|
|
||||||
|
export default async function ContentLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="wrapper">
|
||||||
|
<div className="layout">{children}</div>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
10
apps/docs/app/(landing)/layout.tsx
Normal file
10
apps/docs/app/(landing)/layout.tsx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { Footer } from '@/components/Footer'
|
||||||
|
|
||||||
|
export default async function ContentLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="wrapper">
|
||||||
|
<div className="layout">{children}</div>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
import { Footer } from '@/components/Footer'
|
|
||||||
import { Analytics } from '@vercel/analytics/react'
|
import { Analytics } from '@vercel/analytics/react'
|
||||||
import { Metadata, Viewport } from 'next'
|
import { Metadata, Viewport } from 'next'
|
||||||
import AutoRefresh from '../components/AutoRefresh'
|
import AutoRefresh from '../components/AutoRefresh'
|
||||||
|
@ -7,9 +6,9 @@ import '../styles/hljs.css'
|
||||||
import '../styles/parameters-table.css'
|
import '../styles/parameters-table.css'
|
||||||
import { Providers } from './providers'
|
import { Providers } from './providers'
|
||||||
|
|
||||||
const TITLE = 'tldraw docs'
|
const TITLE = 'tldraw SDK'
|
||||||
const DESCRIPTION =
|
const DESCRIPTION =
|
||||||
'Developer documentation for tldraw. Build infinite canvas experiences for the web.'
|
'Infinite canvas SDK from tldraw. Build whiteboards, design tools, and canvas experiences for the web.'
|
||||||
const TWITTER_HANDLE = '@tldraw'
|
const TWITTER_HANDLE = '@tldraw'
|
||||||
const TWITTER_CARD = 'social-twitter.png'
|
const TWITTER_CARD = 'social-twitter.png'
|
||||||
const FACEBOOK_CARD = 'social-og.png'
|
const FACEBOOK_CARD = 'social-og.png'
|
||||||
|
@ -70,10 +69,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
|
||||||
<html suppressHydrationWarning>
|
<html suppressHydrationWarning>
|
||||||
<body>
|
<body>
|
||||||
<Providers>
|
<Providers>
|
||||||
<div className="wrapper">
|
{children}
|
||||||
<div className="layout">{children}</div>
|
|
||||||
<Footer />
|
|
||||||
</div>
|
|
||||||
<Analytics />
|
<Analytics />
|
||||||
</Providers>
|
</Providers>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -7,15 +7,17 @@ export default async function NotFound() {
|
||||||
const sidebar = await db.getSidebarContentList({})
|
const sidebar = await db.getSidebarContentList({})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="wrapper">
|
||||||
<Header />
|
<div className="layout">
|
||||||
<Sidebar {...sidebar} />
|
<Header />
|
||||||
<main className="article">
|
<Sidebar {...sidebar} />
|
||||||
<div className="page-header">
|
<main className="main-content article">
|
||||||
<h1>Not found.</h1>
|
<div className="page-header">
|
||||||
</div>
|
<h1>Not found.</h1>
|
||||||
<p>There's nothing here. :(</p>
|
</div>
|
||||||
</main>
|
<p>There's nothing here. :(</p>
|
||||||
</>
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
import { ThemeProvider } from 'next-themes'
|
import { ThemeProvider } from 'next-themes'
|
||||||
|
|
||||||
export function Providers({ children }: { children: any }) {
|
export function Providers({ children }: { children: any }) {
|
||||||
return <ThemeProvider>{children}</ThemeProvider>
|
return <ThemeProvider enableSystem>{children}</ThemeProvider>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Article } from '@/types/content-types'
|
import { Article } from '@/types/content-types'
|
||||||
import { getDb } from '@/utils/ContentDatabase'
|
import { getDb } from '@/utils/ContentDatabase'
|
||||||
import { ArticleDetails } from './ArticleDetails'
|
import { ArticleDetails } from './ArticleDetails'
|
||||||
|
import { ArticleHeadingLinks } from './ArticleHeadingLinks'
|
||||||
import { ArticleNavLinks } from './ArticleNavLinks'
|
import { ArticleNavLinks } from './ArticleNavLinks'
|
||||||
import { Breadcrumb } from './Breadcrumb'
|
|
||||||
import { Header } from './Header'
|
import { Header } from './Header'
|
||||||
import { Mdx } from './Mdx'
|
import { Mdx } from './Mdx'
|
||||||
import { Sidebar } from './Sidebar'
|
import { Sidebar } from './Sidebar'
|
||||||
|
@ -20,22 +20,20 @@ export async function ArticleDocsPage({ article }: { article: Article }) {
|
||||||
articleId: article.id,
|
articleId: article.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
const isGenerated = article.sectionId === 'reference'
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header sectionId={section.id} />
|
<Header sectionId={section.id} />
|
||||||
<Sidebar headings={headings} {...sidebar} />
|
<Sidebar {...sidebar} />
|
||||||
<main className={`article${isGenerated ? ' article__api-docs' : ''}`}>
|
<main className="main-content article">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<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} />}
|
||||||
{isGenerated ? null : <ArticleDetails article={article} />}
|
<ArticleDetails article={article} />
|
||||||
{links && <ArticleNavLinks links={links} />}
|
{links && <ArticleNavLinks links={links} />}
|
||||||
</main>
|
</main>
|
||||||
|
<ArticleHeadingLinks article={article} headingLinks={headings} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
46
apps/docs/components/ArticleHeadingLinks.tsx
Normal file
46
apps/docs/components/ArticleHeadingLinks.tsx
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/* eslint-disable no-useless-escape */
|
||||||
|
import { Article, ArticleHeading, ArticleHeadings } from '@/types/content-types'
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
export function ArticleHeadingLinks({
|
||||||
|
headingLinks,
|
||||||
|
}: {
|
||||||
|
article: Article
|
||||||
|
headingLinks: ArticleHeadings
|
||||||
|
}) {
|
||||||
|
const linksToShow = headingLinks.filter((heading) => heading.level < 4)
|
||||||
|
|
||||||
|
if (linksToShow.length <= 1) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="layout__headings">
|
||||||
|
<ul className="sidebar__list sidebar__sections__list">
|
||||||
|
<li className="sidebar__section">
|
||||||
|
<div className="sidebar__section__title uppercase_title">On this page</div>
|
||||||
|
<ul className="sidebar__list">
|
||||||
|
{linksToShow.map((heading) => (
|
||||||
|
<HeaderLink key={heading.slug} heading={heading} />
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function HeaderLink({ heading }: { heading: ArticleHeading }) {
|
||||||
|
return (
|
||||||
|
<li className="sidebar__article">
|
||||||
|
<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>
|
||||||
|
)
|
||||||
|
}
|
36
apps/docs/components/ArticleReferenceDocsPage.tsx
Normal file
36
apps/docs/components/ArticleReferenceDocsPage.tsx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { Article } from '@/types/content-types'
|
||||||
|
import { getDb } from '@/utils/ContentDatabase'
|
||||||
|
import { ArticleNavLinks } from './ArticleNavLinks'
|
||||||
|
import { Breadcrumb } from './Breadcrumb'
|
||||||
|
import { Header } from './Header'
|
||||||
|
import { Mdx } from './Mdx'
|
||||||
|
import { Sidebar } from './Sidebar'
|
||||||
|
import { Image } from './mdx-components/generic'
|
||||||
|
|
||||||
|
export async function ArticleReferenceDocsPage({ article }: { article: Article }) {
|
||||||
|
const db = await getDb()
|
||||||
|
const section = await db.getSection(article.sectionId)
|
||||||
|
const category = await db.getCategory(article.categoryId)
|
||||||
|
const links = await db.getArticleLinks(article)
|
||||||
|
const sidebar = await db.getSidebarContentList({
|
||||||
|
sectionId: section.id,
|
||||||
|
categoryId: category.id,
|
||||||
|
articleId: article.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header sectionId={section.id} />
|
||||||
|
<Sidebar {...sidebar} />
|
||||||
|
<main className="main-content article article__api-docs">
|
||||||
|
<div className="page-header">
|
||||||
|
<Breadcrumb section={section} category={category} />
|
||||||
|
<h1>{article.title}</h1>
|
||||||
|
</div>
|
||||||
|
{article.hero && <Image alt="hero" title={article.title} src={`images/${article.hero}`} />}
|
||||||
|
{article.content && <Mdx content={article.content} />}
|
||||||
|
{links && <ArticleNavLinks links={links} />}
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -23,10 +23,8 @@ export async function CategoryDocsPage({ category }: { category: Category }) {
|
||||||
{articles.length > 0 && (
|
{articles.length > 0 && (
|
||||||
<ul>
|
<ul>
|
||||||
{articles.map((article) => (
|
{articles.map((article) => (
|
||||||
<li>
|
<li key={article.id}>
|
||||||
<Link key={article.id} href={`/${section.id}/${category.id}/${article.id}`}>
|
<Link href={`/${section.id}/${category.id}/${article.id}`}>{article.title}</Link>
|
||||||
{article.title}
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import { Article } from '@/types/content-types'
|
import { Article } from '@/types/content-types'
|
||||||
import { getDb } from '@/utils/ContentDatabase'
|
import { getDb } from '@/utils/ContentDatabase'
|
||||||
import { ArticleNavLinks } from './ArticleNavLinks'
|
import { ArticleNavLinks } from './ArticleNavLinks'
|
||||||
import { Breadcrumb } from './Breadcrumb'
|
|
||||||
import ExampleCodeBlock from './ExampleCodeBlock'
|
import ExampleCodeBlock from './ExampleCodeBlock'
|
||||||
import { Header } from './Header'
|
import { Header } from './Header'
|
||||||
import { Mdx } from './Mdx'
|
import { Mdx } from './Mdx'
|
||||||
import { Sidebar } from './Sidebar'
|
import { Sidebar } from './Sidebar'
|
||||||
import { Image } from './mdx-components/generic'
|
|
||||||
|
|
||||||
export async function ExampleDocsPage({ article }: { article: Article }) {
|
export async function ExampleDocsPage({ article }: { article: Article }) {
|
||||||
const db = await getDb()
|
const db = await getDb()
|
||||||
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 headings = await db.getArticleHeadings(article.id)
|
|
||||||
const links = await db.getArticleLinks(article)
|
const links = await db.getArticleLinks(article)
|
||||||
const sidebar = await db.getSidebarContentList({
|
const sidebar = await db.getSidebarContentList({
|
||||||
sectionId: section.id,
|
sectionId: section.id,
|
||||||
|
@ -23,25 +20,21 @@ export async function ExampleDocsPage({ article }: { article: Article }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header sectionId={section.id} />
|
<Header sectionId={section.id} />
|
||||||
<Sidebar headings={headings} {...sidebar} />
|
<Sidebar {...sidebar} />
|
||||||
<main className={`article article__example`}>
|
<main className={`main-content article article__example`}>
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<Breadcrumb section={section} category={category} />
|
|
||||||
<h1>{article.title}</h1>
|
<h1>{article.title}</h1>
|
||||||
{article.description && <p>{article.description}</p>}
|
{article.description && <p>{article.description}</p>}
|
||||||
</div>
|
</div>
|
||||||
{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
|
||||||
<ExampleCodeBlock
|
articleId={article.id}
|
||||||
articleId={article.id}
|
files={{
|
||||||
files={{
|
'App.tsx': article.componentCode,
|
||||||
'App.tsx': article.componentCode,
|
...(article.componentCodeFiles ? JSON.parse(article.componentCodeFiles) : null),
|
||||||
...(article.componentCodeFiles ? JSON.parse(article.componentCodeFiles) : null),
|
}}
|
||||||
}}
|
activeFile={'App.tsx'}
|
||||||
activeFile={'App.tsx'}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{links && <ArticleNavLinks links={links} />}
|
{links && <ArticleNavLinks links={links} />}
|
||||||
</main>
|
</main>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,44 +1,43 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { debounce } from '@/utils/debounce'
|
import { useRef } from 'react'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
|
||||||
|
|
||||||
export default function FancyBox() {
|
export default function FancyBox() {
|
||||||
const rContainer = useRef<HTMLDivElement>(null)
|
const rContainer = useRef<HTMLDivElement>(null)
|
||||||
const [items, setItems] = useState<number[]>([])
|
// const [items, setItems] = useState<number[]>([])
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
const populate = debounce(() => {
|
// const populate = debounce(() => {
|
||||||
const elm = rContainer.current
|
// const elm = rContainer.current
|
||||||
if (!elm) return
|
// if (!elm) return
|
||||||
|
|
||||||
const width = elm.clientWidth
|
// const width = elm.clientWidth
|
||||||
const height = elm.clientHeight
|
// const height = elm.clientHeight
|
||||||
|
|
||||||
const SIZE = 32
|
// const SIZE = 32
|
||||||
|
|
||||||
const cols = Math.ceil(width / SIZE)
|
// const cols = Math.ceil(width / SIZE)
|
||||||
const rows = Math.ceil(height / SIZE)
|
// const rows = Math.ceil(height / SIZE)
|
||||||
|
|
||||||
const items = Array.from(Array(cols * rows)).map((_, i) => i)
|
// const items = Array.from(Array(cols * rows)).map((_, i) => i)
|
||||||
|
|
||||||
setItems(items)
|
// setItems(items)
|
||||||
}, 100)
|
// }, 100)
|
||||||
|
|
||||||
populate()
|
// populate()
|
||||||
|
|
||||||
window.addEventListener('resize', populate)
|
// window.addEventListener('resize', populate)
|
||||||
return () => {
|
// return () => {
|
||||||
window.removeEventListener('resize', populate)
|
// window.removeEventListener('resize', populate)
|
||||||
}
|
// }
|
||||||
}, [])
|
// }, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="footer__fancybox" ref={rContainer}>
|
<div className="footer__fancybox" ref={rContainer}>
|
||||||
{items.map((i) => {
|
{/* {items.map((i) => {
|
||||||
const c = 1 + (i % 7)
|
const c = 1 + (i % 7)
|
||||||
return <div key={i} className="footer__fancybox__item" data-c={c} />
|
return <div key={i} className="footer__fancybox__item" data-c={c} />
|
||||||
})}
|
})} */}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,7 @@ export function Footer() {
|
||||||
<p>tldraw © {new Date().getFullYear()}</p>
|
<p>tldraw © {new Date().getFullYear()}</p>
|
||||||
</a>
|
</a>
|
||||||
<div className="footer__socials">
|
<div className="footer__socials">
|
||||||
<a
|
<a href="https://x.com/tldraw" className="sidebar__button icon-button" title="x">
|
||||||
href="https://twitter.com/tldraw"
|
|
||||||
className="sidebar__button icon-button"
|
|
||||||
title="twitter"
|
|
||||||
>
|
|
||||||
<Icon icon="twitter" />
|
<Icon icon="twitter" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
|
|
|
@ -10,43 +10,42 @@ export function Header({ sectionId }: { sectionId?: string }) {
|
||||||
<div className="layout__header">
|
<div className="layout__header">
|
||||||
<div className="layout__header__left">
|
<div className="layout__header__left">
|
||||||
<Link href="/quick-start">
|
<Link href="/quick-start">
|
||||||
<div
|
<img className="logo-dark" src="/tldraw_dev_dark.png" />
|
||||||
className="lockup"
|
<img className="logo-light" src="/tldraw_dev_light.png" />
|
||||||
style={{
|
|
||||||
mask: `url(/lockup.svg) center 100% / 100% no-repeat`,
|
|
||||||
WebkitMask: `url(/lockup.svg) center 100% / 100% no-repeat`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<Search />
|
<Search />
|
||||||
<div className="layout__header__sections_and_socials">
|
<div className="layout__header__links">
|
||||||
<SectionLinks sectionId={sectionId} />
|
<div className="layout__header__sections">
|
||||||
<a
|
<SectionLinks sectionId={sectionId} />
|
||||||
href="https://x.com/tldraw/"
|
</div>
|
||||||
className="sidebar__button icon-button"
|
<div className="layout__header__socials">
|
||||||
title="twitter"
|
<a
|
||||||
target="_blank"
|
href="https://x.com/tldraw/"
|
||||||
>
|
className="sidebar__button icon-button"
|
||||||
<Icon icon="twitter" />
|
title="twitter"
|
||||||
</a>
|
target="_blank"
|
||||||
<a
|
>
|
||||||
href="https://discord.com/invite/SBBEVCA4PG"
|
<Icon icon="twitter" />
|
||||||
className="sidebar__button icon-button"
|
</a>
|
||||||
title="discord"
|
<a
|
||||||
target="_blank"
|
href="https://discord.com/invite/SBBEVCA4PG"
|
||||||
>
|
className="sidebar__button icon-button"
|
||||||
<Icon icon="discord" />
|
title="discord"
|
||||||
</a>
|
target="_blank"
|
||||||
<a
|
>
|
||||||
href="https://github.com/tldraw/tldraw"
|
<Icon icon="discord" />
|
||||||
className="sidebar__button icon-button"
|
</a>
|
||||||
title="github"
|
<a
|
||||||
target="_blank"
|
href="https://github.com/tldraw/tldraw"
|
||||||
>
|
className="sidebar__button icon-button"
|
||||||
<Icon icon="github" />
|
title="github"
|
||||||
</a>
|
target="_blank"
|
||||||
<ThemeSwitcher />
|
>
|
||||||
|
<Icon icon="github" />
|
||||||
|
</a>
|
||||||
|
<ThemeSwitcher />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,7 +13,7 @@ export function Chevron({ className }: { className?: string }) {
|
||||||
<path
|
<path
|
||||||
d="M4 6L8 10L12 6"
|
d="M4 6L8 10L12 6"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
strokeWidth="2"
|
strokeWidth="1"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { MDXRemote } from 'next-mdx-remote/rsc'
|
import { MDXRemote } from 'next-mdx-remote/rsc'
|
||||||
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
||||||
|
import rehypeHighlight from 'rehype-highlight'
|
||||||
import rehypeSlug from 'rehype-slug-custom-id'
|
import rehypeSlug from 'rehype-slug-custom-id'
|
||||||
import { components } from './mdx-components'
|
import { components } from './mdx-components'
|
||||||
// import rehypeHighlight from 'rehype-highlight'
|
|
||||||
|
|
||||||
interface MdxProps {
|
interface MdxProps {
|
||||||
content: string
|
content: string
|
||||||
|
@ -17,7 +17,7 @@ export function Mdx({ content }: MdxProps) {
|
||||||
mdxOptions: {
|
mdxOptions: {
|
||||||
// remarkPlugins: [remarkGfm, {}],
|
// remarkPlugins: [remarkGfm, {}],
|
||||||
rehypePlugins: [
|
rehypePlugins: [
|
||||||
// [rehypeHighlight as any, {}],
|
[rehypeHighlight as any, {}],
|
||||||
[rehypeAutolinkHeadings, {}],
|
[rehypeAutolinkHeadings, {}],
|
||||||
[rehypeSlug, { enableCustomId: true, maintainCase: true, removeAccents: true }],
|
[rehypeSlug, { enableCustomId: true, maintainCase: true, removeAccents: true }],
|
||||||
],
|
],
|
||||||
|
|
|
@ -102,7 +102,7 @@ export function Search() {
|
||||||
// {searchType === SEARCH_TYPE.NORMAL ? '✨ Search using AI' : '⭐ Search without AI'}
|
// {searchType === SEARCH_TYPE.NORMAL ? '✨ Search using AI' : '⭐ Search without AI'}
|
||||||
// </button>
|
// </button>
|
||||||
// }
|
// }
|
||||||
groups={['examples', 'docs', 'reference']}
|
groups={['docs', 'examples', 'reference']}
|
||||||
groupsToLabel={{ examples: 'Examples', docs: 'Articles', reference: 'Reference' }}
|
groupsToLabel={{ examples: 'Examples', docs: 'Articles', reference: 'Reference' }}
|
||||||
options={searchResults}
|
options={searchResults}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
|
|
@ -11,7 +11,7 @@ export async function SectionDocsPage({ section }: { section: Section }) {
|
||||||
<>
|
<>
|
||||||
<Header sectionId={section.id} />
|
<Header sectionId={section.id} />
|
||||||
<Sidebar {...sidebar} />
|
<Sidebar {...sidebar} />
|
||||||
<main className="article">
|
<main className="main-content article">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<h1>{section.title}</h1>
|
<h1>{section.title}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -33,7 +33,7 @@ const linkContext = createContext<{
|
||||||
// it keeps re-rendering.
|
// it keeps re-rendering.
|
||||||
let scrollPosition = 0
|
let scrollPosition = 0
|
||||||
|
|
||||||
export function Sidebar({ headings, links, sectionId, categoryId, articleId }: SidebarProps) {
|
export function Sidebar({ links, sectionId, categoryId, articleId }: SidebarProps) {
|
||||||
const activeId = articleId ?? categoryId ?? sectionId
|
const activeId = articleId ?? categoryId ?? sectionId
|
||||||
const sidebarRef = useRef<HTMLDivElement>(null)
|
const sidebarRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ export function Sidebar({ headings, links, sectionId, categoryId, articleId }: S
|
||||||
<div className="sidebar__section__links">
|
<div className="sidebar__section__links">
|
||||||
<SectionLinks sectionId={sectionId} />
|
<SectionLinks sectionId={sectionId} />
|
||||||
</div>
|
</div>
|
||||||
<SidebarLinks headings={headings} links={links} />
|
<SidebarLinks links={links} />
|
||||||
<SidebarCloseButton />
|
<SidebarCloseButton />
|
||||||
</div>
|
</div>
|
||||||
<ToggleMenuButton />
|
<ToggleMenuButton />
|
||||||
|
@ -81,62 +81,48 @@ export function Sidebar({ headings, links, sectionId, categoryId, articleId }: S
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SidebarLinks({
|
export function SidebarLinks({ links }: { links: SidebarContentLink[] }) {
|
||||||
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} headings={headings} {...link} />
|
<SidebarLink key={link.url} {...link} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarLink({ headings, ...props }: SidebarContentLink & { headings?: ArticleHeadings }) {
|
function SidebarLink(props: SidebarContentLink) {
|
||||||
switch (props.type) {
|
switch (props.type) {
|
||||||
case 'section': {
|
case 'section': {
|
||||||
return <SidebarSection headings={headings} {...props} />
|
return <SidebarSection {...props} />
|
||||||
}
|
}
|
||||||
case 'article': {
|
case 'article': {
|
||||||
return <SidebarArticle headings={headings} {...props} />
|
return <SidebarArticle {...props} />
|
||||||
}
|
}
|
||||||
case 'category': {
|
case 'category': {
|
||||||
return <SidebarCategory headings={headings} {...props} />
|
return <SidebarCategory {...props} />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarSection({
|
function SidebarSection({ title, children }: SidebarContentSectionLink) {
|
||||||
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 && <span className="sidebar__section__title">{title}</span>}
|
{title && <span className="sidebar__section__title uppercase_title">{title}</span>}
|
||||||
<ul className="sidebar__list">
|
<ul className="sidebar__list">
|
||||||
{children.map((link) => (
|
{children.map((link) => (
|
||||||
<SidebarLink key={link.url} headings={headings} {...link} />
|
<SidebarLink key={link.url} {...link} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarCategory({
|
function SidebarCategory({ title, children }: SidebarContentCategoryLink) {
|
||||||
title,
|
|
||||||
children,
|
|
||||||
headings,
|
|
||||||
}: SidebarContentCategoryLink & { headings?: ArticleHeadings }) {
|
|
||||||
const linkCtx = useContext(linkContext)
|
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 hasGroups = children.some((child) => !!(child as SidebarContentArticleLink).groupId)
|
||||||
|
@ -171,7 +157,7 @@ function SidebarCategory({
|
||||||
<Accordion.Content>
|
<Accordion.Content>
|
||||||
<ul className="sidebar__list sidebar__group">
|
<ul className="sidebar__list sidebar__group">
|
||||||
{articles.map((link) => (
|
{articles.map((link) => (
|
||||||
<SidebarLink key={link.url} headings={headings} {...link} />
|
<SidebarLink key={link.url} {...link} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</Accordion.Content>
|
</Accordion.Content>
|
||||||
|
|
|
@ -5,12 +5,7 @@ import { useTheme } from 'next-themes'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
export const Code = (props: any) => {
|
export const Code = (props: any) => {
|
||||||
if (!props.className) {
|
return <code {...props} />
|
||||||
return <code {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
const language = props.className.replace('language-', '')
|
|
||||||
return <CodeBlock code={{ [`App.${language}`]: props.children.trim() }} />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CodeBlock({ code }: { code: SandpackFiles }) {
|
export function CodeBlock({ code }: { code: SandpackFiles }) {
|
||||||
|
|
|
@ -150,7 +150,7 @@ export const Footnotes = (props: any) => {
|
||||||
/* -------------------- API docs -------------------- */
|
/* -------------------- API docs -------------------- */
|
||||||
|
|
||||||
export const ApiHeading = (props: any) => {
|
export const ApiHeading = (props: any) => {
|
||||||
return <div {...props} />
|
return <div className="article__api-heading uppercase_title" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Embed = (props: any) => {
|
export const Embed = (props: any) => {
|
||||||
|
@ -161,3 +161,14 @@ export const Embed = (props: any) => {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------- Callouts -------------------- */
|
||||||
|
|
||||||
|
export const Callout = ({ icon, children }: any) => {
|
||||||
|
return (
|
||||||
|
<div className="article__callout">
|
||||||
|
<span>{icon}</span>
|
||||||
|
<p>{children}</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
A,
|
A,
|
||||||
ApiHeading,
|
ApiHeading,
|
||||||
Blockquote,
|
Blockquote,
|
||||||
|
Callout,
|
||||||
Divider,
|
Divider,
|
||||||
Embed,
|
Embed,
|
||||||
Heading1,
|
Heading1,
|
||||||
|
@ -56,6 +57,7 @@ export const components = {
|
||||||
Image,
|
Image,
|
||||||
Small: Small,
|
Small: Small,
|
||||||
Video,
|
Video,
|
||||||
|
Callout,
|
||||||
...customComponents,
|
...customComponents,
|
||||||
...apiComponents,
|
...apiComponents,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
{
|
{
|
||||||
"id": "tldraw",
|
"id": "tldraw",
|
||||||
"name": "tldraw",
|
"name": "tldraw",
|
||||||
"email": "hello@tldraw.com",
|
"email": "sales@tldraw.com",
|
||||||
"twitter": "tldraw",
|
"twitter": "tldraw",
|
||||||
"image": "tldraw.jpg"
|
"image": "tldraw.jpg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api",
|
"id": "api",
|
||||||
"name": "API",
|
"name": "API",
|
||||||
"email": "hello@tldraw.com",
|
"email": "sales@tldraw.com",
|
||||||
"twitter": "tldraw",
|
"twitter": "tldraw",
|
||||||
"image": "api.jpg"
|
"image": "api.jpg"
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ tldraw uses a dual licensing model to support the development of the project.
|
||||||
|
|
||||||
The project's source code, libraries, and distributions are provided under the [tldraw licence](https://github.com/tldraw/tldraw/blob/master/LICENSE.md).
|
The project's source code, libraries, and distributions are provided under the [tldraw licence](https://github.com/tldraw/tldraw/blob/master/LICENSE.md).
|
||||||
|
|
||||||
This license does not permit commercial use. If you wish to use this project in commercial product or enterprise, you need to purchase a commercial license.
|
This license does not permit commercial use. If you wish to use this project in a commercial product or enterprise, you need to purchase a commercial license.
|
||||||
|
|
||||||
To purchase a commercial license, or for more information, please contact us at [sales@tldraw.com](mailto:sales@tldraw.com).
|
To purchase a commercial license, or for more information, please contact us at [sales@tldraw.com](mailto:sales@tldraw.com).
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: User Interface
|
title: User interface
|
||||||
status: published
|
status: published
|
||||||
author: steveruizok
|
author: steveruizok
|
||||||
date: 3/22/2023
|
date: 3/22/2023
|
||||||
|
@ -39,6 +39,27 @@ All of our user interface works by controlling the editor via its `Editor` metho
|
||||||
|
|
||||||
The source for these examples are available in the [tldraw repository](https://github.com/tldraw/tldraw/blob/main/apps/examples/src) or in a [sandbox here](https://stackblitz.com/github/tldraw/tldraw/tree/examples?file=src%2Findex.tsx).
|
The source for these examples are available in the [tldraw repository](https://github.com/tldraw/tldraw/blob/main/apps/examples/src) or in a [sandbox here](https://stackblitz.com/github/tldraw/tldraw/tree/examples?file=src%2Findex.tsx).
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
The [Tldraw](?) component has a prop, `onUiEvent`, that the user interface will call when certain events occur.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
function Example() {
|
||||||
|
function handleEvent(name, data) {
|
||||||
|
// do something with the event
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Tldraw onUiEvent={handleEvent} />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `onUiEvent` callback is called with the name of the event as a string and an object with information about the event's source (e.g. `menu` or `context-menu`) and possibly other data specific to each event, such as the direction in an `align-shapes` event.
|
||||||
|
|
||||||
|
Note that `onUiEvent` is only called when interacting with the user interface. It is not called when running commands manually against the app, e.g. calling [Editor#alignShapes](?) will not call `onUiEvent`.
|
||||||
|
|
||||||
|
See the [tldraw repository](https://github.com/tldraw/tldraw/tree/main/apps/examples) for an example of how to customize tldraw's user interface.
|
||||||
|
|
||||||
|
|
||||||
## Overrides
|
## Overrides
|
||||||
|
|
||||||
The content of tldraw's menus can be controlled via the `overrides` prop. This prop accepts a [TLUiOverrides](/reference/tldraw/TLUiOverrides) object, which has methods for each part of the user interface, such as the `toolbar` or `keyboardShortcutsMenu`.
|
The content of tldraw's menus can be controlled via the `overrides` prop. This prop accepts a [TLUiOverrides](/reference/tldraw/TLUiOverrides) object, which has methods for each part of the user interface, such as the `toolbar` or `keyboardShortcutsMenu`.
|
||||||
|
@ -99,70 +120,6 @@ const myOverrides: TLUiOverrides = {
|
||||||
|
|
||||||
The `tools` object is a map of [TLUiToolItem](/reference/tldraw/TLUiToolItem)s, with each item keyed under its `id`.
|
The `tools` object is a map of [TLUiToolItem](/reference/tldraw/TLUiToolItem)s, with each item keyed under its `id`.
|
||||||
|
|
||||||
### Toolbar and Menus
|
|
||||||
|
|
||||||
The remaining overrides are for toolbar and the various menus: the main menu, actions menu, context menu, help menu, and the keyboard shortcuts menu.
|
|
||||||
|
|
||||||
Each of these overrides accepts a method that receives the default menu schema and returns a mutated version of that schema.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const myOverrides: TLUiOverrides = {
|
|
||||||
actions(editor, actions) {
|
|
||||||
// Create a new action or replace an existing one
|
|
||||||
actions['my-new-action'] = {
|
|
||||||
id: 'my-new-action',
|
|
||||||
label: 'My new action',
|
|
||||||
readonlyOk: true,
|
|
||||||
kbd: '$u',
|
|
||||||
onSelect(source: any) {
|
|
||||||
window.alert('My new action just happened!')
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return actions
|
|
||||||
},
|
|
||||||
contextMenu(editor, contextMenu, { actions }) {
|
|
||||||
const newMenuItem = menuItem(actions['my-new-action'])
|
|
||||||
const newMenuGroup = menuGroup('my-items', newMenuItem)
|
|
||||||
contextMenu.unshift(newMenuItem)
|
|
||||||
return contextMenu
|
|
||||||
},
|
|
||||||
menu(editor, menu, { actions }) {
|
|
||||||
// using the findMenuItem helper
|
|
||||||
const fileMenu = findMenuItem(menu, ['menu', 'file'])
|
|
||||||
if (fileMenu.type === 'submenu') {
|
|
||||||
// add the new item to the file menu's children
|
|
||||||
const newMenuItem = menuItem(actions['my-new-action'])
|
|
||||||
fileMenu.children.unshift(newMenuItem)
|
|
||||||
}
|
|
||||||
return menu
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
A menu schema is an array of either [submenus](/reference/tldraw/TLUiSubMenu), [groups](/reference/tldraw/TLUiMenuGroup), [items](/reference/tldraw/TLUiMenuItem), or [custom items](/reference/tldraw/TLUiCustomMenuItem). Each group or submenu may include any of the other types as its children.
|
|
||||||
|
|
||||||
The menu schema is stateful. Referencing atomic properties (such as computed values in the editor) will cause the menu to update when those values change. If you wish for a menu item to disappear from the menu, you can return `null` from the menu method. You can also provide additional options for each item, `disabled` or `checked`.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const myOverrides: TLUiOverrides = {
|
|
||||||
menu(editor, menu, { actions }) {
|
|
||||||
const selectedShapes = editor.getSelectedShapeIds().length
|
|
||||||
|
|
||||||
const newMenuGroup = menuGroup(
|
|
||||||
'my-actions',
|
|
||||||
selectedShapes > 0 ? menuItem(actions['action-a']) : null,
|
|
||||||
menuItem(actions['action-b'], { disabled: selectedShapes < 3 })
|
|
||||||
)
|
|
||||||
|
|
||||||
menu.unshift(newMenuGroup)
|
|
||||||
|
|
||||||
return menu
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
It's recommmended to explore the [default menu schema](https://github.com/tldraw/tldraw/blob/main/packages/tldraw/src/lib/ui/hooks/useMenuSchema.tsx) in order to understand how menu items work.
|
|
||||||
|
|
||||||
### Translations
|
### Translations
|
||||||
|
|
||||||
The `translations` method accepts a table of new translations. For example, if you wanted a tool to reference a key `"tools.card"`, then you should at minimum provide an english translation for this key.
|
The `translations` method accepts a table of new translations. For example, if you wanted a tool to reference a key `"tools.card"`, then you should at minimum provide an english translation for this key.
|
||||||
|
@ -176,23 +133,3 @@ const myOverrides: TLUiOverrides = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Events
|
|
||||||
|
|
||||||
The [Tldraw](?) component has a prop, `onUiEvent`, that the user interface will call when certain events occur.
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
function Example() {
|
|
||||||
function handleEvent(name, data) {
|
|
||||||
// do something with the event
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Tldraw onUiEvent={handleEvent} />
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `onUiEvent` callback is called with the name of the event as a string and an object with information about the event's source (e.g. `menu` or `context-menu`) and possibly other data specific to each event, such as the direction in an `align-shapes` event.
|
|
||||||
|
|
||||||
Note that `onUiEvent` is only called when interacting with the user interface. It is not called when running commands manually against the app, e.g. calling [Editor#alignShapes](?) will not call `onUiEvent`.
|
|
||||||
|
|
||||||
See the [tldraw repository](https://github.com/tldraw/tldraw/tree/main/apps/examples) for an example of how to customize tldraw's user interface.
|
|
||||||
|
|
|
@ -12,71 +12,64 @@ The tldraw SDK provides a really simple way to craft infinite canvas experiences
|
||||||
|
|
||||||
By the end of this guide you will have made something that looks like this:
|
By the end of this guide you will have made something that looks like this:
|
||||||
|
|
||||||
<Embed className="article__embed--quickstart" src="https://vite-template-five.vercel.app/" />
|
<Embed className="article__embed--quickstart" src="https://examples.tldraw.com/develop" />
|
||||||
|
|
||||||
|
### 1. Installation
|
||||||
|
|
||||||
<hr />
|
- Set up a React project however you normally do. [We recommend Vite](https://vitejs.dev/guide/#scaffolding-your-first-vite-project).
|
||||||
<ol className="ordered-list__quickstart">
|
- Install the tldraw library using this command:
|
||||||
<li>
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
- Set up a React project however you normally do. [We recommend Vite](https://vitejs.dev/guide/#scaffolding-your-first-vite-project).
|
```bash
|
||||||
- Install the tldraw library using this command:
|
npm install @tldraw/tldraw@beta
|
||||||
|
```
|
||||||
```bash
|
|
||||||
npm install tldraw@beta
|
|
||||||
```
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
### Import Styles
|
|
||||||
<br />
|
|
||||||
To import fonts and CSS for tldraw:
|
|
||||||
|
|
||||||
- Create or edit a css file called `index.css`
|
### 2. Import Styles
|
||||||
- Copy and paste this into the file:
|
|
||||||
```CSS
|
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&family=Roboto+Mono:wght@400;700&display=swap");
|
|
||||||
@import url("tldraw/tldraw.css");
|
|
||||||
|
|
||||||
body {
|
To import fonts and CSS for tldraw:
|
||||||
font-family: "Inter";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
### Render Tldraw Component
|
|
||||||
<br />
|
|
||||||
To render the Tldraw component
|
|
||||||
|
|
||||||
- Import the `<Tldraw />` component from `tldraw`
|
- Create or edit a css file called `index.css`
|
||||||
- Import the `index.css` CSS file from earlier
|
- Copy and paste this into the file:
|
||||||
- Wrap the Tldraw component in a `<div>` element with the style attribute set to: `{ position: 'fixed', inset: 0 }`
|
|
||||||
|
|
||||||
<p className="">This will render a full screen canvas:</p>
|
|
||||||
|
|
||||||
```javascript
|
```CSS
|
||||||
import { Tldraw } from "tldraw";
|
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@500;700;&display=swap");
|
||||||
import "./index.css";
|
@import url("@tldraw/tldraw/tldraw.css");
|
||||||
|
|
||||||
export default function App() {
|
body {
|
||||||
return (
|
font-family: "Inter";
|
||||||
<div style={{ position: 'fixed', inset: 0 }}>
|
}
|
||||||
<Tldraw />
|
```
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<hr />
|
### 3. Render Tldraw Component
|
||||||
|
|
||||||
### Next Steps
|
To render the Tldraw component
|
||||||
|
|
||||||
You did it! Now that you have your canvas working, you may be wondering: what next? You can try:
|
- Import the `<Tldraw />` component from `@tldraw/tldraw`
|
||||||
|
- Import the `index.css` CSS file from earlier
|
||||||
|
- Wrap the Tldraw component in a `<div>` element with the style attribute set to: `{ position: 'fixed', inset: 0 }`
|
||||||
|
|
||||||
|
This will render a full screen canvas:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { Tldraw } from "@tldraw/tldraw";
|
||||||
|
import "./index.css";
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<div style={{ position: 'fixed', inset: 0 }}>
|
||||||
|
<Tldraw />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
Now that you have your canvas working, you may be wondering: what next?
|
||||||
|
|
||||||
|
You can try:
|
||||||
|
|
||||||
- Giving the editor a makeover by [customizing the UI](/docs/user-interface)
|
- Giving the editor a makeover by [customizing the UI](/docs/user-interface)
|
||||||
- Adding your own [shapes](/docs/shapes) and [tools](/docs/tools)
|
- Adding your own [shapes](/docs/shapes) and [tools](/docs/tools)
|
||||||
- Providing collaboration using [multiplayer](https://github.com/tldraw/tldraw-yjs-example)
|
- Providing collaboration using [multiplayer](https://github.com/tldraw/tldraw-yjs-example)
|
||||||
|
|
||||||
We provide the above examples and more in our [examples section](/examples/basic/develop). Go build something creative and please do share it with us in our [#show-and-tell](https://discord.com/invite/SBBEVCA4PG) channel on Discord!
|
We provide the above examples and more in our [examples section](/examples). Go build something creative and please do share it with us in our [#show-and-tell](https://discord.com/invite/SBBEVCA4PG) channel on Discord!
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{
|
{
|
||||||
"id": "docs",
|
"id": "docs",
|
||||||
"title": "Learn tldraw",
|
"title": "Learn tldraw",
|
||||||
"description": "Developer documentation for tldraw.",
|
"description": "Learn to use the tldraw SDK.",
|
||||||
"categories": [],
|
"categories": [],
|
||||||
"sidebar_behavior": "show-links"
|
"sidebar_behavior": "show-links"
|
||||||
},
|
},
|
||||||
|
@ -58,7 +58,8 @@
|
||||||
"id": "Namespace",
|
"id": "Namespace",
|
||||||
"path": null
|
"path": null
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"hero": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "store",
|
"id": "store",
|
||||||
|
@ -93,7 +94,8 @@
|
||||||
"id": "Namespace",
|
"id": "Namespace",
|
||||||
"path": null
|
"path": null
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"hero": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "tldraw",
|
"id": "tldraw",
|
||||||
|
@ -128,7 +130,8 @@
|
||||||
"id": "Namespace",
|
"id": "Namespace",
|
||||||
"path": null
|
"path": null
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"hero": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "tlschema",
|
"id": "tlschema",
|
||||||
|
@ -163,7 +166,8 @@
|
||||||
"id": "Namespace",
|
"id": "Namespace",
|
||||||
"path": null
|
"path": null
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"hero": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "validate",
|
"id": "validate",
|
||||||
|
@ -198,9 +202,11 @@
|
||||||
"id": "Namespace",
|
"id": "Namespace",
|
||||||
"path": null
|
"path": null
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"hero": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sidebar_behavior": "reference"
|
"sidebar_behavior": "reference",
|
||||||
|
"hero": null
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
"dev": "concurrently \"NODE_ENV=development next dev --port=3001\" \"tsx ./watcher.ts\" --kill-others",
|
"dev": "concurrently \"NODE_ENV=development next dev --port=3001\" \"tsx ./watcher.ts\" --kill-others",
|
||||||
"next-dev": "next dev",
|
"next-dev": "next dev",
|
||||||
"lint": "yarn run -T tsx ../../scripts/lint.ts",
|
"lint": "yarn run -T tsx ../../scripts/lint.ts",
|
||||||
"build": "yarn create-api-markdown && yarn refresh-content && next build",
|
"build": "yarn create-api-markdown && yarn refresh-content && next build && yarn check-links",
|
||||||
"start": "yarn create-api-markdown && yarn refresh-content && next start",
|
"start": "yarn create-api-markdown && yarn refresh-content && next start",
|
||||||
"fetch-api-source": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/fetch-api-source.ts",
|
"fetch-api-source": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/fetch-api-source.ts",
|
||||||
"fetch-releases": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/fetch-releases.ts",
|
"fetch-releases": "yarn run -T tsx --tsconfig ./tsconfig.content.json ./scripts/fetch-releases.ts",
|
||||||
|
@ -54,7 +54,6 @@
|
||||||
"@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",
|
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^8.2.2",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
|
@ -87,5 +86,8 @@
|
||||||
"unist-util-visit": "^5.0.0",
|
"unist-util-visit": "^5.0.0",
|
||||||
"vectra": "^0.4.4",
|
"vectra": "^0.4.4",
|
||||||
"ws": "^8.16.0"
|
"ws": "^8.16.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"linkinator": "^6.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
apps/docs/public/tldraw_dev_dark.png
Normal file
BIN
apps/docs/public/tldraw_dev_dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
apps/docs/public/tldraw_dev_light.png
Normal file
BIN
apps/docs/public/tldraw_dev_light.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
|
@ -1,29 +1,25 @@
|
||||||
import { nicelog } from '@/utils/nicelog'
|
import { nicelog } from '@/utils/nicelog'
|
||||||
import blc from 'broken-link-checker'
|
import { check } from 'linkinator'
|
||||||
|
|
||||||
const IGNORED_URLS = ['https://twitter.com/tldraw', 'https://tldraw.com']
|
|
||||||
|
|
||||||
export async function checkBrokenLinks() {
|
export async function checkBrokenLinks() {
|
||||||
nicelog('Checking broken links...')
|
const results = await check({
|
||||||
const checked = new Set<string>()
|
path: 'http://localhost:3001',
|
||||||
const checker = new blc.SiteChecker(
|
recurse: true,
|
||||||
{
|
})
|
||||||
filterLevel: 1,
|
|
||||||
},
|
// All good
|
||||||
{
|
if (results.passed) return
|
||||||
link(result) {
|
|
||||||
if (IGNORED_URLS.includes(result.url.original)) return
|
// There seems to be a porblem
|
||||||
if (checked.has(result.url.resolved)) return
|
nicelog(
|
||||||
// nicelog('Checking', result.url.resolved.replace('http://localhost:3001', ''))
|
`𐄂 Broken links detected!\n\n` +
|
||||||
if (result.broken) {
|
results.links
|
||||||
nicelog(`BROKEN: ${result.url.resolved} on page ${result.base.resolved}`)
|
.filter((result) => result.state !== 'OK')
|
||||||
}
|
.map(
|
||||||
checked.add(result.url.resolved)
|
(result, i) =>
|
||||||
},
|
`${i + 1}.\t${result.url}\n\tFrom: ${result.parent}\n\tStatus: ${result.status}`
|
||||||
end() {
|
)
|
||||||
nicelog('done')
|
.join('\n\n') +
|
||||||
},
|
'\n\n'
|
||||||
}
|
|
||||||
)
|
)
|
||||||
checker.enqueue('http://localhost:3001/docs/assets', null)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ export async function createApiMarkdown() {
|
||||||
description: "Reference for the tldraw package's APIs (generated).",
|
description: "Reference for the tldraw package's APIs (generated).",
|
||||||
categories: [],
|
categories: [],
|
||||||
sidebar_behavior: 'reference',
|
sidebar_behavior: 'reference',
|
||||||
|
hero: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
const addedCategories = new Set<string>()
|
const addedCategories = new Set<string>()
|
||||||
|
@ -55,6 +56,7 @@ export async function createApiMarkdown() {
|
||||||
id: title,
|
id: title,
|
||||||
path: null,
|
path: null,
|
||||||
})),
|
})),
|
||||||
|
hero: null,
|
||||||
})
|
})
|
||||||
addedCategories.add(categoryName)
|
addedCategories.add(categoryName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,14 @@ const section: InputSection = {
|
||||||
title: 'Examples',
|
title: 'Examples',
|
||||||
description: 'Code recipes for bending tldraw to your will.',
|
description: 'Code recipes for bending tldraw to your will.',
|
||||||
categories: [
|
categories: [
|
||||||
{ id: 'basic', title: 'Getting Started', description: '', groups: [] },
|
{ id: 'basic', title: 'Getting Started', description: '', groups: [], hero: null },
|
||||||
{ id: 'ui', title: 'UI & Theming', description: '', groups: [] },
|
{ id: 'ui', title: 'UI & Theming', description: '', groups: [], hero: null },
|
||||||
{ id: 'shapes/tools', title: 'Shapes & Tools', description: '', groups: [] },
|
{ id: 'shapes/tools', title: 'Shapes & Tools', description: '', groups: [], hero: null },
|
||||||
{ id: 'data/assets', title: 'Data & Assets', description: '', groups: [] },
|
{ id: 'data/assets', title: 'Data & Assets', description: '', groups: [], hero: null },
|
||||||
{ id: 'editor-api', title: 'Editor API', description: '', groups: [] },
|
{ id: 'editor-api', title: 'Editor API', description: '', groups: [], hero: null },
|
||||||
{ id: 'collaboration', title: 'Collaboration', description: '', groups: [] },
|
{ id: 'collaboration', title: 'Collaboration', description: '', groups: [], hero: null },
|
||||||
],
|
],
|
||||||
|
hero: null,
|
||||||
sidebar_behavior: 'show-links',
|
sidebar_behavior: 'show-links',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,7 @@ export function generateSection(section: InputSection, articles: Articles, index
|
||||||
groups: [],
|
groups: [],
|
||||||
path: `/${section.id}/ucg`,
|
path: `/${section.id}/ucg`,
|
||||||
content: null,
|
content: null,
|
||||||
|
hero: null,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -188,6 +189,7 @@ export function generateSection(section: InputSection, articles: Articles, index
|
||||||
index: i + 1,
|
index: i + 1,
|
||||||
path: `/${section.id}/${inputCategory.id}`,
|
path: `/${section.id}/${inputCategory.id}`,
|
||||||
content: null,
|
content: null,
|
||||||
|
hero: null,
|
||||||
groups: inputCategory.groups.map(({ id }, i) => ({
|
groups: inputCategory.groups.map(({ id }, i) => ({
|
||||||
id,
|
id,
|
||||||
title: id,
|
title: id,
|
||||||
|
@ -210,6 +212,7 @@ export function generateSection(section: InputSection, articles: Articles, index
|
||||||
index,
|
index,
|
||||||
categories,
|
categories,
|
||||||
content: '',
|
content: '',
|
||||||
|
hero: section.hero ?? null,
|
||||||
path: `/${section.id}`,
|
path: `/${section.id}`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,7 +217,7 @@ async function addDocComment(result: Result, member: ApiItem) {
|
||||||
|
|
||||||
if (exampleBlocks.length) {
|
if (exampleBlocks.length) {
|
||||||
result.markdown += `\n\n`
|
result.markdown += `\n\n`
|
||||||
result.markdown += `##### Example\n\n`
|
result.markdown += `<ApiHeading>Example</ApiHeading>\n\n`
|
||||||
for (const example of exampleBlocks) {
|
for (const example of exampleBlocks) {
|
||||||
result.markdown += await MarkdownWriter.docNodeToMarkdown(member, example.content)
|
result.markdown += await MarkdownWriter.docNodeToMarkdown(member, example.content)
|
||||||
}
|
}
|
||||||
|
@ -393,7 +393,7 @@ function addTags(result: Result, member: ApiItem) {
|
||||||
tags.push('readonly')
|
tags.push('readonly')
|
||||||
}
|
}
|
||||||
tags.push(member.kind.toLowerCase())
|
tags.push(member.kind.toLowerCase())
|
||||||
result.markdown += `<Small>${tags.join(' ')}</Small>\n\n`
|
result.markdown += `<Small>${tags.filter((t) => t.toLowerCase() !== 'none').join(' ')}</Small>\n\n`
|
||||||
}
|
}
|
||||||
|
|
||||||
function addReferences(result: Result, member: ApiItem) {
|
function addReferences(result: Result, member: ApiItem) {
|
||||||
|
|
|
@ -19,13 +19,15 @@
|
||||||
--color-tint-5: rgb(144, 144, 144);
|
--color-tint-5: rgb(144, 144, 144);
|
||||||
--color-tint-6: rgb(81, 81, 81);
|
--color-tint-6: rgb(81, 81, 81);
|
||||||
|
|
||||||
|
--color-blockquote: rgb(242, 247, 255);
|
||||||
|
|
||||||
/* Light theme */
|
/* Light theme */
|
||||||
--color-text: #1d1d1d;
|
--color-text: #1d1d1d;
|
||||||
--color-text-secondary: #666;
|
--color-text-secondary: #666;
|
||||||
--color-background: #ffffff;
|
--color-background: #ffffff;
|
||||||
--color-contrast: #ffffff;
|
--color-contrast: #ffffff;
|
||||||
--color-accent: #2f80ed;
|
--color-accent: #2f80ed;
|
||||||
--color-footer-background: #212529;
|
--color-footer-background: hsl(240, 5%, 8%);
|
||||||
--color-footer-text: #fafafa;
|
--color-footer-text: #fafafa;
|
||||||
|
|
||||||
--shadow-small: 0px 0px 16px -2px rgba(0, 0, 0, 0.12), 0px 0px 4px 0px rgba(0, 0, 0, 0.12);
|
--shadow-small: 0px 0px 16px -2px rgba(0, 0, 0, 0.12), 0px 0px 4px 0px rgba(0, 0, 0, 0.12);
|
||||||
|
@ -47,7 +49,8 @@
|
||||||
--border-radius-menu: 4px;
|
--border-radius-menu: 4px;
|
||||||
|
|
||||||
/* Sizes */
|
/* Sizes */
|
||||||
--header-height: 72px;
|
--header-height: 80px;
|
||||||
|
--header-padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme='dark'] {
|
[data-theme='dark'] {
|
||||||
|
@ -57,7 +60,7 @@
|
||||||
--color-background: hsl(240, 5%, 8%);
|
--color-background: hsl(240, 5%, 8%);
|
||||||
--color-contrast: #000;
|
--color-contrast: #000;
|
||||||
--color-accent: #74b0ff;
|
--color-accent: #74b0ff;
|
||||||
--color-footer-background: #0d0d0d;
|
--color-footer-background: hsl(240, 5%, 8%);
|
||||||
--color-footer-text: #ccc;
|
--color-footer-text: #ccc;
|
||||||
|
|
||||||
--shadow-small: 0px 0px 16px -2px rgba(0, 0, 0, 0.52), 0px 0px 4px 0px rgba(0, 0, 0, 0.62);
|
--shadow-small: 0px 0px 16px -2px rgba(0, 0, 0, 0.52), 0px 0px 4px 0px rgba(0, 0, 0, 0.62);
|
||||||
|
@ -71,6 +74,8 @@
|
||||||
--color-tint-5: rgb(144, 144, 144);
|
--color-tint-5: rgb(144, 144, 144);
|
||||||
--color-tint-6: rgb(186, 186, 186);
|
--color-tint-6: rgb(186, 186, 186);
|
||||||
|
|
||||||
|
--color-blockquote: rgb(34, 47, 55);
|
||||||
|
|
||||||
/* Code colors */
|
/* Code colors */
|
||||||
--hl: #c8c5f1;
|
--hl: #c8c5f1;
|
||||||
--hl-0: #5c6370;
|
--hl-0: #5c6370;
|
||||||
|
@ -93,7 +98,7 @@
|
||||||
html {
|
html {
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
scroll-padding-top: var(--header-height);
|
scroll-padding-top: calc(var(--header-height) + var(--header-padding));
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -137,7 +142,7 @@ body {
|
||||||
z-index: 900;
|
z-index: 900;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
display: grid;
|
display: grid;
|
||||||
padding: 16px;
|
padding: 0px 16px;
|
||||||
grid-template-columns: 250px 1fr auto;
|
grid-template-columns: 250px 1fr auto;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -145,24 +150,31 @@ body {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout__header .lockup {
|
.layout__header__left img {
|
||||||
position: relative;
|
width: calc(136px);
|
||||||
width: calc(71px * (30 / 18));
|
height: auto;
|
||||||
height: calc(18px * (30 / 18));
|
|
||||||
background: currentColor;
|
|
||||||
color: var(--color-text);
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout__header__sections_and_socials {
|
.layout__header__links {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout__header__sections {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout__header__socials {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout_header__section {
|
.layout_header__section {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 8px 12px;
|
padding: 13px 12px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -172,7 +184,7 @@ body {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
content: '';
|
content: '';
|
||||||
inset: 7px 1px;
|
inset: 7px 2px;
|
||||||
background-color: var(--bg);
|
background-color: var(--bg);
|
||||||
border-radius: var(--border-radius-menu);
|
border-radius: var(--border-radius-menu);
|
||||||
}
|
}
|
||||||
|
@ -241,11 +253,11 @@ body {
|
||||||
background-color: currentColor;
|
background-color: currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
.article {
|
.main-content {
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: calc(100vh - 64px);
|
min-height: calc(100vh - 64px);
|
||||||
padding: 0px 0px 96px 0px;
|
padding: var(--header-padding) 0px 96px 0px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: visible;
|
overflow-y: visible;
|
||||||
|
@ -354,7 +366,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.article > h2 {
|
.article > h2 {
|
||||||
margin-top: 16px;
|
margin-top: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.article > p + h2 {
|
.article > p + h2 {
|
||||||
|
@ -468,9 +480,10 @@ body {
|
||||||
|
|
||||||
.article > blockquote {
|
.article > blockquote {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
margin: 20px 0px;
|
margin: 32px 0px;
|
||||||
padding-left: 16px;
|
padding: 16px;
|
||||||
border-left: 2px solid var(--color-tint-2);
|
border-radius: var(--border-radius-menu);
|
||||||
|
background-color: var(--color-blockquote);
|
||||||
}
|
}
|
||||||
|
|
||||||
.article pre {
|
.article pre {
|
||||||
|
@ -517,8 +530,7 @@ body {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.article ol h3,
|
.article ol h3 {
|
||||||
.article ol li::marker {
|
|
||||||
font-size: 1.17em;
|
font-size: 1.17em;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
}
|
}
|
||||||
|
@ -551,7 +563,6 @@ body {
|
||||||
|
|
||||||
.page-header > p {
|
.page-header > p {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.article table {
|
.article table {
|
||||||
|
@ -624,6 +635,7 @@ body {
|
||||||
.article__embed--quickstart {
|
.article__embed--quickstart {
|
||||||
aspect-ratio: 16 / 9;
|
aspect-ratio: 16 / 9;
|
||||||
min-height: 405px;
|
min-height: 405px;
|
||||||
|
margin: 32px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 520px) {
|
@media screen and (max-width: 520px) {
|
||||||
|
@ -649,8 +661,8 @@ body {
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
height: 40px;
|
padding-bottom: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
@ -675,7 +687,6 @@ body {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
color: var(--color-footer-text);
|
color: var(--color-footer-text);
|
||||||
border-top: 1px solid rgba(144, 144, 144, 0.28);
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,7 +792,7 @@ body {
|
||||||
align-self: start;
|
align-self: start;
|
||||||
top: var(--header-height);
|
top: var(--header-height);
|
||||||
margin-left: -12px;
|
margin-left: -12px;
|
||||||
padding: 24px 28px 120px 12px;
|
padding: var(--header-padding) 28px 120px 12px;
|
||||||
max-height: calc(100vh);
|
max-height: calc(100vh);
|
||||||
width: 290px;
|
width: 290px;
|
||||||
z-index: 800;
|
z-index: 800;
|
||||||
|
@ -815,7 +826,7 @@ body {
|
||||||
align-self: start;
|
align-self: start;
|
||||||
top: var(--header-height);
|
top: var(--header-height);
|
||||||
margin-left: -12px;
|
margin-left: -12px;
|
||||||
padding: 0px 12px 120px 28px;
|
padding: var(--header-padding) 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;
|
||||||
|
@ -934,18 +945,21 @@ body {
|
||||||
transition-delay: 0s;
|
transition-delay: 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__section__title {
|
.uppercase_title {
|
||||||
|
text-transform: uppercase;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__section__title {
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
position: relative;
|
position: relative;
|
||||||
letter-spacing: 0.5px;
|
padding-bottom: 4px;
|
||||||
height: 40px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
color: var(--color-text-secondary);
|
|
||||||
text-transform: uppercase;
|
|
||||||
--bg: transparent;
|
--bg: transparent;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
@ -958,7 +972,6 @@ body {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
color: var(--color-text-secondary);
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
@ -971,7 +984,6 @@ body {
|
||||||
.sidebar__sections__list > *:nth-last-of-type(n + 2) > .sidebar__list {
|
.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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
|
@ -1113,8 +1125,7 @@ body {
|
||||||
grid-gap: 40px;
|
grid-gap: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout__header .layout__header__sections_and_socials .layout_header__section,
|
.layout__header .NavigationMenuRoot {
|
||||||
.layout__header .layout__header__sections_and_socials .NavigationMenuRoot {
|
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1122,10 +1133,10 @@ body {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
padding: 12px 0px;
|
||||||
padding: 16px 0;
|
border-bottom: 1px solid var(--color-tint-2);
|
||||||
border-top: 1px solid var(--color-accent);
|
margin-bottom: 12px;
|
||||||
border-bottom: 1px solid var(--color-accent);
|
margin-left: -8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.NavigationMenuTrigger {
|
.NavigationMenuTrigger {
|
||||||
|
@ -1142,7 +1153,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout__header {
|
.layout__header {
|
||||||
grid-template-columns: auto auto;
|
grid-template-columns: auto 1fr;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,7 +1238,7 @@ body {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.article {
|
.main-content {
|
||||||
padding: 24px 16px 16px 16px;
|
padding: 24px 16px 16px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1288,6 +1299,14 @@ body {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layout__header__links {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout__header__sections {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.article__links__prev {
|
.article__links__prev {
|
||||||
border: none;
|
border: none;
|
||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
|
@ -1327,6 +1346,7 @@ html[data-theme='light'] .hero__dark {
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-example .sandpack {
|
.code-example .sandpack {
|
||||||
|
margin-top: 20px;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1358,12 +1378,12 @@ html[data-theme='light'] .hero__dark {
|
||||||
|
|
||||||
/* ------------------- Hero images ------------------ */
|
/* ------------------- Hero images ------------------ */
|
||||||
|
|
||||||
.hero__images {
|
.hero__images__wrapper {
|
||||||
margin: 32px 0px;
|
padding-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero_images > a {
|
.hero__images {
|
||||||
margin: 0px;
|
margin: 32px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.article__image {
|
.article__image {
|
||||||
|
@ -1496,3 +1516,83 @@ html[data-theme='light'] .hero__dark {
|
||||||
.scroll-light::-webkit-scrollbar-thumb:hover {
|
.scroll-light::-webkit-scrollbar-thumb:hover {
|
||||||
background-color: rgba(144, 144, 144);
|
background-color: rgba(144, 144, 144);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------ Landing page ------------------ */
|
||||||
|
|
||||||
|
.landing {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__inner {
|
||||||
|
width: fit-content;
|
||||||
|
max-width: 960px;
|
||||||
|
height: fit-content;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__logo img {
|
||||||
|
width: 200px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme='dark'] .logo-light {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme='light'] .logo-dark {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__blurb {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: center;
|
||||||
|
margin: 12px 0 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__links {
|
||||||
|
list-style-type: none;
|
||||||
|
display: flex;
|
||||||
|
gap: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__links a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--color-text);
|
||||||
|
padding: 16px 16px;
|
||||||
|
position: relative;
|
||||||
|
font-size: inherit;
|
||||||
|
font-family: inherit;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing__links a::after {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
content: '';
|
||||||
|
top: 8px;
|
||||||
|
bottom: 8px;
|
||||||
|
left: 1px;
|
||||||
|
right: 1px;
|
||||||
|
background-color: var(--color-tint-1);
|
||||||
|
border-radius: var(--border-radius-menu);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
.landing__links a:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,3 @@
|
||||||
.article__api-heading {
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--color-tint-5);
|
|
||||||
letter-spacing: 0.07em;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.article__parameters-table {
|
.article__parameters-table {
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ export type InputCategory = {
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
groups: InputGroup[]
|
groups: InputGroup[]
|
||||||
|
hero: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InputSection = {
|
export type InputSection = {
|
||||||
|
@ -10,6 +11,7 @@ export type InputSection = {
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
categories: InputCategory[]
|
categories: InputCategory[]
|
||||||
|
hero: string | null
|
||||||
sidebar_behavior: 'show-links' | 'show-title' | 'hidden' | 'reference'
|
sidebar_behavior: 'show-links' | 'show-title' | 'hidden' | 'reference'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +58,8 @@ export interface Section extends ContentPage {
|
||||||
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' | 'hidden' | 'reference'
|
sidebar_behavior: 'show-links' | 'show-title' | 'hidden' | 'reference'
|
||||||
|
/** The section's hero image (optional). */
|
||||||
|
hero: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Category extends ContentPage {
|
export interface Category extends ContentPage {
|
||||||
|
@ -66,6 +70,8 @@ export interface Category extends ContentPage {
|
||||||
index: number
|
index: number
|
||||||
/** The category's groups */
|
/** The category's groups */
|
||||||
groups: Group[]
|
groups: Group[]
|
||||||
|
/** The category's hero image (optional). */
|
||||||
|
hero: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Group extends ContentPage {
|
export interface Group extends ContentPage {
|
||||||
|
@ -179,7 +185,6 @@ 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
|
||||||
|
|
|
@ -1400,7 +1400,136 @@ export const TldrawSelectionBackground: ({ bounds, rotation }: TLSelectionBackgr
|
||||||
export const TldrawSelectionForeground: MemoExoticComponent<({ bounds, rotation, }: TLSelectionForegroundProps) => JSX_2.Element | null>;
|
export const TldrawSelectionForeground: MemoExoticComponent<({ bounds, rotation, }: TLSelectionForegroundProps) => JSX_2.Element | null>;
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export const TldrawUi: React_2.NamedExoticComponent<TldrawUiProps>;
|
export const TldrawUi: React_2.NamedExoticComponent<{
|
||||||
|
children?: any;
|
||||||
|
hideUi?: boolean | undefined;
|
||||||
|
components?: Partial<{
|
||||||
|
ContextMenu: null | React_2.ComponentType<TLUiContextMenuProps>;
|
||||||
|
ActionsMenu: null | React_2.ComponentType<TLUiActionsMenuProps>;
|
||||||
|
HelpMenu: null | React_2.ComponentType<TLUiHelpMenuProps>;
|
||||||
|
ZoomMenu: null | React_2.ComponentType<TLUiZoomMenuProps>;
|
||||||
|
MainMenu: null | React_2.ComponentType<TLUiMainMenuProps>;
|
||||||
|
Minimap: null | React_2.ComponentType;
|
||||||
|
StylePanel: null | React_2.ComponentType<TLUiStylePanelProps>;
|
||||||
|
PageMenu: null | React_2.ComponentType;
|
||||||
|
NavigationPanel: null | React_2.ComponentType;
|
||||||
|
Toolbar: null | React_2.ComponentType;
|
||||||
|
KeyboardShortcutsDialog: null | React_2.ComponentType<TLUiKeyboardShortcutsDialogProps>;
|
||||||
|
QuickActions: null | React_2.ComponentType<TLUiQuickActionsProps>;
|
||||||
|
HelperButtons: null | React_2.ComponentType<TLUiHelperButtonsProps>;
|
||||||
|
DebugMenu: null | React_2.ComponentType;
|
||||||
|
MenuPanel: null | React_2.ComponentType;
|
||||||
|
TopPanel: null | React_2.ComponentType;
|
||||||
|
SharePanel: null | React_2.ComponentType;
|
||||||
|
}> | undefined;
|
||||||
|
renderDebugMenuItems?: (() => React_2.ReactNode) | undefined;
|
||||||
|
assetUrls?: (RecursivePartial<TLUiAssetUrls> & RecursivePartial<TLUiAssetUrls>) | undefined;
|
||||||
|
overrides?: Partial<{
|
||||||
|
actions: TLUiOverride<TLUiActionsContextType, {
|
||||||
|
addToast: (toast: Omit<TLUiToast, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
removeToast: (id: string) => string;
|
||||||
|
clearToasts: () => void;
|
||||||
|
addDialog: (dialog: Omit<TLUiDialog, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
clearDialogs: () => void;
|
||||||
|
removeDialog: (id: string) => string;
|
||||||
|
updateDialog: (id: string, newDialogData: Partial<TLUiDialog>) => string;
|
||||||
|
msg: (id?: string | undefined) => string;
|
||||||
|
isMobile: boolean;
|
||||||
|
}>;
|
||||||
|
toolbar: TLUiOverride<TLUiToolbarSchemaContextType, {
|
||||||
|
tools: TLUiToolsContextType;
|
||||||
|
} & {
|
||||||
|
addToast: (toast: Omit<TLUiToast, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
removeToast: (id: string) => string;
|
||||||
|
clearToasts: () => void;
|
||||||
|
addDialog: (dialog: Omit<TLUiDialog, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
clearDialogs: () => void;
|
||||||
|
removeDialog: (id: string) => string;
|
||||||
|
updateDialog: (id: string, newDialogData: Partial<TLUiDialog>) => string;
|
||||||
|
msg: (id?: string | undefined) => string;
|
||||||
|
isMobile: boolean;
|
||||||
|
}>;
|
||||||
|
tools: TLUiOverride<TLUiToolsContextType, {
|
||||||
|
insertMedia: () => void;
|
||||||
|
} & {
|
||||||
|
addToast: (toast: Omit<TLUiToast, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
removeToast: (id: string) => string;
|
||||||
|
clearToasts: () => void;
|
||||||
|
addDialog: (dialog: Omit<TLUiDialog, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
clearDialogs: () => void;
|
||||||
|
removeDialog: (id: string) => string;
|
||||||
|
updateDialog: (id: string, newDialogData: Partial<TLUiDialog>) => string;
|
||||||
|
msg: (id?: string | undefined) => string;
|
||||||
|
isMobile: boolean;
|
||||||
|
}>;
|
||||||
|
translations: Record<string, Record<string, string>> | undefined;
|
||||||
|
}> | Partial<{
|
||||||
|
actions: TLUiOverride<TLUiActionsContextType, {
|
||||||
|
addToast: (toast: Omit<TLUiToast, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
removeToast: (id: string) => string;
|
||||||
|
clearToasts: () => void;
|
||||||
|
addDialog: (dialog: Omit<TLUiDialog, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
clearDialogs: () => void;
|
||||||
|
removeDialog: (id: string) => string;
|
||||||
|
updateDialog: (id: string, newDialogData: Partial<TLUiDialog>) => string;
|
||||||
|
msg: (id?: string | undefined) => string;
|
||||||
|
isMobile: boolean;
|
||||||
|
}>;
|
||||||
|
toolbar: TLUiOverride<TLUiToolbarSchemaContextType, {
|
||||||
|
tools: TLUiToolsContextType;
|
||||||
|
} & {
|
||||||
|
addToast: (toast: Omit<TLUiToast, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
removeToast: (id: string) => string;
|
||||||
|
clearToasts: () => void;
|
||||||
|
addDialog: (dialog: Omit<TLUiDialog, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
clearDialogs: () => void;
|
||||||
|
removeDialog: (id: string) => string;
|
||||||
|
updateDialog: (id: string, newDialogData: Partial<TLUiDialog>) => string;
|
||||||
|
msg: (id?: string | undefined) => string;
|
||||||
|
isMobile: boolean;
|
||||||
|
}>;
|
||||||
|
tools: TLUiOverride<TLUiToolsContextType, {
|
||||||
|
insertMedia: () => void;
|
||||||
|
} & {
|
||||||
|
addToast: (toast: Omit<TLUiToast, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
removeToast: (id: string) => string;
|
||||||
|
clearToasts: () => void;
|
||||||
|
addDialog: (dialog: Omit<TLUiDialog, "id"> & {
|
||||||
|
id?: string | undefined;
|
||||||
|
}) => string;
|
||||||
|
clearDialogs: () => void;
|
||||||
|
removeDialog: (id: string) => string;
|
||||||
|
updateDialog: (id: string, newDialogData: Partial<TLUiDialog>) => string;
|
||||||
|
msg: (id?: string | undefined) => string;
|
||||||
|
isMobile: boolean;
|
||||||
|
}>;
|
||||||
|
translations: Record<string, Record<string, string>> | undefined;
|
||||||
|
}>[] | undefined;
|
||||||
|
onUiEvent?: TLUiEventHandler | undefined;
|
||||||
|
forceMobile?: boolean | undefined;
|
||||||
|
}>;
|
||||||
|
|
||||||
// @public
|
// @public
|
||||||
export interface TldrawUiBaseProps {
|
export interface TldrawUiBaseProps {
|
||||||
|
@ -1518,7 +1647,7 @@ export function TldrawUiPopoverContent({ side, children, align, sideOffset, alig
|
||||||
export function TldrawUiPopoverTrigger({ children }: TLUiPopoverTriggerProps): JSX_2.Element;
|
export function TldrawUiPopoverTrigger({ children }: TLUiPopoverTriggerProps): JSX_2.Element;
|
||||||
|
|
||||||
// @public
|
// @public
|
||||||
export type TldrawUiProps = TldrawUiBaseProps & TldrawUiContextProviderProps;
|
export type TldrawUiProps = Expand<TldrawUiBaseProps & TldrawUiContextProviderProps>;
|
||||||
|
|
||||||
// @internal (undocumented)
|
// @internal (undocumented)
|
||||||
export const TldrawUiSlider: NamedExoticComponent<TLUiSliderProps>;
|
export const TldrawUiSlider: NamedExoticComponent<TLUiSliderProps>;
|
||||||
|
|
|
@ -16204,16 +16204,808 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": "<"
|
"text": "<{\n children?: any;\n hideUi?: boolean | undefined;\n components?: "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Reference",
|
"kind": "Reference",
|
||||||
"text": "TldrawUiProps",
|
"text": "Partial",
|
||||||
"canonicalReference": "tldraw!TldrawUiProps:type"
|
"canonicalReference": "!Partial:type"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": ">"
|
"text": "<{\n ContextMenu: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"../..\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiContextMenuProps",
|
||||||
|
"canonicalReference": "tldraw!TLUiContextMenuProps:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">;\n ActionsMenu: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"../..\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiActionsMenuProps",
|
||||||
|
"canonicalReference": "tldraw!TLUiActionsMenuProps:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">;\n HelpMenu: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"../..\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiHelpMenuProps",
|
||||||
|
"canonicalReference": "tldraw!TLUiHelpMenuProps:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">;\n ZoomMenu: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"../..\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiZoomMenuProps",
|
||||||
|
"canonicalReference": "tldraw!TLUiZoomMenuProps:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">;\n MainMenu: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"../..\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiMainMenuProps",
|
||||||
|
"canonicalReference": "tldraw!TLUiMainMenuProps:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">;\n Minimap: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n StylePanel: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"../..\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiStylePanelProps",
|
||||||
|
"canonicalReference": "tldraw!TLUiStylePanelProps:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">;\n PageMenu: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n NavigationPanel: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n Toolbar: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n KeyboardShortcutsDialog: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"../..\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiKeyboardShortcutsDialogProps",
|
||||||
|
"canonicalReference": "tldraw!TLUiKeyboardShortcutsDialogProps:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">;\n QuickActions: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"../..\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiQuickActionsProps",
|
||||||
|
"canonicalReference": "tldraw!TLUiQuickActionsProps:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">;\n HelperButtons: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"../..\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiHelperButtonsProps",
|
||||||
|
"canonicalReference": "tldraw!TLUiHelperButtonsProps:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">;\n DebugMenu: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n MenuPanel: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n TopPanel: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n SharePanel: null | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ComponentType",
|
||||||
|
"canonicalReference": "@types/react!React.ComponentType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n }> | undefined;\n renderDebugMenuItems?: (() => "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "React.ReactNode",
|
||||||
|
"canonicalReference": "@types/react!React.ReactNode:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ") | undefined;\n assetUrls?: (import(\"@tldraw/editor\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "RecursivePartial",
|
||||||
|
"canonicalReference": "@tldraw/utils!RecursivePartial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./assetUrls\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiAssetUrls",
|
||||||
|
"canonicalReference": "tldraw!~TLUiAssetUrls:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "> & import(\"@tldraw/editor\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "RecursivePartial",
|
||||||
|
"canonicalReference": "@tldraw/utils!RecursivePartial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./assetUrls\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiAssetUrls",
|
||||||
|
"canonicalReference": "tldraw!~TLUiAssetUrls:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">) | undefined;\n overrides?: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Partial",
|
||||||
|
"canonicalReference": "!Partial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<{\n actions: import(\"./overrides\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiOverride",
|
||||||
|
"canonicalReference": "tldraw!~TLUiOverride:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/actions\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiActionsContextType",
|
||||||
|
"canonicalReference": "tldraw!TLUiActionsContextType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", {\n addToast: (toast: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/toasts\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToast",
|
||||||
|
"canonicalReference": "tldraw!TLUiToast:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n removeToast: (id: string) => string;\n clearToasts: () => void;\n addDialog: (dialog: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n clearDialogs: () => void;\n removeDialog: (id: string) => string;\n updateDialog: (id: string, newDialogData: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Partial",
|
||||||
|
"canonicalReference": "!Partial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">) => string;\n msg: (id?: string | undefined) => string;\n isMobile: boolean;\n }>;\n toolbar: import(\"./overrides\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiOverride",
|
||||||
|
"canonicalReference": "tldraw!~TLUiOverride:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./hooks/useToolbarSchema\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToolbarSchemaContextType",
|
||||||
|
"canonicalReference": "tldraw!TLUiToolbarSchemaContextType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", {\n tools: import(\"./hooks/useTools\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToolsContextType",
|
||||||
|
"canonicalReference": "tldraw!TLUiToolsContextType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n } & {\n addToast: (toast: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/toasts\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToast",
|
||||||
|
"canonicalReference": "tldraw!TLUiToast:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n removeToast: (id: string) => string;\n clearToasts: () => void;\n addDialog: (dialog: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n clearDialogs: () => void;\n removeDialog: (id: string) => string;\n updateDialog: (id: string, newDialogData: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Partial",
|
||||||
|
"canonicalReference": "!Partial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">) => string;\n msg: (id?: string | undefined) => string;\n isMobile: boolean;\n }>;\n tools: import(\"./overrides\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiOverride",
|
||||||
|
"canonicalReference": "tldraw!~TLUiOverride:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./hooks/useTools\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToolsContextType",
|
||||||
|
"canonicalReference": "tldraw!TLUiToolsContextType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", {\n insertMedia: () => void;\n } & {\n addToast: (toast: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/toasts\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToast",
|
||||||
|
"canonicalReference": "tldraw!TLUiToast:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n removeToast: (id: string) => string;\n clearToasts: () => void;\n addDialog: (dialog: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n clearDialogs: () => void;\n removeDialog: (id: string) => string;\n updateDialog: (id: string, newDialogData: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Partial",
|
||||||
|
"canonicalReference": "!Partial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">) => string;\n msg: (id?: string | undefined) => string;\n isMobile: boolean;\n }>;\n translations: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Record",
|
||||||
|
"canonicalReference": "!Record:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<string, "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Record",
|
||||||
|
"canonicalReference": "!Record:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<string, string>> | undefined;\n }> | "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Partial",
|
||||||
|
"canonicalReference": "!Partial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<{\n actions: import(\"./overrides\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiOverride",
|
||||||
|
"canonicalReference": "tldraw!~TLUiOverride:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/actions\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiActionsContextType",
|
||||||
|
"canonicalReference": "tldraw!TLUiActionsContextType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", {\n addToast: (toast: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/toasts\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToast",
|
||||||
|
"canonicalReference": "tldraw!TLUiToast:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n removeToast: (id: string) => string;\n clearToasts: () => void;\n addDialog: (dialog: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n clearDialogs: () => void;\n removeDialog: (id: string) => string;\n updateDialog: (id: string, newDialogData: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Partial",
|
||||||
|
"canonicalReference": "!Partial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">) => string;\n msg: (id?: string | undefined) => string;\n isMobile: boolean;\n }>;\n toolbar: import(\"./overrides\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiOverride",
|
||||||
|
"canonicalReference": "tldraw!~TLUiOverride:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./hooks/useToolbarSchema\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToolbarSchemaContextType",
|
||||||
|
"canonicalReference": "tldraw!TLUiToolbarSchemaContextType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", {\n tools: import(\"./hooks/useTools\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToolsContextType",
|
||||||
|
"canonicalReference": "tldraw!TLUiToolsContextType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ";\n } & {\n addToast: (toast: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/toasts\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToast",
|
||||||
|
"canonicalReference": "tldraw!TLUiToast:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n removeToast: (id: string) => string;\n clearToasts: () => void;\n addDialog: (dialog: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n clearDialogs: () => void;\n removeDialog: (id: string) => string;\n updateDialog: (id: string, newDialogData: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Partial",
|
||||||
|
"canonicalReference": "!Partial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">) => string;\n msg: (id?: string | undefined) => string;\n isMobile: boolean;\n }>;\n tools: import(\"./overrides\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiOverride",
|
||||||
|
"canonicalReference": "tldraw!~TLUiOverride:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./hooks/useTools\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToolsContextType",
|
||||||
|
"canonicalReference": "tldraw!TLUiToolsContextType:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", {\n insertMedia: () => void;\n } & {\n addToast: (toast: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/toasts\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiToast",
|
||||||
|
"canonicalReference": "tldraw!TLUiToast:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n removeToast: (id: string) => string;\n clearToasts: () => void;\n addDialog: (dialog: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Omit",
|
||||||
|
"canonicalReference": "!Omit:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ", \"id\"> & {\n id?: string | undefined;\n }) => string;\n clearDialogs: () => void;\n removeDialog: (id: string) => string;\n updateDialog: (id: string, newDialogData: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Partial",
|
||||||
|
"canonicalReference": "!Partial:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<import(\"./context/dialogs\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiDialog",
|
||||||
|
"canonicalReference": "tldraw!TLUiDialog:interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">) => string;\n msg: (id?: string | undefined) => string;\n isMobile: boolean;\n }>;\n translations: "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Record",
|
||||||
|
"canonicalReference": "!Record:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<string, "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Record",
|
||||||
|
"canonicalReference": "!Record:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<string, string>> | undefined;\n }>[] | undefined;\n onUiEvent?: import(\"./context/events\")."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "TLUiEventHandler",
|
||||||
|
"canonicalReference": "tldraw!TLUiEventHandler:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": " | undefined;\n forceMobile?: boolean | undefined;\n}>"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fileUrlPath": "packages/tldraw/src/lib/ui/TldrawUi.tsx",
|
"fileUrlPath": "packages/tldraw/src/lib/ui/TldrawUi.tsx",
|
||||||
|
@ -16222,7 +17014,7 @@
|
||||||
"name": "TldrawUi",
|
"name": "TldrawUi",
|
||||||
"variableTypeTokenRange": {
|
"variableTypeTokenRange": {
|
||||||
"startIndex": 1,
|
"startIndex": 1,
|
||||||
"endIndex": 5
|
"endIndex": 181
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -18325,12 +19117,21 @@
|
||||||
{
|
{
|
||||||
"kind": "TypeAlias",
|
"kind": "TypeAlias",
|
||||||
"canonicalReference": "tldraw!TldrawUiProps:type",
|
"canonicalReference": "tldraw!TldrawUiProps:type",
|
||||||
"docComment": "/**\n * Props for the {@link tldraw#Tldraw} and {@link TldrawUi} components.\n *\n * @public\n */\n",
|
"docComment": "/**\n * Props for the {@link @tldraw/tldraw#Tldraw} and {@link TldrawUi} components.\n *\n * @public\n */\n",
|
||||||
"excerptTokens": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": "export type TldrawUiProps = "
|
"text": "export type TldrawUiProps = "
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"kind": "Reference",
|
||||||
|
"text": "Expand",
|
||||||
|
"canonicalReference": "@tldraw/utils!Expand:type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": "<"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "Reference",
|
"kind": "Reference",
|
||||||
"text": "TldrawUiBaseProps",
|
"text": "TldrawUiBaseProps",
|
||||||
|
@ -18345,6 +19146,10 @@
|
||||||
"text": "TldrawUiContextProviderProps",
|
"text": "TldrawUiContextProviderProps",
|
||||||
"canonicalReference": "tldraw!TldrawUiContextProviderProps:interface"
|
"canonicalReference": "tldraw!TldrawUiContextProviderProps:interface"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"kind": "Content",
|
||||||
|
"text": ">"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": ";"
|
"text": ";"
|
||||||
|
@ -18355,7 +19160,7 @@
|
||||||
"name": "TldrawUiProps",
|
"name": "TldrawUiProps",
|
||||||
"typeTokenRange": {
|
"typeTokenRange": {
|
||||||
"startIndex": 1,
|
"startIndex": 1,
|
||||||
"endIndex": 4
|
"endIndex": 7
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ToastProvider } from '@radix-ui/react-toast'
|
import { ToastProvider } from '@radix-ui/react-toast'
|
||||||
import { useEditor, useValue } from '@tldraw/editor'
|
import { Expand, useEditor, useValue } from '@tldraw/editor'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import React, { ReactNode } from 'react'
|
import React, { ReactNode } from 'react'
|
||||||
import { TLUiAssetUrlOverrides } from './assetUrls'
|
import { TLUiAssetUrlOverrides } from './assetUrls'
|
||||||
|
@ -23,13 +23,6 @@ import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts'
|
||||||
import { useReadonly } from './hooks/useReadonly'
|
import { useReadonly } from './hooks/useReadonly'
|
||||||
import { useTranslation } from './hooks/useTranslation/useTranslation'
|
import { useTranslation } from './hooks/useTranslation/useTranslation'
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the {@link tldraw#Tldraw} and {@link TldrawUi} components.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export type TldrawUiProps = TldrawUiBaseProps & TldrawUiContextProviderProps
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base props for the {@link tldraw#Tldraw} and {@link TldrawUi} components.
|
* Base props for the {@link tldraw#Tldraw} and {@link TldrawUi} components.
|
||||||
*
|
*
|
||||||
|
@ -60,6 +53,13 @@ export interface TldrawUiBaseProps {
|
||||||
assetUrls?: TLUiAssetUrlOverrides
|
assetUrls?: TLUiAssetUrlOverrides
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Props for the {@link @tldraw/tldraw#Tldraw} and {@link TldrawUi} components.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export type TldrawUiProps = Expand<TldrawUiBaseProps & TldrawUiContextProviderProps>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue