Bump tldraw and some other improvements (#26)

* bump

* fix svg export

* faster export

* handle disappearing shape
This commit is contained in:
Lu Wilson 2024-09-25 12:56:37 +01:00 committed by GitHub
parent d50a544bb1
commit eca5d2c180
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 995 additions and 645 deletions

1227
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
"dependencies": {
"@fal-ai/serverless-client": "^0.6.0",
"@fal-ai/serverless-proxy": "^0.6.0",
"@tldraw/tldraw": "canary",
"@tldraw/tldraw": "3.1.0",
"next": "14.0.3",
"react": "^18",
"react-dom": "^18",
@ -32,4 +32,4 @@
"prettier-plugin-organize-imports": "^3.2.4",
"typescript": "^5"
}
}
}

View File

@ -2,8 +2,7 @@
'use client'
import { LiveImageShape, LiveImageShapeUtil } from '@/components/LiveImageShapeUtil'
import { LiveImageTool,MakeLiveButton } from '@/components/LiveImageTool'
import { LockupLink } from '@/components/LockupLink'
import { LiveImageTool, MakeLiveButton } from '@/components/LiveImageTool'
import { LiveImageProvider } from '@/hooks/useLiveImage'
import * as fal from '@fal-ai/serverless-client'
import {
@ -12,7 +11,6 @@ import {
Editor,
TLUiOverrides,
Tldraw,
toolbarItem,
track,
useEditor,
} from '@tldraw/tldraw'
@ -39,18 +37,18 @@ const overrides: TLUiOverrides = {
}
return tools
},
toolbar(_app, toolbar, { tools }) {
const frameIndex = toolbar.findIndex((item) => item.id === 'frame')
if (frameIndex !== -1) toolbar.splice(frameIndex, 1)
const highlighterIndex = toolbar.findIndex((item) => item.id === 'highlight')
if (highlighterIndex !== -1) {
const highlighterItem = toolbar[highlighterIndex]
toolbar.splice(highlighterIndex, 1)
toolbar.splice(3, 0, highlighterItem)
}
toolbar.splice(2, 0, toolbarItem(tools.liveImage))
return toolbar
},
// toolbar(_app, toolbar, { tools }) {
// const frameIndex = toolbar.findIndex((item) => item.id === 'frame')
// if (frameIndex !== -1) toolbar.splice(frameIndex, 1)
// const highlighterIndex = toolbar.findIndex((item) => item.id === 'highlight')
// if (highlighterIndex !== -1) {
// const highlighterItem = toolbar[highlighterIndex]
// toolbar.splice(highlighterIndex, 1)
// toolbar.splice(3, 0, highlighterItem)
// }
// toolbar.splice(2, 0, toolbarItem(tools.liveImage))
// return toolbar
// },
}
const shapeUtils = [LiveImageShapeUtil]
@ -82,7 +80,7 @@ export default function Home() {
})
}
editor.setStyleForNextShapes(DefaultSizeStyle, 'xl', { ephemeral: true })
editor.setStyleForNextShapes(DefaultSizeStyle, 'xl')
}
return (
@ -90,15 +88,16 @@ export default function Home() {
<main className="tldraw-wrapper">
<div className="tldraw-wrapper__inner">
<Tldraw
persistenceKey="tldraw-fal"
persistenceKey="draw-fast"
onMount={onEditorMount}
shapeUtils={shapeUtils}
tools={tools}
shareZone={<MakeLiveButton />}
components={{
SharePanel: MakeLiveButton,
}}
overrides={overrides}
>
<SneakySideEffects />
<LockupLink />
<LiveImageAssets />
</Tldraw>
</div>

View File

@ -1,22 +0,0 @@
// An 'x' svg icon that represents collaboration between two organisations.
// eg: tldraw x fal
export function Collab() {
return (
<svg
width="100%"
height="100%"
viewBox="0 0 53 53"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
{/* Two paths form a cross */}
<path
d="M26.5 0V53M0 26.5H53"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}

View File

@ -29,16 +29,13 @@ export const FrameLabelInput = forwardRef<
const value = e.currentTarget.value.trim()
if (name === value) return
editor.updateShapes(
[
{
id,
type: 'frame',
props: { name: value },
},
],
{ squashing: true }
)
editor.updateShapes([
{
id,
type: 'frame',
props: { name: value },
},
])
},
[id, editor]
)
@ -52,16 +49,13 @@ export const FrameLabelInput = forwardRef<
const value = e.currentTarget.value
if (name === value) return
editor.updateShapes(
[
{
id,
type: 'frame',
props: { name: value },
},
],
{ squashing: true }
)
editor.updateShapes([
{
id,
type: 'frame',
props: { name: value },
},
])
},
[id, editor]
)

View File

@ -2,7 +2,6 @@
/* eslint-disable react-hooks/rules-of-hooks */
import {
AssetRecordType,
Button,
Geometry2d,
getDefaultColorTheme,
Rectangle2d,
@ -10,9 +9,10 @@ import {
ShapeUtil,
SVGContainer,
TLBaseShape,
TldrawUiButton,
TldrawUiButtonIcon,
TLGroupShape,
TLOnResizeEndHandler,
TLOnResizeHandler,
TLResizeInfo,
TLShape,
TLShapeId,
toDomPrecision,
@ -60,7 +60,6 @@ export class LiveImageShapeUtil extends ShapeUtil<LiveImageShape> {
static type = 'live-image' as any
override canBind = () => false
override canUnmount = () => false
override canEdit = () => true
override isAspectRatioLocked = () => true
@ -116,7 +115,7 @@ export class LiveImageShapeUtil extends ShapeUtil<LiveImageShape> {
}
}
override onResizeEnd: TLOnResizeEndHandler<LiveImageShape> = (shape) => {
override onResizeEnd(shape: LiveImageShape) {
const bounds = this.editor.getShapePageBounds(shape)!
const children = this.editor.getSortedChildIdsForParent(shape.id)
@ -134,7 +133,7 @@ export class LiveImageShapeUtil extends ShapeUtil<LiveImageShape> {
}
}
override onResize: TLOnResizeHandler<any> = (shape, info) => {
override onResize(shape: LiveImageShape, info: TLResizeInfo<LiveImageShape>) {
return resizeBox(shape, info)
}
@ -192,9 +191,8 @@ export class LiveImageShapeUtil extends ShapeUtil<LiveImageShape> {
}}
/>
)}
<Button
<TldrawUiButton
type="icon"
icon={shape.props.overlayResult ? 'chevron-right' : 'chevron-left'}
style={{
position: 'absolute',
top: -4,
@ -213,7 +211,9 @@ export class LiveImageShapeUtil extends ShapeUtil<LiveImageShape> {
props: { overlayResult: !shape.props.overlayResult },
})
}}
/>
>
<TldrawUiButtonIcon icon={shape.props.overlayResult ? 'chevron-right' : 'chevron-left'} />
</TldrawUiButton>
</>
)
}

View File

@ -1,125 +0,0 @@
/* eslint-disable @next/next/no-img-element */
import { useBreakpoint } from '@tldraw/tldraw'
import { FalLogo } from './fal-logo'
export function LockupLink() {
const breakpoint = useBreakpoint()
// const editor = useEditor()
// const isFocusMode = useValue('isFocusMode', () => editor.getInstanceState().isFocusMode, [editor])
// if (isFocusMode) return null
return (
<span
className={`lockup__link ${breakpoint < 7 ? 'lockup__link__mobile' : ''} ${
breakpoint < 6 ? 'lockup__link__mobile__raise' : ''
}`}
>
<By />
{/* <img alt="by" className="lockup__by" src="/by-tldraw.svg" /> */}
<a href="https://twitter.com/tldraw">
<Lockup />
{/* <img alt="tldraw logo" className="lockup" src="/lockup.svg" /> */}
</a>
<span className="lockup__collab">×</span>
<a href="https://twitter.com/fal_ai_data">
<FalLogo />
</a>
</span>
)
}
function Lockup() {
return (
<svg
className="lockup"
width="71"
height="18"
viewBox="0 0 71 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0 1.97802C0 0.88559 0.848303 0 1.89474 0H16.1053C17.1517 0 18 0.885591 18 1.97802V16.022C18 17.1144 17.1517 18 16.1053 18H1.89474C0.848303 18 0 17.1144 0 16.022V1.97802ZM10.6264 5.14801C10.6264 5.58302 10.4777 5.95212 10.1803 6.25531C9.88296 6.5585 9.52095 6.71009 9.0943 6.71009C8.65471 6.71009 8.28624 6.5585 7.98888 6.25531C7.69151 5.95212 7.54283 5.58302 7.54283 5.14801C7.54283 4.71301 7.69151 4.34391 7.98888 4.04072C8.28624 3.73753 8.65471 3.58594 9.0943 3.58594C9.52095 3.58594 9.88296 3.73753 10.1803 4.04072C10.4777 4.34391 10.6264 4.71301 10.6264 5.14801ZM7.52344 10.6224C7.52344 10.1874 7.67212 9.81831 7.96948 9.51512C8.27978 9.19875 8.65471 9.04056 9.0943 9.04056C9.50802 9.04056 9.87003 9.19875 10.1803 9.51512C10.4906 9.81831 10.6716 10.161 10.7233 10.5433C10.8268 11.2552 10.6975 11.9604 10.3355 12.659C9.98639 13.3577 9.48216 13.8916 8.82279 14.2607C8.46078 14.4716 8.16342 14.465 7.9307 14.2409C7.71091 14.03 7.77555 13.7795 8.12463 13.4895C8.31856 13.3445 8.48017 13.16 8.60946 12.9359C8.73875 12.7118 8.82279 12.4811 8.86158 12.2438C8.87451 12.1384 8.82925 12.0856 8.72582 12.0856C8.46725 12.0724 8.2022 11.9274 7.9307 11.6506C7.65919 11.3738 7.52344 11.0311 7.52344 10.6224Z"
fill="currentColor"
fillOpacity="1"
/>
<path
d="M34.156 14.5761C34.2636 14.5761 34.3174 14.5223 34.3174 14.4147V12.2234C34.3174 12.0073 34.1422 11.8321 33.9261 11.8321H33.6424C33.5543 11.8321 33.4859 11.8076 33.437 11.7587C33.3978 11.7196 33.3783 11.6609 33.3783 11.5826V3.73207C33.3783 3.62446 33.3245 3.57065 33.2168 3.57065H30.7467C30.5306 3.57065 30.3554 3.74585 30.3554 3.96196V12.463C30.3554 13.1674 30.556 13.6957 30.9571 14.0478C31.3582 14.4 31.8717 14.5761 32.4978 14.5761H34.156Z"
fill="currentColor"
fillOpacity="1"
/>
<path
d="M29.0935 12.2087C29.0935 11.9926 28.9183 11.8174 28.7022 11.8174H27.6701C27.3375 11.8174 27.1125 11.7587 26.9951 11.6413C26.8484 11.5043 26.775 11.2842 26.775 10.981V9.68478C26.775 9.46867 26.9502 9.29348 27.1663 9.29348H28.7022C28.9183 9.29348 29.0935 9.11829 29.0935 8.90217V6.71087C29.0935 6.60326 29.0397 6.54946 28.9321 6.54946H27.1663C26.9502 6.54946 26.775 6.37426 26.775 6.15815V4.46576C26.775 4.35815 26.7212 4.30435 26.6136 4.30435H24.2315C24.0154 4.30435 23.8402 4.47954 23.8402 4.69565V6.15815C23.8402 6.37426 23.665 6.54946 23.4489 6.54946H23.087C22.8708 6.54946 22.6957 6.72465 22.6957 6.94076V9.13207C22.6957 9.23967 22.7495 9.29348 22.8571 9.29348H23.4489C23.665 9.29348 23.8402 9.46867 23.8402 9.68478V11.2011C23.8402 12.3359 24.1386 13.1821 24.7353 13.7397C25.3321 14.2973 26.1978 14.5761 27.3326 14.5761H28.9321C29.0397 14.5761 29.0935 14.5223 29.0935 14.4147V12.2087Z"
fill="currentColor"
fillOpacity="1"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M37.6867 6.40272C38.1367 6.40272 38.5231 6.51522 38.8459 6.74022C39.1499 6.94586 39.4008 7.21279 39.5985 7.54101C39.6332 7.59855 39.6947 7.63533 39.7619 7.63533C39.8638 7.63533 39.9464 7.55268 39.9464 7.45074V3.96196C39.9464 3.74584 40.1216 3.57065 40.3377 3.57065H42.7198C42.8274 3.57065 42.8812 3.62446 42.8812 3.73207V14.1848C42.8812 14.4009 42.706 14.5761 42.4899 14.5761H40.1079C40.0002 14.5761 39.9464 14.5223 39.9464 14.4147V13.5333C39.9464 13.4285 39.8614 13.3435 39.7566 13.3435C39.692 13.3435 39.6321 13.3765 39.596 13.4301C39.3462 13.8013 39.0668 14.1051 38.7579 14.3413C38.4252 14.5957 38.0095 14.7228 37.5106 14.7228C36.8356 14.7228 36.3024 14.4929 35.9111 14.0332C35.5198 13.5734 35.3242 12.9571 35.3242 12.1842V9.10272C35.3242 8.26141 35.5247 7.60109 35.9258 7.12174C36.3367 6.64239 36.9236 6.40272 37.6867 6.40272ZM38.4204 11.9348C38.528 12.0522 38.7187 12.1109 38.9926 12.1109C39.2693 12.1109 39.5126 12.0774 39.7224 12.0105C39.8636 11.9655 39.9464 11.8265 39.9464 11.6783V9.35616C39.9464 9.22533 39.8827 9.09961 39.7647 9.04299C39.6723 8.9986 39.5763 8.9647 39.4769 8.94131C39.3106 8.89239 39.1492 8.86793 38.9926 8.86793C38.4937 8.86793 38.2443 9.11739 38.2443 9.6163V11.3772C38.2443 11.6413 38.303 11.8272 38.4204 11.9348Z"
fill="currentColor"
fillOpacity="1"
/>
<path
d="M47.1839 14.5761C47.4001 14.5761 47.5752 14.4009 47.5752 14.1848V10.0559C47.5752 9.91955 47.6451 9.79072 47.7678 9.73131C47.8883 9.67299 48.0148 9.62487 48.1475 9.58696C48.353 9.51848 48.5829 9.48424 48.8372 9.48424C49.0231 9.48424 49.1992 9.49891 49.3655 9.52826C49.5291 9.55553 49.6884 9.59123 49.8436 9.63539C49.8671 9.64209 49.8915 9.64565 49.916 9.64565C50.0577 9.64565 50.1725 9.5308 50.1725 9.38912V6.71087C50.1725 6.64239 50.1481 6.5837 50.0992 6.53478C50.0698 6.50544 50.016 6.47609 49.9378 6.44674C49.8595 6.41739 49.7421 6.40272 49.5856 6.40272C49.1258 6.40272 48.7589 6.54457 48.485 6.82826C48.2423 7.07994 48.0533 7.44725 47.918 7.93019C47.8966 8.00665 47.8277 8.06087 47.7483 8.06087C47.6527 8.06087 47.5752 7.9834 47.5752 7.88783V6.71087C47.5752 6.60326 47.5214 6.54946 47.4138 6.54946H44.9878C44.7716 6.54946 44.5964 6.72465 44.5964 6.94076V14.4147C44.5964 14.5223 44.6502 14.5761 44.7579 14.5761H47.1839Z"
fill="currentColor"
fillOpacity="1"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M58.368 9.41087V11.788C58.368 11.9085 58.4096 11.9874 58.4929 12.0246C58.5165 12.0351 58.5407 12.0441 58.5651 12.0526C58.5923 12.0621 58.6196 12.0668 58.6468 12.0668H58.6664C58.8825 12.0668 59.0577 12.242 59.0577 12.4582V14.4147C59.0577 14.5223 59.0039 14.5761 58.8963 14.5761H57.9131C57.4338 14.5761 56.9936 14.4783 56.5925 14.2826C56.2443 14.1085 55.9774 13.857 55.7919 13.528C55.7494 13.4526 55.6716 13.4022 55.585 13.4022C55.5009 13.4022 55.4244 13.4497 55.3826 13.5227C55.1746 13.8859 54.9029 14.1735 54.5675 14.3853C54.2055 14.6103 53.7408 14.7228 53.1734 14.7228C52.4887 14.7228 51.9457 14.537 51.5446 14.1652C51.1436 13.7935 50.943 13.2897 50.943 12.6538V12.0815C50.943 11.3967 51.1436 10.8587 51.5446 10.4674C51.9555 10.0761 52.5327 9.88044 53.2762 9.88044H55.3305C55.444 9.88044 55.5359 9.78846 55.5359 9.675C55.5359 9.33261 55.443 9.10272 55.2571 8.98533C55.0811 8.85815 54.7387 8.79457 54.23 8.79457C53.3815 8.79457 52.5424 8.91812 51.7129 9.16522C51.6889 9.17237 51.664 9.17609 51.6389 9.17609C51.4977 9.17609 51.3832 9.06162 51.3832 8.92041V7.0337C51.3832 6.96522 51.3979 6.9163 51.4273 6.88696C51.4957 6.81848 51.6816 6.74511 51.9849 6.66685C52.2979 6.58859 52.6745 6.52011 53.1148 6.46141C53.5647 6.39294 54.0245 6.3587 54.4941 6.3587C55.8343 6.3587 56.8126 6.60326 57.4289 7.09239C58.055 7.57174 58.368 8.34457 58.368 9.41087ZM54.1566 12.6098C54.5823 12.6098 54.9796 12.5136 55.3484 12.3213C55.4677 12.259 55.5359 12.1319 55.5359 11.9972V11.6951C55.5359 11.479 55.3608 11.3038 55.1446 11.3038H54.1859C54.0196 11.3038 53.8925 11.3478 53.8044 11.4359C53.7262 11.5337 53.687 11.6511 53.687 11.788V12.1402C53.687 12.4533 53.8436 12.6098 54.1566 12.6098Z"
fill="currentColor"
fillOpacity="1"
/>
<path
d="M64.2831 6.54946C64.1006 6.54946 63.9423 6.67566 63.9017 6.85362C63.6938 7.76648 63.5017 8.62378 63.3255 9.42554C63.1518 10.2575 63.0208 11.0466 62.9326 11.7931C62.922 11.8821 62.8468 11.9495 62.7573 11.9495C62.6585 11.9495 62.5792 11.8681 62.5807 11.7694C62.5921 11.0174 62.5616 10.2655 62.4891 9.51359C62.4206 8.70163 62.3326 7.79674 62.225 6.79891C62.2152 6.69131 62.1956 6.62283 62.1663 6.59348C62.1369 6.56413 62.0929 6.54946 62.0342 6.54946H59.9316C59.6887 6.54946 59.5045 6.76857 59.5457 7.008C59.7421 8.14646 59.9308 9.28491 60.1119 10.4234C60.3271 11.7147 60.5424 12.9571 60.7576 14.1505C60.7911 14.3014 60.8282 14.4092 60.8689 14.4739C60.8815 14.4939 60.8984 14.5108 60.918 14.5242C60.9687 14.5588 61.0228 14.5761 61.0804 14.5761H63.6985C63.8764 14.5761 64.032 14.456 64.0769 14.2839C64.1528 13.9935 64.2202 13.7339 64.2793 13.5049C64.3576 13.2016 64.426 12.9033 64.4847 12.6098C64.5434 12.3163 64.6021 11.9935 64.6608 11.6413C64.7227 11.3145 64.7885 10.9198 64.8583 10.4574C64.8714 10.3704 64.9461 10.306 65.034 10.306C65.1228 10.306 65.1979 10.3717 65.2098 10.4597C65.2695 10.902 65.3213 11.2812 65.3652 11.5973C65.4239 11.9397 65.4777 12.2429 65.5266 12.5071C65.5853 12.7614 65.644 13.0207 65.7027 13.2848C65.7614 13.5391 65.8299 13.8326 65.9081 14.1652C65.95 14.3076 65.9919 14.4106 66.0338 14.4741C66.0468 14.4939 66.0637 14.5108 66.0832 14.5242C66.1339 14.5588 66.188 14.5761 66.2456 14.5761H68.9092C69.0998 14.5761 69.2627 14.4388 69.2949 14.251L69.9141 10.6435C70.1391 9.33261 70.3592 8.03152 70.5744 6.74022C70.5842 6.61304 70.5402 6.54946 70.4424 6.54946H68.1855C67.9841 6.54946 67.8155 6.70245 67.7962 6.90299C67.712 7.77975 67.6353 8.61081 67.5663 9.3962C67.5027 10.2129 67.4729 11.0044 67.4767 11.7706C67.4772 11.8691 67.3978 11.9495 67.2993 11.9495C67.2091 11.9495 67.1334 11.8815 67.123 11.7918C67.0341 11.0294 66.8982 10.2455 66.7152 9.44022C66.5293 8.57935 66.3239 7.66957 66.0989 6.71087C66.0695 6.60326 66.0108 6.54946 65.9228 6.54946H64.2831Z"
fill="currentColor"
fillOpacity="1"
/>
</svg>
)
}
// Janky as hell but I gotta do talk-prep
function By() {
return (
<svg width="25" height="52" viewBox="0 0 35 52" fill="none" xmlns="http://www.w3.org/2000/svg">
{/* <path
d="M70.2615 31.9966C71.39 31.9966 72.3048 32.9114 72.3048 34.0399V40.2518C72.3048 40.5938 72.1339 40.7648 71.7922 40.7648H66.7134C63.11 40.7648 60.3609 39.8787 58.466 38.1064C56.5711 36.3341 55.6237 33.6445 55.6237 30.0377V26.0178C55.6237 24.8894 54.7089 23.9746 53.5804 23.9746H52.5018C52.1601 23.9746 51.9893 23.8036 51.9893 23.4616V17.0702C51.9893 16.0666 52.8029 15.253 53.8065 15.253C54.8101 15.253 55.6237 14.4394 55.6237 13.4358V10.1604C55.6237 9.03193 56.5385 8.11714 57.667 8.11714H64.4302C64.7719 8.11714 64.9427 8.28815 64.9427 8.63017V13.2097C64.9427 14.3382 65.8575 15.253 66.986 15.253H71.7922C72.1339 15.253 72.3048 15.424 72.3048 15.766V21.9313C72.3048 23.0598 71.39 23.9746 70.2615 23.9746H66.986C65.8575 23.9746 64.9427 24.8894 64.9427 26.0178V29.3381C64.9427 30.302 65.1757 31.0016 65.6417 31.4369C66.0144 31.81 66.7289 31.9966 67.7851 31.9966H70.2615Z"
fill="currentColor"
/> */}
{/* <path
d="M88.8927 40.2518C88.8927 40.5938 88.7218 40.7648 88.3801 40.7648H83.1149C81.1268 40.7648 79.496 40.2052 78.2224 39.0858C76.9488 37.9665 76.312 36.2874 76.312 34.0487V7.82841C76.312 6.69995 77.2268 5.78516 78.3552 5.78516H85.3981C85.7398 5.78516 85.9106 5.95617 85.9106 6.29819V31.2504C85.9106 31.4991 85.9727 31.6857 86.097 31.81C86.2523 31.9655 86.4697 32.0432 86.7493 32.0432H86.8494C87.9779 32.0432 88.8927 32.958 88.8927 34.0865V40.2518Z"
fill="currentColor"
/>
<path
d="M99.5914 14.7866C101.02 14.7866 102.247 15.1442 103.272 15.8593C104.238 16.5129 105.034 17.3614 105.662 18.4047C105.772 18.5875 105.968 18.7043 106.181 18.7043C106.505 18.7043 106.767 18.4419 106.767 18.1183V7.82841C106.767 6.69995 107.682 5.78516 108.81 5.78516H115.574C115.915 5.78516 116.086 5.95617 116.086 6.29819V38.7216C116.086 39.85 115.171 40.7648 114.043 40.7648H107.28C106.938 40.7648 106.767 40.5938 106.767 40.2518V37.4498C106.767 37.1169 106.497 36.8471 106.164 36.8471C105.959 36.8471 105.769 36.952 105.654 37.1223C104.861 38.3023 103.974 39.2677 102.993 40.0186C101.937 40.827 100.616 41.2312 99.0323 41.2312C96.8889 41.2312 95.1959 40.5005 93.9534 39.0392C92.7108 37.5778 92.0896 35.6189 92.0896 33.1626V23.3683C92.0896 20.6943 92.7264 18.5955 94 17.0719C95.3046 15.5484 97.1684 14.7866 99.5914 14.7866ZM101.921 32.3697C102.263 32.7428 102.869 32.9294 103.738 32.9294C104.415 32.9294 105.028 32.8664 105.579 32.7403C106.333 32.5677 106.767 31.8345 106.767 31.0608V24.6011C106.767 23.9183 106.437 23.2477 105.796 23.0116C105.626 22.949 105.453 22.8969 105.276 22.8552C104.748 22.6998 104.235 22.622 103.738 22.622C102.154 22.622 101.362 23.4149 101.362 25.0007V30.5974C101.362 31.4369 101.548 32.0277 101.921 32.3697Z"
fill="currentColor"
/>
<path
d="M130.817 38.7216C130.817 39.85 129.902 40.7648 128.773 40.7648H121.87C121.529 40.7648 121.358 40.5938 121.358 40.2518V17.2962C121.358 16.1678 122.273 15.253 123.401 15.253H130.304C130.646 15.253 130.817 15.424 130.817 15.766V19.5074C130.817 19.8109 131.063 20.0569 131.366 20.0569C131.618 20.0569 131.837 19.8846 131.905 19.6418C132.335 18.1067 132.935 16.9391 133.706 16.1391C134.575 15.2374 135.74 14.7866 137.2 14.7866C137.697 14.7866 138.07 14.8332 138.319 14.9265C138.567 15.0198 138.738 15.1131 138.831 15.2063C138.986 15.3618 139.064 15.5484 139.064 15.766V24.2794C139.064 24.7293 138.699 25.0939 138.25 25.0939C138.172 25.0939 138.094 25.0826 138.019 25.0613C137.527 24.921 137.021 24.8075 136.501 24.7208C135.973 24.6275 135.414 24.5809 134.824 24.5809C134.016 24.5809 133.286 24.6897 132.634 24.9074C132.36 24.9857 132.095 25.0776 131.837 25.1833C131.179 25.4535 130.817 26.1341 130.817 26.8456V38.7216Z"
fill="currentColor"
/>
<path
d="M163.709 24.3477V31.9033C163.709 32.2506 163.818 32.489 164.036 32.6186C164.151 32.6875 164.28 32.7347 164.411 32.7669C164.472 32.7819 164.533 32.7895 164.595 32.7895C165.315 32.7895 165.899 33.3736 165.899 34.0941V40.2518C165.899 40.5938 165.728 40.7648 165.387 40.7648H162.265C160.743 40.7648 159.345 40.4539 158.071 39.832C156.966 39.2787 156.118 38.4791 155.529 37.4332C155.394 37.1938 155.147 37.0337 154.872 37.0337C154.605 37.0337 154.362 37.1847 154.23 37.4166C153.569 38.5711 152.706 39.4851 151.641 40.1585C150.492 40.8737 149.016 41.2312 147.215 41.2312C145.04 41.2312 143.316 40.6405 142.043 39.4589C140.769 38.2774 140.132 36.6761 140.132 34.655V32.8361C140.132 30.6596 140.769 28.9495 142.043 27.7058C143.347 26.462 145.18 25.8402 147.541 25.8402H154.064C154.424 25.8402 154.716 25.5478 154.716 25.1872C154.716 24.099 154.421 23.3683 153.831 22.9952C153.272 22.5909 152.185 22.3888 150.569 22.3888C147.875 22.3888 145.211 22.7815 142.577 23.5669C142.501 23.5897 142.421 23.6015 142.342 23.6015C141.893 23.6015 141.53 23.238 141.53 22.7897V16.7921C141.53 16.5744 141.577 16.419 141.67 16.3257C141.887 16.108 142.477 15.8749 143.44 15.6261C144.434 15.3774 145.63 15.1597 147.028 14.9732C148.457 14.7555 149.917 14.6467 151.408 14.6467C155.664 14.6467 158.77 15.424 160.727 16.9787C162.715 18.5022 163.709 20.9586 163.709 24.3477ZM148.845 33.0227C148.845 34.0176 149.342 34.5151 150.337 34.5151C151.571 34.5151 152.731 34.2601 153.814 33.7501C154.394 33.4774 154.716 32.8672 154.716 32.2267C154.716 31.1981 153.883 30.3642 152.854 30.3642H150.43C149.902 30.3642 149.498 30.5041 149.218 30.784C148.97 31.0949 148.845 31.468 148.845 31.9033V33.0227Z"
fill="currentColor"
/>
<path
d="M181.14 16.8417C181.351 15.9122 182.177 15.253 183.131 15.253H187.699C187.978 15.253 188.165 15.424 188.258 15.766C188.972 18.8131 189.625 21.7048 190.215 24.441C190.796 27.0006 191.228 29.4922 191.51 31.9158C191.543 32.2004 191.783 32.4164 192.07 32.4164C192.382 32.4164 192.634 32.161 192.633 31.8485C192.621 29.4129 192.716 26.8971 192.917 24.3011C193.117 22.0215 193.338 19.6209 193.578 17.0992C193.678 16.0519 194.559 15.253 195.611 15.253H202.05C202.361 15.253 202.5 15.4551 202.469 15.8593C201.786 19.9636 201.087 24.099 200.373 28.2654C199.755 31.8659 199.138 35.4664 198.52 39.0669C198.352 40.0478 197.502 40.7648 196.506 40.7648H188.724C188.564 40.7648 188.412 40.7228 188.269 40.6389C188.163 40.5763 188.075 40.4854 188.013 40.3789C187.892 40.1747 187.772 39.8681 187.652 39.4589C187.404 38.4018 187.186 37.469 187 36.6606C186.813 35.821 186.627 34.9971 186.441 34.1887C186.285 33.3491 186.114 32.3853 185.928 31.297C185.789 30.2921 185.624 29.0868 185.435 27.681C185.397 27.4015 185.158 27.1927 184.876 27.1927C184.597 27.1927 184.36 27.3974 184.319 27.6734C184.097 29.1435 183.888 30.398 183.691 31.4369C183.505 32.5563 183.319 33.5823 183.132 34.5151C182.946 35.4479 182.728 36.3963 182.48 37.3601C182.334 37.9271 182.171 38.5532 181.993 39.2385C181.759 40.1378 180.946 40.7648 180.017 40.7648H172.322C172.162 40.7648 172.011 40.7228 171.868 40.6389C171.761 40.5763 171.673 40.4856 171.614 40.3772C171.499 40.1675 171.393 39.8459 171.297 39.4123C170.614 35.6189 169.93 31.6701 169.247 27.5658C168.721 24.2596 168.176 20.9534 167.61 17.6473C167.396 16.3969 168.358 15.253 169.626 15.253H175.351C175.537 15.253 175.677 15.2996 175.77 15.3929C175.863 15.4862 175.926 15.7038 175.957 16.0459C176.298 19.2174 176.578 22.0935 176.795 24.6742C177.025 27.0643 177.122 29.4544 177.086 31.8445C177.081 32.1581 177.333 32.4164 177.647 32.4164C177.931 32.4164 178.17 32.2024 178.203 31.9199C178.484 29.5471 178.9 27.0386 179.451 24.3943C179.971 22.0289 180.533 19.5114 181.14 16.8417Z"
fill="currentColor"
/> */}
<path
d="M9.50645 35.9621C8.9842 35.9099 8.5664 35.7793 8.25305 35.5704C7.96581 35.3354 7.74385 35.0481 7.58717 34.7087C7.37827 34.4737 7.24771 34.2909 7.19548 34.1603C7.16937 34.0297 7.16937 33.9122 7.19548 33.8078C7.32604 33.8078 7.44355 33.8078 7.548 33.8078C7.65245 33.7817 7.71774 33.7294 7.74385 33.6511C7.74385 33.5728 7.78302 33.5206 7.86135 33.4944C7.96581 33.4683 8.07026 33.4683 8.17471 33.4944C8.67085 33.5206 9.27144 33.3508 9.97648 32.9852C10.7076 32.6197 11.5041 32.1105 12.3658 31.4576C13.2275 30.7787 14.0892 30.0476 14.951 29.2642C15.6299 28.3764 16.0999 27.7235 16.361 27.3057C16.6483 26.8879 16.7919 26.5746 16.7919 26.3657C16.818 26.1307 16.7658 25.8956 16.6352 25.6606C16.5308 25.4517 16.2827 25.3473 15.891 25.3473C15.4993 25.3473 14.8987 25.6084 14.0892 26.1307C12.9664 26.8357 12.0655 27.4885 11.3866 28.0891C10.7076 28.6897 10.0809 29.3686 9.50645 30.1259C9.29755 30.387 9.06254 30.6743 8.80141 30.9876C8.5664 31.2749 8.3575 31.5229 8.17471 31.7318C8.01803 31.9407 7.93969 32.0452 7.93969 32.0452C7.93969 32.1496 7.78302 32.2802 7.46966 32.4369C7.18242 32.5936 6.93435 32.6719 6.72545 32.6719C6.621 32.6197 6.47738 32.5283 6.29459 32.3977C6.13792 32.241 6.03347 32.0452 5.98124 31.8102C5.74623 31.6274 5.55038 31.4707 5.39371 31.3401C5.23703 31.1835 5.15869 30.9354 5.15869 30.5959C5.15869 30.387 5.1848 30.1259 5.23703 29.8125C5.31537 29.4992 5.41982 29.0944 5.55038 28.5983C5.70706 27.9194 5.87679 27.2143 6.05958 26.4832C6.24237 25.7259 6.4121 25.0862 6.56878 24.5639C6.75157 24.0155 6.88213 23.7152 6.96047 23.663C6.96047 23.663 7.01269 23.5455 7.11714 23.3105C7.22159 23.0755 7.27382 22.8013 7.27382 22.4879C7.32604 22.1746 7.40438 21.9004 7.50883 21.6654C7.7617 21.2102 7.98783 20.7067 8.17471 20.2161C8.38361 19.6678 8.64474 18.9497 8.95809 18.0618C8.95809 17.9835 9.04948 17.7354 9.23227 17.3176C9.41506 16.8737 9.63702 16.3645 9.89814 15.79C10.1593 15.1894 10.4204 14.5758 10.6815 13.9491C10.9688 13.2963 11.2038 12.7218 11.3866 12.2256C11.6999 11.7817 11.961 11.3378 12.1699 10.8939C12.405 10.4239 12.6139 10.1497 12.7967 10.0714C12.9272 10.0452 13.1492 10.0975 13.4625 10.228C13.802 10.3586 14.1415 10.5283 14.4809 10.7372C14.8204 10.9461 15.0554 11.155 15.186 11.3639C15.2643 11.4945 15.3035 11.6251 15.3035 11.7556C15.3296 11.8862 15.2774 12.1081 15.1468 12.4215C15.0162 12.7087 14.7943 13.1918 14.4809 13.8707C14.1676 14.5236 13.7237 15.4506 13.1492 16.6518C12.418 18.2185 11.8435 19.5241 11.4257 20.5687C11.034 21.6132 10.7076 22.5141 10.4465 23.2713C10.2115 24.0286 9.96343 24.7467 9.7023 25.4256C9.64991 25.6561 9.93855 25.8054 10.0964 25.6294L10.5248 25.1514C10.786 24.8903 11.0602 24.6422 11.3474 24.4072C11.6346 24.1722 11.948 23.9372 12.2875 23.7022C12.4964 23.5455 12.7705 23.3888 13.11 23.2321C13.4756 23.0494 13.8281 22.8927 14.1676 22.7621C14.507 22.6316 14.7551 22.5532 14.9118 22.5271C14.9901 22.501 15.2512 22.4488 15.6952 22.3704C16.1652 22.266 16.6222 22.2138 17.0661 22.2138C17.6406 22.2138 18.1367 22.4227 18.5545 22.8405C18.9984 23.2322 19.3901 23.7152 19.7296 24.2897C20.0168 24.8381 20.1213 25.5431 20.0429 26.4048C19.9646 27.2404 19.7426 27.9585 19.3771 28.5591C19.2465 28.6636 19.1159 28.8072 18.9854 28.99C18.8548 29.1467 18.7895 29.2772 18.7895 29.3817C18.7634 29.5645 18.5284 29.9431 18.0845 30.5176C17.6406 31.066 17.1966 31.5882 16.7527 32.0844C16.2827 32.5805 15.7082 33.0766 15.0293 33.5728C14.3504 34.0428 13.6714 34.4737 12.9925 34.8654C12.3397 35.2309 11.7783 35.4921 11.3082 35.6487C11.0993 35.6748 10.799 35.7271 10.4073 35.8054C10.0157 35.8576 9.71536 35.9099 9.50645 35.9621Z"
fill="currentColor"
/>
<path
d="M20.6044 46.2635C20.03 46.368 19.6383 46.3811 19.4294 46.3027C19.2205 46.2244 18.9332 46.0938 18.5677 45.911C18.2804 45.7021 18.0715 45.5454 17.941 45.441C17.8104 45.3365 17.719 45.2321 17.6668 45.1276C17.4056 44.5793 17.3665 44.1745 17.5493 43.9134C17.7321 43.6523 17.9932 43.4825 18.3326 43.4042C18.6982 43.352 19.0116 43.3259 19.2727 43.3259C19.4555 43.4303 19.7558 43.4825 20.1736 43.4825C20.6175 43.4825 20.8917 43.4303 20.9961 43.3259C20.9961 43.3259 21.1136 43.2475 21.3487 43.0909C21.6098 42.9603 21.9493 42.8558 22.3671 42.7775C23.1765 42.3858 23.8163 41.9811 24.2863 41.5633C24.7564 41.1716 25.2786 40.4926 25.8531 39.5265C26.0881 39.1609 26.3362 38.73 26.5973 38.2339C26.8584 37.7639 27.0412 37.2938 27.1457 36.8238C27.3546 36.3016 27.5896 35.5965 27.8507 34.7087C28.138 33.8209 28.386 32.9461 28.5949 32.0844C28.8038 31.1965 28.9213 30.5306 28.9475 30.0867C29.1041 28.6244 29.4044 27.2143 29.8483 25.8565C30.2923 24.4725 30.6448 23.0102 30.9059 21.4695C31.0626 21.104 31.1801 20.8951 31.2584 20.8428C31.3368 20.7645 31.5065 20.7253 31.7676 20.7253C32.0549 20.7253 32.3943 20.8167 32.786 20.9995C33.1777 21.1562 33.465 21.3781 33.6477 21.6654C33.9089 22.1615 34.0264 22.7491 34.0003 23.428C34.0003 24.0808 33.8305 24.6553 33.4911 25.1514C33.2299 25.517 32.9949 26.0915 32.786 26.8749C32.6032 27.6321 32.4204 28.5853 32.2377 29.7342C32.1071 30.3087 31.9635 30.9876 31.8068 31.771C31.6762 32.5283 31.5326 33.3769 31.3759 34.317C31.2715 34.5781 31.1279 34.9829 30.9451 35.5312C30.7623 36.0535 30.6448 36.4713 30.5926 36.7846C30.5664 36.8891 30.4881 37.098 30.3575 37.4113C30.227 37.7247 30.0964 38.025 29.9659 38.3122C29.8353 38.6256 29.7439 38.8345 29.6917 38.9389C28.4383 41.4719 26.989 43.2998 25.3439 44.4226C23.7249 45.5454 22.1451 46.1591 20.6044 46.2635ZM23.8946 35.1787C23.6074 35.1787 23.3071 35.022 22.9938 34.7087C22.7065 34.3953 22.5107 34.1473 22.4062 33.9645C22.3018 33.7033 22.1059 33.4553 21.8187 33.2203C21.5314 32.9852 21.2834 32.698 21.0745 32.3585C20.8656 32.0191 20.8134 31.6013 20.9178 31.1051C21.0223 30.7657 21.1789 30.2565 21.3878 29.5775C21.5967 28.8725 21.8448 28.1022 22.132 27.2666C22.4193 26.4048 22.7065 25.5562 22.9938 24.7206C23.3071 23.885 23.5944 23.1408 23.8555 22.4879C24.1166 21.8351 24.3386 21.3781 24.5214 21.117C24.678 20.9081 24.9261 20.7514 25.2656 20.647C25.605 20.5425 25.9445 20.5164 26.284 20.5687C26.6234 20.6209 26.8715 20.7776 27.0282 21.0387C27.3154 21.4043 27.4721 21.7698 27.4982 22.1354C27.5504 22.4749 27.3676 23.0232 26.9498 23.7805C26.8454 24.0678 26.7148 24.3811 26.5581 24.7206C26.4015 25.0339 26.3231 25.2428 26.3231 25.3473C26.297 25.3995 26.2448 25.5823 26.1665 25.8956C26.1142 26.1829 26.0489 26.4571 25.9706 26.7182C25.8923 26.9793 25.8139 27.1099 25.7356 27.1099C25.6311 27.2143 25.5136 27.4885 25.3831 27.9324C25.2786 28.3764 25.1742 28.8725 25.0697 29.4209C24.9914 29.9431 24.9392 30.4131 24.913 30.8309C24.8869 31.2226 24.9261 31.4185 25.0306 31.4185C25.84 31.4185 26.6234 31.1704 27.3807 30.6743C27.627 30.5044 27.8801 30.2987 28.1402 30.057C28.8119 29.4329 30.0096 29.7738 30.097 30.6865L30.2009 31.771C29.8353 31.9538 29.4958 32.1496 29.1825 32.3585C28.8691 32.5413 28.5819 32.7633 28.3207 33.0244C28.2424 33.1289 28.0596 33.2725 27.7724 33.4553C27.4851 33.6381 27.1979 33.8078 26.9107 33.9645C26.6495 34.095 26.4798 34.1603 26.4015 34.1603C26.4015 34.1603 26.3623 34.1734 26.284 34.1995C26.2317 34.1995 26.2056 34.2517 26.2056 34.3562C26.2056 34.4084 26.0359 34.5128 25.6964 34.6695C25.357 34.8001 25.0044 34.9176 24.6389 35.022C24.2733 35.1265 24.0252 35.1787 23.8946 35.1787Z"
fill="currentColor"
/>
</svg>
)
}

View File

@ -1,14 +1,13 @@
import { LiveImageShape } from '@/components/LiveImageShapeUtil'
import { blobToDataUri } from '@/utils/blob'
import { fastGetSvgAsImage } from '@/utils/screenshot'
import * as fal from '@fal-ai/serverless-client'
import {
AssetRecordType,
Editor,
FileHelpers,
TLShape,
TLShapeId,
getHashForObject,
getSvgAsImage,
rng,
useEditor,
} from '@tldraw/tldraw'
import { createContext, useContext, useEffect, useState } from 'react'
@ -57,7 +56,9 @@ export function LiveImageProvider({
onError: (error) => {
console.error(error)
// force re-connect
setCount((count) => count + 1)
setTimeout(() => {
setCount((count) => count + 1)
}, 500)
},
onResult: (result) => {
if (result.images && result.images[0]) {
@ -141,56 +142,58 @@ export function useLiveImage(
prevPrompt = frame.props.name
try {
const svg = await editor.getSvg([...shapes], {
const svgStringResult = await editor.getSvgString([...shapes], {
background: true,
padding: 0,
darkMode: editor.user.getIsDarkMode(),
bounds: editor.getShapePageBounds(shapeId)!,
})
// cancel if stale:
if (iteration <= finishedIteration) return
if (!svg) {
console.error('No SVG')
updateImage(editor, frame.id, '')
return
}
const image = await getSvgAsImage(svg, editor.environment.isSafari, {
type: 'png',
quality: 1,
scale: 512 / frame.props.w,
})
if (!svgStringResult) {
console.warn('No SVG')
updateImage(editor, frame.id, null)
return
}
const svgString = svgStringResult.svg
// cancel if stale:
if (iteration <= finishedIteration) return
if (!image) {
console.error('No image')
updateImage(editor, frame.id, '')
const blob = await fastGetSvgAsImage(svgString, {
type: 'jpeg',
quality: 0.5,
width: svgStringResult.width,
height: svgStringResult.height,
})
if (iteration <= finishedIteration) return
if (!blob) {
console.warn('No Blob')
updateImage(editor, frame.id, null)
return
}
const imageUrl = await FileHelpers.blobToDataUrl(blob)
// cancel if stale:
if (iteration <= finishedIteration) return
const prompt = frameName
? frameName + ' hd award-winning impressive'
: 'A random image that is safe for work and not surprising—something boring like a city or shoe watercolor'
const imageDataUri = await blobToDataUri(image)
// cancel if stale:
if (iteration <= finishedIteration) return
// downloadDataURLAsFile(imageDataUri, 'image.png')
const random = rng(shapeId)
const result = await fetchImage!({
prompt,
image_url: imageDataUri,
image_url: imageUrl,
sync_mode: true,
strength: 0.65,
seed: 42, // TODO make this configurable in the UI
seed: 42,
enable_safety_checks: false,
})
// cancel if stale:
if (iteration <= finishedIteration) return
@ -226,7 +229,10 @@ export function useLiveImage(
}
function updateImage(editor: Editor, shapeId: TLShapeId, url: string | null) {
const shape = editor.getShape<LiveImageShape>(shapeId)!
const shape = editor.getShape<LiveImageShape>(shapeId)
if (!shape) {
return
}
const id = AssetRecordType.createId(shape.id.split(':')[1])
const asset = editor.getAsset(id)

101
src/utils/screenshot.ts Normal file
View File

@ -0,0 +1,101 @@
import { type } from 'os'
const fileReader = new FileReader()
let _canvas: HTMLCanvasElement | null = null
let _ctx: CanvasRenderingContext2D | null = null
async function fastGetSvgAsString(svg: SVGElement) {
const clone = svg.cloneNode(true) as SVGGraphicsElement
svg.setAttribute('width', +svg.getAttribute('width')! + '')
svg.setAttribute('height', +svg.getAttribute('height')! + '')
const imgs = Array.from(clone.querySelectorAll('image')) as SVGImageElement[]
for (const img of imgs) {
const src = img.getAttribute('xlink:href')
if (src) {
if (!src.startsWith('data:')) {
const blob = await (await fetch(src)).blob()
const base64 = await new Promise<string>((resolve, reject) => {
fileReader.onload = () => resolve(fileReader.result as string)
fileReader.onerror = () => reject(fileReader.error)
fileReader.readAsDataURL(blob)
})
img.setAttribute('xlink:href', base64)
}
}
}
const out = new XMLSerializer()
.serializeToString(clone)
.replaceAll('&#10; ', '')
.replaceAll(/((\s|")[0-9]*\.[0-9]{2})([0-9]*)(\b|"|\))/g, '$1')
return out
}
export async function fastGetSvgAsImage(
svgString: string,
options: {
type: 'png' | 'jpeg' | 'webp'
quality: number
width: number
height: number
}
) {
const svgUrl = URL.createObjectURL(new Blob([svgString], { type: 'image/svg+xml' }))
if (!_canvas) {
_canvas = document.createElement('canvas')
_ctx = _canvas?.getContext('2d')!
_ctx.imageSmoothingEnabled = true
_ctx.imageSmoothingQuality = 'high'
}
const canvas = await new Promise<HTMLCanvasElement | null>((resolve) => {
const image = new Image()
image.crossOrigin = 'anonymous'
image.onload = async () => {
if (!_canvas || !_ctx) {
throw new Error('Canvas not initialized for fast screenshotting')
}
const canvas = _canvas
const ctx = _ctx
if (canvas.width !== options.width || canvas.height !== options.height) {
canvas.width = options.width
canvas.height = options.height
}
ctx.drawImage(image, 0, 0, options.width, options.height)
URL.revokeObjectURL(svgUrl)
resolve(canvas)
}
image.onerror = () => {
resolve(null)
}
image.src = svgUrl
})
if (!canvas) return null
const blobPromise = new Promise<Blob | null>((resolve) =>
canvas.toBlob(
(blob) => {
if (!blob) {
resolve(null)
}
resolve(blob)
},
'image/' + type,
options.quality
)
)
return blobPromise
}