diff --git a/README.md b/README.md index 5d320b38e..a8fb6e4ab 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@
- - tldraw + + tldraw
diff --git a/apps/examples/package.json b/apps/examples/package.json index 08785acda..d9aa060d5 100644 --- a/apps/examples/package.json +++ b/apps/examples/package.json @@ -39,6 +39,7 @@ "@tldraw/assets": "workspace:*", "@tldraw/tldraw": "workspace:*", "@vercel/analytics": "^1.0.1", + "classnames": "^2.3.2", "lazyrepo": "0.0.0-alpha.27", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -47,6 +48,10 @@ }, "devDependencies": { "@vitejs/plugin-react": "^4.2.0", - "dotenv": "^16.0.3" + "dotenv": "^16.0.3", + "remark": "^15.0.1", + "remark-frontmatter": "^5.0.0", + "remark-html": "^16.0.1", + "vfile-matter": "^5.0.0" } } diff --git a/apps/examples/src/ExamplePage.tsx b/apps/examples/src/ExamplePage.tsx new file mode 100644 index 000000000..626917578 --- /dev/null +++ b/apps/examples/src/ExamplePage.tsx @@ -0,0 +1,79 @@ +import { assert, assertExists } from '@tldraw/tldraw' +import { useEffect, useRef } from 'react' +import { Link } from 'react-router-dom' +import ExamplesTldrawLogo from './components/ExamplesTldrawLogo' +import { ListLink } from './components/ListLink' +import { Example, examples } from './examples' + +export function ExamplePage({ + example, + children, +}: { + example: Example + children: React.ReactNode +}) { + const scrollElRef = useRef(null) + const activeElRef = useRef(null) + const isFirstScroll = useRef(true) + + useEffect(() => { + const frame = requestAnimationFrame(() => { + if (activeElRef.current) { + const scrollEl = assertExists(scrollElRef.current) + const activeEl = activeElRef.current + assert(activeEl.offsetParent === scrollEl) + + const isScrolledIntoView = + activeEl.offsetTop >= scrollEl.scrollTop && + activeEl.offsetTop + activeEl.offsetHeight <= scrollEl.scrollTop + scrollEl.offsetHeight + + if (!isScrolledIntoView) { + activeEl.scrollIntoView({ + behavior: isFirstScroll.current ? 'auto' : 'smooth', + block: isFirstScroll.current ? 'start' : 'center', + }) + } + isFirstScroll.current = false + } + }) + return () => cancelAnimationFrame(frame) + }, [example]) + + return ( +
+
+ + examples + +
    + {examples + .filter((e) => !e.hide) + .filter((e) => e.order !== null) + .map((e) => ( + + ))} +
  • +
    +
  • + {examples + .filter((e) => !e.hide) + .filter((e) => e.order === null) + .map((e) => ( + + ))} +
+
+
{children}
+
+ ) +} diff --git a/apps/examples/src/HomePage.tsx b/apps/examples/src/HomePage.tsx new file mode 100644 index 000000000..011c7689a --- /dev/null +++ b/apps/examples/src/HomePage.tsx @@ -0,0 +1,35 @@ +import ExamplesTldrawLogo from './components/ExamplesTldrawLogo' +import { ListLink } from './components/ListLink' +import { examples } from './examples' + +export function HomePage() { + return ( +
+
+
+ examples +
+

+ See docs at tldraw.dev +

+
+
    + {examples + .filter((example) => !example.hide) + .filter((example) => example.order !== null) + .map((example) => ( + + ))} +
+
+
    + {examples + .filter((example) => !example.hide) + .filter((example) => example.order === null) + .map((example) => ( + + ))} +
+
+ ) +} diff --git a/apps/examples/src/components/Icons.tsx b/apps/examples/src/components/Icons.tsx new file mode 100644 index 000000000..94c04b58f --- /dev/null +++ b/apps/examples/src/components/Icons.tsx @@ -0,0 +1,13 @@ +export function StandaloneIcon(props: React.SVGProps) { + return ( + + + + ) +} diff --git a/apps/examples/src/components/ListLink.tsx b/apps/examples/src/components/ListLink.tsx index 1ac6854b0..9cee389df 100644 --- a/apps/examples/src/components/ListLink.tsx +++ b/apps/examples/src/components/ListLink.tsx @@ -1,14 +1,94 @@ +import classNames from 'classnames' +import { ForwardedRef, forwardRef, useEffect, useId, useLayoutEffect, useRef } from 'react' import { Link } from 'react-router-dom' +import { Example } from '../examples' +import { useMergedRefs } from '../hooks/useMegedRefs' +import { StandaloneIcon } from './Icons' +import { Markdown } from './Markdown' -export interface ListLinkProps { - title: string - route: string -} +export const ListLink = forwardRef(function ListLink( + { + example, + isActive, + showDescription, + }: { example: Example; isActive?: boolean; showDescription?: boolean }, + ref: ForwardedRef +) { + const id = useId() + const containerRef = useRef(null) + const wasActiveRef = useRef(isActive) + useEffect(() => { + wasActiveRef.current = isActive + }, [isActive]) + + const heightBefore = + wasActiveRef.current !== isActive ? containerRef.current?.offsetHeight : undefined + + useLayoutEffect(() => { + if (heightBefore !== undefined && containerRef.current) { + containerRef.current.animate( + [{ height: heightBefore + 'px' }, { height: containerRef.current.offsetHeight + 'px' }], + { + duration: 120, + easing: 'ease-out', + fill: 'backwards', + delay: 100, + } + ) + } + }, [heightBefore]) + + const mainDetails = ( + <> +

+ {example.title} + {isActive && ( + + + + )} +

+ {showDescription && } + + ) + + // TODO: re-enable code sandbox links + // const codeSandboxPath = encodeURIComponent( + // `/src/examples${example.path}${example.componentFile.replace(/^\./, '')}` + // ) + const extraDetails = ( + + ) -export function ListLink({ title, route }: ListLinkProps) { return ( -
  • - {title} +
  • + {!isActive && ( + + )} + {mainDetails} + {extraDetails}
  • ) -} +}) diff --git a/apps/examples/src/components/Markdown.tsx b/apps/examples/src/components/Markdown.tsx new file mode 100644 index 000000000..7a4a0017f --- /dev/null +++ b/apps/examples/src/components/Markdown.tsx @@ -0,0 +1,16 @@ +import classNames from 'classnames' + +export function Markdown({ + sanitizedHtml, + className = '', +}: { + sanitizedHtml: string + className?: string +}) { + return ( +
    + ) +} diff --git a/apps/examples/src/components/Spinner.tsx b/apps/examples/src/components/Spinner.tsx new file mode 100644 index 000000000..5aa781f1a --- /dev/null +++ b/apps/examples/src/components/Spinner.tsx @@ -0,0 +1,19 @@ +export function Spinner(props: React.SVGProps) { + return ( + + + + + + + + + ) +} diff --git a/apps/examples/src/examples.tsx b/apps/examples/src/examples.tsx new file mode 100644 index 000000000..7c3f4dc49 --- /dev/null +++ b/apps/examples/src/examples.tsx @@ -0,0 +1,28 @@ +import { ComponentType } from 'react' + +export type Example = { + title: string + description: string + details: string + path: string + codeUrl: string + hide: boolean + order: number | null + componentFile: string + loadComponent: () => Promise +} + +export const examples = ( + Object.values(import.meta.glob('./examples/*/README.md', { eager: true })) as Example[] +).sort((a, b) => { + // sort by order then title: + if (a.order === b.order) { + return a.title.localeCompare(b.title) + } else if (a.order === null) { + return 1 + } else if (b.order === null) { + return -1 + } else { + return a.order - b.order + } +}) diff --git a/apps/examples/src/examples/APIExample.tsx b/apps/examples/src/examples/api/APIExample.tsx similarity index 100% rename from apps/examples/src/examples/APIExample.tsx rename to apps/examples/src/examples/api/APIExample.tsx diff --git a/apps/examples/src/examples/api/README.md b/apps/examples/src/examples/api/README.md new file mode 100644 index 000000000..1dd09e2fb --- /dev/null +++ b/apps/examples/src/examples/api/README.md @@ -0,0 +1,11 @@ +--- +title: Editor API +component: ./APIExample.tsx +order: 2 +--- + +Manipulate the contents of the canvas using the editor API. + +--- + +This example creates and updates shapes, selects and rotates them, and zooms the camera. diff --git a/apps/examples/src/examples/AssetOptionsExample.tsx b/apps/examples/src/examples/asset-props/AssetPropsExample.tsx similarity index 100% rename from apps/examples/src/examples/AssetOptionsExample.tsx rename to apps/examples/src/examples/asset-props/AssetPropsExample.tsx diff --git a/apps/examples/src/examples/asset-props/README.md b/apps/examples/src/examples/asset-props/README.md new file mode 100644 index 000000000..d6485e094 --- /dev/null +++ b/apps/examples/src/examples/asset-props/README.md @@ -0,0 +1,10 @@ +--- +title: Asset props +component: ./AssetPropsExample.tsx +--- + +Control the assets (images, videos, etc.) that can be added to the canvas. + +--- + +This example demonstrates the `` component's props that give you control over assets: which types are allowed, the maximum size, and maximum dimensions. diff --git a/apps/examples/src/examples/CanvasEventsExample.tsx b/apps/examples/src/examples/canvas-events/CanvasEventsExample.tsx similarity index 54% rename from apps/examples/src/examples/CanvasEventsExample.tsx rename to apps/examples/src/examples/canvas-events/CanvasEventsExample.tsx index a3abcc192..7234cf876 100644 --- a/apps/examples/src/examples/CanvasEventsExample.tsx +++ b/apps/examples/src/examples/canvas-events/CanvasEventsExample.tsx @@ -11,34 +11,32 @@ export default function CanvasEventsExample() { return (
    -
    +
    { editor.on('event', (event) => handleEvent(event)) }} />
    -
    -
    - {events.map((t, i) => ( -
    {t}
    - ))} -
    +
    + {events.map((t, i) => ( +
    {t}
    + ))}
    ) diff --git a/apps/examples/src/examples/canvas-events/README.md b/apps/examples/src/examples/canvas-events/README.md new file mode 100644 index 000000000..6d1ede65e --- /dev/null +++ b/apps/examples/src/examples/canvas-events/README.md @@ -0,0 +1,10 @@ +--- +title: Canvas events +component: ./CanvasEventsExample.tsx +--- + +Listen to events from tldraw's canvas. + +--- + +These are the input events that the editor interprets. Try moving your cursor, dragging, using modifier keys, etc. diff --git a/apps/examples/src/examples/CustomComponentsExample.tsx b/apps/examples/src/examples/custom-components/CustomComponentsExample.tsx similarity index 100% rename from apps/examples/src/examples/CustomComponentsExample.tsx rename to apps/examples/src/examples/custom-components/CustomComponentsExample.tsx diff --git a/apps/examples/src/examples/custom-components/README.md b/apps/examples/src/examples/custom-components/README.md new file mode 100644 index 000000000..124802137 --- /dev/null +++ b/apps/examples/src/examples/custom-components/README.md @@ -0,0 +1,12 @@ +--- +title: Canvas components +component: ./CustomComponentsExample.tsx +--- + +Replace tldraw's on-canvas UI with your own. + +--- + +Tldraw's on-canvas UI is build from replaceable React components. + +Try dragging to select or using the eraser tool to see the custom components in this example. diff --git a/apps/examples/src/examples/CustomConfigExample/CardShape/CardShapeTool.tsx b/apps/examples/src/examples/custom-config/CardShape/CardShapeTool.tsx similarity index 100% rename from apps/examples/src/examples/CustomConfigExample/CardShape/CardShapeTool.tsx rename to apps/examples/src/examples/custom-config/CardShape/CardShapeTool.tsx diff --git a/apps/examples/src/examples/CustomConfigExample/CardShape/CardShapeUtil.tsx b/apps/examples/src/examples/custom-config/CardShape/CardShapeUtil.tsx similarity index 100% rename from apps/examples/src/examples/CustomConfigExample/CardShape/CardShapeUtil.tsx rename to apps/examples/src/examples/custom-config/CardShape/CardShapeUtil.tsx diff --git a/apps/examples/src/examples/CustomConfigExample/CardShape/card-shape-migrations.ts b/apps/examples/src/examples/custom-config/CardShape/card-shape-migrations.ts similarity index 100% rename from apps/examples/src/examples/CustomConfigExample/CardShape/card-shape-migrations.ts rename to apps/examples/src/examples/custom-config/CardShape/card-shape-migrations.ts diff --git a/apps/examples/src/examples/CustomConfigExample/CardShape/card-shape-props.ts b/apps/examples/src/examples/custom-config/CardShape/card-shape-props.ts similarity index 100% rename from apps/examples/src/examples/CustomConfigExample/CardShape/card-shape-props.ts rename to apps/examples/src/examples/custom-config/CardShape/card-shape-props.ts diff --git a/apps/examples/src/examples/CustomConfigExample/CardShape/card-shape-types.ts b/apps/examples/src/examples/custom-config/CardShape/card-shape-types.ts similarity index 100% rename from apps/examples/src/examples/CustomConfigExample/CardShape/card-shape-types.ts rename to apps/examples/src/examples/custom-config/CardShape/card-shape-types.ts diff --git a/apps/examples/src/examples/CustomConfigExample/CustomConfigExample.tsx b/apps/examples/src/examples/custom-config/CustomConfigExample.tsx similarity index 100% rename from apps/examples/src/examples/CustomConfigExample/CustomConfigExample.tsx rename to apps/examples/src/examples/custom-config/CustomConfigExample.tsx diff --git a/apps/examples/src/examples/custom-config/README.md b/apps/examples/src/examples/custom-config/README.md new file mode 100644 index 000000000..d57fab4cc --- /dev/null +++ b/apps/examples/src/examples/custom-config/README.md @@ -0,0 +1,11 @@ +--- +title: Custom shapes / tools +component: ./CustomConfigExample.tsx +order: 3 +--- + +Create custom shapes / tools + +--- + +The card shape (select ⚫️ in the toolbar) is a custom shape - but also just a normal react component. diff --git a/apps/examples/src/examples/CustomConfigExample/ui-overrides.ts b/apps/examples/src/examples/custom-config/ui-overrides.ts similarity index 100% rename from apps/examples/src/examples/CustomConfigExample/ui-overrides.ts rename to apps/examples/src/examples/custom-config/ui-overrides.ts diff --git a/apps/examples/src/examples/CustomStylesExample/CardShape.tsx b/apps/examples/src/examples/custom-styles/CardShape.tsx similarity index 100% rename from apps/examples/src/examples/CustomStylesExample/CardShape.tsx rename to apps/examples/src/examples/custom-styles/CardShape.tsx diff --git a/apps/examples/src/examples/CustomStylesExample/CustomStylesExample.tsx b/apps/examples/src/examples/custom-styles/CustomStylesExample.tsx similarity index 100% rename from apps/examples/src/examples/CustomStylesExample/CustomStylesExample.tsx rename to apps/examples/src/examples/custom-styles/CustomStylesExample.tsx diff --git a/apps/examples/src/examples/CustomStylesExample/FilterStyleUi.tsx b/apps/examples/src/examples/custom-styles/FilterStyleUi.tsx similarity index 100% rename from apps/examples/src/examples/CustomStylesExample/FilterStyleUi.tsx rename to apps/examples/src/examples/custom-styles/FilterStyleUi.tsx diff --git a/apps/examples/src/examples/custom-styles/README.md b/apps/examples/src/examples/custom-styles/README.md new file mode 100644 index 000000000..7a2e71cfe --- /dev/null +++ b/apps/examples/src/examples/custom-styles/README.md @@ -0,0 +1,10 @@ +--- +title: Custom styles +component: ./CustomStylesExample.tsx +--- + +Styles are special properties that can be set on many shapes at once. + +--- + +Create several shapes with the ⚫️ tool, then select them and try changing their filter style. diff --git a/apps/examples/src/examples/CustomStylesExample/ui-overrides.ts b/apps/examples/src/examples/custom-styles/ui-overrides.ts similarity index 100% rename from apps/examples/src/examples/CustomStylesExample/ui-overrides.ts rename to apps/examples/src/examples/custom-styles/ui-overrides.ts diff --git a/apps/examples/src/examples/CustomUiExample/CustomUiExample.tsx b/apps/examples/src/examples/custom-ui/CustomUiExample.tsx similarity index 100% rename from apps/examples/src/examples/CustomUiExample/CustomUiExample.tsx rename to apps/examples/src/examples/custom-ui/CustomUiExample.tsx diff --git a/apps/examples/src/examples/custom-ui/README.md b/apps/examples/src/examples/custom-ui/README.md new file mode 100644 index 000000000..523be50fc --- /dev/null +++ b/apps/examples/src/examples/custom-ui/README.md @@ -0,0 +1,10 @@ +--- +title: Custom UI +component: ./CustomUiExample.tsx +--- + +Replace tldraw's UI with your own. + +--- + +This UI has keyboard shortcuts and buttons for selecting tools. diff --git a/apps/examples/src/examples/CustomUiExample/custom-ui.css b/apps/examples/src/examples/custom-ui/custom-ui.css similarity index 100% rename from apps/examples/src/examples/CustomUiExample/custom-ui.css rename to apps/examples/src/examples/custom-ui/custom-ui.css diff --git a/apps/examples/src/BasicExample.tsx b/apps/examples/src/examples/develop/BasicExample.tsx similarity index 100% rename from apps/examples/src/BasicExample.tsx rename to apps/examples/src/examples/develop/BasicExample.tsx diff --git a/apps/examples/src/examples/develop/README.md b/apps/examples/src/examples/develop/README.md new file mode 100644 index 000000000..bffa2cee8 --- /dev/null +++ b/apps/examples/src/examples/develop/README.md @@ -0,0 +1,11 @@ +--- +title: Basic (development) +component: ./BasicExample.tsx +order: 1 +--- + +The easiest way to get started with tldraw. + +--- + +The simplest use of the `` component. diff --git a/apps/examples/src/examples/ErrorBoundaryExample/ErrorBoundaryExample.tsx b/apps/examples/src/examples/error-boundary/ErrorBoundaryExample.tsx similarity index 100% rename from apps/examples/src/examples/ErrorBoundaryExample/ErrorBoundaryExample.tsx rename to apps/examples/src/examples/error-boundary/ErrorBoundaryExample.tsx diff --git a/apps/examples/src/examples/ErrorBoundaryExample/ErrorShape.ts b/apps/examples/src/examples/error-boundary/ErrorShape.ts similarity index 100% rename from apps/examples/src/examples/ErrorBoundaryExample/ErrorShape.ts rename to apps/examples/src/examples/error-boundary/ErrorShape.ts diff --git a/apps/examples/src/examples/error-boundary/README.md b/apps/examples/src/examples/error-boundary/README.md new file mode 100644 index 000000000..a0af90239 --- /dev/null +++ b/apps/examples/src/examples/error-boundary/README.md @@ -0,0 +1,10 @@ +--- +title: Error boundary +component: ./ErrorBoundaryExample.tsx +--- + +Catch errors in shapes. + +--- + +When something goes wrong in a shape, it won't crash the whole editor - just the shape that went wrong. diff --git a/apps/examples/src/examples/ExplodedExample.tsx b/apps/examples/src/examples/exploded/ExplodedExample.tsx similarity index 100% rename from apps/examples/src/examples/ExplodedExample.tsx rename to apps/examples/src/examples/exploded/ExplodedExample.tsx diff --git a/apps/examples/src/examples/exploded/README.md b/apps/examples/src/examples/exploded/README.md new file mode 100644 index 000000000..07505dad6 --- /dev/null +++ b/apps/examples/src/examples/exploded/README.md @@ -0,0 +1,10 @@ +--- +title: Sublibraries +component: ./ExplodedExample.tsx +--- + +Tldraw is built from several sublibraries - like the editor, default shapes & tools, and UI. + +--- + +For full customization, you can use these sublibraries directly, or replace them with your own. diff --git a/apps/examples/src/examples/ExternalContentSourcesExample.tsx b/apps/examples/src/examples/external-content-sources/ExternalContentSourcesExample.tsx similarity index 100% rename from apps/examples/src/examples/ExternalContentSourcesExample.tsx rename to apps/examples/src/examples/external-content-sources/ExternalContentSourcesExample.tsx diff --git a/apps/examples/src/examples/external-content-sources/README.md b/apps/examples/src/examples/external-content-sources/README.md new file mode 100644 index 000000000..21ed65691 --- /dev/null +++ b/apps/examples/src/examples/external-content-sources/README.md @@ -0,0 +1,10 @@ +--- +title: External content sources +component: ./ExternalContentSourcesExample.tsx +--- + +Control what happens when the user pastes content into the editor. + +--- + +In this example, we register a special handler for when the user pastes in 'text/html' content. We add it to a special shape type that renders the html content directly. diff --git a/apps/examples/src/examples/FloatyExample.tsx b/apps/examples/src/examples/floaty-window/FloatyExample.tsx similarity index 100% rename from apps/examples/src/examples/FloatyExample.tsx rename to apps/examples/src/examples/floaty-window/FloatyExample.tsx diff --git a/apps/examples/src/examples/floaty-window/README.md b/apps/examples/src/examples/floaty-window/README.md new file mode 100644 index 000000000..621206df0 --- /dev/null +++ b/apps/examples/src/examples/floaty-window/README.md @@ -0,0 +1,5 @@ +--- +title: Floaty window +hide: true +component: ./FloatyExample.tsx +--- diff --git a/apps/examples/src/examples/ForceBreakpointExample.tsx b/apps/examples/src/examples/force-mobile/ForceBreakpointExample.tsx similarity index 100% rename from apps/examples/src/examples/ForceBreakpointExample.tsx rename to apps/examples/src/examples/force-mobile/ForceBreakpointExample.tsx diff --git a/apps/examples/src/examples/force-mobile/README.md b/apps/examples/src/examples/force-mobile/README.md new file mode 100644 index 000000000..ee328b710 --- /dev/null +++ b/apps/examples/src/examples/force-mobile/README.md @@ -0,0 +1,6 @@ +--- +title: Force mobile breakpoint +component: ./ForceBreakpointExample +--- + +Force the editor UI to render as if it were on a mobile device. diff --git a/apps/examples/src/examples/HideUiExample.tsx b/apps/examples/src/examples/hide-ui/HideUiExample.tsx similarity index 100% rename from apps/examples/src/examples/HideUiExample.tsx rename to apps/examples/src/examples/hide-ui/HideUiExample.tsx diff --git a/apps/examples/src/examples/hide-ui/README.md b/apps/examples/src/examples/hide-ui/README.md new file mode 100644 index 000000000..061506d01 --- /dev/null +++ b/apps/examples/src/examples/hide-ui/README.md @@ -0,0 +1,10 @@ +--- +title: Hide UI +component: ./HideUiExample.tsx +--- + +Hide tldraw's UI with the `hideUi` prop. + +--- + +Useful for a bare-bones editor, or if you want to build your own UI. diff --git a/apps/examples/src/examples/HostedImagesExample.tsx b/apps/examples/src/examples/hosted-images/HostedImagesExample.tsx similarity index 100% rename from apps/examples/src/examples/HostedImagesExample.tsx rename to apps/examples/src/examples/hosted-images/HostedImagesExample.tsx diff --git a/apps/examples/src/examples/hosted-images/README.md b/apps/examples/src/examples/hosted-images/README.md new file mode 100644 index 000000000..d7ba0360f --- /dev/null +++ b/apps/examples/src/examples/hosted-images/README.md @@ -0,0 +1,5 @@ +--- +title: Hosted images +component: ./HostedImagesExample.tsx +hide: true +--- diff --git a/apps/examples/src/examples/ImagesExamples.tsx b/apps/examples/src/examples/local-images/LocalImagesExample.tsx similarity index 88% rename from apps/examples/src/examples/ImagesExamples.tsx rename to apps/examples/src/examples/local-images/LocalImagesExample.tsx index 4201e21f1..557dd8ecb 100644 --- a/apps/examples/src/examples/ImagesExamples.tsx +++ b/apps/examples/src/examples/local-images/LocalImagesExample.tsx @@ -5,7 +5,7 @@ import { useCallback } from 'react' // This is an example of how you can add an image to the editor. The image is already // present in the `public` folder, so we can just use it directly. // If you want to allow users to upload the images please take a look at the `HostedImagesExample.tsx` -export default function ImageExample() { +export default function LocalImagesExample() { const handleMount = useCallback((editor: Editor) => { // Assets are records that store data about shared assets like images, videos, etc. // Each image has an associated asset record, so we'll create that first. @@ -22,7 +22,7 @@ export default function ImageExample() { typeName: 'asset', props: { name: 'tldraw.png', - src: '/tldraw.png', + src: '/tldraw.png', // You could also use a base64 encoded string here w: imageWidth, h: imageHeight, mimeType: 'image/png', @@ -51,7 +51,10 @@ export default function ImageExample() { return (
    - +
    ) } diff --git a/apps/examples/src/examples/local-images/README.md b/apps/examples/src/examples/local-images/README.md new file mode 100644 index 000000000..5288f19f0 --- /dev/null +++ b/apps/examples/src/examples/local-images/README.md @@ -0,0 +1,11 @@ +--- +title: Local images +component: ./LocalImagesExample.tsx +hide: false +--- + +How to use local images in the built-in `ImageShape` shape. + +--- + +This example shows how to use local images in the built-in `ImageShape` shape. You must first create an asset that holds the source of the image, then create a shape that references the asset. diff --git a/apps/examples/src/examples/MetaExample.tsx b/apps/examples/src/examples/meta-on-change/OnChangeShapeMetaExample.tsx similarity index 57% rename from apps/examples/src/examples/MetaExample.tsx rename to apps/examples/src/examples/meta-on-change/OnChangeShapeMetaExample.tsx index 8a40917d6..c20f350a5 100644 --- a/apps/examples/src/examples/MetaExample.tsx +++ b/apps/examples/src/examples/meta-on-change/OnChangeShapeMetaExample.tsx @@ -1,19 +1,16 @@ import { Tldraw } from '@tldraw/tldraw' import '@tldraw/tldraw/tldraw.css' -export default function MetaExample() { +export default function OnChangeShapeMetaExample() { return (
    { - // There's no API for setting getInitialMetaForShape yet, but - // you can replace it at runtime like this. This will run for - // all shapes created by the user. + // See the "meta-on-create" example for more about setting the + // initial meta for a shape. editor.getInitialMetaForShape = (_shape) => { return { - createdBy: editor.user.getId(), - createdAt: Date.now(), updatedBy: editor.user.getId(), updatedAt: Date.now(), } @@ -21,14 +18,13 @@ export default function MetaExample() { // We can also use the sideEffects API to modify a shape before // its change is committed to the database. This will run for // all shapes whenever they are updated. - editor.sideEffects.registerBeforeChangeHandler('shape', (record, _prev, source) => { - if (source !== 'user') return record - record.meta = { - ...record.meta, + editor.sideEffects.registerBeforeChangeHandler('shape', (_prev, next, source) => { + if (source !== 'user') return next + next.meta = { updatedBy: editor.user.getId(), updatedAt: Date.now(), } - return record + return next }) }} /> diff --git a/apps/examples/src/examples/meta-on-change/README.md b/apps/examples/src/examples/meta-on-change/README.md new file mode 100644 index 000000000..61d9601a9 --- /dev/null +++ b/apps/examples/src/examples/meta-on-change/README.md @@ -0,0 +1,10 @@ +--- +title: Shape Meta (on change) +component: ./OnChangeShapeMetaExample.tsx +--- + +Add custom metadata to shapes when they're changed. + +--- + +In this example, we add updatedAt metadata to shapes when they're updated. diff --git a/apps/examples/src/examples/meta-on-create/OnCreateShapeMetaExample.tsx b/apps/examples/src/examples/meta-on-create/OnCreateShapeMetaExample.tsx new file mode 100644 index 000000000..efba15739 --- /dev/null +++ b/apps/examples/src/examples/meta-on-create/OnCreateShapeMetaExample.tsx @@ -0,0 +1,23 @@ +import { Tldraw } from '@tldraw/tldraw' +import '@tldraw/tldraw/tldraw.css' + +export default function OnCreateShapeMetaExample() { + return ( +
    + { + // There's no API for setting getInitialMetaForShape yet, but + // you can replace it at runtime like this. This will run for + // all shapes created by the user. + editor.getInitialMetaForShape = (_shape) => { + return { + createdBy: editor.user.getId(), + createdAt: Date.now(), + } + } + }} + /> +
    + ) +} diff --git a/apps/examples/src/examples/meta-on-create/README.md b/apps/examples/src/examples/meta-on-create/README.md new file mode 100644 index 000000000..95df4c758 --- /dev/null +++ b/apps/examples/src/examples/meta-on-create/README.md @@ -0,0 +1,10 @@ +--- +title: Shape Meta (on create) +component: ./OnCreateShapeMetaExample.tsx +--- + +Add custom metadata to shapes when they're created. + +--- + +In this example, we add createdBy and createdAt metadata to shapes when they're created. diff --git a/apps/examples/src/examples/MultipleExample.tsx b/apps/examples/src/examples/multiple/MultipleExample.tsx similarity index 100% rename from apps/examples/src/examples/MultipleExample.tsx rename to apps/examples/src/examples/multiple/MultipleExample.tsx diff --git a/apps/examples/src/examples/multiple/README.md b/apps/examples/src/examples/multiple/README.md new file mode 100644 index 000000000..dc5fce94f --- /dev/null +++ b/apps/examples/src/examples/multiple/README.md @@ -0,0 +1,6 @@ +--- +title: Multiple editors +component: ./MultipleExample.tsx +--- + +Use multiple components on the same page. diff --git a/apps/examples/src/examples/only-editor/README.md b/apps/examples/src/examples/only-editor/README.md new file mode 100644 index 000000000..22b362c0b --- /dev/null +++ b/apps/examples/src/examples/only-editor/README.md @@ -0,0 +1,10 @@ +--- +title: Minimal +component: ./OnlyEditor.tsx +--- + +Use the `` component to render a bare-bones editor with minimal built-in shapes and tools. + +--- + +This example show show the `` component can be used to render a bare-bones editor. It uses minimal built-in shapes and tools. diff --git a/apps/examples/src/examples/PersistenceExample.tsx b/apps/examples/src/examples/persistence/PersistenceExample.tsx similarity index 100% rename from apps/examples/src/examples/PersistenceExample.tsx rename to apps/examples/src/examples/persistence/PersistenceExample.tsx diff --git a/apps/examples/src/examples/persistence/README.md b/apps/examples/src/examples/persistence/README.md new file mode 100644 index 000000000..0697d1bc9 --- /dev/null +++ b/apps/examples/src/examples/persistence/README.md @@ -0,0 +1,11 @@ +--- +title: Persistence +component: ./PersistenceExample.tsx +order: 5 +--- + +Save the contents of the editor + +--- + +In this example, we load the contents of the editor from your browser's localStorage, and save it there when you make changes. diff --git a/apps/examples/src/examples/readonly/README.md b/apps/examples/src/examples/readonly/README.md new file mode 100644 index 000000000..52d9a7c59 --- /dev/null +++ b/apps/examples/src/examples/readonly/README.md @@ -0,0 +1,10 @@ +--- +title: Readonly +component: ./ReadOnlyExample +--- + +Use the editor in readonly mode. + +--- + +Users can still pan and zoom the canvas, but they can't change the contents. diff --git a/apps/examples/src/examples/ReadOnlyExample.tsx b/apps/examples/src/examples/readonly/ReadOnlyExample.tsx similarity index 100% rename from apps/examples/src/examples/ReadOnlyExample.tsx rename to apps/examples/src/examples/readonly/ReadOnlyExample.tsx diff --git a/apps/examples/src/examples/screenshot-tool/README.md b/apps/examples/src/examples/screenshot-tool/README.md new file mode 100644 index 000000000..695ee6fd2 --- /dev/null +++ b/apps/examples/src/examples/screenshot-tool/README.md @@ -0,0 +1,10 @@ +--- +title: Custom tool (screenshot) +component: ./ScreenshotToolExample.tsx +--- + +Draw a box on the canvas to capture a screenshot of that area. + +--- + +Tools are the parts of tldraw's state chart. Most interactions in tldraw are tools. diff --git a/apps/examples/src/examples/ScreenshotToolExample/ScreenshotTool/ScreenshotTool.ts b/apps/examples/src/examples/screenshot-tool/ScreenshotTool/ScreenshotTool.ts similarity index 100% rename from apps/examples/src/examples/ScreenshotToolExample/ScreenshotTool/ScreenshotTool.ts rename to apps/examples/src/examples/screenshot-tool/ScreenshotTool/ScreenshotTool.ts diff --git a/apps/examples/src/examples/ScreenshotToolExample/ScreenshotTool/childStates/Dragging.ts b/apps/examples/src/examples/screenshot-tool/ScreenshotTool/childStates/Dragging.ts similarity index 100% rename from apps/examples/src/examples/ScreenshotToolExample/ScreenshotTool/childStates/Dragging.ts rename to apps/examples/src/examples/screenshot-tool/ScreenshotTool/childStates/Dragging.ts diff --git a/apps/examples/src/examples/ScreenshotToolExample/ScreenshotTool/childStates/Idle.ts b/apps/examples/src/examples/screenshot-tool/ScreenshotTool/childStates/Idle.ts similarity index 100% rename from apps/examples/src/examples/ScreenshotToolExample/ScreenshotTool/childStates/Idle.ts rename to apps/examples/src/examples/screenshot-tool/ScreenshotTool/childStates/Idle.ts diff --git a/apps/examples/src/examples/ScreenshotToolExample/ScreenshotTool/childStates/Pointing.ts b/apps/examples/src/examples/screenshot-tool/ScreenshotTool/childStates/Pointing.ts similarity index 100% rename from apps/examples/src/examples/ScreenshotToolExample/ScreenshotTool/childStates/Pointing.ts rename to apps/examples/src/examples/screenshot-tool/ScreenshotTool/childStates/Pointing.ts diff --git a/apps/examples/src/examples/ScreenshotToolExample/ScreenshotToolExample.tsx b/apps/examples/src/examples/screenshot-tool/ScreenshotToolExample.tsx similarity index 97% rename from apps/examples/src/examples/ScreenshotToolExample/ScreenshotToolExample.tsx rename to apps/examples/src/examples/screenshot-tool/ScreenshotToolExample.tsx index 0b710d240..0c379fa88 100644 --- a/apps/examples/src/examples/ScreenshotToolExample/ScreenshotToolExample.tsx +++ b/apps/examples/src/examples/screenshot-tool/ScreenshotToolExample.tsx @@ -4,6 +4,7 @@ import { TLUiAssetUrlOverrides, TLUiOverrides, Tldraw, + Vec2d, toolbarItem, useEditor, useValue, @@ -68,7 +69,10 @@ function ScreenshotBox() { // "page space", i.e. uneffected by scale, and relative to the tldraw // page's top left corner. const zoomLevel = editor.getZoomLevel() - const { x, y } = editor.pageToScreen({ x: box.x, y: box.y }) + const { x, y } = Vec2d.Sub( + editor.pageToScreen({ x: box.x, y: box.y }), + editor.getViewportScreenBounds() + ) return new Box2d(x, y, box.w * zoomLevel, box.h * zoomLevel) }, [editor] diff --git a/apps/examples/src/examples/scroll/README.md b/apps/examples/src/examples/scroll/README.md new file mode 100644 index 000000000..b3ea5b6bc --- /dev/null +++ b/apps/examples/src/examples/scroll/README.md @@ -0,0 +1,10 @@ +--- +title: Scrolling container +component: ./ScrollExample.tsx +--- + +Use the editor inside a scrollable container. + +--- + +Tldraw doesn't have to be full screen. diff --git a/apps/examples/src/examples/ScrollExample.tsx b/apps/examples/src/examples/scroll/ScrollExample.tsx similarity index 100% rename from apps/examples/src/examples/ScrollExample.tsx rename to apps/examples/src/examples/scroll/ScrollExample.tsx diff --git a/apps/examples/src/examples/shape-meta/README.md b/apps/examples/src/examples/shape-meta/README.md new file mode 100644 index 000000000..690536f41 --- /dev/null +++ b/apps/examples/src/examples/shape-meta/README.md @@ -0,0 +1,10 @@ +--- +title: Shape meta +component: ./ShapeMetaExample.tsx +--- + +Add a label to shapes with the meta property. + +--- + +Select a shape and try changing its label. The label is stored in the shape's meta property, which can be used to add custom data to any shape. diff --git a/apps/examples/src/examples/ShapeMetaExample.tsx b/apps/examples/src/examples/shape-meta/ShapeMetaExample.tsx similarity index 100% rename from apps/examples/src/examples/ShapeMetaExample.tsx rename to apps/examples/src/examples/shape-meta/ShapeMetaExample.tsx diff --git a/apps/examples/src/examples/snapshots/README.md b/apps/examples/src/examples/snapshots/README.md new file mode 100644 index 000000000..85eef914f --- /dev/null +++ b/apps/examples/src/examples/snapshots/README.md @@ -0,0 +1,10 @@ +--- +title: Snapshots +component: ./SnapshotExample.tsx +--- + +Load a snapshot of the editor's contents. + +--- + +Use `editor.store.getSnapshot()` and `editor.store.loadSnapshot()` to save and restore the editor's contents. diff --git a/apps/examples/src/examples/SnapshotExample/SnapshotExample.tsx b/apps/examples/src/examples/snapshots/SnapshotExample.tsx similarity index 100% rename from apps/examples/src/examples/SnapshotExample/SnapshotExample.tsx rename to apps/examples/src/examples/snapshots/SnapshotExample.tsx diff --git a/apps/examples/src/examples/SnapshotExample/snapshot.json b/apps/examples/src/examples/snapshots/snapshot.json similarity index 100% rename from apps/examples/src/examples/SnapshotExample/snapshot.json rename to apps/examples/src/examples/snapshots/snapshot.json diff --git a/apps/examples/src/examples/CustomShapeWithHandles/CustomShapeWithHandles.tsx b/apps/examples/src/examples/speech-bubble/CustomShapeWithHandles.tsx similarity index 92% rename from apps/examples/src/examples/CustomShapeWithHandles/CustomShapeWithHandles.tsx rename to apps/examples/src/examples/speech-bubble/CustomShapeWithHandles.tsx index b27fe5408..216ff0992 100644 --- a/apps/examples/src/examples/CustomShapeWithHandles/CustomShapeWithHandles.tsx +++ b/apps/examples/src/examples/speech-bubble/CustomShapeWithHandles.tsx @@ -10,7 +10,7 @@ const tools = [SpeechBubbleTool] export default function CustomShapeWithHandles() { return ( -
    +
    -
    +
    -
    -
    - {storeEvents.map((t, i) => ( -
    {t}
    - ))} -
    +
    + {storeEvents.map((t, i) => ( +
    {t}
    + ))}
    ) diff --git a/apps/examples/src/examples/OnTheCanvas.tsx b/apps/examples/src/examples/things-on-the-canvas/OnTheCanvas.tsx similarity index 88% rename from apps/examples/src/examples/OnTheCanvas.tsx rename to apps/examples/src/examples/things-on-the-canvas/OnTheCanvas.tsx index 3a42fa4c6..c4dcd00bb 100644 --- a/apps/examples/src/examples/OnTheCanvas.tsx +++ b/apps/examples/src/examples/things-on-the-canvas/OnTheCanvas.tsx @@ -1,4 +1,11 @@ -import { stopEventPropagation, Tldraw, TLEditorComponents, track, useEditor } from '@tldraw/tldraw' +import { + stopEventPropagation, + Tldraw, + TLEditorComponents, + track, + useEditor, + Vec2d, +} from '@tldraw/tldraw' import '@tldraw/tldraw/tldraw.css' import { useState } from 'react' @@ -55,7 +62,10 @@ const MyComponentInFront = track(() => { if (!selectionRotatedPageBounds) return null - const pageCoordinates = editor.pageToScreen(selectionRotatedPageBounds.point) + const pageCoordinates = Vec2d.Sub( + editor.pageToScreen(selectionRotatedPageBounds.point), + editor.getViewportScreenBounds() + ) return (
    -
    +
    -
    -
    - {uiEvents.map((t, i) => ( -
    {t}
    - ))} -
    +
    + {uiEvents.map((t, i) => ( +
    {t}
    + ))}
    ) diff --git a/apps/examples/src/examples/user-presence/README.md b/apps/examples/src/examples/user-presence/README.md new file mode 100644 index 000000000..cf39f5d26 --- /dev/null +++ b/apps/examples/src/examples/user-presence/README.md @@ -0,0 +1,12 @@ +--- +title: User presence +component: ./UserPresenceExample.tsx +--- + +Show other users editing the same document. + +--- + +Here, we add fake InstancePresence records to the store to simulate other users. + +If you have your own presence system, you could add real records to the store in the same way. diff --git a/apps/examples/src/examples/UserPresenceExample.tsx b/apps/examples/src/examples/user-presence/UserPresenceExample.tsx similarity index 100% rename from apps/examples/src/examples/UserPresenceExample.tsx rename to apps/examples/src/examples/user-presence/UserPresenceExample.tsx diff --git a/apps/examples/src/examples/zones/README.md b/apps/examples/src/examples/zones/README.md new file mode 100644 index 000000000..baa120610 --- /dev/null +++ b/apps/examples/src/examples/zones/README.md @@ -0,0 +1,12 @@ +--- +title: UI zones +component: ./ZonesExample.tsx +--- + +Inject custom components into tldraw's UI. + +--- + +Our default UI has two empty "zones" - the `topZone` (in the top-center of the screen) and `shareZone` (in the top right). + +You can set these zones to any React component you want. diff --git a/apps/examples/src/examples/ZonesExample.tsx b/apps/examples/src/examples/zones/ZonesExample.tsx similarity index 100% rename from apps/examples/src/examples/ZonesExample.tsx rename to apps/examples/src/examples/zones/ZonesExample.tsx diff --git a/apps/examples/src/hooks/useMegedRefs.tsx b/apps/examples/src/hooks/useMegedRefs.tsx new file mode 100644 index 000000000..f2d608007 --- /dev/null +++ b/apps/examples/src/hooks/useMegedRefs.tsx @@ -0,0 +1,16 @@ +import { ForwardedRef, useCallback } from 'react' + +export function useMergedRefs(...refs: ForwardedRef[]) { + return useCallback( + (node: T) => { + for (const ref of refs) { + if (typeof ref === 'function') { + ref(node) + } else if (ref != null) { + ref.current = node + } + } + }, + [refs] + ) +} diff --git a/apps/examples/src/index.tsx b/apps/examples/src/index.tsx index 6e7b5fe5b..6bc9250b8 100644 --- a/apps/examples/src/index.tsx +++ b/apps/examples/src/index.tsx @@ -5,46 +5,12 @@ import { setDefaultEditorAssetUrls, setDefaultUiAssetUrls, } from '@tldraw/tldraw' -import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { RouterProvider, createBrowserRouter } from 'react-router-dom' - -import ExamplesTldrawLogo from './components/ExamplesTldrawLogo' -import { ListLink } from './components/ListLink' - -import BasicExample from './BasicExample' -import APIExample from './examples/APIExample' -import AssetPropsExample from './examples/AssetOptionsExample' -import CanvasEventsExample from './examples/CanvasEventsExample' -import CustomComponentsExample from './examples/CustomComponentsExample' -import CustomConfigExample from './examples/CustomConfigExample/CustomConfigExample' -import CustomShapeWithHandles from './examples/CustomShapeWithHandles/CustomShapeWithHandles' -import CustomStylesExample from './examples/CustomStylesExample/CustomStylesExample' -import CustomUiExample from './examples/CustomUiExample/CustomUiExample' -import ErrorBoundaryExample from './examples/ErrorBoundaryExample/ErrorBoundaryExample' -import ExplodedExample from './examples/ExplodedExample' -import ExternalContentSourcesExample from './examples/ExternalContentSourcesExample' -import FloatyExample from './examples/FloatyExample' -import ForceMobileExample from './examples/ForceBreakpointExample' -import HideUiExample from './examples/HideUiExample' -import HostedImagesExample from './examples/HostedImagesExample' -import ImageExample from './examples/ImagesExamples' -import MetaExample from './examples/MetaExample' -import MultipleExample from './examples/MultipleExample' -import OnTheCanvasExample from './examples/OnTheCanvas' -import PersistenceExample from './examples/PersistenceExample' -import ReadOnlyExample from './examples/ReadOnlyExample' -import ScreenshotToolExample from './examples/ScreenshotToolExample/ScreenshotToolExample' -import ScrollExample from './examples/ScrollExample' -import ShapeMetaExample from './examples/ShapeMetaExample' -import SnapshotExample from './examples/SnapshotExample/SnapshotExample' -import StoreEventsExample from './examples/StoreEventsExample' -import UiEventsExample from './examples/UiEventsExample' -import UserPresenceExample from './examples/UserPresenceExample' -import ZonesExample from './examples/ZonesExample' -import EndToEnd from './examples/end-to-end/end-to-end' -import OnlyEditorExample from './examples/only-editor/OnlyEditor' -import YjsExample from './examples/yjs/YjsExample' +import { ExamplePage } from './ExamplePage' +import { HomePage } from './HomePage' +import { examples } from './examples' +import EndToEnd from './testing/end-to-end' // This example is only used for end to end tests @@ -54,219 +20,50 @@ const assetUrls = getAssetUrlsByMetaUrl() setDefaultEditorAssetUrls(assetUrls) setDefaultUiAssetUrls(assetUrls) -type Example = { - path: string - title?: string - element: JSX.Element -} - -export const allExamples: Example[] = [ +const router = createBrowserRouter([ { - title: 'Basic (development)', - path: 'develop', - element: , + path: '/', + element: , }, - { - title: 'Collaboration (with Yjs)', - path: 'yjs', - element: , - }, - { - title: 'Editor API', - path: 'api', - element: , - }, - { - title: 'Multiple editors', - path: 'multiple', - element: , - }, - { - title: 'Meta Example', - path: 'meta', - element: , - }, - { - title: 'Readonly Example', - path: 'readonly', - element: , - }, - { - title: 'Things on the canvas', - path: 'things-on-the-canvas', - element: , - }, - { - title: 'Scroll example', - path: 'scroll', - element: , - }, - { - title: 'Custom shapes / tools', - path: 'custom-config', - element: , - }, - { - title: 'Sublibraries', - path: 'exploded', - element: , - }, - { - title: 'Error boundary', - path: 'error-boundary', - element: , - }, - { - title: 'Custom UI', - path: 'custom-ui', - element: , - }, - { - title: 'Custom Tool (Screenshot)', - path: 'screenshot-tool', - element: , - }, - { - title: 'Hide UI', - path: 'hide-ui', - element: , - }, - { - title: 'UI components', - path: 'custom-components', - element: , - }, - { - title: 'UI events', - path: 'ui-events', - element: , - }, - { - title: 'Canvas events', - path: 'canvas-events', - element: , - }, - { - title: 'Store events', - path: 'store-events', - element: , - }, - { - title: 'User presence', - path: 'user-presence', - element: , - }, - { - title: 'UI zones', - path: 'zones', - element: , - }, - { - title: 'Persistence', - path: 'persistence', - element: , - }, - { - title: 'Snapshots', - path: 'snapshots', - element: , - }, - { - title: 'Force mobile breakpoint', - path: 'force-mobile', - element: , - }, - { - title: 'Custom styles', - path: 'custom-styles', - element: , - }, - { - title: 'Shape meta property', - path: 'shape-meta', - element: , - }, - { - title: 'Only editor', - path: 'only-editor', - element: , - }, - { - title: 'Adding images', - path: 'images', - element: , - }, - { - title: 'Hosted images example', - path: 'hosted-images', - element: , - }, - { - title: 'Asset props', - path: 'asset-props', - element: , - }, - { - title: 'Floaty window', - path: 'floaty-window', - element: , - }, - { - title: 'External content sources', - path: 'external-content-sources', - element: , - }, - { - title: 'Custom Shape With Handles', - path: 'custom-shape-with-handles', - element: , - }, - // not listed { path: 'end-to-end', element: , }, -] - -function App() { - return ( -
    -
    - -

    - See docs at tldraw.dev -

    -
    -
      - {allExamples - .filter((example) => example.title) - .map((example) => ( - - ))} -
    -
    - ) -} - -const router = createBrowserRouter([ - { - path: '/', - element: , - }, - ...allExamples, + ...examples.flatMap((example) => [ + { + path: example.path, + lazy: async () => { + const Component = await example.loadComponent() + return { + element: ( + + + + ), + } + }, + }, + { + path: `${example.path}/full`, + lazy: async () => { + const Component = await example.loadComponent() + return { + element: , + } + }, + }, + ]), ]) document.addEventListener('DOMContentLoaded', () => { const rootElement = document.getElementById('root')! const root = createRoot(rootElement!) root.render( - - } - onError={(error) => console.error(error)} - > - - - + } + onError={(error) => console.error(error)} + > + + ) }) diff --git a/apps/examples/src/styles.css b/apps/examples/src/styles.css index 27d208e3e..57b850b05 100644 --- a/apps/examples/src/styles.css +++ b/apps/examples/src/styles.css @@ -1,4 +1,4 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap'); html, body { @@ -13,6 +13,12 @@ body { min-height: -webkit-fill-available; height: 100%; } +@media screen and (max-width: 600px) { + html, + body { + font-size: 14px; + } +} html, * { @@ -20,45 +26,258 @@ html, } .tldraw__editor { - position: fixed; + position: absolute; inset: 0px; overflow: hidden; } .examples { - padding: 16px; + padding: 1.5rem; + max-width: 1080px; + margin: 0 auto; +} + +.examples hr { + border: none; + border-top: 1px solid #e8e8e8; + margin: 0; } .examples__header { - width: fit-content; - padding-bottom: 32px; + padding-bottom: 2rem; + display: flex; + align-items: center; +} +@media screen and (max-width: 500px) { + .examples__header { + flex-direction: column; + align-items: flex-start; + padding-bottom: 1rem; + } +} +.examples__title { + display: flex; + align-items: center; + margin-right: auto; + font-size: 1.45rem; } - .examples__lockup { - height: 56px; + height: 1.875rem; width: auto; + margin-right: 0.5rem; } .examples__list { - display: flex; - flex-direction: column; + display: grid; + grid-template-columns: repeat(1, 1fr); padding: 0; - margin: 0; + margin: 0 -1.5rem 0 -1.5rem; list-style: none; + gap: 0rem; +} + +@media screen and (max-width: 800px) { + .examples__list { + grid-template-columns: repeat(1, 1fr); + } +} + +@media screen and (max-width: 600px) { + .examples__list { + grid-template-columns: repeat(1, 1fr); + } } .examples__list__item { - padding: 8px 12px; - margin: 0px -12px; + overflow: hidden; + position: relative; + padding: 1.5rem; +} +.examples__list__item__link { + position: absolute; + inset: 0; + z-index: 1; + cursor: pointer; } -.examples__list__item a { - padding: 8px 12px; - margin: 0px -12px; +.examples__list__item__active { + display: block; + padding: 1.5rem; text-decoration: none; color: inherit; + width: 100%; + position: relative; } -.examples__list__item a:hover { - text-decoration: underline; +.examples__list__item::before { + content: ' '; + position: absolute; + inset: 0.5rem; + border-radius: 6px; + background: #f5f5f5; + z-index: -1; + opacity: 0; + transition: opacity 0.12s ease-in-out; +} +.examples__list__item:hover::before, +.examples__list__item__active::before { + opacity: 1; +} + +.examples__list__item h3 { + all: unset; + font-weight: 700; + font-size: 1rem; + margin: 0.25rem 0rem; + display: flex; + align-items: center; + justify-content: space-between; +} +.examples__list__item__details { + margin-top: 1rem; + position: absolute; + left: 1rem; + right: 1rem; + opacity: 0; + transition: opacity 0.12s ease-in-out; +} +.examples__list__item__active .examples__list__item__details { + position: static; + opacity: 1; + transition-delay: 0.1s; +} +.examples__list__item__standalone { + color: inherit; + opacity: 0.8; + padding: 0.5rem; + margin: -0.5rem; + display: block; + width: 16px; + height: 16px; + box-sizing: content-box; +} +.examples__list__item__code { + margin-top: 0.5rem; + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; +} +.examples__list__item__code a { + margin-top: 0.5rem; + padding: 0.5rem 0.5rem; + border-radius: 6px; + background-color: white; + display: flex; + flex: 1 1 auto; + text-align: center; + align-items: center; + justify-content: center; + color: inherit; + text-decoration: none; + box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.12), 0px 1px 3px rgba(0, 0, 0, 0.04); +} + +.example { + position: absolute; + inset: 0; + display: flex; + align-items: stretch; +} +.example__info { + width: 25vw; + max-width: 300px; + position: relative; + z-index: 1; + border-right: 1px solid #e8e8e8; + display: flex; + flex-direction: column; + height: 100%; + flex: none; +} +@media screen and (max-width: 800px) { + .example__info { + display: none; + } +} +.example__logo { + all: unset; + cursor: pointer; + flex: none; + font-size: 1.15rem; + display: flex; + align-items: center; + justify-content: start; + padding: calc(1rem - 0.5px) 1rem; +} +.example__logo .examples__lockup { + height: 1.5rem; +} +.example__info__list { + flex: auto; + margin: 0; + list-style: none; + padding: 0; + overflow: auto; + position: relative; + font-size: 13px; +} +.example__info__list .examples__list__item { + padding: 0.75rem 1rem; +} +.example__info__list .examples__list__item::before { + inset-block: 0.25rem; + inset-inline: 0.5rem; +} +.example__info__list h3 { + font-size: 14px; +} +.example__content { + flex: 1 1 auto; + position: relative; + z-index: 0; + overflow: auto; +} + +.examples__markdown p { + all: unset; + display: block; +} +.examples__markdown p:not(:last-child) { + margin-bottom: 0.5rem; +} + +.scroll-light { + scrollbar-width: thin; +} +.scroll-light::-webkit-scrollbar { + display: block; + width: 8px; + height: 8px; + position: absolute; + top: 0; + left: 0; + background-color: inherit; +} +.scroll-light::-webkit-scrollbar-button { + display: none; + width: 0; + height: 10px; +} +.scroll-light::-webkit-scrollbar-thumb { + background-clip: padding-box; + width: 0; + min-height: 36px; + border: 2px solid transparent; + border-radius: 6px; + background-color: rgba(0, 0, 0, 0.25); +} +.scroll-light::-webkit-scrollbar-thumb:hover { + background-color: rgba(0, 0, 0, 0.3); +} + +.example__info__list hr { + border: none; + border-top: 1px solid #e8e8e8; + margin: 0; } diff --git a/apps/examples/src/examples/end-to-end/end-to-end.tsx b/apps/examples/src/testing/end-to-end.tsx similarity index 100% rename from apps/examples/src/examples/end-to-end/end-to-end.tsx rename to apps/examples/src/testing/end-to-end.tsx diff --git a/apps/examples/src/vite-env.d.ts b/apps/examples/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/apps/examples/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/examples/vite.config.ts b/apps/examples/vite.config.ts index 84b4ea9aa..747314d44 100644 --- a/apps/examples/vite.config.ts +++ b/apps/examples/vite.config.ts @@ -1,9 +1,9 @@ import react from '@vitejs/plugin-react' import path from 'path' -import { defineConfig } from 'vite' +import { PluginOption, defineConfig } from 'vite' export default defineConfig({ - plugins: [react()], + plugins: [react(), exampleReadmePlugin()], root: path.join(__dirname, 'src'), publicDir: path.join(__dirname, 'public'), build: { @@ -21,3 +21,81 @@ export default defineConfig({ 'process.env.TLDRAW_ENV': JSON.stringify(process.env.VERCEL_ENV ?? 'development'), }, }) + +function exampleReadmePlugin(): PluginOption { + return { + name: 'example-readme', + async transform(src, id) { + const match = id.match(/examples\/src\/examples\/(.*)\/README.md$/) + if (!match) return + + const remark = (await import('remark')).remark + const remarkFrontmatter = (await import('remark-frontmatter')).default + const remarkHtml = (await import('remark-html')).default + const matter = (await import('vfile-matter')).matter + + const file = await remark() + .use(remarkFrontmatter) + .use(remarkHtml) + .use(() => (_, file) => matter(file)) + .process(src) + + const frontmatter = parseFrontMatter(file.data.matter, id) + + const separator = '\n
    \n' + const parts = String(file).split(separator) + const description = parts[0] + const details = parts.slice(1).join(separator) + const path = `/${match[1]}` + const codeUrl = `https://github.com/tldraw/tldraw/tree/main/apps/examples/src/examples${path}` + + const result = [ + `export const title = ${JSON.stringify(frontmatter.title)};`, + `export const order = ${JSON.stringify(frontmatter.order)};`, + `export const hide = ${JSON.stringify(frontmatter.hide)};`, + `export const description = ${JSON.stringify(description)};`, + `export const details = ${JSON.stringify(details)};`, + `export const codeUrl = ${JSON.stringify(codeUrl)};`, + `export const path = ${JSON.stringify(path)};`, + `export const componentFile = ${JSON.stringify(frontmatter.component)};`, + `import {lazy} from 'react';`, + `export const loadComponent = async () => {`, + ` return (await import(${JSON.stringify(frontmatter.component)})).default;`, + `};`, + ] + + return result.join('\n') + }, + } +} + +function parseFrontMatter(data: unknown, fileName: string) { + if (!data || typeof data !== 'object') { + throw new Error(`Frontmatter missing in ${fileName}`) + } + + if (!('title' in data && typeof data.title === 'string')) { + throw new Error(`Frontmatter key 'title' must be string in ${fileName}`) + } + + if (!('component' in data && typeof data.component === 'string')) { + throw new Error(`Frontmatter key 'component' must be string in ${fileName}`) + } + + const order = 'order' in data ? data.order : null + if (order !== null && typeof order !== 'number') { + throw new Error(`Frontmatter key 'order' must be number in ${fileName}`) + } + + const hide = 'hide' in data ? data.hide : false + if (hide !== false && hide !== true) { + throw new Error(`Frontmatter key 'hide' must be boolean in ${fileName}`) + } + + return { + title: data.title, + component: data.component, + order, + hide, + } +} diff --git a/package.json b/package.json index 22c8fa0d0..9d799cfaf 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "postinstall": "husky install && yarn refresh-assets", "refresh-assets": "lazy refresh-assets", "build": "lazy build", - "dev": "lazy run dev --filter='{,bublic/}apps/examples' --filter='{,bublic/}packages/tldraw'", + "dev": "LAZYREPO_PRETTY_OUTPUT=0 lazy run dev --filter='{,bublic/}apps/examples' --filter='{,bublic/}packages/tldraw'", "dev-vscode": "code ./apps/vscode/extension && lazy run dev --filter='{,bublic/}apps/vscode/{extension,editor}'", "build-types": "lazy inherit", "build-api": "lazy build-api", diff --git a/packages/tldraw/README.md b/packages/tldraw/README.md index c639bf444..7cce4c737 100644 --- a/packages/tldraw/README.md +++ b/packages/tldraw/README.md @@ -40,7 +40,7 @@ import { Tldraw } from '@tldraw/tldraw' import '@tldraw/tldraw/tldraw.css' export default function () { - return + return } ``` diff --git a/public-yarn.lock b/public-yarn.lock index 4e39591d9..654e83186 100644 --- a/public-yarn.lock +++ b/public-yarn.lock @@ -4911,6 +4911,15 @@ __metadata: languageName: node linkType: hard +"@types/hast@npm:^3.0.0": + version: 3.0.3 + resolution: "@types/hast@npm:3.0.3" + dependencies: + "@types/unist": "*" + checksum: ca204207550fd6848ee20b5ba2018fd54f515d59a8b80375cdbe392ba2b4b130dac25fdfbaf9f2a70d2aec9d074a34dc14d4d59d31fa3ede80ef9850afad5d3c + languageName: node + linkType: hard + "@types/history@npm:^4.7.11": version: 4.7.11 resolution: "@types/history@npm:4.7.11" @@ -5083,6 +5092,15 @@ __metadata: languageName: node linkType: hard +"@types/mdast@npm:^4.0.0": + version: 4.0.3 + resolution: "@types/mdast@npm:4.0.3" + dependencies: + "@types/unist": "*" + checksum: 345c5a22fccf05f35239ea6313ee4aaf6ebed5927c03ac79744abccb69b9ba5e692f9b771e36a012b79e17429082cada30f579e9c43b8a54e0ffb365431498b6 + languageName: node + linkType: hard + "@types/mdurl@npm:^1.0.0": version: 1.0.2 resolution: "@types/mdurl@npm:1.0.2" @@ -5287,6 +5305,13 @@ __metadata: languageName: node linkType: hard +"@types/unist@npm:^3.0.0": + version: 3.0.2 + resolution: "@types/unist@npm:3.0.2" + checksum: 3d04d0be69316e5f14599a0d993a208606c12818cf631fd399243d1dc7a9bd8a3917d6066baa6abc290814afbd744621484756803c80cba892c39cd4b4a85616 + languageName: node + linkType: hard + "@types/vscode@npm:^1.75.1": version: 1.77.0 resolution: "@types/vscode@npm:1.77.0" @@ -5516,6 +5541,13 @@ __metadata: languageName: node linkType: hard +"@ungap/structured-clone@npm:^1.0.0, @ungap/structured-clone@npm:^1.2.0": + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 + languageName: node + linkType: hard + "@use-gesture/core@npm:10.2.27": version: 10.2.27 resolution: "@use-gesture/core@npm:10.2.27" @@ -6818,6 +6850,13 @@ __metadata: languageName: node linkType: hard +"ccount@npm:^2.0.0": + version: 2.0.1 + resolution: "ccount@npm:2.0.1" + checksum: 48193dada54c9e260e0acf57fc16171a225305548f9ad20d5471e0f7a8c026aedd8747091dccb0d900cde7df4e4ddbd235df0d8de4a64c71b12f0d3303eeafd4 + languageName: node + linkType: hard + "chalk@npm:5.2.0": version: 5.2.0 resolution: "chalk@npm:5.2.0" @@ -7819,6 +7858,15 @@ __metadata: languageName: node linkType: hard +"devlop@npm:^1.0.0": + version: 1.1.0 + resolution: "devlop@npm:1.1.0" + dependencies: + dequal: ^2.0.0 + checksum: d2ff650bac0bb6ef08c48f3ba98640bb5fec5cce81e9957eb620408d1bab1204d382a45b785c6b3314dc867bb0684936b84c6867820da6db97cbb5d3c15dd185 + languageName: node + linkType: hard + "diff-sequences@npm:^28.1.1": version: 28.1.1 resolution: "diff-sequences@npm:28.1.1" @@ -9260,11 +9308,16 @@ __metadata: "@tldraw/tldraw": "workspace:*" "@vercel/analytics": ^1.0.1 "@vitejs/plugin-react": ^4.2.0 + classnames: ^2.3.2 dotenv: ^16.0.3 lazyrepo: 0.0.0-alpha.27 react: ^18.2.0 react-dom: ^18.2.0 react-router-dom: ^6.9.0 + remark: ^15.0.1 + remark-frontmatter: ^5.0.0 + remark-html: ^16.0.1 + vfile-matter: ^5.0.0 vite: ^4.3.4 languageName: unknown linkType: soft @@ -10328,6 +10381,63 @@ __metadata: languageName: node linkType: hard +"hast-util-from-parse5@npm:^8.0.0": + version: 8.0.1 + resolution: "hast-util-from-parse5@npm:8.0.1" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + hastscript: ^8.0.0 + property-information: ^6.0.0 + vfile: ^6.0.0 + vfile-location: ^5.0.0 + web-namespaces: ^2.0.0 + checksum: fdd1ab8b03af13778ecb94ef9a58b1e3528410cdfceb3d6bb7600508967d0d836b451bc7bc3baf66efb7c730d3d395eea4bb1b30352b0162823d9f0de976774b + languageName: node + linkType: hard + +"hast-util-parse-selector@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-parse-selector@npm:4.0.0" + dependencies: + "@types/hast": ^3.0.0 + checksum: 76087670d3b0b50b23a6cb70bca53a6176d6608307ccdbb3ed18b650b82e7c3513bfc40348f1389dc0c5ae872b9a768851f4335f44654abd7deafd6974c52402 + languageName: node + linkType: hard + +"hast-util-raw@npm:^9.0.0": + version: 9.0.1 + resolution: "hast-util-raw@npm:9.0.1" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + "@ungap/structured-clone": ^1.0.0 + hast-util-from-parse5: ^8.0.0 + hast-util-to-parse5: ^8.0.0 + html-void-elements: ^3.0.0 + mdast-util-to-hast: ^13.0.0 + parse5: ^7.0.0 + unist-util-position: ^5.0.0 + unist-util-visit: ^5.0.0 + vfile: ^6.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 4b486eb4782eafb471ae639d45c14ac8797676518cf5da16adc973f52d7b8e1075a1451558c023b390820bd9fd213213e6248a2dae71b68ac5040b277509b8d9 + languageName: node + linkType: hard + +"hast-util-sanitize@npm:^5.0.0": + version: 5.0.1 + resolution: "hast-util-sanitize@npm:5.0.1" + dependencies: + "@types/hast": ^3.0.0 + "@ungap/structured-clone": ^1.2.0 + unist-util-position: ^5.0.0 + checksum: cf7f3d1bb615f228fb90313adfd22ab4f7b2f34982d8d5aa86e3a5008964c0767de874b43530f2daae05823d16432783461c5dc4f45639018a3139d5363571de + languageName: node + linkType: hard + "hast-util-to-estree@npm:^2.0.0": version: 2.3.2 resolution: "hast-util-to-estree@npm:2.3.2" @@ -10351,6 +10461,41 @@ __metadata: languageName: node linkType: hard +"hast-util-to-html@npm:^9.0.0": + version: 9.0.0 + resolution: "hast-util-to-html@npm:9.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + ccount: ^2.0.0 + comma-separated-tokens: ^2.0.0 + hast-util-raw: ^9.0.0 + hast-util-whitespace: ^3.0.0 + html-void-elements: ^3.0.0 + mdast-util-to-hast: ^13.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + stringify-entities: ^4.0.0 + zwitch: ^2.0.4 + checksum: 62d5805edaa4e4ee72d77b8276a95cf6cf380631e20a3be2301f89dbe51d53a079a8a1390ce253927c18efdbd1fed0d93f65cd34e107d3cded296ec3e8c0a45b + languageName: node + linkType: hard + +"hast-util-to-parse5@npm:^8.0.0": + version: 8.0.0 + resolution: "hast-util-to-parse5@npm:8.0.0" + dependencies: + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 137469209cb2b32b57387928878dc85310fbd5afa4807a8da69529199bb1d19044bfc95b50c3dc68d4fb2b6cb8bf99b899285597ab6ab318f50422eefd5599dd + languageName: node + linkType: hard + "hast-util-whitespace@npm:^2.0.0": version: 2.0.1 resolution: "hast-util-whitespace@npm:2.0.1" @@ -10358,6 +10503,28 @@ __metadata: languageName: node linkType: hard +"hast-util-whitespace@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-whitespace@npm:3.0.0" + dependencies: + "@types/hast": ^3.0.0 + checksum: 41d93ccce218ba935dc3c12acdf586193c35069489c8c8f50c2aa824c00dec94a3c78b03d1db40fa75381942a189161922e4b7bca700b3a2cc779634c351a1e4 + languageName: node + linkType: hard + +"hastscript@npm:^8.0.0": + version: 8.0.0 + resolution: "hastscript@npm:8.0.0" + dependencies: + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + hast-util-parse-selector: ^4.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + checksum: ae3c20223e7b847320c0f98b6fb3c763ebe1bf3913c5805fbc176cf84553a9db1117ca34cf842a5235890b4b9ae0e94501bfdc9a9b870a5dbf5fc52426db1097 + languageName: node + linkType: hard + "he@npm:1.2.0": version: 1.2.0 resolution: "he@npm:1.2.0" @@ -10399,6 +10566,13 @@ __metadata: languageName: node linkType: hard +"html-void-elements@npm:^3.0.0": + version: 3.0.0 + resolution: "html-void-elements@npm:3.0.0" + checksum: 59be397525465a7489028afa064c55763d9cccd1d7d9f630cca47137317f0e897a9ca26cef7e745e7cff1abc44260cfa407742b243a54261dfacd42230e94fce + languageName: node + linkType: hard + "htmlparser2@npm:^8.0.1": version: 8.0.2 resolution: "htmlparser2@npm:8.0.2" @@ -12553,6 +12727,26 @@ __metadata: languageName: node linkType: hard +"mdast-util-from-markdown@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-from-markdown@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + mdast-util-to-string: ^4.0.0 + micromark: ^4.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-decode-string: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 4e8d8a46b4b588486c41b80c39da333a91593bc8d60cd7421c6cd3c22003b8e5a62478292fb7bc97b9255b6301a2250cca32340ef43c309156e215453c5b92be + languageName: node + linkType: hard + "mdast-util-frontmatter@npm:^1.0.0": version: 1.0.1 resolution: "mdast-util-frontmatter@npm:1.0.1" @@ -12564,6 +12758,20 @@ __metadata: languageName: node linkType: hard +"mdast-util-frontmatter@npm:^2.0.0": + version: 2.0.1 + resolution: "mdast-util-frontmatter@npm:2.0.1" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + escape-string-regexp: ^5.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + checksum: 86a7c8d9eb183be2621d6d9134b9d33df2a3647e3255f68a9796e2425e25643ffae00a501e36c57d9c10973087b94aa5a2ffd865d33cdd274cc9b88cd2d90a2e + languageName: node + linkType: hard + "mdast-util-mdx-expression@npm:^1.0.0": version: 1.3.2 resolution: "mdast-util-mdx-expression@npm:1.3.2" @@ -12627,6 +12835,16 @@ __metadata: languageName: node linkType: hard +"mdast-util-phrasing@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-phrasing@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + unist-util-is: ^6.0.0 + checksum: 95d5d8e18d5ea6dbfe2ee4ed1045961372efae9077e5c98e10bfef7025ee3fd9449f9a82840068ff50aa98fa43af0a0a14898ae10b5e46e96edde01e2797df34 + languageName: node + linkType: hard + "mdast-util-to-hast@npm:^11.0.0": version: 11.3.0 resolution: "mdast-util-to-hast@npm:11.3.0" @@ -12644,6 +12862,22 @@ __metadata: languageName: node linkType: hard +"mdast-util-to-hast@npm:^13.0.0": + version: 13.0.2 + resolution: "mdast-util-to-hast@npm:13.0.2" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + "@ungap/structured-clone": ^1.0.0 + devlop: ^1.0.0 + micromark-util-sanitize-uri: ^2.0.0 + trim-lines: ^3.0.0 + unist-util-position: ^5.0.0 + unist-util-visit: ^5.0.0 + checksum: 8fef6c3752476461d9c00b1dea4f141bc7d980e1b3bac7bd965bc68f532b6d30fb1c9e810433327c167176e68e071b8f4ab5a45355954857dc095c878421f35e + languageName: node + linkType: hard + "mdast-util-to-markdown@npm:^1.0.0, mdast-util-to-markdown@npm:^1.3.0": version: 1.5.0 resolution: "mdast-util-to-markdown@npm:1.5.0" @@ -12660,6 +12894,22 @@ __metadata: languageName: node linkType: hard +"mdast-util-to-markdown@npm:^2.0.0": + version: 2.1.0 + resolution: "mdast-util-to-markdown@npm:2.1.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + longest-streak: ^3.0.0 + mdast-util-phrasing: ^4.0.0 + mdast-util-to-string: ^4.0.0 + micromark-util-decode-string: ^2.0.0 + unist-util-visit: ^5.0.0 + zwitch: ^2.0.0 + checksum: 3a2cf3957e23b34e2e092e6e76ae72ee0b8745955bd811baba6814cf3a3d916c3fd52264b4b58f3bb3d512a428f84a1e998b6fc7e28434e388a9ae8fb6a9c173 + languageName: node + linkType: hard + "mdast-util-to-string@npm:^3.0.0, mdast-util-to-string@npm:^3.1.0": version: 3.2.0 resolution: "mdast-util-to-string@npm:3.2.0" @@ -12669,6 +12919,15 @@ __metadata: languageName: node linkType: hard +"mdast-util-to-string@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-to-string@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + checksum: 35489fb5710d58cbc2d6c8b6547df161a3f81e0f28f320dfb3548a9393555daf07c310c0c497708e67ed4dfea4a06e5655799e7d631ca91420c288b4525d6c29 + languageName: node + linkType: hard + "mdn-data@npm:2.0.28": version: 2.0.28 resolution: "mdn-data@npm:2.0.28" @@ -12765,6 +13024,30 @@ __metadata: languageName: node linkType: hard +"micromark-core-commonmark@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-core-commonmark@npm:2.0.0" + dependencies: + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-factory-destination: ^2.0.0 + micromark-factory-label: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-factory-title: ^2.0.0 + micromark-factory-whitespace: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-classify-character: ^2.0.0 + micromark-util-html-tag-name: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9c12fb580cf4ce71f60872043bd2794efe129f44d7b2b73afa155bbc0a66b7bc35655ba8cef438a6bd068441837ed3b6dc6ad7e5a18f815462c1750793e03a42 + languageName: node + linkType: hard + "micromark-extension-frontmatter@npm:^1.0.0": version: 1.1.0 resolution: "micromark-extension-frontmatter@npm:1.1.0" @@ -12777,6 +13060,18 @@ __metadata: languageName: node linkType: hard +"micromark-extension-frontmatter@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-frontmatter@npm:2.0.0" + dependencies: + fault: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: f68032df38c00ae47de15b63bcd72515bfcce39de4a9262a3a1ac9c5990f253f8e41bdc65fd17ec4bb3d144c32529ce0829571331e4901a9a413f1a53785d1e8 + languageName: node + linkType: hard + "micromark-extension-mdx-expression@npm:^1.0.0": version: 1.0.4 resolution: "micromark-extension-mdx-expression@npm:1.0.4" @@ -12861,6 +13156,17 @@ __metadata: languageName: node linkType: hard +"micromark-factory-destination@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-destination@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: d36e65ed1c072ff4148b016783148ba7c68a078991154625723e24bda3945160268fb91079fb28618e1613c2b6e70390a8ddc544c45410288aa27b413593071a + languageName: node + linkType: hard + "micromark-factory-label@npm:^1.0.0": version: 1.0.2 resolution: "micromark-factory-label@npm:1.0.2" @@ -12873,6 +13179,18 @@ __metadata: languageName: node linkType: hard +"micromark-factory-label@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-label@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: c021dbd0ed367610d35f2bae21209bc804d1a6d1286ffce458fd6a717f4d7fe581a7cba7d5c2d7a63757c44eb927c80d6a571d6ea7969fae1b48ab6461d109c4 + languageName: node + linkType: hard + "micromark-factory-mdx-expression@npm:^1.0.0": version: 1.0.7 resolution: "micromark-factory-mdx-expression@npm:1.0.7" @@ -12899,6 +13217,16 @@ __metadata: languageName: node linkType: hard +"micromark-factory-space@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-space@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 4ffdcdc2f759887bbb356500cb460b3915ecddcb5d85c3618d7df68ad05d13ed02b1153ee1845677b7d8126df8f388288b84fcf0d943bd9c92bcc71cd7222e37 + languageName: node + linkType: hard + "micromark-factory-title@npm:^1.0.0": version: 1.0.2 resolution: "micromark-factory-title@npm:1.0.2" @@ -12912,6 +13240,18 @@ __metadata: languageName: node linkType: hard +"micromark-factory-title@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-title@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 39e1ac23af3554e6e652e56065579bc7faf21ade7b8704b29c175871b4152b7109b790bb3cae0f7e088381139c6bac9553b8400772c3d322e4fa635f813a3578 + languageName: node + linkType: hard + "micromark-factory-whitespace@npm:^1.0.0": version: 1.0.0 resolution: "micromark-factory-whitespace@npm:1.0.0" @@ -12924,6 +13264,18 @@ __metadata: languageName: node linkType: hard +"micromark-factory-whitespace@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-whitespace@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9587c2546d1a58b4d5472b42adf05463f6212d0449455285662d63cd8eaed89c6b159ac82713fcee5f9dd88628c24307d9533cccd8971a2f3f4d48702f8f850a + languageName: node + linkType: hard + "micromark-util-character@npm:^1.0.0": version: 1.1.0 resolution: "micromark-util-character@npm:1.1.0" @@ -12934,6 +13286,16 @@ __metadata: languageName: node linkType: hard +"micromark-util-character@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-character@npm:2.0.1" + dependencies: + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 318d6e16fdcbe9d89e18b8e7796568d986abbb10a9f3037b7ac9b92a236bcc962f3cd380e26a7c49df40fd1d9ca33eb546268956345b662f4c4ca4962c7695f2 + languageName: node + linkType: hard + "micromark-util-chunked@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-chunked@npm:1.0.0" @@ -12943,6 +13305,15 @@ __metadata: languageName: node linkType: hard +"micromark-util-chunked@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-chunked@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: 324f95cccdae061332a8241936eaba6ef0782a1e355bac5c607ad2564fd3744929be7dc81651315a2921535747a33243e6a5606bcb64b7a56d49b6d74ea1a3d4 + languageName: node + linkType: hard + "micromark-util-classify-character@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-classify-character@npm:1.0.0" @@ -12954,6 +13325,17 @@ __metadata: languageName: node linkType: hard +"micromark-util-classify-character@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-classify-character@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 086e52904deffebb793fb1c08c94aabb8901f76958142dfc3a6282890ebaa983b285e69bd602b9d507f1b758ed38e75a994d2ad9fbbefa7de2584f67a16af405 + languageName: node + linkType: hard + "micromark-util-combine-extensions@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-combine-extensions@npm:1.0.0" @@ -12964,6 +13346,16 @@ __metadata: languageName: node linkType: hard +"micromark-util-combine-extensions@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-combine-extensions@npm:2.0.0" + dependencies: + micromark-util-chunked: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 107c47700343f365b4ed81551e18bc3458b573c500e56ac052b2490bd548adc475216e41d2271633a8867fac66fc22ba3e0a2d74a31ed79b9870ca947eb4e3ba + languageName: node + linkType: hard + "micromark-util-decode-numeric-character-reference@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-decode-numeric-character-reference@npm:1.0.0" @@ -12973,6 +13365,15 @@ __metadata: languageName: node linkType: hard +"micromark-util-decode-numeric-character-reference@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-decode-numeric-character-reference@npm:2.0.1" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: 9512507722efd2033a9f08715eeef787fbfe27e23edf55db21423d46d82ab46f76c89b4f960be3f5e50a2d388d89658afc0647989cf256d051e9ea01277a1adb + languageName: node + linkType: hard + "micromark-util-decode-string@npm:^1.0.0": version: 1.0.2 resolution: "micromark-util-decode-string@npm:1.0.2" @@ -12985,6 +13386,18 @@ __metadata: languageName: node linkType: hard +"micromark-util-decode-string@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-decode-string@npm:2.0.0" + dependencies: + decode-named-character-reference: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: a75daf32a4a6b549e9f19b4d833ebfeb09a32a9a1f9ce50f35dec6b6a3e4f9f121f49024ba7f9c91c55ebe792f7c7a332fc9604795181b6a612637df0df5b959 + languageName: node + linkType: hard + "micromark-util-encode@npm:^1.0.0": version: 1.0.1 resolution: "micromark-util-encode@npm:1.0.1" @@ -12992,6 +13405,13 @@ __metadata: languageName: node linkType: hard +"micromark-util-encode@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-encode@npm:2.0.0" + checksum: 853a3f33fce72aaf4ffa60b7f2b6fcfca40b270b3466e1b96561b02185d2bd8c01dd7948bc31a24ac014f4cc854e545ca9a8e9cf7ea46262f9d24c9e88551c66 + languageName: node + linkType: hard + "micromark-util-events-to-acorn@npm:^1.0.0": version: 1.2.1 resolution: "micromark-util-events-to-acorn@npm:1.2.1" @@ -13014,6 +13434,13 @@ __metadata: languageName: node linkType: hard +"micromark-util-html-tag-name@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-html-tag-name@npm:2.0.0" + checksum: d786d4486f93eb0ac5b628779809ca97c5dc60f3c9fc03eb565809831db181cf8cb7f05f9ac76852f3eb35461af0f89fa407b46f3a03f4f97a96754d8dc540d8 + languageName: node + linkType: hard + "micromark-util-normalize-identifier@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-normalize-identifier@npm:1.0.0" @@ -13023,6 +13450,15 @@ __metadata: languageName: node linkType: hard +"micromark-util-normalize-identifier@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-normalize-identifier@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: b36da2d3fd102053dadd953ce5c558328df12a63a8ac0e5aad13d4dda8e43b6a5d4a661baafe0a1cd8a260bead4b4a8e6e0e74193dd651e8484225bd4f4e68aa + languageName: node + linkType: hard + "micromark-util-resolve-all@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-resolve-all@npm:1.0.0" @@ -13032,6 +13468,15 @@ __metadata: languageName: node linkType: hard +"micromark-util-resolve-all@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-resolve-all@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: 31fe703b85572cb3f598ebe32750e59516925c7ff1f66cfe6afaebe0771a395a9eaa770787f2523d3c46082ea80e6c14f83643303740b3d650af7c96ebd30ccc + languageName: node + linkType: hard + "micromark-util-sanitize-uri@npm:^1.0.0": version: 1.1.0 resolution: "micromark-util-sanitize-uri@npm:1.1.0" @@ -13043,6 +13488,17 @@ __metadata: languageName: node linkType: hard +"micromark-util-sanitize-uri@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-sanitize-uri@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: ea4c28bbffcf2430e9aff2d18554296789a8b0a1f54ac24020d1dde76624a7f93e8f2a83e88cd5a846b6d2c4287b71b1142d1b89fa7f1b0363a9b33711a141fe + languageName: node + linkType: hard + "micromark-util-subtokenize@npm:^1.0.0": version: 1.0.2 resolution: "micromark-util-subtokenize@npm:1.0.2" @@ -13055,6 +13511,18 @@ __metadata: languageName: node linkType: hard +"micromark-util-subtokenize@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-subtokenize@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 77d9c7d59c05a20468d49ce2a3640e9cb268c083ccad02322f26c84e1094c25b44f4b8139ef0a247ca11a4fef7620c5bf82fbffd98acdb2989e79cbe7bd8f1db + languageName: node + linkType: hard + "micromark-util-symbol@npm:^1.0.0": version: 1.0.1 resolution: "micromark-util-symbol@npm:1.0.1" @@ -13062,6 +13530,13 @@ __metadata: languageName: node linkType: hard +"micromark-util-symbol@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-symbol@npm:2.0.0" + checksum: fa4a05bff575d9fbf0ad96a1013003e3bb6087ed6b34b609a141b6c0d2137b57df594aca409a95f4c5fda199f227b56a7d8b1f82cea0768df161d8a3a3660764 + languageName: node + linkType: hard + "micromark-util-types@npm:^1.0.0, micromark-util-types@npm:^1.0.1": version: 1.0.2 resolution: "micromark-util-types@npm:1.0.2" @@ -13069,6 +13544,13 @@ __metadata: languageName: node linkType: hard +"micromark-util-types@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-types@npm:2.0.0" + checksum: 819fef3ab5770c37893d2a60381fb2694396c8d22803b6e103c830c3a1bc1490363c2b0470bb2acaaddad776dfbc2fc1fcfde39cb63c4f54d95121611672e3d0 + languageName: node + linkType: hard + "micromark@npm:^3.0.0": version: 3.1.0 resolution: "micromark@npm:3.1.0" @@ -13094,6 +13576,31 @@ __metadata: languageName: node linkType: hard +"micromark@npm:^4.0.0": + version: 4.0.0 + resolution: "micromark@npm:4.0.0" + dependencies: + "@types/debug": ^4.0.0 + debug: ^4.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: b84ab5ab1a0b28c063c52e9c2c9d7d44b954507235c10c9492d66e0b38f7de24bf298f914a1fbdf109f2a57a88cf0412de217c84cfac5fd60e3e42a74dbac085 + languageName: node + linkType: hard + "micromatch@npm:^4.0.0, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": version: 4.0.5 resolution: "micromatch@npm:4.0.5" @@ -15183,6 +15690,31 @@ __metadata: languageName: node linkType: hard +"remark-frontmatter@npm:^5.0.0": + version: 5.0.0 + resolution: "remark-frontmatter@npm:5.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-frontmatter: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + unified: ^11.0.0 + checksum: b36e11d528d1d0172489c74ce7961bb6073f7272e71ea1349f765fc79c4246a758aef949174d371a088c48e458af776fcfbb3b043c49cd1120ca8239aeafe16a + languageName: node + linkType: hard + +"remark-html@npm:^16.0.1": + version: 16.0.1 + resolution: "remark-html@npm:16.0.1" + dependencies: + "@types/mdast": ^4.0.0 + hast-util-sanitize: ^5.0.0 + hast-util-to-html: ^9.0.0 + mdast-util-to-hast: ^13.0.0 + unified: ^11.0.0 + checksum: f8cc31a774762b378d0ffb405cf5d3044526031894833e260c925038ac81a9ade49820158c8f9d42764ddb85671ab8ba14b4aa9dbf764d643be53b0dfdcdd482 + languageName: node + linkType: hard + "remark-mdx-frontmatter@npm:^1.0.1": version: 1.1.1 resolution: "remark-mdx-frontmatter@npm:1.1.1" @@ -15206,6 +15738,18 @@ __metadata: languageName: node linkType: hard +"remark-parse@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-parse@npm:11.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-from-markdown: ^2.0.0 + micromark-util-types: ^2.0.0 + unified: ^11.0.0 + checksum: d83d245290fa84bb04fb3e78111f09c74f7417e7c012a64dd8dc04fccc3699036d828fbd8eeec8944f774b6c30cc1d925c98f8c46495ebcee7c595496342ab7f + languageName: node + linkType: hard + "remark-rehype@npm:^9.0.0": version: 9.1.0 resolution: "remark-rehype@npm:9.1.0" @@ -15218,6 +15762,29 @@ __metadata: languageName: node linkType: hard +"remark-stringify@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-stringify@npm:11.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-to-markdown: ^2.0.0 + unified: ^11.0.0 + checksum: 59e07460eb629d6c3b3c0f438b0b236e7e6858fd5ab770303078f5a556ec00354d9c7fb9ef6d5f745a4617ac7da1ab618b170fbb4dac120e183fecd9cc86bce6 + languageName: node + linkType: hard + +"remark@npm:^15.0.1": + version: 15.0.1 + resolution: "remark@npm:15.0.1" + dependencies: + "@types/mdast": ^4.0.0 + remark-parse: ^11.0.0 + remark-stringify: ^11.0.0 + unified: ^11.0.0 + checksum: ac7edb7f9b70c22964bbc6c5d1c038dd10e1a43ccf436fbdb55fb8c89d54f1b77190b89386063ba410fbdd086fde9dca81ef470fc8358eed1ff76a9741ae3dcc + languageName: node + linkType: hard + "remove-markdown@npm:^0.3.0": version: 0.3.0 resolution: "remove-markdown@npm:0.3.0" @@ -16614,6 +17181,13 @@ __metadata: languageName: node linkType: hard +"trim-lines@npm:^3.0.0": + version: 3.0.1 + resolution: "trim-lines@npm:3.0.1" + checksum: e241da104682a0e0d807222cc1496b92e716af4db7a002f4aeff33ae6a0024fef93165d49eab11aa07c71e1347c42d46563f91dfaa4d3fb945aa535cdead53ed + languageName: node + linkType: hard + "trough@npm:^2.0.0": version: 2.1.0 resolution: "trough@npm:2.1.0" @@ -17111,6 +17685,21 @@ __metadata: languageName: node linkType: hard +"unified@npm:^11.0.0": + version: 11.0.4 + resolution: "unified@npm:11.0.4" + dependencies: + "@types/unist": ^3.0.0 + bail: ^2.0.0 + devlop: ^1.0.0 + extend: ^3.0.0 + is-plain-obj: ^4.0.0 + trough: ^2.0.0 + vfile: ^6.0.0 + checksum: cfb023913480ac2bd5e787ffb8c27782c43e6be4a55f8f1c288233fce46a7ebe7718ccc5adb80bf8d56b7ef85f5fc32239c7bfccda006f9f2382e0cc2e2a77e4 + languageName: node + linkType: hard + "unique-filename@npm:^1.1.1": version: 1.1.1 resolution: "unique-filename@npm:1.1.1" @@ -17172,6 +17761,15 @@ __metadata: languageName: node linkType: hard +"unist-util-is@npm:^6.0.0": + version: 6.0.0 + resolution: "unist-util-is@npm:6.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: f630a925126594af9993b091cf807b86811371e465b5049a6283e08537d3e6ba0f7e248e1e7dab52cfe33f9002606acef093441137181b327f6fe504884b20e2 + languageName: node + linkType: hard + "unist-util-position-from-estree@npm:^1.0.0, unist-util-position-from-estree@npm:^1.1.0": version: 1.1.2 resolution: "unist-util-position-from-estree@npm:1.1.2" @@ -17190,6 +17788,15 @@ __metadata: languageName: node linkType: hard +"unist-util-position@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-position@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: f89b27989b19f07878de9579cd8db2aa0194c8360db69e2c99bd2124a480d79c08f04b73a64daf01a8fb3af7cba65ff4b45a0b978ca243226084ad5f5d441dde + languageName: node + linkType: hard + "unist-util-remove-position@npm:^4.0.0": version: 4.0.2 resolution: "unist-util-remove-position@npm:4.0.2" @@ -17209,6 +17816,15 @@ __metadata: languageName: node linkType: hard +"unist-util-stringify-position@npm:^4.0.0": + version: 4.0.0 + resolution: "unist-util-stringify-position@npm:4.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: e2e7aee4b92ddb64d314b4ac89eef7a46e4c829cbd3ee4aee516d100772b490eb6b4974f653ba0717a0071ca6ea0770bf22b0a2ea62c65fcba1d071285e96324 + languageName: node + linkType: hard + "unist-util-visit-parents@npm:^5.1.1": version: 5.1.3 resolution: "unist-util-visit-parents@npm:5.1.3" @@ -17219,6 +17835,16 @@ __metadata: languageName: node linkType: hard +"unist-util-visit-parents@npm:^6.0.0": + version: 6.0.1 + resolution: "unist-util-visit-parents@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + checksum: 08927647c579f63b91aafcbec9966dc4a7d0af1e5e26fc69f4e3e6a01215084835a2321b06f3cbe7bf7914a852830fc1439f0fc3d7153d8804ac3ef851ddfa20 + languageName: node + linkType: hard + "unist-util-visit@npm:^4.0.0": version: 4.1.2 resolution: "unist-util-visit@npm:4.1.2" @@ -17230,6 +17856,17 @@ __metadata: languageName: node linkType: hard +"unist-util-visit@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-visit@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 9ec42e618e7e5d0202f3c191cd30791b51641285732767ee2e6bcd035931032e3c1b29093f4d7fd0c79175bbc1f26f24f26ee49770d32be76f8730a652a857e6 + languageName: node + linkType: hard + "universal-user-agent@npm:^6.0.0": version: 6.0.0 resolution: "universal-user-agent@npm:6.0.0" @@ -17449,6 +18086,26 @@ __metadata: languageName: node linkType: hard +"vfile-location@npm:^5.0.0": + version: 5.0.2 + resolution: "vfile-location@npm:5.0.2" + dependencies: + "@types/unist": ^3.0.0 + vfile: ^6.0.0 + checksum: b61c048cedad3555b4f007f390412c6503f58a6a130b58badf4ee340c87e0d7421e9c86bbc1494c57dedfccadb60f5176cc60ba3098209d99fb3a3d8804e4c38 + languageName: node + linkType: hard + +"vfile-matter@npm:^5.0.0": + version: 5.0.0 + resolution: "vfile-matter@npm:5.0.0" + dependencies: + vfile: ^6.0.0 + yaml: ^2.0.0 + checksum: 713327640ebc9579f82e8fb1586613bad4d43d969e29feceaf5c4231402d320abef67d2f36369e68c52329cc1d7971a3aba2e6f992103af7ef0d1159f301a4c0 + languageName: node + linkType: hard + "vfile-message@npm:^3.0.0": version: 3.1.4 resolution: "vfile-message@npm:3.1.4" @@ -17459,6 +18116,16 @@ __metadata: languageName: node linkType: hard +"vfile-message@npm:^4.0.0": + version: 4.0.2 + resolution: "vfile-message@npm:4.0.2" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 964e7e119f4c0e0270fc269119c41c96da20afa01acb7c9809a88365c8e0c64aa692fafbd952669382b978002ecd7ad31ef4446d85e8a22cdb62f6df20186c2d + languageName: node + linkType: hard + "vfile@npm:^5.0.0": version: 5.3.7 resolution: "vfile@npm:5.3.7" @@ -17471,6 +18138,17 @@ __metadata: languageName: node linkType: hard +"vfile@npm:^6.0.0": + version: 6.0.1 + resolution: "vfile@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + vfile-message: ^4.0.0 + checksum: 05ccee73aeb00402bc8a5d0708af299e9f4a33f5132805449099295085e3ca3b0d018328bad9ff44cf2e6f4cd364f1d558d3fb9b394243a25b2739207edcb0ed + languageName: node + linkType: hard + "vite-node@npm:^0.28.5": version: 0.28.5 resolution: "vite-node@npm:0.28.5" @@ -17613,6 +18291,13 @@ __metadata: languageName: node linkType: hard +"web-namespaces@npm:^2.0.0": + version: 2.0.1 + resolution: "web-namespaces@npm:2.0.1" + checksum: b6d9f02f1a43d0ef0848a812d89c83801d5bbad57d8bb61f02eb6d7eb794c3736f6cc2e1191664bb26136594c8218ac609f4069722c6f56d9fc2d808fa9271c6 + languageName: node + linkType: hard + "web-vitals@npm:0.2.4": version: 0.2.4 resolution: "web-vitals@npm:0.2.4" @@ -18001,6 +18686,13 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.0.0": + version: 2.3.4 + resolution: "yaml@npm:2.3.4" + checksum: e6d1dae1c6383bcc8ba11796eef3b8c02d5082911c6723efeeb5ba50fc8e881df18d645e64de68e421b577296000bea9c75d6d9097c2f6699da3ae0406c030d8 + languageName: node + linkType: hard + "yaml@npm:^2.1.1, yaml@npm:^2.2.1": version: 2.2.1 resolution: "yaml@npm:2.2.1" @@ -18165,7 +18857,7 @@ __metadata: languageName: node linkType: hard -"zwitch@npm:^2.0.0": +"zwitch@npm:^2.0.0, zwitch@npm:^2.0.4": version: 2.0.4 resolution: "zwitch@npm:2.0.4" checksum: f22ec5fc2d5f02c423c93d35cdfa83573a3a3bd98c66b927c368ea4d0e7252a500df2a90a6b45522be536a96a73404393c958e945fdba95e6832c200791702b6