[improvement] Embed shape cleanup (#1569)

This PR does some cleanup around our Embed Shape.

It:
- removes used `doesResize` and `overridePermissions` props
- removes the no-longer-needed `tmpOldUrl` prop
- adds a `canUnmount` property to embed definitions, so that some embeds
can unmount when desired

### Change Type

- [x] `patch` — Bug Fix

### Test Plan

1. Create embed shapes
2. Migrate old data that includes embed shapes?

- [x] Unit Tests

### Release Notes

- [editor] Remove unused props for `TLEditorShape`
- [editor] Adds `canUnmount` property to embed definitions
This commit is contained in:
Steve Ruiz 2023-06-13 09:27:54 +01:00 committed by GitHub
parent 439a2ed3bc
commit b65aef5cf2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 231 additions and 98 deletions

View file

@ -1051,6 +1051,9 @@ export function getPointerInfo(e: PointerEvent | React.PointerEvent, container:
// @public
export function getResizedImageDataUrl(dataURLForImage: string, width: number, height: number): Promise<string>;
// @public (undocumented)
export function getRotatedBoxShadow(rotation: number): string;
// @public (undocumented)
export function getSplineForLineShape(shape: TLLineShape): NonNullable<CubicSpline2d | Polyline2d>;
@ -1324,6 +1327,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1335,7 +1339,8 @@ export function matchEmbedUrl(url: string): {
readonly width: 520;
readonly height: 400;
readonly doesResize: true;
readonly toEmbedUrl: (url: string) => string | undefined; /** @public */
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "codesandbox";
@ -1346,6 +1351,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1355,6 +1361,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
@ -1365,6 +1372,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1374,6 +1382,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1383,6 +1392,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1394,6 +1404,7 @@ export function matchEmbedUrl(url: string): {
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
readonly instructionLink: "https://support.google.com/calendar/answer/41207?hl=en";
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
@ -1404,6 +1415,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1415,6 +1427,7 @@ export function matchEmbedUrl(url: string): {
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1424,6 +1437,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly isAspectRatioLocked: false;
readonly backgroundColor: "#fff";
readonly toEmbedUrl: (url: string) => string | undefined;
@ -1435,6 +1449,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1444,6 +1459,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 520;
readonly height: 400;
readonly doesResize: false;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1455,6 +1471,7 @@ export function matchEmbedUrl(url: string): {
readonly minHeight: 500;
readonly overrideOutlineRadius: 12;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1464,6 +1481,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 640;
readonly height: 360;
readonly doesResize: true;
readonly canUnmount: false;
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
@ -1474,6 +1492,7 @@ export function matchEmbedUrl(url: string): {
readonly width: 800;
readonly height: 450;
readonly doesResize: true;
readonly canUnmount: false;
readonly overridePermissions: {
readonly 'allow-presentation': true;
};
@ -1496,6 +1515,7 @@ export function matchUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1507,7 +1527,8 @@ export function matchUrl(url: string): {
readonly width: 520;
readonly height: 400;
readonly doesResize: true;
readonly toEmbedUrl: (url: string) => string | undefined; /** @public */
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "codesandbox";
@ -1518,6 +1539,7 @@ export function matchUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1527,6 +1549,7 @@ export function matchUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
@ -1537,6 +1560,7 @@ export function matchUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1546,6 +1570,7 @@ export function matchUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1555,6 +1580,7 @@ export function matchUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1566,6 +1592,7 @@ export function matchUrl(url: string): {
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
readonly instructionLink: "https://support.google.com/calendar/answer/41207?hl=en";
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
@ -1576,6 +1603,7 @@ export function matchUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1587,6 +1615,7 @@ export function matchUrl(url: string): {
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1596,6 +1625,7 @@ export function matchUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly isAspectRatioLocked: false;
readonly backgroundColor: "#fff";
readonly toEmbedUrl: (url: string) => string | undefined;
@ -1607,6 +1637,7 @@ export function matchUrl(url: string): {
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1616,6 +1647,7 @@ export function matchUrl(url: string): {
readonly width: 520;
readonly height: 400;
readonly doesResize: false;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1627,6 +1659,7 @@ export function matchUrl(url: string): {
readonly minHeight: 500;
readonly overrideOutlineRadius: 12;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
@ -1636,6 +1669,7 @@ export function matchUrl(url: string): {
readonly width: 640;
readonly height: 360;
readonly doesResize: true;
readonly canUnmount: false;
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
@ -1646,6 +1680,7 @@ export function matchUrl(url: string): {
readonly width: 800;
readonly height: 450;
readonly doesResize: true;
readonly canUnmount: false;
readonly overridePermissions: {
readonly 'allow-presentation': true;
};
@ -1826,24 +1861,6 @@ export type RequiredKeys<T, K extends keyof T> = Pick<T, K> & Partial<T>;
// @internal (undocumented)
export const RICH_TYPES: Record<string, boolean>;
// @public (undocumented)
export function rotateBoxShadow(rotation: number, shadows: {
offsetX: number;
offsetY: number;
blur: number;
spread: number;
color: string;
}[]): string;
// @public (undocumented)
export const ROTATING_SHADOWS: {
offsetX: number;
offsetY: number;
blur: number;
spread: number;
color: string;
}[];
// @public (undocumented)
export const runtime: {
openWindow: (url: string, target: string) => void;

View file

@ -78,7 +78,6 @@ export {
MULTI_CLICK_DURATION,
REMOVE_SYMBOL,
RICH_TYPES,
ROTATING_SHADOWS,
STYLES,
SVG_PADDING,
TEXT_PROPS,
@ -226,10 +225,10 @@ export {
} from './lib/utils/data'
export { debugFlags, featureFlags, type DebugFlag } from './lib/utils/debug-flags'
export {
getRotatedBoxShadow,
loopToHtmlElement,
preventDefault,
releasePointerCapture,
rotateBoxShadow,
setPointerCapture,
truncateStringWithEllipsis,
usePrefersReducedMotion,

View file

@ -100,24 +100,6 @@ export const DEFAULT_BOOKMARK_WIDTH = 300
/** @internal */
export const DEFAULT_BOOKMARK_HEIGHT = 320
/** @public */
export const ROTATING_SHADOWS = [
{
offsetX: 0,
offsetY: 2,
blur: 4,
spread: 0,
color: '#00000029',
},
{
offsetX: 0,
offsetY: 3,
blur: 6,
spread: 0,
color: '#0000001f',
},
]
/** @public */
export const GRID_STEPS = [
{ min: -1, mid: 0.15, step: 100 },

View file

@ -2,14 +2,13 @@ import { toDomPrecision } from '@tldraw/primitives'
import { AssetRecordType, TLAssetId, TLBookmarkAsset, TLBookmarkShape } from '@tldraw/tlschema'
import { debounce, getHashForString } from '@tldraw/utils'
import { HTMLContainer } from '../../../components/HTMLContainer'
import { ROTATING_SHADOWS } from '../../../constants'
const DEFAULT_BOOKMARK_WIDTH = 300
const DEFAULT_BOOKMARK_HEIGHT = 320
import { isValidUrl } from '../../../utils/data'
import {
rotateBoxShadow,
getRotatedBoxShadow,
stopEventPropagation,
truncateStringWithEllipsis,
} from '../../../utils/dom'
@ -50,7 +49,7 @@ export class BookmarkShapeUtil extends BaseBoxShapeUtil<TLBookmarkShape> {
<div
className="tl-bookmark__container tl-hitarea-stroke"
style={{
boxShadow: rotateBoxShadow(pageRotation, ROTATING_SHADOWS),
boxShadow: getRotatedBoxShadow(pageRotation),
}}
>
<div className="tl-bookmark__image_container">

View file

@ -10,9 +10,8 @@ import { useMemo } from 'react'
import { useValue } from 'signia-react'
import { DefaultSpinner } from '../../../components/DefaultSpinner'
import { HTMLContainer } from '../../../components/HTMLContainer'
import { ROTATING_SHADOWS } from '../../../constants'
import { useIsEditing } from '../../../hooks/useIsEditing'
import { rotateBoxShadow } from '../../../utils/dom'
import { getRotatedBoxShadow } from '../../../utils/dom'
import { getEmbedInfo, getEmbedInfoUnsafely } from '../../../utils/embeds'
import { BaseBoxShapeUtil } from '../BaseBoxShapeUtil'
import { TLOnResizeHandler, TLShapeUtilFlag } from '../ShapeUtil'
@ -29,32 +28,30 @@ const getSandboxPermissions = (permissions: TLEmbedShapePermissions) => {
export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
static override type = 'embed' as const
override canUnmount: TLShapeUtilFlag<TLEmbedShape> = () => false
override canResize = (shape: TLEmbedShape) => {
const result = getEmbedInfo(shape.props.url)
return !!result?.definition?.doesResize
}
override hideSelectionBoundsBg: TLShapeUtilFlag<TLEmbedShape> = (shape) => !this.canResize(shape)
override hideSelectionBoundsFg: TLShapeUtilFlag<TLEmbedShape> = (shape) => !this.canResize(shape)
override canEdit: TLShapeUtilFlag<TLEmbedShape> = () => true
override canUnmount: TLShapeUtilFlag<TLEmbedShape> = (shape: TLEmbedShape) => {
return !!getEmbedInfo(shape.props.url)?.definition?.canUnmount
}
override canResize = (shape: TLEmbedShape) => {
return !!getEmbedInfo(shape.props.url)?.definition?.doesResize
}
override defaultProps(): TLEmbedShape['props'] {
return {
w: 300,
h: 300,
url: '',
doesResize: true,
}
}
isAspectRatioLocked: TLShapeUtilFlag<TLEmbedShape> = (shape) => {
override isAspectRatioLocked: TLShapeUtilFlag<TLEmbedShape> = (shape) => {
const embedInfo = getEmbedInfo(shape.props.url)
return embedInfo?.definition.isAspectRatioLocked ?? false
}
onResize: TLOnResizeHandler<TLEmbedShape> = (shape, info) => {
override onResize: TLOnResizeHandler<TLEmbedShape> = (shape, info) => {
const isAspectRatioLocked = this.isAspectRatioLocked(shape)
const embedInfo = getEmbedInfo(shape.props.url)
let minWidth = embedInfo?.definition.minWidth ?? 200
@ -75,7 +72,7 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
return resizeBox(shape, info, { minWidth, minHeight })
}
render(shape: TLEmbedShape) {
override render(shape: TLEmbedShape) {
const { w, h, url } = shape.props
const isEditing = useIsEditing(shape.id)
const embedInfo = useMemo(() => getEmbedInfoUnsafely(url), [url])
@ -91,6 +88,7 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
return true
}
}
return false
},
[]
@ -102,7 +100,8 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
if (embedInfo?.definition.type === 'github_gist') {
const idFromGistUrl = embedInfo.url.split('/').pop()
if (idFromGistUrl) {
if (!idFromGistUrl) throw Error('No gist id!')
return (
<HTMLContainer className="tl-embed-container" id={shape.id}>
<Gist
@ -115,7 +114,6 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
</HTMLContainer>
)
}
}
const sandbox = getSandboxPermissions({
...embedShapePermissionDefaults,
@ -139,7 +137,7 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
pointerEvents: isInteractive ? 'auto' : 'none',
// Fix for safari <https://stackoverflow.com/a/49150908>
zIndex: isInteractive ? '' : '-1',
boxShadow: rotateBoxShadow(pageRotation, ROTATING_SHADOWS),
boxShadow: getRotatedBoxShadow(pageRotation),
borderRadius: embedInfo?.definition.overrideOutlineRadius ?? 8,
background: embedInfo?.definition.backgroundColor,
}}
@ -153,7 +151,7 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
)
}
indicator(shape: TLEmbedShape) {
override indicator(shape: TLEmbedShape) {
const embedInfo = useMemo(() => getEmbedInfo(shape.props.url), [shape.props.url])
return (
<rect
@ -183,14 +181,8 @@ function Gist({
pageRotation: number
style?: React.CSSProperties
}) {
const rIframe = React.useRef<HTMLIFrameElement>(null)
const fileArg = file ? `?file=${file}` : ''
const gistLink = `https://gist.github.com/${id}.js${fileArg}`
return (
<iframe
ref={rIframe}
className="tl-embed"
draggable={false}
width={toDomPrecision(width)}
@ -204,7 +196,7 @@ function Gist({
pointerEvents: isInteractive ? 'all' : 'none',
// Fix for safari <https://stackoverflow.com/a/49150908>
zIndex: isInteractive ? '' : '-1',
boxShadow: rotateBoxShadow(pageRotation, ROTATING_SHADOWS),
boxShadow: getRotatedBoxShadow(pageRotation),
}}
srcDoc={`
<html>
@ -212,7 +204,7 @@ function Gist({
<base target="_blank">
</head>
<body>
<script src=${gistLink}></script>
<script src=${`https://gist.github.com/${id}.js${file ? `?file=${file}` : ''}`}></script>
<style type="text/css">
* { margin: 0px; }
table { height: 100%; background-color: red; }

View file

@ -406,7 +406,7 @@ describe('When in readonly mode', () => {
x: 100,
y: 100,
opacity: 1,
props: { w: 100, h: 100, url: '', doesResize: false },
props: { w: 100, h: 100, url: '' },
},
])
editor.setReadOnly(true)

View file

@ -83,12 +83,26 @@ export function releasePointerCapture(
}
}
export const ROTATING_BOX_SHADOWS = [
{
offsetX: 0,
offsetY: 2,
blur: 4,
spread: 0,
color: '#00000029',
},
{
offsetX: 0,
offsetY: 3,
blur: 6,
spread: 0,
color: '#0000001f',
},
]
/** @public */
export function rotateBoxShadow(
rotation: number,
shadows: { offsetX: number; offsetY: number; blur: number; spread: number; color: string }[]
) {
const cssStrings = shadows.map((shadow) => {
export function getRotatedBoxShadow(rotation: number) {
const cssStrings = ROTATING_BOX_SHADOWS.map((shadow) => {
const { offsetX, offsetY, blur, spread, color } = shadow
const vec = new Vec2d(offsetX, offsetY)
const { x, y } = vec.rot(-rotation)

View file

@ -128,6 +128,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -139,6 +140,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -150,6 +152,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 520;
readonly height: 400;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -159,6 +162,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 520;
readonly height: 400;
readonly doesResize: false;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -168,6 +172,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 800;
readonly height: 450;
readonly doesResize: true;
readonly canUnmount: false;
readonly overridePermissions: {
readonly 'allow-presentation': true;
};
@ -181,6 +186,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -190,6 +196,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -201,6 +208,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
readonly instructionLink: "https://support.google.com/calendar/answer/41207?hl=en";
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
@ -213,6 +221,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -222,6 +231,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -231,6 +241,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -240,6 +251,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -251,6 +263,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly minHeight: 500;
readonly overrideOutlineRadius: 12;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
}, {
@ -260,6 +273,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 640;
readonly height: 360;
readonly doesResize: true;
readonly canUnmount: false;
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
@ -270,6 +284,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
@ -280,6 +295,7 @@ export const EMBED_DEFINITIONS: readonly [{
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
readonly isAspectRatioLocked: false;
readonly backgroundColor: "#fff";
readonly toEmbedUrl: (url: string) => string | undefined;
@ -296,6 +312,7 @@ export type EmbedDefinition = {
readonly width: number;
readonly height: number;
readonly doesResize: boolean;
readonly canUnmount: boolean;
readonly isAspectRatioLocked?: boolean;
readonly overridePermissions?: TLEmbedShapePermissions;
readonly instructionLink?: string;

View file

@ -1110,6 +1110,51 @@ describe('hoist opacity', () => {
})
})
describe('Removes does resize from embed', () => {
const { up, down } = embedShapeMigrations.migrators[2]
test('up works as expected', () => {
expect(up({ props: { url: 'https://tldraw.com', doesResize: true } })).toEqual({
props: { url: 'https://tldraw.com' },
})
})
test('down works as expected', () => {
expect(down({ props: { url: 'https://tldraw.com' } })).toEqual({
props: { url: 'https://tldraw.com', doesResize: true },
})
})
})
describe('Removes tmpOldUrl from embed', () => {
const { up, down } = embedShapeMigrations.migrators[3]
test('up works as expected', () => {
expect(up({ props: { url: 'https://tldraw.com', tmpOldUrl: 'https://tldraw.com' } })).toEqual({
props: { url: 'https://tldraw.com' },
})
})
test('down works as expected', () => {
expect(down({ props: { url: 'https://tldraw.com' } })).toEqual({
props: { url: 'https://tldraw.com' },
})
})
})
describe('Removes overridePermissions from embed', () => {
const { up, down } = embedShapeMigrations.migrators[4]
test('up works as expected', () => {
expect(
up({ props: { url: 'https://tldraw.com', overridePermissions: { display: 'maybe' } } })
).toEqual({
props: { url: 'https://tldraw.com' },
})
})
test('down works as expected', () => {
expect(down({ props: { url: 'https://tldraw.com' } })).toEqual({
props: { url: 'https://tldraw.com' },
})
})
})
/* --- PUT YOUR MIGRATIONS TESTS ABOVE HERE --- */
for (const migrator of allMigrators) {

View file

@ -24,6 +24,7 @@ export const EMBED_DEFINITIONS = [
width: 720,
height: 500,
doesResize: true,
canUnmount: true,
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
if (urlObj && urlObj.pathname.match(TLDRAW_APP_RE)) {
@ -48,6 +49,7 @@ export const EMBED_DEFINITIONS = [
width: 720,
height: 500,
doesResize: true,
canUnmount: false,
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
const matches = urlObj && urlObj.pathname.match(/\/s\/([^/]+)\/?/)
@ -74,6 +76,7 @@ export const EMBED_DEFINITIONS = [
width: 520,
height: 400,
doesResize: true,
canUnmount: false,
toEmbedUrl: (url) => {
const CODEPEN_URL_REGEXP = /https:\/\/codepen.io\/([^/]+)\/pen\/([^/]+)/
const matches = url.match(CODEPEN_URL_REGEXP)
@ -100,6 +103,7 @@ export const EMBED_DEFINITIONS = [
width: 520,
height: 400,
doesResize: false,
canUnmount: false,
toEmbedUrl: (url) => {
const SCRATCH_URL_REGEXP = /https?:\/\/scratch.mit.edu\/projects\/([^/]+)/
const matches = url.match(SCRATCH_URL_REGEXP)
@ -126,6 +130,7 @@ export const EMBED_DEFINITIONS = [
width: 800,
height: 450,
doesResize: true,
canUnmount: false,
overridePermissions: {
'allow-presentation': true,
},
@ -168,6 +173,7 @@ export const EMBED_DEFINITIONS = [
width: 720,
height: 500,
doesResize: true,
canUnmount: true,
toEmbedUrl: (url) => {
if (
!!url.match(
@ -198,6 +204,7 @@ export const EMBED_DEFINITIONS = [
width: 720,
height: 500,
doesResize: true,
canUnmount: false,
toEmbedUrl: (url) => {
if (url.includes('/maps/')) {
const match = url.match(/@(.*),(.*),(.*)z/)
@ -236,6 +243,7 @@ export const EMBED_DEFINITIONS = [
minWidth: 460,
minHeight: 360,
doesResize: true,
canUnmount: false,
instructionLink: 'https://support.google.com/calendar/answer/41207?hl=en',
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
@ -278,6 +286,7 @@ export const EMBED_DEFINITIONS = [
minWidth: 460,
minHeight: 360,
doesResize: true,
canUnmount: false,
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
@ -312,9 +321,11 @@ export const EMBED_DEFINITIONS = [
width: 720,
height: 500,
doesResize: true,
canUnmount: true,
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
if (urlObj && urlObj.pathname.match(/\/([^/]+)\/([^/]+)/)) {
if (!url.split('/').pop()) return
return url
}
return
@ -322,6 +333,7 @@ export const EMBED_DEFINITIONS = [
fromEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
if (urlObj && urlObj.pathname.match(/\/([^/]+)\/([^/]+)/)) {
if (!url.split('/').pop()) return
return url
}
return
@ -334,6 +346,7 @@ export const EMBED_DEFINITIONS = [
width: 720,
height: 500,
doesResize: true,
canUnmount: false,
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
if (urlObj && urlObj.pathname.match(/\/@([^/]+)\/([^/]+)/)) {
@ -361,6 +374,7 @@ export const EMBED_DEFINITIONS = [
width: 720,
height: 500,
doesResize: true,
canUnmount: false,
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
if (urlObj && urlObj.pathname.match(/^\/map\//)) {
@ -386,6 +400,7 @@ export const EMBED_DEFINITIONS = [
minHeight: 500,
overrideOutlineRadius: 12,
doesResize: true,
canUnmount: false,
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
if (urlObj && urlObj.pathname.match(/^\/(artist|album)\//)) {
@ -408,6 +423,7 @@ export const EMBED_DEFINITIONS = [
width: 640,
height: 360,
doesResize: true,
canUnmount: false,
isAspectRatioLocked: true,
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
@ -438,6 +454,7 @@ export const EMBED_DEFINITIONS = [
width: 720,
height: 500,
doesResize: true,
canUnmount: false,
isAspectRatioLocked: true,
toEmbedUrl: (url) => {
const urlObj = safeParseUrl(url)
@ -461,6 +478,7 @@ export const EMBED_DEFINITIONS = [
width: 720,
height: 500,
doesResize: true,
canUnmount: false,
isAspectRatioLocked: false,
backgroundColor: '#fff',
toEmbedUrl: (url) => {
@ -551,10 +569,6 @@ export type TLEmbedShapeProps = {
w: number
h: number
url: string
// TODO: This is to store during migration in case anything goes wrong so we can revert.
tmpOldUrl?: string
doesResize: boolean
overridePermissions?: TLEmbedShapePermissions
}
/** @public */
@ -565,14 +579,6 @@ export const embedShapeProps: ShapeProps<TLEmbedShape> = {
w: T.nonZeroNumber,
h: T.nonZeroNumber,
url: T.string,
tmpOldUrl: T.string.optional(),
doesResize: T.boolean,
overridePermissions: T.dict(
T.setEnum(
new Set(Object.keys(embedShapePermissionDefaults) as (keyof TLEmbedShapePermissions)[])
),
T.boolean.optional()
).optional(),
}
/** @public */
@ -585,6 +591,7 @@ export type EmbedDefinition = {
readonly width: number
readonly height: number
readonly doesResize: boolean
readonly canUnmount: boolean
readonly isAspectRatioLocked?: boolean
readonly overridePermissions?: TLEmbedShapePermissions
readonly instructionLink?: string
@ -597,11 +604,14 @@ export type EmbedDefinition = {
const Versions = {
GenOriginalUrlInEmbed: 1,
RemoveDoesResize: 2,
RemoveTmpOldUrl: 3,
RemovePermissionOverrides: 4,
} as const
/** @internal */
export const embedShapeMigrations = defineMigrations({
currentVersion: Versions.GenOriginalUrlInEmbed,
currentVersion: Versions.RemovePermissionOverrides,
migrators: {
[Versions.GenOriginalUrlInEmbed]: {
// add tmpOldUrl property
@ -657,5 +667,63 @@ export const embedShapeMigrations = defineMigrations({
}
},
},
[Versions.RemoveDoesResize]: {
up: (shape) => {
const { doesResize: _, ...props } = shape.props
return {
...shape,
props: {
...props,
},
}
},
down: (shape) => {
return {
...shape,
props: {
...shape.props,
doesResize: true,
},
}
},
},
[Versions.RemoveTmpOldUrl]: {
up: (shape) => {
const { tmpOldUrl: _, ...props } = shape.props
return {
...shape,
props: {
...props,
},
}
},
down: (shape) => {
return {
...shape,
props: {
...shape.props,
},
}
},
},
[Versions.RemovePermissionOverrides]: {
up: (shape) => {
const { overridePermissions: _, ...props } = shape.props
return {
...shape,
props: {
...props,
},
}
},
down: (shape) => {
return {
...shape,
props: {
...shape.props,
},
}
},
},
},
})