Adds dev server

This commit is contained in:
Steve Ruiz 2021-08-10 18:19:30 +01:00
parent 5998879e24
commit 4ac1b93f96
22 changed files with 1165 additions and 1896 deletions

View file

@ -1,11 +1,15 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
plugins: ['@typescript-eslint'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
overrides: [
{
// enable the rule specifically for TypeScript files
files: ['*.ts', '*.tsx'],
rules: {
'@typescript-eslint/explicit-module-boundary-types': [false],
},
},
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
};
}

View file

@ -9,6 +9,6 @@
"packages": [
"packages/core",
"packages/tldraw",
"packages/www"
"packages/dev"
]
}
}

View file

@ -10,8 +10,18 @@
"license": "MIT",
"version": "0.0.36",
"workspaces": [
"packages/*"
"packages/core",
"packages/tldraw",
"packages/dev"
],
"scripts": {
"test": "jest",
"lerna": "lerna",
"start": "lerna run dev --stream --parallel",
"start:www": "lerna run dev --stream --parallel & cd packages/www && yarn build",
"build": "yarn build:packages && cd packages/www && yarn build",
"build:packages": "cd packages/core && yarn build && cd ../tldraw && yarn build"
},
"devDependencies": {
"@babel/plugin-syntax-import-meta": "^7.10.4",
"@babel/preset-react": "^7.14.5",
@ -32,20 +42,13 @@
"tslib": "^2.3.0",
"typescript": "^4.3.5"
},
"scripts": {
"test": "jest",
"lerna": "lerna",
"start": "lerna run dev --stream --parallel",
"build": "yarn build:packages && cd packages/www && yarn build",
"build:packages": "cd packages/core && yarn build && cd ../tldraw && yarn build"
},
"dependencies": {},
"prettier": {
"trailingComma": "es5",
"singleQuote": true,
"semi": false,
"printWidth": 100
},
"dependencies": {},
"jest": {
"preset": "ts-jest",
"transform": {

View file

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import * as React from 'react'
export function usePreventNavigation(rCanvas: React.RefObject<SVGGElement>) {
export function usePreventNavigation(rCanvas: React.RefObject<SVGGElement>): void {
React.useEffect(() => {
const preventGestureNavigation = (event: TouchEvent) => {
event.preventDefault()
@ -27,7 +27,7 @@ export function usePreventNavigation(rCanvas: React.RefObject<SVGGElement>) {
const elm = rCanvas.current
if (!elm) return () => {}
if (!elm) return () => void null
elm.addEventListener('touchstart', preventGestureNavigation)

View file

@ -41,7 +41,7 @@ function useTheme<T = AnyTheme>(prefix: string, theme: T, selector = ':root') {
function useStyle(uid: string, rules: string) {
React.useLayoutEffect(() => {
if (styles.get(uid)) {
return () => {}
return () => void null
}
const style = document.createElement('style')

View file

@ -15,6 +15,8 @@ export function useZoomEvents() {
useWheel(
({ event: e, delta }) => {
e.preventDefault()
if (Vec.isEqual(delta, [0, 0])) return
const info = inputs.pan(delta, e as WheelEvent)

18
packages/dev/README.md Normal file
View file

@ -0,0 +1,18 @@
# react-esbuild-starter
Starter template for React and Typescript.
Inspired by https://github.com/sikanhe/rescript-esbuild-starter
It provides minimal yet 🔥 blazing fast ™ development boilerplate for rapid React prototyping.
- `yarn start` Starts typescript typechecking and esbuild in watch mode, and serves web page at localhost:5000.
- `yarn build` Builds production bundle for browser, outputs bundle to dist/bundle.js with source map.
- `yarn clean` Clean up assets produced by esbuild.
All code bundling and transpilation is handled by esbuild. Its configuration is kept inside `esbuild.config.mjs`. Follow [esbuild docs](https://esbuild.github.io/getting-started/) to see all supported options.
### Caveats
- No output file hashing
- No test runner
- Importing CSS in JS file is not supported in esbuild yet. It is currently in development https://github.com/evanw/esbuild/issues/20. In meantime either opt-in for some CSS-in-JS solution, or include styles directly in `www/index.html`.

View file

@ -0,0 +1,34 @@
/* eslint-disable no-undef */
import esbuild from 'esbuild'
import serve, { error, log } from 'create-serve'
const isDevServer = process.argv.includes('--dev')
esbuild
.build({
entryPoints: ['src/index.tsx'],
bundle: true,
outfile: 'dist/bundle.js',
minify: false,
sourcemap: true,
incremental: isDevServer,
target: ['chrome58', 'firefox57', 'safari11', 'edge18'],
define: {
'process.env.NODE_ENV': isDevServer ? '"development"' : '"production"',
},
watch: isDevServer && {
onRebuild(err) {
serve.update()
err ? error('❌ Failed') : log('✅ Updated')
},
},
})
.catch(() => process.exit(1))
if (isDevServer) {
serve.start({
port: 5000,
root: './dist',
live: true,
})
}

34
packages/dev/package.json Normal file
View file

@ -0,0 +1,34 @@
{
"name": "react-esbuild-starter",
"version": "2.1.0",
"private": true,
"description": "Starter template for React + Typescript, powered by Esbuild",
"repository": "https://github.com/belaczek/react-esbuild-starter.git",
"author": "Tomas Belada <tomas@belada.net>",
"license": "MIT",
"keywords": [
"react",
"typescript",
"esbuild"
],
"scripts": {
"dev": "node ./esbuild.config.mjs --dev tsc --watch",
"test": "echo 'TODO'"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"@tldraw/tldraw": "*",
"idb": "^6.1.2"
},
"devDependencies": {
"@types/node": "^14.14.35",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"concurrently": "6.0.1",
"create-serve": "1.0.1",
"esbuild": "0.11.5",
"rimraf": "3.0.2",
"typescript": "4.2.3"
}
}

6
packages/dev/src/app.tsx Normal file
View file

@ -0,0 +1,6 @@
import * as React from 'react'
import Editor from './components/editor'
export default function App(): JSX.Element {
return <Editor />
}

View file

@ -0,0 +1,99 @@
import * as React from 'react'
import { ColorStyle, DashStyle, SizeStyle, TLDrawShapeType, TLDrawState } from '@tldraw/tldraw'
import { TLDraw, TLDrawDocument } from '@tldraw/tldraw'
import { usePersistence } from '../hooks/usePersistence'
const initialDoc: TLDrawDocument = {
id: 'doc',
pages: {
page1: {
id: 'page1',
shapes: {
rect1: {
id: 'rect1',
parentId: 'page1',
name: 'Rectangle',
childIndex: 1,
type: TLDrawShapeType.Rectangle,
point: [32, 32],
size: [100, 100],
style: {
dash: DashStyle.Draw,
size: SizeStyle.Medium,
color: ColorStyle.Blue,
},
},
ellipse1: {
id: 'ellipse1',
parentId: 'page1',
name: 'Ellipse',
childIndex: 2,
type: TLDrawShapeType.Ellipse,
point: [132, 132],
radius: [50, 50],
style: {
dash: DashStyle.Draw,
size: SizeStyle.Medium,
color: ColorStyle.Cyan,
},
},
draw1: {
id: 'draw1',
parentId: 'page1',
name: 'Draw',
childIndex: 3,
type: TLDrawShapeType.Draw,
point: [232, 232],
points: [
[50, 0],
[100, 100],
[0, 100],
[50, 0],
[100, 100],
[0, 100],
[50, 0],
[56, 5],
],
style: {
dash: DashStyle.Draw,
size: SizeStyle.Medium,
color: ColorStyle.Green,
},
},
},
bindings: {},
},
},
pageStates: {
page1: {
id: 'page1',
selectedIds: [],
currentParentId: 'page1',
camera: {
point: [0, 0],
zoom: 1,
},
},
},
}
export default function Editor(): JSX.Element {
const { value, setValue, status } = usePersistence('doc', initialDoc)
const handleChange = React.useCallback(
(tlstate: TLDrawState, reason: string) => {
if (reason.startsWith('session')) {
return
}
setValue(tlstate.document)
},
[setValue]
)
if (status === 'loading' || value === null) {
return <div />
}
return <TLDraw document={value} onChange={handleChange} />
}

View file

@ -0,0 +1,93 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import * as React from 'react'
import { openDB, DBSchema } from 'idb'
import type { TLDrawDocument } from '@tldraw/tldraw'
interface TLDatabase extends DBSchema {
documents: {
key: string
value: TLDrawDocument
}
}
/**
* Persist a value in indexdb. This hook is designed to be used primarily through
* its methods, `setValue` and `forceUpdate`. The `setValue` method will update the
* value in the database, howeever it will NOT cause the hook's component to update.
* The `forceUpdate` method will cause the component to update with the latest value
* in the database.
*
* ### Example
*
*```ts
* const {status, value, setValue, forceUpdate} = usePersistence()
*```
*/
export function usePersistence(id: string, doc: TLDrawDocument) {
const [status, setStatus] = React.useState<'loading' | 'ready'>('loading')
const [value, _setValue] = React.useState<TLDrawDocument | null>(null)
// A function that other parts of the program can use to manually update
// the state to the latest value in the database.
const forceUpdate = React.useCallback(() => {
_setValue(null)
setStatus('loading')
openDB<TLDatabase>('db', 1).then((db) =>
db.get('documents', id).then((v) => {
if (!v) throw Error(`Could not find document with id: ${id}`)
_setValue(v)
setStatus('ready')
})
)
}, [id])
// A function that other parts of the program can use to manually set the
// value in the database.
const setValue = React.useCallback(
(doc: TLDrawDocument) => {
openDB<TLDatabase>('db', 1).then((db) => db.put('documents', doc, id))
},
[id]
)
// Whenever the id or doc changes, save the new value to the database and update
// the state.
React.useEffect(() => {
async function handleLoad() {
const db = await openDB<TLDatabase>('db', 1, {
upgrade(db) {
db.createObjectStore('documents')
},
})
let savedDoc: TLDrawDocument
try {
const restoredDoc = await db.get('documents', id)
if (!restoredDoc) throw Error('No document')
savedDoc = restoredDoc
restoredDoc.pageStates = Object.fromEntries(
Object.entries(restoredDoc.pageStates).map(([pageId, pageState]) => [
pageId,
{
...pageState,
hoveredId: undefined,
editingId: undefined,
},
])
)
} catch (e) {
await db.put('documents', doc, id)
savedDoc = doc
}
_setValue(savedDoc)
setStatus('ready')
}
handleLoad()
}, [id, doc])
return { value, status, setValue, forceUpdate }
}

View file

@ -0,0 +1,10 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './app'
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)

View file

@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.json",
"include": ["src"],
"exclude": ["node_modules", "**/*.test.ts", "dist"],
"compilerOptions": {
"jsx": "preserve",
"lib": ["dom", "esnext"],
"module": "esnext",
"outDir": "./dist/types"
}
}

559
packages/dev/yarn.lock Normal file
View file

@ -0,0 +1,559 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@babel/code-frame@^7.0.0":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658"
integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==
dependencies:
"@babel/highlight" "^7.12.13"
"@babel/helper-validator-identifier@^7.12.11":
version "7.12.11"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
"@babel/highlight@^7.12.13":
version "7.13.10"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1"
integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==
dependencies:
"@babel/helper-validator-identifier" "^7.12.11"
chalk "^2.0.0"
js-tokens "^4.0.0"
"@types/node@14.14.35":
version "14.14.35"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.35.tgz#42c953a4e2b18ab931f72477e7012172f4ffa313"
integrity sha512-Lt+wj8NVPx0zUmUwumiVXapmaLUcAk3yPuHCFVXras9k5VT9TdhJqKqGVUQCD60OTMCl0qxJ57OiTL0Mic3Iag==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
"@types/prop-types@*":
version "15.7.3"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
"@types/react-dom@17.0.2":
version "17.0.2"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.2.tgz#35654cf6c49ae162d5bc90843d5437dc38008d43"
integrity sha512-Icd9KEgdnFfJs39KyRyr0jQ7EKhq8U6CcHRMGAS45fp5qgUvxL3ujUCfWFttUK2UErqZNj97t9gsVPNAqcwoCg==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@17.0.3":
version "17.0.3"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79"
integrity sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/scheduler@*":
version "0.16.1"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275"
integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==
ansi-regex@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
dependencies:
color-convert "^1.9.0"
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
chalk@^2.0.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
wrap-ansi "^7.0.0"
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
dependencies:
color-name "1.1.3"
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
dependencies:
color-name "~1.1.4"
color-name@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
concurrently@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-6.0.1.tgz#b472efd9398bd9f5b117e22f72c3e50bf0a8a651"
integrity sha512-YCF/Wf31a910hXu7eGN9/SyHKD/usw3Shw4IPYuqIsxxC39v92engYlIlOs/zXnBJtX/6aVuhgzfhZeGJkhU4w==
dependencies:
chalk "^4.1.0"
date-fns "^2.16.1"
lodash "^4.17.20"
read-pkg "^5.2.0"
rxjs "^6.6.3"
spawn-command "^0.0.2-1"
supports-color "^8.1.0"
tree-kill "^1.2.2"
yargs "^16.2.0"
create-serve@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/create-serve/-/create-serve-1.0.1.tgz#a52ec4cbd2d0f776d3e42338fa1f0dae69080c59"
integrity sha512-cDAmBGhkwolS7ihq7SnPE8KwjYUZl5FaI9Pq5ZBwNelSKvFR9OoAA4/B5BfB/NC+eYaykBpX9RVMfuU4DHtrPw==
csstype@^3.0.2:
version "3.0.7"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b"
integrity sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g==
date-fns@^2.16.1:
version "2.19.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.19.0.tgz#65193348635a28d5d916c43ec7ce6fbd145059e1"
integrity sha512-X3bf2iTPgCAQp9wvjOQytnf5vO5rESYRXlPIVcgSbtT5OTScPcsf9eZU+B/YIkKAtYr5WeCii58BgATrNitlWg==
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
dependencies:
is-arrayish "^0.2.1"
esbuild@0.11.5:
version "0.11.5"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.11.5.tgz#25b18a2ff2fb9580683edce26a48f64c08c2f2df"
integrity sha512-aRs6jAE+bVRp1tyfzUugAw1T/Y0Fwzp4Z2ROikF3h+UifoD5QlEbEYQGc6orNnnSIRhWR5VWBH7LozlAumaLHg==
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
glob@^7.1.3:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
hosted-git-info@^2.1.4:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-core-module@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
dependencies:
has "^1.0.3"
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
json-parse-even-better-errors@^2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
lines-and-columns@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
lodash@^4.17.20:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
loose-envify@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
dependencies:
brace-expansion "^1.1.7"
normalize-package-data@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
dependencies:
hosted-git-info "^2.1.4"
resolve "^1.10.0"
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
parse-json@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
dependencies:
"@babel/code-frame" "^7.0.0"
error-ex "^1.3.1"
json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
path-parse@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
react-dom@17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
scheduler "^0.20.2"
react@17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
read-pkg@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==
dependencies:
"@types/normalize-package-data" "^2.4.0"
normalize-package-data "^2.5.0"
parse-json "^5.0.0"
type-fest "^0.6.0"
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
resolve@^1.10.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
dependencies:
is-core-module "^2.2.0"
path-parse "^1.0.6"
rimraf@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
dependencies:
glob "^7.1.3"
rxjs@^6.6.3:
version "6.6.6"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.6.tgz#14d8417aa5a07c5e633995b525e1e3c0dec03b70"
integrity sha512-/oTwee4N4iWzAMAL9xdGKjkEHmIwupR3oXbQjCKywF1BeFohswF3vZdogbmEF6pZkOsXTzWkrZszrWpQTByYVg==
dependencies:
tslib "^1.9.0"
scheduler@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
"semver@2 || 3 || 4 || 5":
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
spawn-command@^0.0.2-1:
version "0.0.2-1"
resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=
spdx-correct@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
dependencies:
spdx-expression-parse "^3.0.0"
spdx-license-ids "^3.0.0"
spdx-exceptions@^2.1.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
spdx-expression-parse@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
dependencies:
spdx-exceptions "^2.1.0"
spdx-license-ids "^3.0.0"
spdx-license-ids@^3.0.0:
version "3.0.7"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65"
integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
string-width@^4.1.0, string-width@^4.2.0:
version "4.2.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
strip-ansi@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
dependencies:
ansi-regex "^5.0.0"
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
dependencies:
has-flag "^3.0.0"
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"
supports-color@^8.1.0:
version "8.1.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
dependencies:
has-flag "^4.0.0"
tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
type-fest@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
typescript@4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3"
integrity sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==
validate-npm-package-license@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
dependencies:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
y18n@^5.0.5:
version "5.0.5"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18"
integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==
yargs-parser@^20.2.2:
version "20.2.7"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a"
integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==
yargs@^16.2.0:
version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
dependencies:
cliui "^7.0.2"
escalade "^3.1.1"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
string-width "^4.2.0"
y18n "^5.0.5"
yargs-parser "^20.2.2"

View file

@ -1,7 +1,7 @@
import * as React from 'react'
import { useTLDrawContext } from '../hooks'
import type { Data } from '../state'
import styled from '../styles'
import { useTLDrawContext } from '../../hooks'
import type { Data } from '../../state'
import styled from '../../styles'
const activeToolSelector = (s: Data) => s.appState.activeTool

View file

@ -9,7 +9,7 @@ import {
TextIcon,
} from '@radix-ui/react-icons'
import * as React from 'react'
import { StatusBar } from '../status-bar'
import { StatusBar } from './status-bar'
import { FloatingContainer } from '../shared'
import { PrimaryButton, SecondaryButton } from './shared'
import styled from '../../styles'
@ -24,118 +24,118 @@ const activeToolSelector = (s: Data) => s.appState.activeTool
const isToolLockedSelector = (s: Data) => s.appState.isToolLocked
const isDebugModeSelector = (s: Data) => s.settings.isDebugMode
export const ToolsPanel = React.memo(
(): JSX.Element => {
const { tlstate, useSelector } = useTLDrawContext()
export const ToolsPanel = React.memo((): JSX.Element => {
const { tlstate, useSelector } = useTLDrawContext()
const activeTool = useSelector(activeToolSelector)
const activeTool = useSelector(activeToolSelector)
const isToolLocked = useSelector(isToolLockedSelector)
const isToolLocked = useSelector(isToolLockedSelector)
const isDebugMode = useSelector(isDebugModeSelector)
const isDebugMode = useSelector(isDebugModeSelector)
const selectSelectTool = React.useCallback(() => {
tlstate.selectTool('select')
}, [tlstate])
const selectSelectTool = React.useCallback(() => {
tlstate.selectTool('select')
}, [tlstate])
const selectDrawTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Draw)
}, [tlstate])
const selectDrawTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Draw)
}, [tlstate])
const selectRectangleTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Rectangle)
}, [tlstate])
const selectRectangleTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Rectangle)
}, [tlstate])
const selectEllipseTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Ellipse)
}, [tlstate])
const selectEllipseTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Ellipse)
}, [tlstate])
const selectArrowTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Arrow)
}, [tlstate])
const selectArrowTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Arrow)
}, [tlstate])
const selectTextTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Text)
}, [tlstate])
const selectTextTool = React.useCallback(() => {
tlstate.selectTool(TLDrawShapeType.Text)
}, [tlstate])
return (
<ToolsPanelContainer>
<LeftWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
<Zoom />
<FloatingContainer>
<SecondaryButton
label={'Select'}
kbd={'1'}
onClick={selectSelectTool}
isActive={activeTool === 'select'}
>
<CursorArrowIcon />
</SecondaryButton>
</FloatingContainer>
</LeftWrap>
<CenterWrap>
<BackToContent />
<FloatingContainer>
<PrimaryButton
kbd={'2'}
label={TLDrawShapeType.Draw}
onClick={selectDrawTool}
isActive={activeTool === TLDrawShapeType.Draw}
>
<Pencil1Icon />
</PrimaryButton>
<PrimaryButton
kbd={'3'}
label={TLDrawShapeType.Rectangle}
onClick={selectRectangleTool}
isActive={activeTool === TLDrawShapeType.Rectangle}
>
<SquareIcon />
</PrimaryButton>
<PrimaryButton
kbd={'4'}
label={TLDrawShapeType.Draw}
onClick={selectEllipseTool}
isActive={activeTool === TLDrawShapeType.Ellipse}
>
<CircleIcon />
</PrimaryButton>
<PrimaryButton
kbd={'5'}
label={TLDrawShapeType.Arrow}
onClick={selectArrowTool}
isActive={activeTool === TLDrawShapeType.Arrow}
>
<ArrowTopRightIcon />
</PrimaryButton>
<PrimaryButton
kbd={'6'}
label={TLDrawShapeType.Text}
onClick={selectTextTool}
isActive={activeTool === TLDrawShapeType.Text}
>
<TextIcon />
</PrimaryButton>
</FloatingContainer>
</CenterWrap>
<RightWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
<FloatingContainer>
<SecondaryButton
kbd={'7'}
label={'Lock Tool'}
onClick={tlstate.toggleToolLock}
isActive={isToolLocked}
>
{isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
</SecondaryButton>
</FloatingContainer>
<UndoRedo />
</RightWrap>
<StatusWrap>{isDebugMode && <StatusBar />}</StatusWrap>
</ToolsPanelContainer>
)
}
)
return (
<ToolsPanelContainer>
<LeftWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
<Zoom />
<FloatingContainer>
<SecondaryButton
label={'Select'}
kbd={'1'}
onClick={selectSelectTool}
isActive={activeTool === 'select'}
>
<CursorArrowIcon />
</SecondaryButton>
</FloatingContainer>
</LeftWrap>
<CenterWrap>
<BackToContent />
<FloatingContainer>
<PrimaryButton
kbd={'2'}
label={TLDrawShapeType.Draw}
onClick={selectDrawTool}
isActive={activeTool === TLDrawShapeType.Draw}
>
<Pencil1Icon />
</PrimaryButton>
<PrimaryButton
kbd={'3'}
label={TLDrawShapeType.Rectangle}
onClick={selectRectangleTool}
isActive={activeTool === TLDrawShapeType.Rectangle}
>
<SquareIcon />
</PrimaryButton>
<PrimaryButton
kbd={'4'}
label={TLDrawShapeType.Draw}
onClick={selectEllipseTool}
isActive={activeTool === TLDrawShapeType.Ellipse}
>
<CircleIcon />
</PrimaryButton>
<PrimaryButton
kbd={'5'}
label={TLDrawShapeType.Arrow}
onClick={selectArrowTool}
isActive={activeTool === TLDrawShapeType.Arrow}
>
<ArrowTopRightIcon />
</PrimaryButton>
<PrimaryButton
kbd={'6'}
label={TLDrawShapeType.Text}
onClick={selectTextTool}
isActive={activeTool === TLDrawShapeType.Text}
>
<TextIcon />
</PrimaryButton>
</FloatingContainer>
</CenterWrap>
<RightWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
<FloatingContainer>
<SecondaryButton
kbd={'7'}
label={'Lock Tool'}
onClick={tlstate.toggleToolLock}
isActive={isToolLocked}
>
{isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
</SecondaryButton>
</FloatingContainer>
<UndoRedo />
</RightWrap>
<StatusWrap>
<StatusBar />
</StatusWrap>
</ToolsPanelContainer>
)
})
const ToolsPanelContainer = styled('div', {
position: 'fixed',

View file

@ -18,13 +18,7 @@ import {
Vec,
} from '@tldraw/core'
import { brushUpdater } from '@tldraw/core'
import {
defaultStyle,
ShapeStyles,
TLDrawShape,
TLDrawShapeType,
TLDrawToolType,
} from '../shape'
import { defaultStyle, ShapeStyles, TLDrawShape, TLDrawShapeType, TLDrawToolType } from '../shape'
import type {
Data,
Session,
@ -45,19 +39,13 @@ import {
TextSession,
} from './session'
import { TLDR } from './tldr'
import {
TLDrawDocument,
MoveType,
AlignType,
StretchType,
DistributeType,
} from '../types'
import { TLDrawDocument, MoveType, AlignType, StretchType, DistributeType } from '../types'
const initialData: Data = {
settings: {
isPenMode: false,
isDarkMode: false,
isDebugMode: false,
isDebugMode: process.env.NODE_ENV === 'development',
isReadonlyMode: false,
nudgeDistanceLarge: 10,
nudgeDistanceSmall: 1,
@ -115,9 +103,7 @@ export class TLDrawState implements TLCallbacks {
// Low API
getState = this.store.getState
setState = <T extends keyof Data>(
data: Partial<Data> | ((data: Data) => Partial<Data>)
) => {
setState = <T extends keyof Data>(data: Partial<Data> | ((data: Data) => Partial<Data>)) => {
const current = this.getState()
// Apply incoming change
@ -130,11 +116,7 @@ export class TLDrawState implements TLCallbacks {
...next.page,
shapes: Object.fromEntries(
Object.entries(next.page.shapes).filter(([_, shape]) => {
return (
shape &&
(shape.parentId === next.page.id ||
next.page.shapes[shape.parentId])
)
return shape && (shape.parentId === next.page.id || next.page.shapes[shape.parentId])
})
),
}
@ -241,9 +223,7 @@ export class TLDrawState implements TLCallbacks {
...data.appState,
activeTool: tool,
activeToolType:
tool === 'select'
? 'select'
: TLDR.getShapeUtils({ type: tool } as TLDrawShape).toolType,
tool === 'select' ? 'select' : TLDR.getShapeUtils({ type: tool } as TLDrawShape).toolType,
},
}))
return this
@ -261,18 +241,14 @@ export class TLDrawState implements TLCallbacks {
/* --------------------- Camera --------------------- */
zoomIn = () => {
const i = Math.round(
(this.store.getState().pageState.camera.zoom * 100) / 25
)
const i = Math.round((this.store.getState().pageState.camera.zoom * 100) / 25)
const nextZoom = TLDR.getCameraZoom((i + 1) * 0.25)
this.zoomTo(nextZoom)
return this
}
zoomOut = () => {
const i = Math.round(
(this.store.getState().pageState.camera.zoom * 100) / 25
)
const i = Math.round((this.store.getState().pageState.camera.zoom * 100) / 25)
const nextZoom = TLDR.getCameraZoom((i - 1) * 0.25)
this.zoomTo(nextZoom)
return this
@ -284,9 +260,7 @@ export class TLDrawState implements TLCallbacks {
if (shapes.length === 0) return { pageState: data.pageState }
const bounds = Utils.getCommonBounds(
Object.values(shapes).map(TLDR.getBounds)
)
const bounds = Utils.getCommonBounds(Object.values(shapes).map(TLDR.getBounds))
const zoom = TLDR.getCameraZoom(
bounds.width > bounds.height
@ -313,8 +287,7 @@ export class TLDrawState implements TLCallbacks {
zoomToSelection = () => {
this.setState((data) => {
if (TLDR.getSelectedIds(data).length === 0)
return { pageState: data.pageState }
if (TLDR.getSelectedIds(data).length === 0) return { pageState: data.pageState }
const bounds = TLDR.getSelectedBounds(data)
@ -360,9 +333,7 @@ export class TLDrawState implements TLCallbacks {
if (shapes.length === 0) return { pageState: data.pageState }
const bounds = Utils.getCommonBounds(
Object.values(shapes).map(TLDR.getBounds)
)
const bounds = Utils.getCommonBounds(Object.values(shapes).map(TLDR.getBounds))
const { zoom } = data.pageState.camera
const mx = (window.innerWidth - bounds.width * zoom) / 2 / zoom
@ -452,10 +423,7 @@ export class TLDrawState implements TLCallbacks {
}
/* ---------------------- Document --------------------- */
loadDocument = (
document: TLDrawDocument,
onChange?: TLDrawState['_onChange']
) => {
loadDocument = (document: TLDrawDocument, onChange?: TLDrawState['_onChange']) => {
this._onChange = onChange
this.currentDocumentId = document.id
this.pages = Utils.deepClone(document.pages)
@ -489,19 +457,14 @@ export class TLDrawState implements TLCallbacks {
}
/* -------------------- Sessions -------------------- */
startSession<T extends Session>(
session: T,
...args: ParametersExceptFirst<T['start']>
) {
startSession<T extends Session>(session: T, ...args: ParametersExceptFirst<T['start']>) {
this.session = session
this.setState((data) => session.start(data, ...args))
this._onChange?.(this, `session:start_${session.id}`)
return this
}
updateSession<T extends Session>(
...args: ParametersExceptFirst<T['update']>
) {
updateSession<T extends Session>(...args: ParametersExceptFirst<T['update']>) {
const { session } = this
if (!session) return this
this.setState((data) => session.update(data, ...args))
@ -509,9 +472,7 @@ export class TLDrawState implements TLCallbacks {
return this
}
cancelSession<T extends Session>(
...args: ParametersExceptFirst<T['cancel']>
) {
cancelSession<T extends Session>(...args: ParametersExceptFirst<T['cancel']>) {
const { session } = this
if (!session) return this
@ -522,9 +483,7 @@ export class TLDrawState implements TLCallbacks {
return this
}
completeSession<T extends Session>(
...args: ParametersExceptFirst<T['complete']>
) {
completeSession<T extends Session>(...args: ParametersExceptFirst<T['complete']>) {
const { session } = this
if (!session) return this
@ -560,9 +519,7 @@ export class TLDrawState implements TLCallbacks {
history.pointer = history.stack.length - 1
this.setState((data) =>
Utils.deepMerge<Data>(data, history.stack[history.pointer].after)
)
this.setState((data) => Utils.deepMerge<Data>(data, history.stack[history.pointer].after))
this._onChange?.(this, `command:${command.id}`)
@ -607,9 +564,7 @@ export class TLDrawState implements TLCallbacks {
return {
pageState: {
...data.pageState,
selectedIds: push
? [...data.pageState.selectedIds, ...ids]
: [...ids],
selectedIds: push ? [...data.pageState.selectedIds, ...ids] : [...ids],
},
}
})
@ -715,9 +670,7 @@ export class TLDrawState implements TLCallbacks {
nudge = (delta: number[], isMajor = false, ids?: string[]) => {
const data = this.store.getState()
const idsToMutate = ids ? ids : data.pageState.selectedIds
this.do(
commands.translate(data, idsToMutate, Vec.mul(delta, isMajor ? 10 : 1))
)
this.do(commands.translate(data, idsToMutate, Vec.mul(delta, isMajor ? 10 : 1)))
return this
}
@ -846,20 +799,14 @@ export class TLDrawState implements TLCallbacks {
} catch (e) {
// Create a text shape from the given string
const childIndex =
Object.values(data.page.shapes).sort(
(a, b) => b.childIndex - a.childIndex
)[0].childIndex + 1
Object.values(data.page.shapes).sort((a, b) => b.childIndex - a.childIndex)[0]
.childIndex + 1
const shape = TLDR.getShapeUtils<TextShape>(
TLDrawShapeType.Text
).create({
const shape = TLDR.getShapeUtils<TextShape>(TLDrawShapeType.Text).create({
id: Utils.uniqueId(),
parentId: data.page.id,
childIndex,
point: this.getPagePoint([
window.innerWidth / 2,
window.innerHeight / 2,
]),
point: this.getPagePoint([window.innerWidth / 2, window.innerHeight / 2]),
style: { ...data.appState.currentStyle },
})
@ -888,19 +835,14 @@ export class TLDrawState implements TLCallbacks {
}
})
const commonBounds = Utils.getCommonBounds(
shapesToPaste.map(TLDR.getBounds)
)
const commonBounds = Utils.getCommonBounds(shapesToPaste.map(TLDR.getBounds))
const centeredBounds = Utils.centerBounds(
commonBounds,
this.getPagePoint([window.innerWidth / 2, window.innerHeight / 2])
)
let delta = Vec.sub(
Utils.getBoundsCenter(centeredBounds),
Utils.getBoundsCenter(commonBounds)
)
let delta = Vec.sub(Utils.getBoundsCenter(centeredBounds), Utils.getBoundsCenter(commonBounds))
if (Vec.isEqual(delta, [0, 0])) {
delta = [16, 16]
@ -948,11 +890,7 @@ export class TLDrawState implements TLCallbacks {
return this
}
updateTranslateSession = (
point: number[],
shiftKey = false,
altKey = false
) => {
updateTranslateSession = (point: number[], shiftKey = false, altKey = false) => {
this.updateSession<TranslateSession>(point, shiftKey, altKey)
return this
}
@ -983,26 +921,14 @@ export class TLDrawState implements TLCallbacks {
)
} else {
this.startSession(
new TransformSession(
this.store.getState(),
point,
this.pointedBoundsHandle
)
new TransformSession(this.store.getState(), point, this.pointedBoundsHandle)
)
}
return this
}
updateTransformSession = (
point: number[],
shiftKey = false,
altKey = false
) => {
this.updateSession<TransformSingleSession | TransformSession>(
point,
shiftKey,
altKey
)
updateTransformSession = (point: number[], shiftKey = false, altKey = false) => {
this.updateSession<TransformSingleSession | TransformSession>(point, shiftKey, altKey)
return this
}
@ -1029,23 +955,14 @@ export class TLDrawState implements TLCallbacks {
return this
}
startHandleSession = (
point: number[],
handleId: string,
commandId?: string
) => {
startHandleSession = (point: number[], handleId: string, commandId?: string) => {
this.startSession<HandleSession>(
new HandleSession(this.store.getState(), handleId, point, commandId)
)
return this
}
updateHandleSession = (
point: number[],
shiftKey = false,
altKey = false,
metaKey = false
) => {
updateHandleSession = (point: number[], shiftKey = false, altKey = false, metaKey = false) => {
this.updateSession<HandleSession>(point, shiftKey, altKey, metaKey)
return this
}
@ -1055,20 +972,14 @@ export class TLDrawState implements TLCallbacks {
case 'pointingBoundsHandle': {
if (Vec.dist(info.origin, info.point) > 4) {
this.setStatus('transforming')
this.startTransformSession(
this.getPagePoint(info.origin),
this.pointedBoundsHandle!
)
this.startTransformSession(this.getPagePoint(info.origin), this.pointedBoundsHandle!)
}
break
}
case 'pointingHandle': {
if (Vec.dist(info.origin, info.point) > 4) {
this.setStatus('translatingHandle')
this.startHandleSession(
this.getPagePoint(info.origin),
this.pointedHandle!
)
this.startHandleSession(this.getPagePoint(info.origin), this.pointedHandle!)
}
break
}
@ -1084,52 +995,29 @@ export class TLDrawState implements TLCallbacks {
break
}
case 'translating': {
this.updateTranslateSession(
this.getPagePoint(info.point),
info.shiftKey,
info.altKey
)
this.updateTranslateSession(this.getPagePoint(info.point), info.shiftKey, info.altKey)
break
}
case 'transforming': {
this.updateTransformSession(
this.getPagePoint(info.point),
info.shiftKey,
info.altKey
)
this.updateTransformSession(this.getPagePoint(info.point), info.shiftKey, info.altKey)
break
}
case 'translatingHandle': {
this.updateHandleSession(
this.getPagePoint(info.point),
info.shiftKey,
info.altKey
)
this.updateHandleSession(this.getPagePoint(info.point), info.shiftKey, info.altKey)
break
}
case 'creating': {
switch (this.appState.activeToolType) {
case 'draw': {
this.updateDrawSession(
this.getPagePoint(info.point),
info.pressure,
info.shiftKey
)
this.updateDrawSession(this.getPagePoint(info.point), info.pressure, info.shiftKey)
break
}
case 'bounds': {
this.updateTransformSession(
this.getPagePoint(info.point),
info.shiftKey
)
this.updateTransformSession(this.getPagePoint(info.point), info.shiftKey)
break
}
case 'handle': {
this.updateHandleSession(
this.getPagePoint(info.point),
info.shiftKey,
info.altKey
)
this.updateHandleSession(this.getPagePoint(info.point), info.shiftKey, info.altKey)
break
}
case 'point': {
@ -1193,11 +1081,7 @@ export class TLDrawState implements TLCallbacks {
break
}
case TLDrawToolType.Bounds: {
this.startTransformSession(
pagePoint,
TLBoundsCorner.BottomRight,
`create_${activeTool}`
)
this.startTransformSession(pagePoint, TLBoundsCorner.BottomRight, `create_${activeTool}`)
break
}
case TLDrawToolType.Handle: {
@ -1242,11 +1126,7 @@ export class TLDrawState implements TLCallbacks {
}
if (key === 'Shift' || key === 'Alt') {
this.updateTranslateSession(
this.getPagePoint(info.point),
info.shiftKey,
info.altKey
)
this.updateTranslateSession(this.getPagePoint(info.point), info.shiftKey, info.altKey)
}
break
}
@ -1256,11 +1136,7 @@ export class TLDrawState implements TLCallbacks {
}
if (key === 'Shift' || key === 'Alt') {
this.updateTransformSession(
this.getPagePoint(info.point),
info.shiftKey,
info.altKey
)
this.updateTransformSession(this.getPagePoint(info.point), info.shiftKey, info.altKey)
}
break
}
@ -1277,21 +1153,13 @@ export class TLDrawState implements TLCallbacks {
}
case 'transforming': {
if (key === 'Shift' || key === 'Alt') {
this.updateTransformSession(
this.getPagePoint(info.point),
info.shiftKey,
info.altKey
)
this.updateTransformSession(this.getPagePoint(info.point), info.shiftKey, info.altKey)
}
break
}
case 'translating': {
if (key === 'Shift' || key === 'Alt') {
this.updateTransformSession(
this.getPagePoint(info.point),
info.shiftKey,
info.altKey
)
this.updateTransformSession(this.getPagePoint(info.point), info.shiftKey, info.altKey)
}
break
}
@ -1380,9 +1248,7 @@ export class TLDrawState implements TLCallbacks {
if (info.shiftKey) {
// Unless we just shift-selected the shape, remove it from the selected shapes
if (this.pointedId !== info.target) {
this.setSelectedIds(
data.pageState.selectedIds.filter((id) => id !== info.target)
)
this.setSelectedIds(data.pageState.selectedIds.filter((id) => id !== info.target))
}
}
} else if (this.pointedId === info.target) {

View file

@ -6,6 +6,9 @@
"jsx": "preserve",
"lib": ["dom", "esnext"],
"module": "esnext",
"outDir": "./dist/types"
"outDir": "./dist/types",
"paths": {
"@tldraw/core": ["packages/core/dist"]
}
}
}

View file

@ -19,7 +19,7 @@
},
"dependencies": {
"@stitches/react": "^0.2.3",
"@tldraw/tldraw": "latest",
"@tldraw/tldraw": "*",
"idb": "^6.1.2",
"next": "^11.0.1",
"next-transpile-modules": "^8.0.0",
@ -36,4 +36,4 @@
"eslint-config-next": "11.0.1",
"typescript": "^4.3.5"
}
}
}

View file

@ -26,7 +26,7 @@
"strictFunctionTypes": true /* Enable strict checking of function types. */,
"strictNullChecks": true /* Enable strict null checks. */,
"target": "es5",
"typeRoots": ["node_modules/@types"],
"typeRoots": ["node_modules/@types", "node_modules/jest"],
"types": ["node", "jest"],
"paths": {
"@tldraw/*": ["./packages/*"]

1699
yarn.lock

File diff suppressed because it is too large Load diff