@tldraw/editor 3.16.0-canary.4c3f2b4783e6 → 3.16.0-canary.5170ef6b6e20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +33 -0
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +11 -10
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +13 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgJsx.js +34 -14
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +7 -5
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/license/LicenseManager.js +17 -22
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/license/LicenseProvider.js +5 -0
- package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
- package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +3 -0
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +33 -0
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +11 -10
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +13 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +34 -14
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +7 -5
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseManager.mjs +17 -22
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseProvider.mjs +5 -0
- package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
- package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +4 -1
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +8 -0
- package/package.json +7 -7
- package/src/index.ts +1 -0
- package/src/lib/components/default-components/DefaultCanvas.tsx +3 -1
- package/src/lib/editor/Editor.ts +19 -21
- package/src/lib/editor/shapes/ShapeUtil.ts +35 -0
- package/src/lib/exports/getSvgJsx.test.ts +868 -0
- package/src/lib/exports/getSvgJsx.tsx +76 -19
- package/src/lib/hooks/useCanvasEvents.ts +6 -6
- package/src/lib/license/LicenseManager.test.ts +58 -51
- package/src/lib/license/LicenseManager.ts +32 -24
- package/src/lib/license/LicenseProvider.tsx +8 -0
- package/src/lib/license/useLicenseManagerState.ts +2 -2
- package/src/lib/primitives/Box.test.ts +126 -0
- package/src/lib/primitives/Box.ts +10 -1
- package/src/version.ts +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/license/LicenseManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { atom } from '@tldraw/state'\nimport { fetch } from '@tldraw/utils'\nimport { publishDates } from '../../version'\nimport { getDefaultCdnBaseUrl } from '../utils/assets'\nimport { importPublicKey, str2ab } from '../utils/licensing'\n\nconst GRACE_PERIOD_DAYS = 5\n\nexport const FLAGS = {\n\tANNUAL_LICENSE: 0x1,\n\tPERPETUAL_LICENSE: 0x2,\n\tINTERNAL_LICENSE: 0x4,\n\tWITH_WATERMARK: 0x8,\n}\nconst HIGHEST_FLAG = Math.max(...Object.values(FLAGS))\n\nexport const PROPERTIES = {\n\tID: 0,\n\tHOSTS: 1,\n\tFLAGS: 2,\n\tEXPIRY_DATE: 3,\n}\nconst NUMBER_OF_KNOWN_PROPERTIES = Object.keys(PROPERTIES).length\n\nconst LICENSE_EMAIL = 'sales@tldraw.com'\n\nconst WATERMARK_TRACK_SRC = `${getDefaultCdnBaseUrl()}/watermarks/watermark-track.svg`\n\n/** @internal */\nexport interface LicenseInfo {\n\tid: string\n\thosts: string[]\n\tflags: number\n\texpiryDate: string\n}\n/** @internal */\nexport type InvalidLicenseReason =\n\t| 'invalid-license-key'\n\t| 'no-key-provided'\n\t| 'has-key-development-mode'\n\n/** @internal */\nexport type LicenseFromKeyResult = InvalidLicenseKeyResult | ValidLicenseKeyResult\n\n/** @internal */\nexport interface InvalidLicenseKeyResult {\n\tisLicenseParseable: false\n\treason: InvalidLicenseReason\n}\n\n/** @internal */\nexport interface ValidLicenseKeyResult {\n\tisLicenseParseable: true\n\tlicense: LicenseInfo\n\tisDevelopment: boolean\n\tisDomainValid: boolean\n\texpiryDate: Date\n\tisAnnualLicense: boolean\n\tisAnnualLicenseExpired: boolean\n\tisPerpetualLicense: boolean\n\tisPerpetualLicenseExpired: boolean\n\tisInternalLicense: boolean\n\tisLicensedWithWatermark: boolean\n}\n\n/** @internal */\nexport type TestEnvironment = 'development' | 'production'\n\n/** @internal */\nexport class LicenseManager {\n\tprivate publicKey =\n\t\t'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHJh0uUfxHtCGyerXmmatE368Hd9rI6LH9oPDQihnaCryRFWEVeOvf9U/SPbyxX74LFyJs5tYeAHq5Nc0Ax25LQ'\n\tpublic isDevelopment: boolean\n\tpublic isTest: boolean\n\tpublic isCryptoAvailable: boolean\n\tstate = atom<'pending' | 'licensed' | 'licensed-with-watermark' | 'unlicensed'>(\n\t\t'license state',\n\t\t'pending'\n\t)\n\tpublic verbose = true\n\n\tconstructor(\n\t\tlicenseKey: string | undefined,\n\t\ttestPublicKey?: string,\n\t\ttestEnvironment?: TestEnvironment\n\t) {\n\t\tthis.isTest = process.env.NODE_ENV === 'test'\n\t\tthis.isDevelopment = this.getIsDevelopment(testEnvironment)\n\t\tthis.publicKey = testPublicKey || this.publicKey\n\t\tthis.isCryptoAvailable = !!crypto.subtle\n\n\t\tthis.getLicenseFromKey(licenseKey).then((result) => {\n\t\t\tconst isUnlicensed = isEditorUnlicensed(result)\n\n\t\t\tif (!this.isDevelopment && isUnlicensed) {\n\t\t\t\tfetch(WATERMARK_TRACK_SRC)\n\t\t\t}\n\n\t\t\tif (isUnlicensed) {\n\t\t\t\tthis.state.set('unlicensed')\n\t\t\t} else if ((result as ValidLicenseKeyResult).isLicensedWithWatermark) {\n\t\t\t\tthis.state.set('licensed-with-watermark')\n\t\t\t} else {\n\t\t\t\tthis.state.set('licensed')\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate getIsDevelopment(testEnvironment?: TestEnvironment) {\n\t\tif (testEnvironment === 'development') return true\n\t\tif (testEnvironment === 'production') return false\n\n\t\t// If we are using https on a non-localhost domain we assume it's a production env and a development one otherwise\n\t\treturn (\n\t\t\t!['https:', 'vscode-webview:'].includes(window.location.protocol) ||\n\t\t\twindow.location.hostname === 'localhost'\n\t\t)\n\t}\n\n\tprivate async extractLicenseKey(licenseKey: string): Promise<LicenseInfo> {\n\t\tconst [data, signature] = licenseKey.split('.')\n\t\tconst [prefix, encodedData] = data.split('/')\n\n\t\tif (!prefix.startsWith('tldraw-')) {\n\t\t\tthrow new Error(`Unsupported prefix '${prefix}'`)\n\t\t}\n\n\t\tconst publicCryptoKey = await importPublicKey(this.publicKey)\n\n\t\tlet isVerified\n\t\ttry {\n\t\t\tisVerified = await crypto.subtle.verify(\n\t\t\t\t{\n\t\t\t\t\tname: 'ECDSA',\n\t\t\t\t\thash: { name: 'SHA-256' },\n\t\t\t\t},\n\t\t\t\tpublicCryptoKey,\n\t\t\t\tnew Uint8Array(str2ab(atob(signature))),\n\t\t\t\tnew Uint8Array(str2ab(atob(encodedData)))\n\t\t\t)\n\t\t} catch (e) {\n\t\t\tconsole.error(e)\n\t\t\tthrow new Error('Could not perform signature validation')\n\t\t}\n\n\t\tif (!isVerified) {\n\t\t\tthrow new Error('Invalid signature')\n\t\t}\n\n\t\tlet decodedData: any\n\t\ttry {\n\t\t\tdecodedData = JSON.parse(atob(encodedData))\n\t\t} catch {\n\t\t\tthrow new Error('Could not parse object')\n\t\t}\n\t\tif (decodedData.length > NUMBER_OF_KNOWN_PROPERTIES) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'License key contains some unknown properties.',\n\t\t\t\t'You may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t])\n\t\t}\n\n\t\treturn {\n\t\t\tid: decodedData[PROPERTIES.ID],\n\t\t\thosts: decodedData[PROPERTIES.HOSTS],\n\t\t\tflags: decodedData[PROPERTIES.FLAGS],\n\t\t\texpiryDate: decodedData[PROPERTIES.EXPIRY_DATE],\n\t\t}\n\t}\n\n\tasync getLicenseFromKey(licenseKey?: string): Promise<LicenseFromKeyResult> {\n\t\tif (!licenseKey) {\n\t\t\tif (!this.isDevelopment) {\n\t\t\t\tthis.outputNoLicenseKeyProvided()\n\t\t\t}\n\n\t\t\treturn { isLicenseParseable: false, reason: 'no-key-provided' }\n\t\t}\n\n\t\tif (this.isDevelopment && !this.isCryptoAvailable) {\n\t\t\tif (this.verbose) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t'tldraw: you seem to be in a development environment that does not support crypto. License not verified.'\n\t\t\t\t)\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log('You should check that this works in production separately.')\n\t\t\t}\n\t\t\t// We can't parse the license if we are in development mode since crypto\n\t\t\t// is not available on http\n\t\t\treturn { isLicenseParseable: false, reason: 'has-key-development-mode' }\n\t\t}\n\n\t\t// Borrowed idea from AG Grid:\n\t\t// Copying from various sources (like PDFs) can include zero-width characters.\n\t\t// This helps makes sure the key validation doesn't fail.\n\t\tlet cleanedLicenseKey = licenseKey.replace(/[\\u200B-\\u200D\\uFEFF]/g, '')\n\t\tcleanedLicenseKey = cleanedLicenseKey.replace(/\\r?\\n|\\r/g, '')\n\n\t\ttry {\n\t\t\tconst licenseInfo = await this.extractLicenseKey(cleanedLicenseKey)\n\t\t\tconst expiryDate = new Date(licenseInfo.expiryDate)\n\t\t\tconst isAnnualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\tconst isPerpetualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.PERPETUAL_LICENSE)\n\n\t\t\tconst result: ValidLicenseKeyResult = {\n\t\t\t\tlicense: licenseInfo,\n\t\t\t\tisLicenseParseable: true,\n\t\t\t\tisDevelopment: this.isDevelopment,\n\t\t\t\tisDomainValid: this.isDomainValid(licenseInfo),\n\t\t\t\texpiryDate,\n\t\t\t\tisAnnualLicense,\n\t\t\t\tisAnnualLicenseExpired: isAnnualLicense && this.isAnnualLicenseExpired(expiryDate),\n\t\t\t\tisPerpetualLicense,\n\t\t\t\tisPerpetualLicenseExpired: isPerpetualLicense && this.isPerpetualLicenseExpired(expiryDate),\n\t\t\t\tisInternalLicense: this.isFlagEnabled(licenseInfo.flags, FLAGS.INTERNAL_LICENSE),\n\t\t\t\tisLicensedWithWatermark: this.isFlagEnabled(licenseInfo.flags, FLAGS.WITH_WATERMARK),\n\t\t\t}\n\t\t\tthis.outputLicenseInfoIfNeeded(result)\n\n\t\t\treturn result\n\t\t} catch (e: any) {\n\t\t\tthis.outputInvalidLicenseKey(e.message)\n\t\t\t// If the license can't be parsed, it's invalid\n\t\t\treturn { isLicenseParseable: false, reason: 'invalid-license-key' }\n\t\t}\n\t}\n\n\tprivate isDomainValid(licenseInfo: LicenseInfo) {\n\t\tconst currentHostname = window.location.hostname.toLowerCase()\n\n\t\treturn licenseInfo.hosts.some((host) => {\n\t\t\tconst normalizedHost = host.toLowerCase().trim()\n\n\t\t\t// Allow the domain if listed and www variations, 'example.com' allows 'example.com' and 'www.example.com'\n\t\t\tif (\n\t\t\t\tnormalizedHost === currentHostname ||\n\t\t\t\t`www.${normalizedHost}` === currentHostname ||\n\t\t\t\tnormalizedHost === `www.${currentHostname}`\n\t\t\t) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// If host is '*', we allow all domains.\n\t\t\tif (host === '*') {\n\t\t\t\t// All domains allowed.\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Glob testing, we only support '*.somedomain.com' right now.\n\t\t\tif (host.includes('*')) {\n\t\t\t\tconst globToRegex = new RegExp(host.replace(/\\*/g, '.*?'))\n\t\t\t\treturn globToRegex.test(currentHostname) || globToRegex.test(`www.${currentHostname}`)\n\t\t\t}\n\n\t\t\t// VSCode support\n\t\t\tif (window.location.protocol === 'vscode-webview:') {\n\t\t\t\tconst currentUrl = new URL(window.location.href)\n\t\t\t\tconst extensionId = currentUrl.searchParams.get('extensionId')\n\t\t\t\tif (normalizedHost === extensionId) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false\n\t\t})\n\t}\n\n\tprivate getExpirationDateWithoutGracePeriod(expiryDate: Date) {\n\t\treturn new Date(expiryDate.getFullYear(), expiryDate.getMonth(), expiryDate.getDate())\n\t}\n\n\tprivate getExpirationDateWithGracePeriod(expiryDate: Date) {\n\t\treturn new Date(\n\t\t\texpiryDate.getFullYear(),\n\t\t\texpiryDate.getMonth(),\n\t\t\texpiryDate.getDate() + GRACE_PERIOD_DAYS + 1 // Add 1 day to include the expiration day\n\t\t)\n\t}\n\n\tprivate isAnnualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\tconst isExpired = new Date() >= expiration\n\t\t// If it is not expired yet (including the grace period), but after the expiry date we warn the users\n\t\tif (!isExpired && new Date() >= this.getExpirationDateWithoutGracePeriod(expiryDate)) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'tldraw license is about to expire, you are in a grace period.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} if you would like to renew your license.`,\n\t\t\t])\n\t\t}\n\t\treturn isExpired\n\t}\n\n\tprivate isPerpetualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\tconst dates = {\n\t\t\tmajor: new Date(publishDates.major),\n\t\t\tminor: new Date(publishDates.minor),\n\t\t}\n\t\t// We allow patch releases, but the major and minor releases should be within the expiration date\n\t\treturn dates.major >= expiration || dates.minor >= expiration\n\t}\n\n\tprivate isFlagEnabled(flags: number, flag: number) {\n\t\treturn (flags & flag) === flag\n\t}\n\n\tprivate outputNoLicenseKeyProvided() {\n\t\t// Noop, we don't need to show this message.\n\t\t// this.outputMessages([\n\t\t// \t'No tldraw license key provided!',\n\t\t// \t`Please reach out to ${LICENSE_EMAIL} if you would like to license tldraw or if you'd like a trial.`,\n\t\t// ])\n\t}\n\n\tprivate outputInvalidLicenseKey(msg: string) {\n\t\tthis.outputMessages(['Invalid tldraw license key', `Reason: ${msg}`])\n\t}\n\n\tprivate outputLicenseInfoIfNeeded(result: ValidLicenseKeyResult) {\n\t\tif (result.isAnnualLicenseExpired) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'Your tldraw license has expired!',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew.`,\n\t\t\t])\n\t\t}\n\n\t\tif (!result.isDomainValid && !result.isDevelopment) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'This tldraw license key is not valid for this domain!',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} if you would like to use tldraw on other domains.`,\n\t\t\t])\n\t\t}\n\t\t// If we added a new flag it will be twice the value of the currently highest flag.\n\t\t// And if all the current flags are on we would get the `HIGHEST_FLAG * 2 - 1`, so anything higher than that means there are new flags.\n\t\tif (result.license.flags >= HIGHEST_FLAG * 2) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'This tldraw license contains some unknown flags.',\n\t\t\t\t'You may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t])\n\t\t}\n\t}\n\n\tprivate outputMessages(messages: string[]) {\n\t\tif (this.isTest) return\n\t\tif (this.verbose) {\n\t\t\tthis.outputDelimiter()\n\t\t\tfor (const message of messages) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t`%c${message}`,\n\t\t\t\t\t`color: white; background: crimson; padding: 2px; border-radius: 3px;`\n\t\t\t\t)\n\t\t\t}\n\t\t\tthis.outputDelimiter()\n\t\t}\n\t}\n\n\tprivate outputDelimiter() {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(\n\t\t\t'%c-------------------------------------------------------------------',\n\t\t\t`color: white; background: crimson; padding: 2px; border-radius: 3px;`\n\t\t)\n\t}\n\n\tstatic className = 'tl-watermark_SEE-LICENSE'\n}\n\nexport function isEditorUnlicensed(result: LicenseFromKeyResult) {\n\tif (!result.isLicenseParseable) return true\n\tif (!result.isDomainValid && !result.isDevelopment) return true\n\tif (result.isPerpetualLicenseExpired || result.isAnnualLicenseExpired) {\n\t\tif (result.isInternalLicense) {\n\t\t\tthrow new Error('License: Internal license expired.')\n\t\t}\n\t\treturn true\n\t}\n\n\treturn false\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,YAAY;AACrB,SAAS,aAAa;AACtB,SAAS,oBAAoB;AAC7B,SAAS,4BAA4B;AACrC,SAAS,iBAAiB,cAAc;AAExC,MAAM,oBAAoB;AAEnB,MAAM,QAAQ;AAAA,EACpB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,gBAAgB;AACjB;AACA,MAAM,eAAe,KAAK,IAAI,GAAG,OAAO,OAAO,KAAK,CAAC;AAE9C,MAAM,aAAa;AAAA,EACzB,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,aAAa;AACd;AACA,MAAM,6BAA6B,OAAO,KAAK,UAAU,EAAE;AAE3D,MAAM,gBAAgB;AAEtB,MAAM,sBAAsB,GAAG,qBAAqB,CAAC;
|
|
4
|
+
"sourcesContent": ["import { atom } from '@tldraw/state'\nimport { fetch } from '@tldraw/utils'\nimport { publishDates } from '../../version'\nimport { getDefaultCdnBaseUrl } from '../utils/assets'\nimport { importPublicKey, str2ab } from '../utils/licensing'\n\nconst GRACE_PERIOD_DAYS = 5\n\nexport const FLAGS = {\n\tANNUAL_LICENSE: 0x1,\n\tPERPETUAL_LICENSE: 0x2,\n\tINTERNAL_LICENSE: 0x4,\n\tWITH_WATERMARK: 0x8,\n}\nconst HIGHEST_FLAG = Math.max(...Object.values(FLAGS))\n\nexport const PROPERTIES = {\n\tID: 0,\n\tHOSTS: 1,\n\tFLAGS: 2,\n\tEXPIRY_DATE: 3,\n}\nconst NUMBER_OF_KNOWN_PROPERTIES = Object.keys(PROPERTIES).length\n\nconst LICENSE_EMAIL = 'sales@tldraw.com'\n\nconst WATERMARK_TRACK_SRC = `${getDefaultCdnBaseUrl()}/watermarks/watermark-track.svg`\n\n/** @internal */\nexport interface LicenseInfo {\n\tid: string\n\thosts: string[]\n\tflags: number\n\texpiryDate: string\n}\n\n/** @internal */\nexport type LicenseState =\n\t| 'pending'\n\t| 'licensed'\n\t| 'licensed-with-watermark'\n\t| 'unlicensed'\n\t| 'internal-expired'\n/** @internal */\nexport type InvalidLicenseReason =\n\t| 'invalid-license-key'\n\t| 'no-key-provided'\n\t| 'has-key-development-mode'\n\n/** @internal */\nexport type LicenseFromKeyResult = InvalidLicenseKeyResult | ValidLicenseKeyResult\n\n/** @internal */\nexport interface InvalidLicenseKeyResult {\n\tisLicenseParseable: false\n\treason: InvalidLicenseReason\n}\n\n/** @internal */\nexport interface ValidLicenseKeyResult {\n\tisLicenseParseable: true\n\tlicense: LicenseInfo\n\tisDevelopment: boolean\n\tisDomainValid: boolean\n\texpiryDate: Date\n\tisAnnualLicense: boolean\n\tisAnnualLicenseExpired: boolean\n\tisPerpetualLicense: boolean\n\tisPerpetualLicenseExpired: boolean\n\tisInternalLicense: boolean\n\tisLicensedWithWatermark: boolean\n}\n\n/** @internal */\nexport type TestEnvironment = 'development' | 'production'\n\n/** @internal */\nexport class LicenseManager {\n\tprivate publicKey =\n\t\t'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHJh0uUfxHtCGyerXmmatE368Hd9rI6LH9oPDQihnaCryRFWEVeOvf9U/SPbyxX74LFyJs5tYeAHq5Nc0Ax25LQ'\n\tpublic isDevelopment: boolean\n\tpublic isTest: boolean\n\tpublic isCryptoAvailable: boolean\n\tstate = atom<LicenseState>('license state', 'pending')\n\tpublic verbose = true\n\n\tconstructor(\n\t\tlicenseKey: string | undefined,\n\t\ttestPublicKey?: string,\n\t\ttestEnvironment?: TestEnvironment\n\t) {\n\t\tthis.isTest = process.env.NODE_ENV === 'test'\n\t\tthis.isDevelopment = this.getIsDevelopment(testEnvironment)\n\t\tthis.publicKey = testPublicKey || this.publicKey\n\t\tthis.isCryptoAvailable = !!crypto.subtle\n\n\t\tthis.getLicenseFromKey(licenseKey)\n\t\t\t.then((result) => {\n\t\t\t\tconst licenseState = getLicenseState(result)\n\n\t\t\t\tif (!this.isDevelopment && licenseState === 'unlicensed') {\n\t\t\t\t\tfetch(WATERMARK_TRACK_SRC)\n\t\t\t\t}\n\n\t\t\t\tthis.state.set(licenseState)\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconsole.error('License validation failed:', error)\n\t\t\t\tthis.state.set('unlicensed')\n\t\t\t})\n\t}\n\n\tprivate getIsDevelopment(testEnvironment?: TestEnvironment) {\n\t\tif (testEnvironment === 'development') return true\n\t\tif (testEnvironment === 'production') return false\n\n\t\t// If we are using https on a non-localhost domain we assume it's a production env and a development one otherwise\n\t\treturn (\n\t\t\t!['https:', 'vscode-webview:'].includes(window.location.protocol) ||\n\t\t\twindow.location.hostname === 'localhost'\n\t\t)\n\t}\n\n\tprivate async extractLicenseKey(licenseKey: string): Promise<LicenseInfo> {\n\t\tconst [data, signature] = licenseKey.split('.')\n\t\tconst [prefix, encodedData] = data.split('/')\n\n\t\tif (!prefix.startsWith('tldraw-')) {\n\t\t\tthrow new Error(`Unsupported prefix '${prefix}'`)\n\t\t}\n\n\t\tconst publicCryptoKey = await importPublicKey(this.publicKey)\n\n\t\tlet isVerified\n\t\ttry {\n\t\t\tisVerified = await crypto.subtle.verify(\n\t\t\t\t{\n\t\t\t\t\tname: 'ECDSA',\n\t\t\t\t\thash: { name: 'SHA-256' },\n\t\t\t\t},\n\t\t\t\tpublicCryptoKey,\n\t\t\t\tnew Uint8Array(str2ab(atob(signature))),\n\t\t\t\tnew Uint8Array(str2ab(atob(encodedData)))\n\t\t\t)\n\t\t} catch (e) {\n\t\t\tconsole.error(e)\n\t\t\tthrow new Error('Could not perform signature validation')\n\t\t}\n\n\t\tif (!isVerified) {\n\t\t\tthrow new Error('Invalid signature')\n\t\t}\n\n\t\tlet decodedData: any\n\t\ttry {\n\t\t\tdecodedData = JSON.parse(atob(encodedData))\n\t\t} catch {\n\t\t\tthrow new Error('Could not parse object')\n\t\t}\n\t\tif (decodedData.length > NUMBER_OF_KNOWN_PROPERTIES) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'License key contains some unknown properties.',\n\t\t\t\t'You may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t])\n\t\t}\n\n\t\treturn {\n\t\t\tid: decodedData[PROPERTIES.ID],\n\t\t\thosts: decodedData[PROPERTIES.HOSTS],\n\t\t\tflags: decodedData[PROPERTIES.FLAGS],\n\t\t\texpiryDate: decodedData[PROPERTIES.EXPIRY_DATE],\n\t\t}\n\t}\n\n\tasync getLicenseFromKey(licenseKey?: string): Promise<LicenseFromKeyResult> {\n\t\tif (!licenseKey) {\n\t\t\tif (!this.isDevelopment) {\n\t\t\t\tthis.outputNoLicenseKeyProvided()\n\t\t\t}\n\n\t\t\treturn { isLicenseParseable: false, reason: 'no-key-provided' }\n\t\t}\n\n\t\tif (this.isDevelopment && !this.isCryptoAvailable) {\n\t\t\tif (this.verbose) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t'tldraw: you seem to be in a development environment that does not support crypto. License not verified.'\n\t\t\t\t)\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log('You should check that this works in production separately.')\n\t\t\t}\n\t\t\t// We can't parse the license if we are in development mode since crypto\n\t\t\t// is not available on http\n\t\t\treturn { isLicenseParseable: false, reason: 'has-key-development-mode' }\n\t\t}\n\n\t\t// Borrowed idea from AG Grid:\n\t\t// Copying from various sources (like PDFs) can include zero-width characters.\n\t\t// This helps makes sure the key validation doesn't fail.\n\t\tlet cleanedLicenseKey = licenseKey.replace(/[\\u200B-\\u200D\\uFEFF]/g, '')\n\t\tcleanedLicenseKey = cleanedLicenseKey.replace(/\\r?\\n|\\r/g, '')\n\n\t\ttry {\n\t\t\tconst licenseInfo = await this.extractLicenseKey(cleanedLicenseKey)\n\t\t\tconst expiryDate = new Date(licenseInfo.expiryDate)\n\t\t\tconst isAnnualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\tconst isPerpetualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.PERPETUAL_LICENSE)\n\n\t\t\tconst result: ValidLicenseKeyResult = {\n\t\t\t\tlicense: licenseInfo,\n\t\t\t\tisLicenseParseable: true,\n\t\t\t\tisDevelopment: this.isDevelopment,\n\t\t\t\tisDomainValid: this.isDomainValid(licenseInfo),\n\t\t\t\texpiryDate,\n\t\t\t\tisAnnualLicense,\n\t\t\t\tisAnnualLicenseExpired: isAnnualLicense && this.isAnnualLicenseExpired(expiryDate),\n\t\t\t\tisPerpetualLicense,\n\t\t\t\tisPerpetualLicenseExpired: isPerpetualLicense && this.isPerpetualLicenseExpired(expiryDate),\n\t\t\t\tisInternalLicense: this.isFlagEnabled(licenseInfo.flags, FLAGS.INTERNAL_LICENSE),\n\t\t\t\tisLicensedWithWatermark: this.isFlagEnabled(licenseInfo.flags, FLAGS.WITH_WATERMARK),\n\t\t\t}\n\t\t\tthis.outputLicenseInfoIfNeeded(result)\n\n\t\t\treturn result\n\t\t} catch (e: any) {\n\t\t\tthis.outputInvalidLicenseKey(e.message)\n\t\t\t// If the license can't be parsed, it's invalid\n\t\t\treturn { isLicenseParseable: false, reason: 'invalid-license-key' }\n\t\t}\n\t}\n\n\tprivate isDomainValid(licenseInfo: LicenseInfo) {\n\t\tconst currentHostname = window.location.hostname.toLowerCase()\n\n\t\treturn licenseInfo.hosts.some((host) => {\n\t\t\tconst normalizedHost = host.toLowerCase().trim()\n\n\t\t\t// Allow the domain if listed and www variations, 'example.com' allows 'example.com' and 'www.example.com'\n\t\t\tif (\n\t\t\t\tnormalizedHost === currentHostname ||\n\t\t\t\t`www.${normalizedHost}` === currentHostname ||\n\t\t\t\tnormalizedHost === `www.${currentHostname}`\n\t\t\t) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// If host is '*', we allow all domains.\n\t\t\tif (host === '*') {\n\t\t\t\t// All domains allowed.\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Glob testing, we only support '*.somedomain.com' right now.\n\t\t\tif (host.includes('*')) {\n\t\t\t\tconst globToRegex = new RegExp(host.replace(/\\*/g, '.*?'))\n\t\t\t\treturn globToRegex.test(currentHostname) || globToRegex.test(`www.${currentHostname}`)\n\t\t\t}\n\n\t\t\t// VSCode support\n\t\t\tif (window.location.protocol === 'vscode-webview:') {\n\t\t\t\tconst currentUrl = new URL(window.location.href)\n\t\t\t\tconst extensionId = currentUrl.searchParams.get('extensionId')\n\t\t\t\tif (normalizedHost === extensionId) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false\n\t\t})\n\t}\n\n\tprivate getExpirationDateWithoutGracePeriod(expiryDate: Date) {\n\t\treturn new Date(expiryDate.getFullYear(), expiryDate.getMonth(), expiryDate.getDate())\n\t}\n\n\tprivate getExpirationDateWithGracePeriod(expiryDate: Date) {\n\t\treturn new Date(\n\t\t\texpiryDate.getFullYear(),\n\t\t\texpiryDate.getMonth(),\n\t\t\texpiryDate.getDate() + GRACE_PERIOD_DAYS + 1 // Add 1 day to include the expiration day\n\t\t)\n\t}\n\n\tprivate isAnnualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\tconst isExpired = new Date() >= expiration\n\t\t// If it is not expired yet (including the grace period), but after the expiry date we warn the users\n\t\tif (!isExpired && new Date() >= this.getExpirationDateWithoutGracePeriod(expiryDate)) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'tldraw license is about to expire, you are in a grace period.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} if you would like to renew your license.`,\n\t\t\t])\n\t\t}\n\t\treturn isExpired\n\t}\n\n\tprivate isPerpetualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\tconst dates = {\n\t\t\tmajor: new Date(publishDates.major),\n\t\t\tminor: new Date(publishDates.minor),\n\t\t}\n\t\t// We allow patch releases, but the major and minor releases should be within the expiration date\n\t\treturn dates.major >= expiration || dates.minor >= expiration\n\t}\n\n\tprivate isFlagEnabled(flags: number, flag: number) {\n\t\treturn (flags & flag) === flag\n\t}\n\n\tprivate outputNoLicenseKeyProvided() {\n\t\t// Noop, we don't need to show this message.\n\t\t// this.outputMessages([\n\t\t// \t'No tldraw license key provided!',\n\t\t// \t`Please reach out to ${LICENSE_EMAIL} if you would like to license tldraw or if you'd like a trial.`,\n\t\t// ])\n\t}\n\n\tprivate outputInvalidLicenseKey(msg: string) {\n\t\tthis.outputMessages(['Invalid tldraw license key', `Reason: ${msg}`])\n\t}\n\n\tprivate outputLicenseInfoIfNeeded(result: ValidLicenseKeyResult) {\n\t\tif (result.isAnnualLicenseExpired) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'Your tldraw license has expired!',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew.`,\n\t\t\t])\n\t\t}\n\n\t\tif (!result.isDomainValid && !result.isDevelopment) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'This tldraw license key is not valid for this domain!',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} if you would like to use tldraw on other domains.`,\n\t\t\t])\n\t\t}\n\t\t// If we added a new flag it will be twice the value of the currently highest flag.\n\t\t// And if all the current flags are on we would get the `HIGHEST_FLAG * 2 - 1`, so anything higher than that means there are new flags.\n\t\tif (result.license.flags >= HIGHEST_FLAG * 2) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'This tldraw license contains some unknown flags.',\n\t\t\t\t'You may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t])\n\t\t}\n\t}\n\n\tprivate outputMessages(messages: string[]) {\n\t\tif (this.isTest) return\n\t\tif (this.verbose) {\n\t\t\tthis.outputDelimiter()\n\t\t\tfor (const message of messages) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t`%c${message}`,\n\t\t\t\t\t`color: white; background: crimson; padding: 2px; border-radius: 3px;`\n\t\t\t\t)\n\t\t\t}\n\t\t\tthis.outputDelimiter()\n\t\t}\n\t}\n\n\tprivate outputDelimiter() {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(\n\t\t\t'%c-------------------------------------------------------------------',\n\t\t\t`color: white; background: crimson; padding: 2px; border-radius: 3px;`\n\t\t)\n\t}\n\n\tstatic className = 'tl-watermark_SEE-LICENSE'\n}\n\nexport function getLicenseState(result: LicenseFromKeyResult): LicenseState {\n\tif (!result.isLicenseParseable) return 'unlicensed'\n\tif (!result.isDomainValid && !result.isDevelopment) return 'unlicensed'\n\tif (result.isPerpetualLicenseExpired || result.isAnnualLicenseExpired) {\n\t\t// Check if it's an expired internal license with valid domain\n\t\tconst internalExpired = result.isInternalLicense && result.isDomainValid\n\t\treturn internalExpired ? 'internal-expired' : 'unlicensed'\n\t}\n\n\t// License is valid, determine if it has watermark\n\tif (result.isLicensedWithWatermark) {\n\t\treturn 'licensed-with-watermark'\n\t}\n\n\treturn 'licensed'\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useValue } from "@tldraw/state-react";
|
|
2
3
|
import { createContext, useContext, useState } from "react";
|
|
3
4
|
import { LicenseManager } from "./LicenseManager.mjs";
|
|
4
5
|
const LicenseContext = createContext({});
|
|
@@ -8,6 +9,10 @@ function LicenseProvider({
|
|
|
8
9
|
children
|
|
9
10
|
}) {
|
|
10
11
|
const [licenseManager] = useState(() => new LicenseManager(licenseKey));
|
|
12
|
+
const licenseState = useValue(licenseManager.state);
|
|
13
|
+
if (licenseState === "internal-expired") {
|
|
14
|
+
return /* @__PURE__ */ jsx("div", { "data-testid": "tl-license-expired", style: { display: "none" } });
|
|
15
|
+
}
|
|
11
16
|
return /* @__PURE__ */ jsx(LicenseContext.Provider, { value: licenseManager, children });
|
|
12
17
|
}
|
|
13
18
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/license/LicenseProvider.tsx"],
|
|
4
|
-
"sourcesContent": ["import { createContext, ReactNode, useContext, useState } from 'react'\nimport { LicenseManager } from './LicenseManager'\n\n/** @internal */\nexport const LicenseContext = createContext({} as LicenseManager)\n\n/** @internal */\nexport const useLicenseContext = () => useContext(LicenseContext)\n\n/** @internal */\nexport function LicenseProvider({\n\tlicenseKey,\n\tchildren,\n}: {\n\tlicenseKey?: string\n\tchildren: ReactNode\n}) {\n\tconst [licenseManager] = useState(() => new LicenseManager(licenseKey))\n\treturn <LicenseContext.Provider value={licenseManager}>{children}</LicenseContext.Provider>\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { createContext, ReactNode, useContext, useState } from 'react'\nimport { LicenseManager } from './LicenseManager'\n\n/** @internal */\nexport const LicenseContext = createContext({} as LicenseManager)\n\n/** @internal */\nexport const useLicenseContext = () => useContext(LicenseContext)\n\n/** @internal */\nexport function LicenseProvider({\n\tlicenseKey,\n\tchildren,\n}: {\n\tlicenseKey?: string\n\tchildren: ReactNode\n}) {\n\tconst [licenseManager] = useState(() => new LicenseManager(licenseKey))\n\tconst licenseState = useValue(licenseManager.state)\n\n\t// If internal license has expired, don't render the editor at all\n\tif (licenseState === 'internal-expired') {\n\t\treturn <div data-testid=\"tl-license-expired\" style={{ display: 'none' }} />\n\t}\n\n\treturn <LicenseContext.Provider value={licenseManager}>{children}</LicenseContext.Provider>\n}\n"],
|
|
5
|
+
"mappings": "AAuBS;AAvBT,SAAS,gBAAgB;AACzB,SAAS,eAA0B,YAAY,gBAAgB;AAC/D,SAAS,sBAAsB;AAGxB,MAAM,iBAAiB,cAAc,CAAC,CAAmB;AAGzD,MAAM,oBAAoB,MAAM,WAAW,cAAc;AAGzD,SAAS,gBAAgB;AAAA,EAC/B;AAAA,EACA;AACD,GAGG;AACF,QAAM,CAAC,cAAc,IAAI,SAAS,MAAM,IAAI,eAAe,UAAU,CAAC;AACtE,QAAM,eAAe,SAAS,eAAe,KAAK;AAGlD,MAAI,iBAAiB,oBAAoB;AACxC,WAAO,oBAAC,SAAI,eAAY,sBAAqB,OAAO,EAAE,SAAS,OAAO,GAAG;AAAA,EAC1E;AAEA,SAAO,oBAAC,eAAe,UAAf,EAAwB,OAAO,gBAAiB,UAAS;AAClE;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/license/useLicenseManagerState.ts"],
|
|
4
|
-
"sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { LicenseManager } from './LicenseManager'\n\n/** @internal */\nexport function useLicenseManagerState(licenseManager: LicenseManager) {\n\treturn useValue('watermarkState', () => licenseManager.state.get(), [licenseManager])\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,gBAAgB;AAIlB,SAAS,uBAAuB,
|
|
4
|
+
"sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { LicenseManager, LicenseState } from './LicenseManager'\n\n/** @internal */\nexport function useLicenseManagerState(licenseManager: LicenseManager): LicenseState {\n\treturn useValue('watermarkState', () => licenseManager.state.get(), [licenseManager])\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,gBAAgB;AAIlB,SAAS,uBAAuB,gBAA8C;AACpF,SAAO,SAAS,kBAAkB,MAAM,eAAe,MAAM,IAAI,GAAG,CAAC,cAAc,CAAC;AACrF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Vec } from "./Vec.mjs";
|
|
2
|
-
import { PI, PI2, toPrecision } from "./utils.mjs";
|
|
2
|
+
import { approximatelyLte, PI, PI2, toPrecision } from "./utils.mjs";
|
|
3
3
|
class Box {
|
|
4
4
|
constructor(x = 0, y = 0, w = 0, h = 0) {
|
|
5
5
|
this.x = x;
|
|
@@ -329,6 +329,9 @@ class Box {
|
|
|
329
329
|
static Contains(A, B) {
|
|
330
330
|
return A.minX < B.minX && A.minY < B.minY && A.maxY > B.maxY && A.maxX > B.maxX;
|
|
331
331
|
}
|
|
332
|
+
static ContainsApproximately(A, B, precision) {
|
|
333
|
+
return approximatelyLte(A.minX, B.minX, precision) && approximatelyLte(A.minY, B.minY, precision) && approximatelyLte(B.maxX, A.maxX, precision) && approximatelyLte(B.maxY, A.maxY, precision);
|
|
334
|
+
}
|
|
332
335
|
static Includes(A, B) {
|
|
333
336
|
return Box.Collides(A, B) || Box.Contains(A, B);
|
|
334
337
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/primitives/Box.ts"],
|
|
4
|
-
"sourcesContent": ["import { BoxModel } from '@tldraw/tlschema'\nimport { Vec, VecLike } from './Vec'\nimport { PI, PI2, toPrecision } from './utils'\n\n/** @public */\nexport type BoxLike = BoxModel | Box\n\n/** @public */\nexport type SelectionEdge = 'top' | 'right' | 'bottom' | 'left'\n\n/** @public */\nexport type SelectionCorner = 'top_left' | 'top_right' | 'bottom_right' | 'bottom_left'\n\n/** @public */\nexport type SelectionHandle = SelectionEdge | SelectionCorner\n\n/** @public */\nexport type RotateCorner =\n\t| 'top_left_rotate'\n\t| 'top_right_rotate'\n\t| 'bottom_right_rotate'\n\t| 'bottom_left_rotate'\n\t| 'mobile_rotate'\n\n/** @public */\nexport class Box {\n\tconstructor(x = 0, y = 0, w = 0, h = 0) {\n\t\tthis.x = x\n\t\tthis.y = y\n\t\tthis.w = w\n\t\tthis.h = h\n\t}\n\n\tx = 0\n\ty = 0\n\tw = 0\n\th = 0\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget point() {\n\t\treturn new Vec(this.x, this.y)\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset point(val: Vec) {\n\t\tthis.x = val.x\n\t\tthis.y = val.y\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget minX() {\n\t\treturn this.x\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset minX(n: number) {\n\t\tthis.x = n\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget left() {\n\t\treturn this.x\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget midX() {\n\t\treturn this.x + this.w / 2\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget maxX() {\n\t\treturn this.x + this.w\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget right() {\n\t\treturn this.x + this.w\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget minY() {\n\t\treturn this.y\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset minY(n: number) {\n\t\tthis.y = n\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget top() {\n\t\treturn this.y\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget midY() {\n\t\treturn this.y + this.h / 2\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget maxY() {\n\t\treturn this.y + this.h\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget bottom() {\n\t\treturn this.y + this.h\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget width() {\n\t\treturn this.w\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset width(n: number) {\n\t\tthis.w = n\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget height() {\n\t\treturn this.h\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset height(n: number) {\n\t\tthis.h = n\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget aspectRatio() {\n\t\treturn this.width / this.height\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget center() {\n\t\treturn new Vec(this.x + this.w / 2, this.y + this.h / 2)\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset center(v: Vec) {\n\t\tthis.x = v.x - this.w / 2\n\t\tthis.y = v.y - this.h / 2\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget corners() {\n\t\treturn [\n\t\t\tnew Vec(this.x, this.y),\n\t\t\tnew Vec(this.x + this.w, this.y),\n\t\t\tnew Vec(this.x + this.w, this.y + this.h),\n\t\t\tnew Vec(this.x, this.y + this.h),\n\t\t]\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget cornersAndCenter() {\n\t\treturn [\n\t\t\tnew Vec(this.x, this.y),\n\t\t\tnew Vec(this.x + this.w, this.y),\n\t\t\tnew Vec(this.x + this.w, this.y + this.h),\n\t\t\tnew Vec(this.x, this.y + this.h),\n\t\t\tnew Vec(this.x + this.w / 2, this.y + this.h / 2),\n\t\t]\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget sides(): Array<[Vec, Vec]> {\n\t\tconst { corners } = this\n\t\treturn [\n\t\t\t[corners[0], corners[1]],\n\t\t\t[corners[1], corners[2]],\n\t\t\t[corners[2], corners[3]],\n\t\t\t[corners[3], corners[0]],\n\t\t]\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget size(): Vec {\n\t\treturn new Vec(this.w, this.h)\n\t}\n\n\ttoFixed() {\n\t\tthis.x = toPrecision(this.x)\n\t\tthis.y = toPrecision(this.y)\n\t\tthis.w = toPrecision(this.w)\n\t\tthis.h = toPrecision(this.h)\n\t\treturn this\n\t}\n\n\tsetTo(B: Box) {\n\t\tthis.x = B.x\n\t\tthis.y = B.y\n\t\tthis.w = B.w\n\t\tthis.h = B.h\n\t\treturn this\n\t}\n\n\tset(x = 0, y = 0, w = 0, h = 0) {\n\t\tthis.x = x\n\t\tthis.y = y\n\t\tthis.w = w\n\t\tthis.h = h\n\t\treturn this\n\t}\n\n\texpand(A: Box) {\n\t\tconst minX = Math.min(this.x, A.x)\n\t\tconst minY = Math.min(this.y, A.y)\n\t\tconst maxX = Math.max(this.x + this.w, A.x + A.w)\n\t\tconst maxY = Math.max(this.y + this.h, A.y + A.h)\n\n\t\tthis.x = minX\n\t\tthis.y = minY\n\t\tthis.w = maxX - minX\n\t\tthis.h = maxY - minY\n\t\treturn this\n\t}\n\n\texpandBy(n: number) {\n\t\tthis.x -= n\n\t\tthis.y -= n\n\t\tthis.w += n * 2\n\t\tthis.h += n * 2\n\t\treturn this\n\t}\n\n\tscale(n: number) {\n\t\tthis.x /= n\n\t\tthis.y /= n\n\t\tthis.w /= n\n\t\tthis.h /= n\n\t\treturn this\n\t}\n\n\tclone() {\n\t\tconst { x, y, w, h } = this\n\t\treturn new Box(x, y, w, h)\n\t}\n\n\ttranslate(delta: VecLike) {\n\t\tthis.x += delta.x\n\t\tthis.y += delta.y\n\t\treturn this\n\t}\n\n\tsnapToGrid(size: number) {\n\t\tconst minX = Math.round(this.x / size) * size\n\t\tconst minY = Math.round(this.y / size) * size\n\t\tconst maxX = Math.round((this.x + this.w) / size) * size\n\t\tconst maxY = Math.round((this.y + this.h) / size) * size\n\t\tthis.minX = minX\n\t\tthis.minY = minY\n\t\tthis.width = Math.max(1, maxX - minX)\n\t\tthis.height = Math.max(1, maxY - minY)\n\t}\n\n\tcollides(B: Box) {\n\t\treturn Box.Collides(this, B)\n\t}\n\n\tcontains(B: Box) {\n\t\treturn Box.Contains(this, B)\n\t}\n\n\tincludes(B: Box) {\n\t\treturn Box.Includes(this, B)\n\t}\n\n\tcontainsPoint(V: VecLike, margin = 0) {\n\t\treturn Box.ContainsPoint(this, V, margin)\n\t}\n\n\tgetHandlePoint(handle: SelectionCorner | SelectionEdge) {\n\t\tswitch (handle) {\n\t\t\tcase 'top_left':\n\t\t\t\treturn new Vec(this.x, this.y)\n\t\t\tcase 'top_right':\n\t\t\t\treturn new Vec(this.x + this.w, this.y)\n\t\t\tcase 'bottom_left':\n\t\t\t\treturn new Vec(this.x, this.y + this.h)\n\t\t\tcase 'bottom_right':\n\t\t\t\treturn new Vec(this.x + this.w, this.y + this.h)\n\t\t\tcase 'top':\n\t\t\t\treturn new Vec(this.x + this.w / 2, this.y)\n\t\t\tcase 'right':\n\t\t\t\treturn new Vec(this.x + this.w, this.y + this.h / 2)\n\t\t\tcase 'bottom':\n\t\t\t\treturn new Vec(this.x + this.w / 2, this.y + this.h)\n\t\t\tcase 'left':\n\t\t\t\treturn new Vec(this.x, this.y + this.h / 2)\n\t\t}\n\t}\n\n\ttoJson(): BoxModel {\n\t\treturn { x: this.x, y: this.y, w: this.w, h: this.h }\n\t}\n\n\tresize(handle: SelectionCorner | SelectionEdge | string, dx: number, dy: number) {\n\t\tconst { minX: a0x, minY: a0y, maxX: a1x, maxY: a1y } = this\n\t\tlet { minX: b0x, minY: b0y, maxX: b1x, maxY: b1y } = this\n\n\t\t// Use the delta to adjust the new box by changing its corners.\n\t\t// The dragging handle (corner or edge) will determine which\n\t\t// corners should change.\n\t\tswitch (handle) {\n\t\t\tcase 'left':\n\t\t\tcase 'top_left':\n\t\t\tcase 'bottom_left': {\n\t\t\t\tb0x += dx\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'right':\n\t\t\tcase 'top_right':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tb1x += dx\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tswitch (handle) {\n\t\t\tcase 'top':\n\t\t\tcase 'top_left':\n\t\t\tcase 'top_right': {\n\t\t\t\tb0y += dy\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom':\n\t\t\tcase 'bottom_left':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tb1y += dy\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tconst scaleX = (b1x - b0x) / (a1x - a0x)\n\t\tconst scaleY = (b1y - b0y) / (a1y - a0y)\n\n\t\tconst flipX = scaleX < 0\n\t\tconst flipY = scaleY < 0\n\n\t\tif (flipX) {\n\t\t\tconst t = b1x\n\t\t\tb1x = b0x\n\t\t\tb0x = t\n\t\t}\n\n\t\tif (flipY) {\n\t\t\tconst t = b1y\n\t\t\tb1y = b0y\n\t\t\tb0y = t\n\t\t}\n\n\t\tthis.minX = b0x\n\t\tthis.minY = b0y\n\t\tthis.width = Math.abs(b1x - b0x)\n\t\tthis.height = Math.abs(b1y - b0y)\n\t}\n\n\tunion(box: BoxModel) {\n\t\tconst minX = Math.min(this.x, box.x)\n\t\tconst minY = Math.min(this.y, box.y)\n\t\tconst maxX = Math.max(this.x + this.w, box.x + box.w)\n\t\tconst maxY = Math.max(this.y + this.h, box.y + box.h)\n\n\t\tthis.x = minX\n\t\tthis.y = minY\n\t\tthis.width = maxX - minX\n\t\tthis.height = maxY - minY\n\n\t\treturn this\n\t}\n\n\tstatic From(box: BoxModel) {\n\t\treturn new Box(box.x, box.y, box.w, box.h)\n\t}\n\n\tstatic FromCenter(center: VecLike, size: VecLike) {\n\t\treturn new Box(center.x - size.x / 2, center.y - size.y / 2, size.x, size.y)\n\t}\n\n\tstatic FromPoints(points: VecLike[]) {\n\t\tif (points.length === 0) return new Box()\n\t\tlet minX = Infinity\n\t\tlet minY = Infinity\n\t\tlet maxX = -Infinity\n\t\tlet maxY = -Infinity\n\t\tlet point: VecLike\n\t\tfor (let i = 0, n = points.length; i < n; i++) {\n\t\t\tpoint = points[i]\n\t\t\tminX = Math.min(point.x, minX)\n\t\t\tminY = Math.min(point.y, minY)\n\t\t\tmaxX = Math.max(point.x, maxX)\n\t\t\tmaxY = Math.max(point.y, maxY)\n\t\t}\n\n\t\treturn new Box(minX, minY, maxX - minX, maxY - minY)\n\t}\n\n\tstatic Expand(A: Box, B: Box) {\n\t\tconst minX = Math.min(B.minX, A.minX)\n\t\tconst minY = Math.min(B.minY, A.minY)\n\t\tconst maxX = Math.max(B.maxX, A.maxX)\n\t\tconst maxY = Math.max(B.maxY, A.maxY)\n\n\t\treturn new Box(minX, minY, maxX - minX, maxY - minY)\n\t}\n\n\tstatic ExpandBy(A: Box, n: number) {\n\t\treturn new Box(A.minX - n, A.minY - n, A.width + n * 2, A.height + n * 2)\n\t}\n\n\tstatic Collides(A: Box, B: Box) {\n\t\treturn !(A.maxX < B.minX || A.minX > B.maxX || A.maxY < B.minY || A.minY > B.maxY)\n\t}\n\n\tstatic Contains(A: Box, B: Box) {\n\t\treturn A.minX < B.minX && A.minY < B.minY && A.maxY > B.maxY && A.maxX > B.maxX\n\t}\n\n\tstatic Includes(A: Box, B: Box) {\n\t\treturn Box.Collides(A, B) || Box.Contains(A, B)\n\t}\n\n\tstatic ContainsPoint(A: Box, B: VecLike, margin = 0) {\n\t\treturn !(\n\t\t\tB.x < A.minX - margin ||\n\t\t\tB.y < A.minY - margin ||\n\t\t\tB.x > A.maxX + margin ||\n\t\t\tB.y > A.maxY + margin\n\t\t)\n\t}\n\n\tstatic Common(boxes: Box[]) {\n\t\tlet minX = Infinity\n\t\tlet minY = Infinity\n\t\tlet maxX = -Infinity\n\t\tlet maxY = -Infinity\n\n\t\tfor (let i = 0; i < boxes.length; i++) {\n\t\t\tconst B = boxes[i]\n\t\t\tminX = Math.min(minX, B.minX)\n\t\t\tminY = Math.min(minY, B.minY)\n\t\t\tmaxX = Math.max(maxX, B.maxX)\n\t\t\tmaxY = Math.max(maxY, B.maxY)\n\t\t}\n\n\t\treturn new Box(minX, minY, maxX - minX, maxY - minY)\n\t}\n\n\tstatic Sides(A: Box, inset = 0) {\n\t\tconst { corners } = A\n\t\tif (inset) {\n\t\t\t// TODO: Inset the corners by the inset amount.\n\t\t}\n\n\t\treturn [\n\t\t\t[corners[0], corners[1]],\n\t\t\t[corners[1], corners[2]],\n\t\t\t[corners[2], corners[3]],\n\t\t\t[corners[3], corners[0]],\n\t\t]\n\t}\n\n\tstatic Resize(\n\t\tbox: Box,\n\t\thandle: SelectionCorner | SelectionEdge | string,\n\t\tdx: number,\n\t\tdy: number,\n\t\tisAspectRatioLocked = false\n\t) {\n\t\tconst { minX: a0x, minY: a0y, maxX: a1x, maxY: a1y } = box\n\t\tlet { minX: b0x, minY: b0y, maxX: b1x, maxY: b1y } = box\n\n\t\t// Use the delta to adjust the new box by changing its corners.\n\t\t// The dragging handle (corner or edge) will determine which\n\t\t// corners should change.\n\t\tswitch (handle) {\n\t\t\tcase 'left':\n\t\t\tcase 'top_left':\n\t\t\tcase 'bottom_left': {\n\t\t\t\tb0x += dx\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'right':\n\t\t\tcase 'top_right':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tb1x += dx\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tswitch (handle) {\n\t\t\tcase 'top':\n\t\t\tcase 'top_left':\n\t\t\tcase 'top_right': {\n\t\t\t\tb0y += dy\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom':\n\t\t\tcase 'bottom_left':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tb1y += dy\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tconst scaleX = (b1x - b0x) / (a1x - a0x)\n\t\tconst scaleY = (b1y - b0y) / (a1y - a0y)\n\n\t\tconst flipX = scaleX < 0\n\t\tconst flipY = scaleY < 0\n\n\t\t/*\n 2. Aspect ratio\n If the aspect ratio is locked, adjust the corners so that the\n new box's aspect ratio matches the original aspect ratio.\n */\n\t\tif (isAspectRatioLocked) {\n\t\t\tconst aspectRatio = (a1x - a0x) / (a1y - a0y)\n\t\t\tconst bw = Math.abs(b1x - b0x)\n\t\t\tconst bh = Math.abs(b1y - b0y)\n\t\t\tconst tw = bw * (scaleY < 0 ? 1 : -1) * (1 / aspectRatio)\n\t\t\tconst th = bh * (scaleX < 0 ? 1 : -1) * aspectRatio\n\t\t\tconst isTall = aspectRatio < bw / bh\n\n\t\t\tswitch (handle) {\n\t\t\t\tcase 'top_left': {\n\t\t\t\t\tif (isTall) b0y = b1y + tw\n\t\t\t\t\telse b0x = b1x + th\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'top_right': {\n\t\t\t\t\tif (isTall) b0y = b1y + tw\n\t\t\t\t\telse b1x = b0x - th\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'bottom_right': {\n\t\t\t\t\tif (isTall) b1y = b0y - tw\n\t\t\t\t\telse b1x = b0x - th\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'bottom_left': {\n\t\t\t\t\tif (isTall) b1y = b0y - tw\n\t\t\t\t\telse b0x = b1x + th\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'bottom':\n\t\t\t\tcase 'top': {\n\t\t\t\t\tconst m = (b0x + b1x) / 2\n\t\t\t\t\tconst w = bh * aspectRatio\n\t\t\t\t\tb0x = m - w / 2\n\t\t\t\t\tb1x = m + w / 2\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'left':\n\t\t\t\tcase 'right': {\n\t\t\t\t\tconst m = (b0y + b1y) / 2\n\t\t\t\t\tconst h = bw / aspectRatio\n\t\t\t\t\tb0y = m - h / 2\n\t\t\t\t\tb1y = m + h / 2\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (flipX) {\n\t\t\tconst t = b1x\n\t\t\tb1x = b0x\n\t\t\tb0x = t\n\t\t}\n\n\t\tif (flipY) {\n\t\t\tconst t = b1y\n\t\t\tb1y = b0y\n\t\t\tb0y = t\n\t\t}\n\n\t\tconst final = new Box(b0x, b0y, Math.abs(b1x - b0x), Math.abs(b1y - b0y))\n\n\t\treturn {\n\t\t\tbox: final,\n\t\t\tscaleX: +((final.width / box.width) * (scaleX > 0 ? 1 : -1)).toFixed(5),\n\t\t\tscaleY: +((final.height / box.height) * (scaleY > 0 ? 1 : -1)).toFixed(5),\n\t\t}\n\t}\n\n\tequals(other: Box | BoxModel) {\n\t\treturn Box.Equals(this, other)\n\t}\n\n\tstatic Equals(a: Box | BoxModel, b: Box | BoxModel) {\n\t\treturn b.x === a.x && b.y === a.y && b.w === a.w && b.h === a.h\n\t}\n\n\tzeroFix() {\n\t\tthis.w = Math.max(1, this.w)\n\t\tthis.h = Math.max(1, this.h)\n\t\treturn this\n\t}\n\n\tstatic ZeroFix(other: Box | BoxModel) {\n\t\treturn new Box(other.x, other.y, Math.max(1, other.w), Math.max(1, other.h))\n\t}\n}\n\n/** @public */\nexport function flipSelectionHandleY(handle: SelectionHandle) {\n\tswitch (handle) {\n\t\tcase 'top':\n\t\t\treturn 'bottom'\n\t\tcase 'bottom':\n\t\t\treturn 'top'\n\t\tcase 'top_left':\n\t\t\treturn 'bottom_left'\n\t\tcase 'top_right':\n\t\t\treturn 'bottom_right'\n\t\tcase 'bottom_left':\n\t\t\treturn 'top_left'\n\t\tcase 'bottom_right':\n\t\t\treturn 'top_right'\n\t\tdefault:\n\t\t\treturn handle\n\t}\n}\n\n/** @public */\nexport function flipSelectionHandleX(handle: SelectionHandle) {\n\tswitch (handle) {\n\t\tcase 'left':\n\t\t\treturn 'right'\n\t\tcase 'right':\n\t\t\treturn 'left'\n\t\tcase 'top_left':\n\t\t\treturn 'top_right'\n\t\tcase 'top_right':\n\t\t\treturn 'top_left'\n\t\tcase 'bottom_left':\n\t\t\treturn 'bottom_right'\n\t\tcase 'bottom_right':\n\t\t\treturn 'bottom_left'\n\t\tdefault:\n\t\t\treturn handle\n\t}\n}\n\nconst ORDERED_SELECTION_HANDLES = [\n\t'top',\n\t'top_right',\n\t'right',\n\t'bottom_right',\n\t'bottom',\n\t'bottom_left',\n\t'left',\n\t'top_left',\n] as const\n\n/** @public */\nexport function rotateSelectionHandle(handle: SelectionHandle, rotation: number): SelectionHandle {\n\t// first find out how many tau we need to rotate by\n\trotation = rotation % PI2\n\tconst numSteps = Math.round(rotation / (PI / 4))\n\n\tconst currentIndex = ORDERED_SELECTION_HANDLES.indexOf(handle)\n\treturn ORDERED_SELECTION_HANDLES[(currentIndex + numSteps) % ORDERED_SELECTION_HANDLES.length]\n}\n\n/** @public */\nexport function isSelectionCorner(selection: string): selection is SelectionCorner {\n\treturn (\n\t\tselection === 'top_left' ||\n\t\tselection === 'top_right' ||\n\t\tselection === 'bottom_right' ||\n\t\tselection === 'bottom_left'\n\t)\n}\n\n/** @public */\nexport const ROTATE_CORNER_TO_SELECTION_CORNER = {\n\ttop_left_rotate: 'top_left',\n\ttop_right_rotate: 'top_right',\n\tbottom_right_rotate: 'bottom_right',\n\tbottom_left_rotate: 'bottom_left',\n\tmobile_rotate: 'top_left',\n} as const\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { BoxModel } from '@tldraw/tlschema'\nimport { Vec, VecLike } from './Vec'\nimport { approximatelyLte, PI, PI2, toPrecision } from './utils'\n\n/** @public */\nexport type BoxLike = BoxModel | Box\n\n/** @public */\nexport type SelectionEdge = 'top' | 'right' | 'bottom' | 'left'\n\n/** @public */\nexport type SelectionCorner = 'top_left' | 'top_right' | 'bottom_right' | 'bottom_left'\n\n/** @public */\nexport type SelectionHandle = SelectionEdge | SelectionCorner\n\n/** @public */\nexport type RotateCorner =\n\t| 'top_left_rotate'\n\t| 'top_right_rotate'\n\t| 'bottom_right_rotate'\n\t| 'bottom_left_rotate'\n\t| 'mobile_rotate'\n\n/** @public */\nexport class Box {\n\tconstructor(x = 0, y = 0, w = 0, h = 0) {\n\t\tthis.x = x\n\t\tthis.y = y\n\t\tthis.w = w\n\t\tthis.h = h\n\t}\n\n\tx = 0\n\ty = 0\n\tw = 0\n\th = 0\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget point() {\n\t\treturn new Vec(this.x, this.y)\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset point(val: Vec) {\n\t\tthis.x = val.x\n\t\tthis.y = val.y\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget minX() {\n\t\treturn this.x\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset minX(n: number) {\n\t\tthis.x = n\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget left() {\n\t\treturn this.x\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget midX() {\n\t\treturn this.x + this.w / 2\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget maxX() {\n\t\treturn this.x + this.w\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget right() {\n\t\treturn this.x + this.w\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget minY() {\n\t\treturn this.y\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset minY(n: number) {\n\t\tthis.y = n\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget top() {\n\t\treturn this.y\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget midY() {\n\t\treturn this.y + this.h / 2\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget maxY() {\n\t\treturn this.y + this.h\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget bottom() {\n\t\treturn this.y + this.h\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget width() {\n\t\treturn this.w\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset width(n: number) {\n\t\tthis.w = n\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget height() {\n\t\treturn this.h\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset height(n: number) {\n\t\tthis.h = n\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget aspectRatio() {\n\t\treturn this.width / this.height\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget center() {\n\t\treturn new Vec(this.x + this.w / 2, this.y + this.h / 2)\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tset center(v: Vec) {\n\t\tthis.x = v.x - this.w / 2\n\t\tthis.y = v.y - this.h / 2\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget corners() {\n\t\treturn [\n\t\t\tnew Vec(this.x, this.y),\n\t\t\tnew Vec(this.x + this.w, this.y),\n\t\t\tnew Vec(this.x + this.w, this.y + this.h),\n\t\t\tnew Vec(this.x, this.y + this.h),\n\t\t]\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget cornersAndCenter() {\n\t\treturn [\n\t\t\tnew Vec(this.x, this.y),\n\t\t\tnew Vec(this.x + this.w, this.y),\n\t\t\tnew Vec(this.x + this.w, this.y + this.h),\n\t\t\tnew Vec(this.x, this.y + this.h),\n\t\t\tnew Vec(this.x + this.w / 2, this.y + this.h / 2),\n\t\t]\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget sides(): Array<[Vec, Vec]> {\n\t\tconst { corners } = this\n\t\treturn [\n\t\t\t[corners[0], corners[1]],\n\t\t\t[corners[1], corners[2]],\n\t\t\t[corners[2], corners[3]],\n\t\t\t[corners[3], corners[0]],\n\t\t]\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget size(): Vec {\n\t\treturn new Vec(this.w, this.h)\n\t}\n\n\ttoFixed() {\n\t\tthis.x = toPrecision(this.x)\n\t\tthis.y = toPrecision(this.y)\n\t\tthis.w = toPrecision(this.w)\n\t\tthis.h = toPrecision(this.h)\n\t\treturn this\n\t}\n\n\tsetTo(B: Box) {\n\t\tthis.x = B.x\n\t\tthis.y = B.y\n\t\tthis.w = B.w\n\t\tthis.h = B.h\n\t\treturn this\n\t}\n\n\tset(x = 0, y = 0, w = 0, h = 0) {\n\t\tthis.x = x\n\t\tthis.y = y\n\t\tthis.w = w\n\t\tthis.h = h\n\t\treturn this\n\t}\n\n\texpand(A: Box) {\n\t\tconst minX = Math.min(this.x, A.x)\n\t\tconst minY = Math.min(this.y, A.y)\n\t\tconst maxX = Math.max(this.x + this.w, A.x + A.w)\n\t\tconst maxY = Math.max(this.y + this.h, A.y + A.h)\n\n\t\tthis.x = minX\n\t\tthis.y = minY\n\t\tthis.w = maxX - minX\n\t\tthis.h = maxY - minY\n\t\treturn this\n\t}\n\n\texpandBy(n: number) {\n\t\tthis.x -= n\n\t\tthis.y -= n\n\t\tthis.w += n * 2\n\t\tthis.h += n * 2\n\t\treturn this\n\t}\n\n\tscale(n: number) {\n\t\tthis.x /= n\n\t\tthis.y /= n\n\t\tthis.w /= n\n\t\tthis.h /= n\n\t\treturn this\n\t}\n\n\tclone() {\n\t\tconst { x, y, w, h } = this\n\t\treturn new Box(x, y, w, h)\n\t}\n\n\ttranslate(delta: VecLike) {\n\t\tthis.x += delta.x\n\t\tthis.y += delta.y\n\t\treturn this\n\t}\n\n\tsnapToGrid(size: number) {\n\t\tconst minX = Math.round(this.x / size) * size\n\t\tconst minY = Math.round(this.y / size) * size\n\t\tconst maxX = Math.round((this.x + this.w) / size) * size\n\t\tconst maxY = Math.round((this.y + this.h) / size) * size\n\t\tthis.minX = minX\n\t\tthis.minY = minY\n\t\tthis.width = Math.max(1, maxX - minX)\n\t\tthis.height = Math.max(1, maxY - minY)\n\t}\n\n\tcollides(B: Box) {\n\t\treturn Box.Collides(this, B)\n\t}\n\n\tcontains(B: Box) {\n\t\treturn Box.Contains(this, B)\n\t}\n\n\tincludes(B: Box) {\n\t\treturn Box.Includes(this, B)\n\t}\n\n\tcontainsPoint(V: VecLike, margin = 0) {\n\t\treturn Box.ContainsPoint(this, V, margin)\n\t}\n\n\tgetHandlePoint(handle: SelectionCorner | SelectionEdge) {\n\t\tswitch (handle) {\n\t\t\tcase 'top_left':\n\t\t\t\treturn new Vec(this.x, this.y)\n\t\t\tcase 'top_right':\n\t\t\t\treturn new Vec(this.x + this.w, this.y)\n\t\t\tcase 'bottom_left':\n\t\t\t\treturn new Vec(this.x, this.y + this.h)\n\t\t\tcase 'bottom_right':\n\t\t\t\treturn new Vec(this.x + this.w, this.y + this.h)\n\t\t\tcase 'top':\n\t\t\t\treturn new Vec(this.x + this.w / 2, this.y)\n\t\t\tcase 'right':\n\t\t\t\treturn new Vec(this.x + this.w, this.y + this.h / 2)\n\t\t\tcase 'bottom':\n\t\t\t\treturn new Vec(this.x + this.w / 2, this.y + this.h)\n\t\t\tcase 'left':\n\t\t\t\treturn new Vec(this.x, this.y + this.h / 2)\n\t\t}\n\t}\n\n\ttoJson(): BoxModel {\n\t\treturn { x: this.x, y: this.y, w: this.w, h: this.h }\n\t}\n\n\tresize(handle: SelectionCorner | SelectionEdge | string, dx: number, dy: number) {\n\t\tconst { minX: a0x, minY: a0y, maxX: a1x, maxY: a1y } = this\n\t\tlet { minX: b0x, minY: b0y, maxX: b1x, maxY: b1y } = this\n\n\t\t// Use the delta to adjust the new box by changing its corners.\n\t\t// The dragging handle (corner or edge) will determine which\n\t\t// corners should change.\n\t\tswitch (handle) {\n\t\t\tcase 'left':\n\t\t\tcase 'top_left':\n\t\t\tcase 'bottom_left': {\n\t\t\t\tb0x += dx\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'right':\n\t\t\tcase 'top_right':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tb1x += dx\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tswitch (handle) {\n\t\t\tcase 'top':\n\t\t\tcase 'top_left':\n\t\t\tcase 'top_right': {\n\t\t\t\tb0y += dy\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom':\n\t\t\tcase 'bottom_left':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tb1y += dy\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tconst scaleX = (b1x - b0x) / (a1x - a0x)\n\t\tconst scaleY = (b1y - b0y) / (a1y - a0y)\n\n\t\tconst flipX = scaleX < 0\n\t\tconst flipY = scaleY < 0\n\n\t\tif (flipX) {\n\t\t\tconst t = b1x\n\t\t\tb1x = b0x\n\t\t\tb0x = t\n\t\t}\n\n\t\tif (flipY) {\n\t\t\tconst t = b1y\n\t\t\tb1y = b0y\n\t\t\tb0y = t\n\t\t}\n\n\t\tthis.minX = b0x\n\t\tthis.minY = b0y\n\t\tthis.width = Math.abs(b1x - b0x)\n\t\tthis.height = Math.abs(b1y - b0y)\n\t}\n\n\tunion(box: BoxModel) {\n\t\tconst minX = Math.min(this.x, box.x)\n\t\tconst minY = Math.min(this.y, box.y)\n\t\tconst maxX = Math.max(this.x + this.w, box.x + box.w)\n\t\tconst maxY = Math.max(this.y + this.h, box.y + box.h)\n\n\t\tthis.x = minX\n\t\tthis.y = minY\n\t\tthis.width = maxX - minX\n\t\tthis.height = maxY - minY\n\n\t\treturn this\n\t}\n\n\tstatic From(box: BoxModel) {\n\t\treturn new Box(box.x, box.y, box.w, box.h)\n\t}\n\n\tstatic FromCenter(center: VecLike, size: VecLike) {\n\t\treturn new Box(center.x - size.x / 2, center.y - size.y / 2, size.x, size.y)\n\t}\n\n\tstatic FromPoints(points: VecLike[]) {\n\t\tif (points.length === 0) return new Box()\n\t\tlet minX = Infinity\n\t\tlet minY = Infinity\n\t\tlet maxX = -Infinity\n\t\tlet maxY = -Infinity\n\t\tlet point: VecLike\n\t\tfor (let i = 0, n = points.length; i < n; i++) {\n\t\t\tpoint = points[i]\n\t\t\tminX = Math.min(point.x, minX)\n\t\t\tminY = Math.min(point.y, minY)\n\t\t\tmaxX = Math.max(point.x, maxX)\n\t\t\tmaxY = Math.max(point.y, maxY)\n\t\t}\n\n\t\treturn new Box(minX, minY, maxX - minX, maxY - minY)\n\t}\n\n\tstatic Expand(A: Box, B: Box) {\n\t\tconst minX = Math.min(B.minX, A.minX)\n\t\tconst minY = Math.min(B.minY, A.minY)\n\t\tconst maxX = Math.max(B.maxX, A.maxX)\n\t\tconst maxY = Math.max(B.maxY, A.maxY)\n\n\t\treturn new Box(minX, minY, maxX - minX, maxY - minY)\n\t}\n\n\tstatic ExpandBy(A: Box, n: number) {\n\t\treturn new Box(A.minX - n, A.minY - n, A.width + n * 2, A.height + n * 2)\n\t}\n\n\tstatic Collides(A: Box, B: Box) {\n\t\treturn !(A.maxX < B.minX || A.minX > B.maxX || A.maxY < B.minY || A.minY > B.maxY)\n\t}\n\n\tstatic Contains(A: Box, B: Box) {\n\t\treturn A.minX < B.minX && A.minY < B.minY && A.maxY > B.maxY && A.maxX > B.maxX\n\t}\n\n\tstatic ContainsApproximately(A: Box, B: Box, precision?: number) {\n\t\treturn (\n\t\t\tapproximatelyLte(A.minX, B.minX, precision) &&\n\t\t\tapproximatelyLte(A.minY, B.minY, precision) &&\n\t\t\tapproximatelyLte(B.maxX, A.maxX, precision) &&\n\t\t\tapproximatelyLte(B.maxY, A.maxY, precision)\n\t\t)\n\t}\n\n\tstatic Includes(A: Box, B: Box) {\n\t\treturn Box.Collides(A, B) || Box.Contains(A, B)\n\t}\n\n\tstatic ContainsPoint(A: Box, B: VecLike, margin = 0) {\n\t\treturn !(\n\t\t\tB.x < A.minX - margin ||\n\t\t\tB.y < A.minY - margin ||\n\t\t\tB.x > A.maxX + margin ||\n\t\t\tB.y > A.maxY + margin\n\t\t)\n\t}\n\n\tstatic Common(boxes: Box[]) {\n\t\tlet minX = Infinity\n\t\tlet minY = Infinity\n\t\tlet maxX = -Infinity\n\t\tlet maxY = -Infinity\n\n\t\tfor (let i = 0; i < boxes.length; i++) {\n\t\t\tconst B = boxes[i]\n\t\t\tminX = Math.min(minX, B.minX)\n\t\t\tminY = Math.min(minY, B.minY)\n\t\t\tmaxX = Math.max(maxX, B.maxX)\n\t\t\tmaxY = Math.max(maxY, B.maxY)\n\t\t}\n\n\t\treturn new Box(minX, minY, maxX - minX, maxY - minY)\n\t}\n\n\tstatic Sides(A: Box, inset = 0) {\n\t\tconst { corners } = A\n\t\tif (inset) {\n\t\t\t// TODO: Inset the corners by the inset amount.\n\t\t}\n\n\t\treturn [\n\t\t\t[corners[0], corners[1]],\n\t\t\t[corners[1], corners[2]],\n\t\t\t[corners[2], corners[3]],\n\t\t\t[corners[3], corners[0]],\n\t\t]\n\t}\n\n\tstatic Resize(\n\t\tbox: Box,\n\t\thandle: SelectionCorner | SelectionEdge | string,\n\t\tdx: number,\n\t\tdy: number,\n\t\tisAspectRatioLocked = false\n\t) {\n\t\tconst { minX: a0x, minY: a0y, maxX: a1x, maxY: a1y } = box\n\t\tlet { minX: b0x, minY: b0y, maxX: b1x, maxY: b1y } = box\n\n\t\t// Use the delta to adjust the new box by changing its corners.\n\t\t// The dragging handle (corner or edge) will determine which\n\t\t// corners should change.\n\t\tswitch (handle) {\n\t\t\tcase 'left':\n\t\t\tcase 'top_left':\n\t\t\tcase 'bottom_left': {\n\t\t\t\tb0x += dx\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'right':\n\t\t\tcase 'top_right':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tb1x += dx\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tswitch (handle) {\n\t\t\tcase 'top':\n\t\t\tcase 'top_left':\n\t\t\tcase 'top_right': {\n\t\t\t\tb0y += dy\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom':\n\t\t\tcase 'bottom_left':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tb1y += dy\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tconst scaleX = (b1x - b0x) / (a1x - a0x)\n\t\tconst scaleY = (b1y - b0y) / (a1y - a0y)\n\n\t\tconst flipX = scaleX < 0\n\t\tconst flipY = scaleY < 0\n\n\t\t/*\n 2. Aspect ratio\n If the aspect ratio is locked, adjust the corners so that the\n new box's aspect ratio matches the original aspect ratio.\n */\n\t\tif (isAspectRatioLocked) {\n\t\t\tconst aspectRatio = (a1x - a0x) / (a1y - a0y)\n\t\t\tconst bw = Math.abs(b1x - b0x)\n\t\t\tconst bh = Math.abs(b1y - b0y)\n\t\t\tconst tw = bw * (scaleY < 0 ? 1 : -1) * (1 / aspectRatio)\n\t\t\tconst th = bh * (scaleX < 0 ? 1 : -1) * aspectRatio\n\t\t\tconst isTall = aspectRatio < bw / bh\n\n\t\t\tswitch (handle) {\n\t\t\t\tcase 'top_left': {\n\t\t\t\t\tif (isTall) b0y = b1y + tw\n\t\t\t\t\telse b0x = b1x + th\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'top_right': {\n\t\t\t\t\tif (isTall) b0y = b1y + tw\n\t\t\t\t\telse b1x = b0x - th\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'bottom_right': {\n\t\t\t\t\tif (isTall) b1y = b0y - tw\n\t\t\t\t\telse b1x = b0x - th\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'bottom_left': {\n\t\t\t\t\tif (isTall) b1y = b0y - tw\n\t\t\t\t\telse b0x = b1x + th\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'bottom':\n\t\t\t\tcase 'top': {\n\t\t\t\t\tconst m = (b0x + b1x) / 2\n\t\t\t\t\tconst w = bh * aspectRatio\n\t\t\t\t\tb0x = m - w / 2\n\t\t\t\t\tb1x = m + w / 2\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'left':\n\t\t\t\tcase 'right': {\n\t\t\t\t\tconst m = (b0y + b1y) / 2\n\t\t\t\t\tconst h = bw / aspectRatio\n\t\t\t\t\tb0y = m - h / 2\n\t\t\t\t\tb1y = m + h / 2\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (flipX) {\n\t\t\tconst t = b1x\n\t\t\tb1x = b0x\n\t\t\tb0x = t\n\t\t}\n\n\t\tif (flipY) {\n\t\t\tconst t = b1y\n\t\t\tb1y = b0y\n\t\t\tb0y = t\n\t\t}\n\n\t\tconst final = new Box(b0x, b0y, Math.abs(b1x - b0x), Math.abs(b1y - b0y))\n\n\t\treturn {\n\t\t\tbox: final,\n\t\t\tscaleX: +((final.width / box.width) * (scaleX > 0 ? 1 : -1)).toFixed(5),\n\t\t\tscaleY: +((final.height / box.height) * (scaleY > 0 ? 1 : -1)).toFixed(5),\n\t\t}\n\t}\n\n\tequals(other: Box | BoxModel) {\n\t\treturn Box.Equals(this, other)\n\t}\n\n\tstatic Equals(a: Box | BoxModel, b: Box | BoxModel) {\n\t\treturn b.x === a.x && b.y === a.y && b.w === a.w && b.h === a.h\n\t}\n\n\tzeroFix() {\n\t\tthis.w = Math.max(1, this.w)\n\t\tthis.h = Math.max(1, this.h)\n\t\treturn this\n\t}\n\n\tstatic ZeroFix(other: Box | BoxModel) {\n\t\treturn new Box(other.x, other.y, Math.max(1, other.w), Math.max(1, other.h))\n\t}\n}\n\n/** @public */\nexport function flipSelectionHandleY(handle: SelectionHandle) {\n\tswitch (handle) {\n\t\tcase 'top':\n\t\t\treturn 'bottom'\n\t\tcase 'bottom':\n\t\t\treturn 'top'\n\t\tcase 'top_left':\n\t\t\treturn 'bottom_left'\n\t\tcase 'top_right':\n\t\t\treturn 'bottom_right'\n\t\tcase 'bottom_left':\n\t\t\treturn 'top_left'\n\t\tcase 'bottom_right':\n\t\t\treturn 'top_right'\n\t\tdefault:\n\t\t\treturn handle\n\t}\n}\n\n/** @public */\nexport function flipSelectionHandleX(handle: SelectionHandle) {\n\tswitch (handle) {\n\t\tcase 'left':\n\t\t\treturn 'right'\n\t\tcase 'right':\n\t\t\treturn 'left'\n\t\tcase 'top_left':\n\t\t\treturn 'top_right'\n\t\tcase 'top_right':\n\t\t\treturn 'top_left'\n\t\tcase 'bottom_left':\n\t\t\treturn 'bottom_right'\n\t\tcase 'bottom_right':\n\t\t\treturn 'bottom_left'\n\t\tdefault:\n\t\t\treturn handle\n\t}\n}\n\nconst ORDERED_SELECTION_HANDLES = [\n\t'top',\n\t'top_right',\n\t'right',\n\t'bottom_right',\n\t'bottom',\n\t'bottom_left',\n\t'left',\n\t'top_left',\n] as const\n\n/** @public */\nexport function rotateSelectionHandle(handle: SelectionHandle, rotation: number): SelectionHandle {\n\t// first find out how many tau we need to rotate by\n\trotation = rotation % PI2\n\tconst numSteps = Math.round(rotation / (PI / 4))\n\n\tconst currentIndex = ORDERED_SELECTION_HANDLES.indexOf(handle)\n\treturn ORDERED_SELECTION_HANDLES[(currentIndex + numSteps) % ORDERED_SELECTION_HANDLES.length]\n}\n\n/** @public */\nexport function isSelectionCorner(selection: string): selection is SelectionCorner {\n\treturn (\n\t\tselection === 'top_left' ||\n\t\tselection === 'top_right' ||\n\t\tselection === 'bottom_right' ||\n\t\tselection === 'bottom_left'\n\t)\n}\n\n/** @public */\nexport const ROTATE_CORNER_TO_SELECTION_CORNER = {\n\ttop_left_rotate: 'top_left',\n\ttop_right_rotate: 'top_right',\n\tbottom_right_rotate: 'bottom_right',\n\tbottom_left_rotate: 'bottom_left',\n\tmobile_rotate: 'top_left',\n} as const\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/version.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const version = "3.16.0-canary.
|
|
1
|
+
const version = "3.16.0-canary.5170ef6b6e20";
|
|
2
2
|
const publishDates = {
|
|
3
3
|
major: "2024-09-13T14:36:29.063Z",
|
|
4
|
-
minor: "2025-08-
|
|
5
|
-
patch: "2025-08-
|
|
4
|
+
minor: "2025-08-29T13:37:30.941Z",
|
|
5
|
+
patch: "2025-08-29T13:37:30.941Z"
|
|
6
6
|
};
|
|
7
7
|
export {
|
|
8
8
|
publishDates,
|
package/dist-esm/version.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/version.ts"],
|
|
4
|
-
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-canary.
|
|
4
|
+
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-canary.5170ef6b6e20'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-08-29T13:37:30.941Z',\n\tpatch: '2025-08-29T13:37:30.941Z',\n}\n"],
|
|
5
5
|
"mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/editor.css
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
--tl-layer-watermark: 200;
|
|
30
30
|
--tl-layer-canvas-shapes: 300;
|
|
31
31
|
--tl-layer-canvas-overlays: 500;
|
|
32
|
+
--tl-layer-canvas-in-front: 600;
|
|
32
33
|
--tl-layer-canvas-blocker: 10000;
|
|
33
34
|
|
|
34
35
|
/* Canvas overlays z-index */
|
|
@@ -297,6 +298,13 @@ input,
|
|
|
297
298
|
contain: strict;
|
|
298
299
|
}
|
|
299
300
|
|
|
301
|
+
.tl-canvas__in-front {
|
|
302
|
+
position: absolute;
|
|
303
|
+
inset: 0;
|
|
304
|
+
pointer-events: none;
|
|
305
|
+
z-index: var(--tl-layer-canvas-in-front);
|
|
306
|
+
}
|
|
307
|
+
|
|
300
308
|
.tl-shapes {
|
|
301
309
|
position: relative;
|
|
302
310
|
z-index: var(--tl-layer-canvas-shapes);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/editor",
|
|
3
3
|
"description": "tldraw infinite canvas SDK (editor).",
|
|
4
|
-
"version": "3.16.0-canary.
|
|
4
|
+
"version": "3.16.0-canary.5170ef6b6e20",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -50,12 +50,12 @@
|
|
|
50
50
|
"@tiptap/core": "^2.9.1",
|
|
51
51
|
"@tiptap/pm": "^2.9.1",
|
|
52
52
|
"@tiptap/react": "^2.9.1",
|
|
53
|
-
"@tldraw/state": "3.16.0-canary.
|
|
54
|
-
"@tldraw/state-react": "3.16.0-canary.
|
|
55
|
-
"@tldraw/store": "3.16.0-canary.
|
|
56
|
-
"@tldraw/tlschema": "3.16.0-canary.
|
|
57
|
-
"@tldraw/utils": "3.16.0-canary.
|
|
58
|
-
"@tldraw/validate": "3.16.0-canary.
|
|
53
|
+
"@tldraw/state": "3.16.0-canary.5170ef6b6e20",
|
|
54
|
+
"@tldraw/state-react": "3.16.0-canary.5170ef6b6e20",
|
|
55
|
+
"@tldraw/store": "3.16.0-canary.5170ef6b6e20",
|
|
56
|
+
"@tldraw/tlschema": "3.16.0-canary.5170ef6b6e20",
|
|
57
|
+
"@tldraw/utils": "3.16.0-canary.5170ef6b6e20",
|
|
58
|
+
"@tldraw/validate": "3.16.0-canary.5170ef6b6e20",
|
|
59
59
|
"@types/core-js": "^2.5.8",
|
|
60
60
|
"@use-gesture/react": "^10.3.1",
|
|
61
61
|
"classnames": "^2.5.1",
|
package/src/index.ts
CHANGED
|
@@ -172,10 +172,12 @@ export function DefaultCanvas({ className }: TLCanvasComponentProps) {
|
|
|
172
172
|
<LiveCollaborators />
|
|
173
173
|
</div>
|
|
174
174
|
</div>
|
|
175
|
+
<div className="tl-canvas__in-front">
|
|
176
|
+
<InFrontOfTheCanvasWrapper />
|
|
177
|
+
</div>
|
|
175
178
|
<MovingCameraHitTestBlocker />
|
|
176
179
|
</div>
|
|
177
180
|
<MenuClickCapture />
|
|
178
|
-
<InFrontOfTheCanvasWrapper />
|
|
179
181
|
</>
|
|
180
182
|
)
|
|
181
183
|
}
|
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -4860,27 +4860,25 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
4860
4860
|
return this.store.createComputedCache('pageMaskCache', (shape) => {
|
|
4861
4861
|
if (isPageId(shape.parentId)) return undefined
|
|
4862
4862
|
|
|
4863
|
-
const
|
|
4864
|
-
|
|
4865
|
-
)
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
return []
|
|
4883
|
-
})
|
|
4863
|
+
const clipPaths: Vec[][] = []
|
|
4864
|
+
// Get all ancestors that can potentially clip this shape
|
|
4865
|
+
for (const ancestor of this.getShapeAncestors(shape.id)) {
|
|
4866
|
+
const util = this.getShapeUtil(ancestor)
|
|
4867
|
+
const clipPath = util.getClipPath?.(ancestor)
|
|
4868
|
+
if (!clipPath) continue
|
|
4869
|
+
if (util.shouldClipChild?.(shape) === false) continue
|
|
4870
|
+
const pageTransform = this.getShapePageTransform(ancestor.id)
|
|
4871
|
+
clipPaths.push(pageTransform.applyToPoints(clipPath))
|
|
4872
|
+
}
|
|
4873
|
+
if (clipPaths.length === 0) return undefined
|
|
4874
|
+
|
|
4875
|
+
const pageMask = clipPaths.reduce((acc, b) => {
|
|
4876
|
+
const intersection = intersectPolygonPolygon(acc, b)
|
|
4877
|
+
if (intersection) {
|
|
4878
|
+
return intersection.map(Vec.Cast)
|
|
4879
|
+
}
|
|
4880
|
+
return []
|
|
4881
|
+
})
|
|
4884
4882
|
|
|
4885
4883
|
return pageMask
|
|
4886
4884
|
})
|
|
@@ -296,6 +296,27 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
296
296
|
return false
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Get the clip path to apply to this shape's children.
|
|
301
|
+
*
|
|
302
|
+
* @param shape - The shape to get the clip path for
|
|
303
|
+
* @returns Array of points defining the clipping polygon in local coordinates, or undefined if no clipping
|
|
304
|
+
* @public
|
|
305
|
+
*/
|
|
306
|
+
getClipPath?(shape: Shape): Vec[] | undefined
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Whether a specific child shape should be clipped by this shape.
|
|
310
|
+
* Only called if getClipPath returns a valid polygon.
|
|
311
|
+
*
|
|
312
|
+
* If not defined, the default behavior is to clip all children.
|
|
313
|
+
*
|
|
314
|
+
* @param child - The child shape to check
|
|
315
|
+
* @returns boolean indicating if this child should be clipped
|
|
316
|
+
* @public
|
|
317
|
+
*/
|
|
318
|
+
shouldClipChild?(child: TLShape): boolean
|
|
319
|
+
|
|
299
320
|
/**
|
|
300
321
|
* Whether the shape should hide its resize handles when selected.
|
|
301
322
|
*
|
|
@@ -341,6 +362,20 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
341
362
|
return false
|
|
342
363
|
}
|
|
343
364
|
|
|
365
|
+
/**
|
|
366
|
+
* By default, the bounds of an image export are the bounds of all the shapes it contains, plus
|
|
367
|
+
* some padding. If an export includes a shape where `isExportBoundsContainer` is true, then the
|
|
368
|
+
* padding is skipped _if the bounds of that shape contains all the other shapes_. This is
|
|
369
|
+
* useful in cases like annotating on top of an image, where you usually want to avoid extra
|
|
370
|
+
* padding around the image if you don't need it.
|
|
371
|
+
*
|
|
372
|
+
* @param _shape - The shape to check
|
|
373
|
+
* @returns True if this shape should be treated as an export bounds container
|
|
374
|
+
*/
|
|
375
|
+
isExportBoundsContainer(_shape: Shape): boolean {
|
|
376
|
+
return false
|
|
377
|
+
}
|
|
378
|
+
|
|
344
379
|
/**
|
|
345
380
|
* Get a JSX element for the shape (as an HTML element) to be rendered as part of the canvas background - behind any other shape content.
|
|
346
381
|
*
|