[dx] use Biome instead of Prettier, part 2 (#2731)

Biome seems to be MUCH faster than Prettier. Unfortunately, it
introduces some formatting changes around the ternary operator, so we
have to update files in the repo. To make revert easier if we need it,
the change is split into two PRs. This PR introduces a Biome CI check
and reformats all files accordingly.

## Change Type
- [x] `minor` — New feature
This commit is contained in:
Dan Groshev 2024-02-05 17:54:02 +00:00 committed by GitHub
parent 826433751c
commit e6e4e7f6cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 286 additions and 264 deletions

View file

@ -41,8 +41,8 @@ jobs:
- name: Setup Biome CLI - name: Setup Biome CLI
uses: biomejs/setup-biome@v2 uses: biomejs/setup-biome@v2
# - name: Run Biome - name: Run Biome
# run: biome ci --formatter-enabled=true --linter-enabled=false --organize-imports-enabled=false . run: biome ci --formatter-enabled=true --linter-enabled=false --organize-imports-enabled=false .
- name: Typecheck - name: Typecheck
run: yarn build-types run: yarn build-types

View file

@ -109,7 +109,9 @@ export async function GET(req: NextRequest) {
} }
}) })
Object.keys(results).forEach((section: string) => results[section as keyof Data['results']].sort((a, b) => b.score - a.score)) Object.keys(results).forEach((section: string) =>
results[section as keyof Data['results']].sort((a, b) => b.score - a.score)
)
results.articles.sort( results.articles.sort(
(a, b) => (b.type === 'heading' ? -1 : 1) - (a.type === 'heading' ? -1 : 1) (a, b) => (b.type === 'heading' ? -1 : 1) - (a.type === 'heading' ? -1 : 1)

View file

@ -115,8 +115,8 @@ export function generateSection(section: InputSection, articles: Articles, index
section.id === 'getting-started' section.id === 'getting-started'
? `/${articleId}` ? `/${articleId}`
: isUncategorized : isUncategorized
? `/${section.id}/${articleId}` ? `/${section.id}/${articleId}`
: `/${section.id}/${categoryId}/${articleId}`, : `/${section.id}/${categoryId}/${articleId}`,
} }
if (isExamples) { if (isExamples) {

View file

@ -161,8 +161,8 @@ export class ContentDatabase {
sectionId === 'examples' sectionId === 'examples'
? this._sidebarExamplesContentLinks ? this._sidebarExamplesContentLinks
: sectionId === 'reference' : sectionId === 'reference'
? this._sidebarReferenceContentLinks ? this._sidebarReferenceContentLinks
: this._sidebarContentLinks : this._sidebarContentLinks
if (cachedLinks && process.env.NODE_ENV !== 'development') { if (cachedLinks && process.env.NODE_ENV !== 'development') {
// Use the previously cached sidebar links // Use the previously cached sidebar links
links = cachedLinks links = cachedLinks

View file

@ -217,8 +217,8 @@ export async function getVectorDb(
INCLUDE_API_CONTENT && INCLUDE_CONTENT INCLUDE_API_CONTENT && INCLUDE_CONTENT
? await db.all('SELECT * FROM articles') ? await db.all('SELECT * FROM articles')
: INCLUDE_API_CONTENT : INCLUDE_API_CONTENT
? await db.all('SELECT * FROM articles WHERE articles.sectionId = ?', 'reference') ? await db.all('SELECT * FROM articles WHERE articles.sectionId = ?', 'reference')
: await db.all('SELECT * FROM articles WHERE articles.sectionId != ?', 'reference') : await db.all('SELECT * FROM articles WHERE articles.sectionId != ?', 'reference')
nicelog(`Adding articles to index`) nicelog(`Adding articles to index`)
const max = Math.min(articles.length, MAX_ARTICLES) const max = Math.min(articles.length, MAX_ARTICLES)

View file

@ -3,9 +3,11 @@ import { AlarmScheduler } from './AlarmScheduler'
jest.useFakeTimers() jest.useFakeTimers()
function makeMockAlarmScheduler<Key extends string>(alarms: { function makeMockAlarmScheduler<Key extends string>(
[K in Key]: jest.Mock<Promise<void>, []> alarms: {
}) { [K in Key]: jest.Mock<Promise<void>, []>
}
) {
const data = new Map<string, number>() const data = new Map<string, number>()
let scheduledAlarm: number | null = null let scheduledAlarm: number | null = null

View file

@ -38,7 +38,7 @@ export function BoardHistorySnapshot({
...(token ...(token
? { ? {
Authorization: 'Bearer ' + token, Authorization: 'Bearer ' + token,
} }
: {}), : {}),
}, },
body: JSON.stringify({ timestamp }), body: JSON.stringify({ timestamp }),

View file

@ -50,8 +50,8 @@ export const PeopleMenuItem = track(function PeopleMenuItem({ userId }: { userId
theyAreFollowingYou theyAreFollowingYou
? msg('people-menu.leading') ? msg('people-menu.leading')
: youAreFollowingThem : youAreFollowingThem
? msg('people-menu.following') ? msg('people-menu.following')
: msg('people-menu.follow') : msg('people-menu.follow')
} }
icon={theyAreFollowingYou ? 'leading' : youAreFollowingThem ? 'following' : 'follow'} icon={theyAreFollowingYou ? 'leading' : youAreFollowingThem ? 'following' : 'follow'}
onClick={handleFollowClick} onClick={handleFollowClick}

View file

@ -188,8 +188,8 @@ export const ShareMenu = React.memo(function ShareMenu() {
shareState.state === 'offline' shareState.state === 'offline'
? 'share-menu.offline-note' ? 'share-menu.offline-note'
: isReadOnlyLink : isReadOnlyLink
? 'share-menu.copy-readonly-link-note' ? 'share-menu.copy-readonly-link-note'
: 'share-menu.copy-link-note' : 'share-menu.copy-link-note'
)} )}
</p> </p>
</div> </div>

View file

@ -10,7 +10,7 @@ const { loader, useData } = defineLoader(async (args) => {
? ((await result.json()) as { ? ((await result.json()) as {
schema: SerializedSchema schema: SerializedSchema
records: TLRecord[] records: TLRecord[]
}) })
: null : null
}) })

View file

@ -10,7 +10,6 @@ export function LocalMigration() {
useEffect(() => { useEffect(() => {
let didCancel = false let didCancel = false
;(async () => { ;(async () => {
if (!isEditorEmpty(editor)) return if (!isEditorEmpty(editor)) return

View file

@ -97,7 +97,7 @@ export function useFileSystem({ isMultiplayer }: { isMultiplayer: boolean }): TL
const newItem = menuItem(actions[NEW_PROJECT_ACTION]) const newItem = menuItem(actions[NEW_PROJECT_ACTION])
const group = isMultiplayer const group = isMultiplayer
? // open is not currently supported in multiplayer ? // open is not currently supported in multiplayer
menuGroup('filesystem', saveItem) menuGroup('filesystem', saveItem)
: menuGroup('filesystem', newItem, openItem, saveItem) : menuGroup('filesystem', newItem, openItem, saveItem)
fileMenu.children.unshift(group!) fileMenu.children.unshift(group!)

View file

@ -97,7 +97,6 @@ const InsideOfEditorContext = () => {
return null return null
} }
/* /*
Introduction: Introduction:
@ -120,4 +119,4 @@ Another (sneakier) way to access the current app is through React context.
The Tldraw component provides the context, so you can add children to The Tldraw component provides the context, so you can add children to
the component and access the app through the useEditor hook. This is cool. the component and access the app through the useEditor hook. This is cool.
*/ */

View file

@ -60,11 +60,11 @@ export default function UserPresenceExample() {
t < 1 t < 1
? '' ? ''
: t > 2 : t > 2
? CURSOR_CHAT_MESSAGE ? CURSOR_CHAT_MESSAGE
: CURSOR_CHAT_MESSAGE.slice( : CURSOR_CHAT_MESSAGE.slice(
0, 0,
Math.ceil((t - 1) * CURSOR_CHAT_MESSAGE.length) Math.ceil((t - 1) * CURSOR_CHAT_MESSAGE.length)
) )
} }
editor.store.put([ editor.store.put([

View file

@ -157,8 +157,8 @@ function getStateFromElapsedTime(elapsed: number) {
return elapsed > COLLABORATOR_INACTIVE_TIMEOUT return elapsed > COLLABORATOR_INACTIVE_TIMEOUT
? 'inactive' ? 'inactive'
: elapsed > COLLABORATOR_IDLE_TIMEOUT : elapsed > COLLABORATOR_IDLE_TIMEOUT
? 'idle' ? 'idle'
: 'active' : 'active'
} }
function useCollaboratorState(latestPresence: TLInstancePresence | null) { function useCollaboratorState(latestPresence: TLInstancePresence | null) {

View file

@ -32,13 +32,13 @@ export function createTLStore({ initialData, defaultName = '', ...rest }: TLStor
const schema = const schema =
'schema' in rest && rest.schema 'schema' in rest && rest.schema
? // we have a schema ? // we have a schema
rest.schema rest.schema
: // we need a schema : // we need a schema
createTLSchema({ createTLSchema({
shapes: currentPageShapesToShapeMap( shapes: currentPageShapesToShapeMap(
checkShapesAndAddCore('shapeUtils' in rest && rest.shapeUtils ? rest.shapeUtils : []) checkShapesAndAddCore('shapeUtils' in rest && rest.shapeUtils ? rest.shapeUtils : [])
), ),
}) })
return new Store({ return new Store({
schema, schema,

View file

@ -5759,12 +5759,12 @@ export class Editor extends EventEmitter<TLEventMap> {
? { ? {
...translateStartChanges, ...translateStartChanges,
[val]: shape[val] + localDelta[val], [val]: shape[val] + localDelta[val],
} }
: { : {
id: shape.id as any, id: shape.id as any,
type: shape.type, type: shape.type,
[val]: shape[val] + localDelta[val], [val]: shape[val] + localDelta[val],
} }
) )
v += pageBounds[shape.id][dim] + shapeGap v += pageBounds[shape.id][dim] + shapeGap
@ -7850,16 +7850,16 @@ export class Editor extends EventEmitter<TLEventMap> {
newShape.props.start = mappedId newShape.props.start = mappedId
? { ...newShape.props.start, boundShapeId: mappedId } ? { ...newShape.props.start, boundShapeId: mappedId }
: // this shouldn't happen, if you copy an arrow but not it's bound shape it should : // this shouldn't happen, if you copy an arrow but not it's bound shape it should
// convert the binding to a point at the time of copying // convert the binding to a point at the time of copying
{ type: 'point', x: 0, y: 0 } { type: 'point', x: 0, y: 0 }
} }
if (newShape.props.end.type === 'binding') { if (newShape.props.end.type === 'binding') {
const mappedId = idMap.get(newShape.props.end.boundShapeId) const mappedId = idMap.get(newShape.props.end.boundShapeId)
newShape.props.end = mappedId newShape.props.end = mappedId
? { ...newShape.props.end, boundShapeId: mappedId } ? { ...newShape.props.end, boundShapeId: mappedId }
: // this shouldn't happen, if you copy an arrow but not it's bound shape it should : // this shouldn't happen, if you copy an arrow but not it's bound shape it should
// convert the binding to a point at the time of copying // convert the binding to a point at the time of copying
{ type: 'point', x: 0, y: 0 } { type: 'point', x: 0, y: 0 }
} }
} }

View file

@ -643,8 +643,8 @@ export class SnapManager {
? 'x' ? 'x'
: 'y' : 'y'
: nearestSnapsX.length : nearestSnapsX.length
? 'x' ? 'x'
: 'y' : 'y'
const ratio = initialSelectionPageBounds.aspectRatio const ratio = initialSelectionPageBounds.aspectRatio
@ -1193,7 +1193,7 @@ export class SnapManager {
'forward', 'forward',
gapBreadthIntersection gapBreadthIntersection
), ),
] ]
: [ : [
...findAdjacentGaps( ...findAdjacentGaps(
horizontal, horizontal,
@ -1209,7 +1209,7 @@ export class SnapManager {
) as [Vec, Vec], ) as [Vec, Vec],
endEdge: selectionSides.left, endEdge: selectionSides.left,
}, },
], ],
}) })
break break
@ -1297,7 +1297,7 @@ export class SnapManager {
'forward', 'forward',
gapBreadthIntersection gapBreadthIntersection
), ),
] ]
: [ : [
...findAdjacentGaps( ...findAdjacentGaps(
vertical, vertical,
@ -1313,7 +1313,7 @@ export class SnapManager {
) as [Vec, Vec], ) as [Vec, Vec],
endEdge: selectionSides.top, endEdge: selectionSides.top,
}, },
], ],
}) })
} }
break break

View file

@ -23,10 +23,10 @@ export const EASINGS = {
t <= 0 t <= 0
? 0 ? 0
: t >= 1 : t >= 1
? 1 ? 1
: t < 0.5 : t < 0.5
? Math.pow(2, 20 * t - 10) / 2 ? Math.pow(2, 20 * t - 10) / 2
: (2 - Math.pow(2, -20 * t + 10)) / 2, : (2 - Math.pow(2, -20 * t + 10)) / 2,
} as const } as const
/** @public */ /** @public */

View file

@ -14,7 +14,7 @@ export function getIncrementedName(name: string, others: string[]) {
result = /^.*(\d+)$/.exec(result)?.[1] result = /^.*(\d+)$/.exec(result)?.[1]
? result.replace(/(\d+)(?=\D?)$/, (m) => { ? result.replace(/(\d+)(?=\D?)$/, (m) => {
return (+m + 1).toString() return (+m + 1).toString()
}) })
: `${result} 1` : `${result} 1`
} }

View file

@ -1,5 +1,8 @@
[ [
["functions", ["atom-1", "computed-1", "react", "reactor-1", "transact", "transaction"]], [
"functions",
["atom-1", "computed-1", "react", "reactor-1", "transact", "transaction"]
],
["classes"], ["classes"],
["interfaces", ["Signal"]] ["interfaces", ["Signal"]]
] ]

View file

@ -121,13 +121,13 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
migrations: ourType.migrations, migrations: ourType.migrations,
fromVersion: persistedVersion, fromVersion: persistedVersion,
toVersion: ourVersion, toVersion: ourVersion,
}) })
: migrateRecord<R>({ : migrateRecord<R>({
record, record,
migrations: ourType.migrations, migrations: ourType.migrations,
fromVersion: ourVersion, fromVersion: ourVersion,
toVersion: persistedVersion, toVersion: persistedVersion,
}) })
if (result.type === 'error') { if (result.type === 'error') {
return result return result
} }
@ -174,13 +174,13 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
migrations: ourSubTypeMigrations, migrations: ourSubTypeMigrations,
fromVersion: persistedSubTypeVersion, fromVersion: persistedSubTypeVersion,
toVersion: ourSubTypeMigrations.currentVersion, toVersion: ourSubTypeMigrations.currentVersion,
}) })
: migrateRecord<R>({ : migrateRecord<R>({
record, record,
migrations: ourSubTypeMigrations, migrations: ourSubTypeMigrations,
fromVersion: ourSubTypeMigrations.currentVersion, fromVersion: ourSubTypeMigrations.currentVersion,
toVersion: persistedSubTypeVersion, toVersion: persistedSubTypeVersion,
}) })
if (result.type === 'error') { if (result.type === 'error') {
return result return result
@ -258,12 +258,12 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
k, k,
v.currentVersion, v.currentVersion,
]) ])
) )
: undefined, : undefined,
} }
: { : {
version: type.migrations.currentVersion, version: type.migrations.currentVersion,
}, },
]) ])
), ),
} }
@ -286,12 +286,12 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
k, k,
v.firstVersion, v.firstVersion,
]) ])
) )
: undefined, : undefined,
} }
: { : {
version: type.migrations.firstVersion, version: type.migrations.firstVersion,
}, },
]) ])
), ),
} }

View file

@ -213,105 +213,105 @@ type Range<From extends number, To extends number> = To extends From
type Decrement<n extends number> = n extends 0 type Decrement<n extends number> = n extends 0
? never ? never
: n extends 1 : n extends 1
? 0 ? 0
: n extends 2 : n extends 2
? 1 ? 1
: n extends 3 : n extends 3
? 2 ? 2
: n extends 4 : n extends 4
? 3 ? 3
: n extends 5 : n extends 5
? 4 ? 4
: n extends 6 : n extends 6
? 5 ? 5
: n extends 7 : n extends 7
? 6 ? 6
: n extends 8 : n extends 8
? 7 ? 7
: n extends 9 : n extends 9
? 8 ? 8
: n extends 10 : n extends 10
? 9 ? 9
: n extends 11 : n extends 11
? 10 ? 10
: n extends 12 : n extends 12
? 11 ? 11
: n extends 13 : n extends 13
? 12 ? 12
: n extends 14 : n extends 14
? 13 ? 13
: n extends 15 : n extends 15
? 14 ? 14
: n extends 16 : n extends 16
? 15 ? 15
: n extends 17 : n extends 17
? 16 ? 16
: n extends 18 : n extends 18
? 17 ? 17
: n extends 19 : n extends 19
? 18 ? 18
: n extends 20 : n extends 20
? 19 ? 19
: n extends 21 : n extends 21
? 20 ? 20
: n extends 22 : n extends 22
? 21 ? 21
: n extends 23 : n extends 23
? 22 ? 22
: n extends 24 : n extends 24
? 23 ? 23
: n extends 25 : n extends 25
? 24 ? 24
: n extends 26 : n extends 26
? 25 ? 25
: n extends 27 : n extends 27
? 26 ? 26
: n extends 28 : n extends 28
? 27 ? 27
: n extends 29 : n extends 29
? 28 ? 28
: n extends 30 : n extends 30
? 29 ? 29
: n extends 31 : n extends 31
? 30 ? 30
: n extends 32 : n extends 32
? 31 ? 31
: n extends 33 : n extends 33
? 32 ? 32
: n extends 34 : n extends 34
? 33 ? 33
: n extends 35 : n extends 35
? 34 ? 34
: n extends 36 : n extends 36
? 35 ? 35
: n extends 37 : n extends 37
? 36 ? 36
: n extends 38 : n extends 38
? 37 ? 37
: n extends 39 : n extends 39
? 38 ? 38
: n extends 40 : n extends 40
? 39 ? 39
: n extends 41 : n extends 41
? 40 ? 40
: n extends 42 : n extends 42
? 41 ? 41
: n extends 43 : n extends 43
? 42 ? 42
: n extends 44 : n extends 44
? 43 ? 43
: n extends 45 : n extends 45
? 44 ? 44
: n extends 46 : n extends 46
? 45 ? 45
: n extends 47 : n extends 47
? 46 ? 46
: n extends 48 : n extends 48
? 47 ? 47
: n extends 49 : n extends 49
? 48 ? 48
: n extends 50 : n extends 50
? 49 ? 49
: n extends 51 : n extends 51
? 50 ? 50
: never : never

View file

@ -140,7 +140,7 @@ export const TldrawSelectionForeground: TLSelectionForegroundComponent = track(
shouldDisplayControls && shouldDisplayControls &&
(onlyShape (onlyShape
? editor.getShapeUtil(onlyShape).canResize(onlyShape) && ? editor.getShapeUtil(onlyShape).canResize(onlyShape) &&
!editor.getShapeUtil(onlyShape).hideResizeHandles(onlyShape) !editor.getShapeUtil(onlyShape).hideResizeHandles(onlyShape)
: true) && : true) &&
!showCropHandles && !showCropHandles &&
!isLockedShape !isLockedShape

View file

@ -104,7 +104,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
? new Edge2d({ ? new Edge2d({
start: Vec.From(info.start.point), start: Vec.From(info.start.point),
end: Vec.From(info.end.point), end: Vec.From(info.end.point),
}) })
: new Arc2d({ : new Arc2d({
center: Vec.Cast(info.handleArc.center), center: Vec.Cast(info.handleArc.center),
radius: info.handleArc.radius, radius: info.handleArc.radius,
@ -112,7 +112,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
end: Vec.Cast(info.end.point), end: Vec.Cast(info.end.point),
sweepFlag: info.bodyArc.sweepFlag, sweepFlag: info.bodyArc.sweepFlag,
largeArcFlag: info.bodyArc.largeArcFlag, largeArcFlag: info.bodyArc.largeArcFlag,
}) })
let labelGeom let labelGeom
if (shape.props.text.trim()) { if (shape.props.text.trim()) {
@ -583,8 +583,8 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
? shape.props.start.isExact ? shape.props.start.isExact
? '' ? ''
: shape.props.start.isPrecise : shape.props.start.isPrecise
? 'url(#arrowhead-cross)' ? 'url(#arrowhead-cross)'
: 'url(#arrowhead-dot)' : 'url(#arrowhead-dot)'
: '' : ''
} }
markerEnd={ markerEnd={
@ -592,8 +592,8 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
? shape.props.end.isExact ? shape.props.end.isExact
? '' ? ''
: shape.props.end.isPrecise : shape.props.end.isPrecise
? 'url(#arrowhead-cross)' ? 'url(#arrowhead-cross)'
: 'url(#arrowhead-dot)' : 'url(#arrowhead-dot)'
: '' : ''
} }
opacity={0.16} opacity={0.16}

View file

@ -39,7 +39,7 @@ export function getArrowLabelSize(editor: Editor, shape: TLArrowShape) {
? new Edge2d({ ? new Edge2d({
start: Vec.From(info.start.point), start: Vec.From(info.start.point),
end: Vec.From(info.end.point), end: Vec.From(info.end.point),
}) })
: new Arc2d({ : new Arc2d({
center: Vec.Cast(info.handleArc.center), center: Vec.Cast(info.handleArc.center),
radius: info.handleArc.radius, radius: info.handleArc.radius,
@ -47,7 +47,7 @@ export function getArrowLabelSize(editor: Editor, shape: TLArrowShape) {
end: Vec.Cast(info.end.point), end: Vec.Cast(info.end.point),
sweepFlag: info.bodyArc.sweepFlag, sweepFlag: info.bodyArc.sweepFlag,
largeArcFlag: info.bodyArc.largeArcFlag, largeArcFlag: info.bodyArc.largeArcFlag,
}) })
if (shape.props.text.trim()) { if (shape.props.text.trim()) {
const bodyBounds = bodyGeom.bounds const bodyBounds = bodyGeom.bounds

View file

@ -29,8 +29,8 @@ function getArrowPoints(
? ints[0] ? ints[0]
: ints[1] : ints[1]
: info.handleArc.sweepFlag : info.handleArc.sweepFlag
? ints[1] ? ints[1]
: ints[0] : ints[0]
} }
return { return {

View file

@ -72,10 +72,10 @@ export function getFreehandOptions(
...(forceSolid ...(forceSolid
? solidSettings(strokeWidth) ? solidSettings(strokeWidth)
: shapeProps.dash === 'draw' : shapeProps.dash === 'draw'
? shapeProps.isPen ? shapeProps.isPen
? realPressureSettings(strokeWidth) ? realPressureSettings(strokeWidth)
: simulatePressureSettings(strokeWidth) : simulatePressureSettings(strokeWidth)
: solidSettings(strokeWidth)), : solidSettings(strokeWidth)),
last: shapeProps.isComplete || forceComplete, last: shapeProps.isComplete || forceComplete,
} }
} }

View file

@ -322,14 +322,14 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
shape.props.align === 'start' shape.props.align === 'start'
? 0 ? 0
: shape.props.align === 'end' : shape.props.align === 'end'
? w - labelWidth ? w - labelWidth
: (w - labelWidth) / 2, : (w - labelWidth) / 2,
y: y:
shape.props.verticalAlign === 'start' shape.props.verticalAlign === 'start'
? 0 ? 0
: shape.props.verticalAlign === 'end' : shape.props.verticalAlign === 'end'
? h - labelHeight ? h - labelHeight
: (h - labelHeight) / 2, : (h - labelHeight) / 2,
width: labelWidth, width: labelWidth,
height: labelHeight, height: labelHeight,
isFilled: true, isFilled: true,

View file

@ -59,7 +59,7 @@ export function getPillPoints(width: number, height: number, numPoints: number)
center: new Vec(radius, radius), center: new Vec(radius, radius),
startAngle: PI / 2, startAngle: PI / 2,
}, },
] ]
: [ : [
{ {
type: 'straight', type: 'straight',
@ -81,7 +81,7 @@ export function getPillPoints(width: number, height: number, numPoints: number)
center: new Vec(radius, radius), center: new Vec(radius, radius),
startAngle: PI, startAngle: PI,
}, },
] ]
let sectionOffset = 0 let sectionOffset = 0

View file

@ -39,10 +39,10 @@ export const DashStyleCloud = React.memo(function DashStylePolygon({
{arcs.map(({ leftPoint, rightPoint, center, radius }, i) => { {arcs.map(({ leftPoint, rightPoint, center, radius }, i) => {
const arcLength = center const arcLength = center
? radius * ? radius *
canonicalizeRotation( canonicalizeRotation(
canonicalizeRotation(Vec.Angle(center, rightPoint)) - canonicalizeRotation(Vec.Angle(center, rightPoint)) -
canonicalizeRotation(Vec.Angle(center, leftPoint)) canonicalizeRotation(Vec.Angle(center, leftPoint))
) )
: Vec.Dist(leftPoint, rightPoint) : Vec.Dist(leftPoint, rightPoint)
const { strokeDasharray, strokeDashoffset } = getPerfectDashProps( const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(
@ -99,10 +99,10 @@ export function DashStyleCloudSvg({
for (const { leftPoint, rightPoint, center, radius } of arcs) { for (const { leftPoint, rightPoint, center, radius } of arcs) {
const arcLength = center const arcLength = center
? radius * ? radius *
canonicalizeRotation( canonicalizeRotation(
canonicalizeRotation(Vec.Angle(center, rightPoint)) - canonicalizeRotation(Vec.Angle(center, rightPoint)) -
canonicalizeRotation(Vec.Angle(center, leftPoint)) canonicalizeRotation(Vec.Angle(center, leftPoint))
) )
: Vec.Dist(leftPoint, rightPoint) : Vec.Dist(leftPoint, rightPoint)
const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(arcLength, strokeWidth, { const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(arcLength, strokeWidth, {

View file

@ -94,8 +94,8 @@ export class Pointing extends StateNode {
shape.props.geo === 'star' shape.props.geo === 'star'
? new Box(0, 0, 200, 190) ? new Box(0, 0, 200, 190)
: shape.props.geo === 'cloud' : shape.props.geo === 'cloud'
? new Box(0, 0, 300, 180) ? new Box(0, 0, 300, 180)
: new Box(0, 0, 200, 200) : new Box(0, 0, 200, 200)
const delta = bounds.center const delta = bounds.center
const parentTransform = this.editor.getShapeParentTransform(shape) const parentTransform = this.editor.getShapeParentTransform(shape)

View file

@ -82,7 +82,7 @@ export const TextLabel = React.memo(function TextLabel<
width: bounds.width, width: bounds.width,
height: bounds.height, height: bounds.height,
position: 'absolute', position: 'absolute',
} }
: {}), : {}),
}} }}
> >

View file

@ -59,8 +59,8 @@ export function createTextSvgElementFromSpans(
(opts.verticalTextAlign === 'start' (opts.verticalTextAlign === 'start'
? padding ? padding
: opts.verticalTextAlign === 'end' : opts.verticalTextAlign === 'end'
? opts.height - padding - bounds.height ? opts.height - padding - bounds.height
: (Math.ceil(opts.height) - bounds.height) / 2) : (Math.ceil(opts.height) - bounds.height) / 2)
// Create text span elements for each word // Create text span elements for each word
let currentLineTop = null let currentLineTop = null

View file

@ -207,15 +207,15 @@ export function getStrokeOutlinePoints(
start.taper === false start.taper === false
? 0 ? 0
: start.taper === true : start.taper === true
? Math.max(size, totalLength) ? Math.max(size, totalLength)
: (start.taper as number) : (start.taper as number)
const taperEnd = const taperEnd =
end.taper === false end.taper === false
? 0 ? 0
: end.taper === true : end.taper === true
? Math.max(size, totalLength) ? Math.max(size, totalLength)
: (end.taper as number) : (end.taper as number)
// The minimum allowed distance between points (squared) // The minimum allowed distance between points (squared)
// Our collected left and right points // Our collected left and right points

View file

@ -89,15 +89,15 @@ export function setStrokePointRadii(strokePoints: StrokePoint[], options: Stroke
start.taper === false start.taper === false
? 0 ? 0
: start.taper === true : start.taper === true
? Math.max(size, totalLength) ? Math.max(size, totalLength)
: (start.taper as number) : (start.taper as number)
const taperEnd = const taperEnd =
end.taper === false end.taper === false
? 0 ? 0
: end.taper === true : end.taper === true
? Math.max(size, totalLength) ? Math.max(size, totalLength)
: (end.taper as number) : (end.taper as number)
if (taperStart || taperEnd) { if (taperStart || taperEnd) {
for (let i = 0; i < strokePoints.length; i++) { for (let i = 0; i < strokePoints.length; i++) {

View file

@ -378,7 +378,7 @@ function getTextSize(editor: Editor, props: TLTextShape['props']) {
const cw = autoSize const cw = autoSize
? null ? null
: // `measureText` floors the number so we need to do the same here to avoid issues. : // `measureText` floors the number so we need to do the same here to avoid issues.
Math.floor(Math.max(minWidth, w)) Math.floor(Math.max(minWidth, w))
const result = editor.textMeasure.measureText(text, { const result = editor.textMeasure.measureText(text, {
...TEXT_PROPS, ...TEXT_PROPS,

View file

@ -199,10 +199,10 @@ export class Idle extends StateNode {
hoveredShape && !this.editor.isShapeOfType<TLGroupShape>(hoveredShape, 'group') hoveredShape && !this.editor.isShapeOfType<TLGroupShape>(hoveredShape, 'group')
? hoveredShape ? hoveredShape
: this.editor.getSelectedShapeAtPoint(this.editor.inputs.currentPagePoint) ?? : this.editor.getSelectedShapeAtPoint(this.editor.inputs.currentPagePoint) ??
this.editor.getShapeAtPoint(this.editor.inputs.currentPagePoint, { this.editor.getShapeAtPoint(this.editor.inputs.currentPagePoint, {
margin: HIT_TEST_MARGIN / this.editor.getZoomLevel(), margin: HIT_TEST_MARGIN / this.editor.getZoomLevel(),
hitInside: false, hitInside: false,
}) })
const focusedGroupId = this.editor.getFocusedGroupId() const focusedGroupId = this.editor.getFocusedGroupId()
@ -358,7 +358,7 @@ export class Idle extends StateNode {
hitLabels: true, hitLabels: true,
hitFrameInside: false, hitFrameInside: false,
renderingOnly: true, renderingOnly: true,
}) })
if (hitShape) { if (hitShape) {
this.onRightClick({ this.onRightClick({
@ -567,8 +567,8 @@ export class Idle extends StateNode {
? gridSize * GRID_INCREMENT ? gridSize * GRID_INCREMENT
: gridSize : gridSize
: shiftKey : shiftKey
? MAJOR_NUDGE_FACTOR ? MAJOR_NUDGE_FACTOR
: MINOR_NUDGE_FACTOR : MINOR_NUDGE_FACTOR
this.editor.nudgeShapes(this.editor.getSelectedShapeIds(), delta.mul(step)) this.editor.nudgeShapes(this.editor.getSelectedShapeIds(), delta.mul(step))
} }

View file

@ -39,7 +39,7 @@ export class PointingSelection extends StateNode {
hitInside: true, hitInside: true,
margin: 0, margin: 0,
renderingOnly: true, renderingOnly: true,
}) })
if (hitShape) { if (hitShape) {
// todo: extract the double click shape logic from idle so that we can share it here // todo: extract the double click shape logic from idle so that we can share it here

View file

@ -35,8 +35,8 @@ export const ActionsMenu = memo(function ActionsMenu() {
? `${msg(label)} ${kbdStr(kbd)}` ? `${msg(label)} ${kbdStr(kbd)}`
: `${msg(label)}` : `${msg(label)}`
: kbd : kbd
? `${kbdStr(kbd)}` ? `${kbdStr(kbd)}`
: '' : ''
} }
onClick={() => onSelect('actions-menu')} onClick={() => onSelect('actions-menu')}
disabled={item.disabled} disabled={item.disabled}

View file

@ -91,11 +91,16 @@ const CurrentState = track(function CurrentState() {
const shape = path === 'select.idle' || !path.includes('select.') ? hoverShape : selectedShape const shape = path === 'select.idle' || !path.includes('select.') ? hoverShape : selectedShape
const shapeInfo = const shapeInfo =
shape && path.includes('select.') shape && path.includes('select.')
? ` / ${shape.type || ''}${'geo' in shape.props ? ' / ' + shape.props.geo : ''} / [${Vec.ToFixed(editor.getPointInShapeSpace(shape, editor.inputs.currentPagePoint), 0)}]` ? ` / ${shape.type || ''}${
'geo' in shape.props ? ' / ' + shape.props.geo : ''
} / [${Vec.ToFixed(editor.getPointInShapeSpace(shape, editor.inputs.currentPagePoint), 0)}]`
: '' : ''
const ruler = const ruler =
path.startsWith('select.') && !path.includes('.idle') path.startsWith('select.') && !path.includes('.idle')
? ` / [${Vec.ToFixed(editor.inputs.originPagePoint, 0)}] → [${Vec.ToFixed(editor.inputs.currentPagePoint, 0)}] = ${Vec.Dist(editor.inputs.originPagePoint, editor.inputs.currentPagePoint).toFixed(0)}` ? ` / [${Vec.ToFixed(editor.inputs.originPagePoint, 0)}] → [${Vec.ToFixed(
editor.inputs.currentPagePoint,
0
)}] = ${Vec.Dist(editor.inputs.originPagePoint, editor.inputs.currentPagePoint).toFixed(0)}`
: '' : ''
return <div className="tlui-debug-panel__current-state">{`${path}${shapeInfo}${ruler}`}</div> return <div className="tlui-debug-panel__current-state">{`${path}${shapeInfo}${ruler}`}</div>

View file

@ -65,8 +65,8 @@ function MenuContent() {
depth <= 1 depth <= 1
? 'medium' ? 'medium'
: breakpoint < 3 || (parent?.type === 'submenu' && depth > 2) : breakpoint < 3 || (parent?.type === 'submenu' && depth > 2)
? 'tiny' ? 'tiny'
: 'medium' : 'medium'
} }
key={item.id} key={item.id}
> >

View file

@ -129,7 +129,7 @@ function CommonStylePickerSet({
minBy(tldrawSupportedOpacities, (supportedOpacity) => minBy(tldrawSupportedOpacities, (supportedOpacity) =>
Math.abs(supportedOpacity - opacity.value) Math.abs(supportedOpacity - opacity.value)
)! )!
) )
return ( return (
<> <>

View file

@ -244,12 +244,12 @@ export async function pasteExcalidrawContent(editor: Editor, clipboard: any, poi
normalizedAnchor: { x: 0.5, y: 0.5 }, normalizedAnchor: { x: 0.5, y: 0.5 },
isPrecise: false, isPrecise: false,
isExact: false, isExact: false,
} }
: { : {
type: 'point', type: 'point',
x: start[0], x: start[0],
y: start[1], y: start[1],
}, },
end: endTargetId end: endTargetId
? { ? {
type: 'binding', type: 'binding',
@ -257,12 +257,12 @@ export async function pasteExcalidrawContent(editor: Editor, clipboard: any, poi
normalizedAnchor: { x: 0.5, y: 0.5 }, normalizedAnchor: { x: 0.5, y: 0.5 },
isPrecise: false, isPrecise: false,
isExact: false, isExact: false,
} }
: { : {
type: 'point', type: 'point',
x: end[0], x: end[0],
y: end[1], y: end[1],
}, },
arrowheadEnd: arrowheadsToArrowheadTypes[element.endArrowhead] ?? 'none', arrowheadEnd: arrowheadsToArrowheadTypes[element.endArrowhead] ?? 'none',
arrowheadStart: arrowheadsToArrowheadTypes[element.startArrowhead] ?? 'none', arrowheadStart: arrowheadsToArrowheadTypes[element.startArrowhead] ?? 'none',
}, },

View file

@ -420,11 +420,11 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
? { ? {
x: commonBounds.width + 10, x: commonBounds.width + 10,
y: 0, y: 0,
} }
: { : {
x: 16 / editor.getZoomLevel(), x: 16 / editor.getZoomLevel(),
y: 16 / editor.getZoomLevel(), y: 16 / editor.getZoomLevel(),
} }
} }
editor.mark('duplicate shapes') editor.mark('duplicate shapes')

View file

@ -80,8 +80,8 @@ export const ActionsMenuSchemaProvider = ({
allowGroup allowGroup
? menuItem(actions['group'], { disabled: !twoSelected }) ? menuItem(actions['group'], { disabled: !twoSelected })
: allowUngroup : allowUngroup
? menuItem(actions['ungroup']) ? menuItem(actions['ungroup'])
: menuItem(actions['group'], { disabled: !twoSelected }), : menuItem(actions['group'], { disabled: !twoSelected }),
] ]
if (overrides) { if (overrides) {

View file

@ -50,10 +50,12 @@ type DefaultHelpers = ReturnType<typeof useDefaultHelpers>
export type TLUiOverride<Type, Helpers> = (editor: Editor, schema: Type, helpers: Helpers) => Type export type TLUiOverride<Type, Helpers> = (editor: Editor, schema: Type, helpers: Helpers) => Type
type WithDefaultHelpers<T extends TLUiOverride<any, any>> = type WithDefaultHelpers<T extends TLUiOverride<any, any>> = T extends TLUiOverride<
T extends TLUiOverride<infer Type, infer Helpers> infer Type,
? TLUiOverride<Type, Helpers extends undefined ? DefaultHelpers : Helpers & DefaultHelpers> infer Helpers
: never >
? TLUiOverride<Type, Helpers extends undefined ? DefaultHelpers : Helpers & DefaultHelpers>
: never
/** @public */ /** @public */
export type TLUiOverrides = Partial<{ export type TLUiOverrides = Partial<{

View file

@ -222,7 +222,7 @@ export class TestEditor extends Editor {
? ({ ? ({
target: 'shape', target: 'shape',
shape: this.getShape(info as any), shape: this.getShape(info as any),
} as T) } as T)
: info : info
} }
@ -267,18 +267,18 @@ export class TestEditor extends Editor {
key === 'Shift' key === 'Shift'
? 'ShiftLeft' ? 'ShiftLeft'
: key === 'Alt' : key === 'Alt'
? 'AltLeft' ? 'AltLeft'
: key === 'Control' || key === 'Meta' : key === 'Control' || key === 'Meta'
? 'CtrlLeft' ? 'CtrlLeft'
: key === ' ' : key === ' '
? 'Space' ? 'Space'
: key === 'Enter' || : key === 'Enter' ||
key === 'ArrowRight' || key === 'ArrowRight' ||
key === 'ArrowLeft' || key === 'ArrowLeft' ||
key === 'ArrowUp' || key === 'ArrowUp' ||
key === 'ArrowDown' key === 'ArrowDown'
? key ? key
: 'Key' + key[0].toUpperCase() + key.slice(1), : 'Key' + key[0].toUpperCase() + key.slice(1),
type: 'keyboard', type: 'keyboard',
key, key,
} }

View file

@ -61,7 +61,7 @@ export type TLAssetPartial<T extends TLAsset = TLAsset> = T extends T
type: T['type'] type: T['type']
props?: Partial<T['props']> props?: Partial<T['props']>
meta?: Partial<T['meta']> meta?: Partial<T['meta']>
} & Partial<Omit<T, 'type' | 'id' | 'props' | 'meta'>> } & Partial<Omit<T, 'type' | 'id' | 'props' | 'meta'>>
: never : never
/** @public */ /** @public */

View file

@ -364,12 +364,12 @@ export const instanceMigrations = defineMigrations({
opacity < 0.175 opacity < 0.175
? '0.1' ? '0.1'
: opacity < 0.375 : opacity < 0.375
? '0.25' ? '0.25'
: opacity < 0.625 : opacity < 0.625
? '0.5' ? '0.5'
: opacity < 0.875 : opacity < 0.875
? '0.75' ? '0.75'
: '1', : '1',
}, },
} }
}, },

View file

@ -60,7 +60,7 @@ export type TLShapePartial<T extends TLShape = TLShape> = T extends T
type: T['type'] type: T['type']
props?: Partial<T['props']> props?: Partial<T['props']>
meta?: Partial<T['meta']> meta?: Partial<T['meta']>
} & Partial<Omit<T, 'type' | 'id' | 'props' | 'meta'>> } & Partial<Omit<T, 'type' | 'id' | 'props' | 'meta'>>
: never : never
/** @public */ /** @public */
@ -124,12 +124,12 @@ export const rootShapeMigrations = defineMigrations({
opacity < 0.175 opacity < 0.175
? '0.1' ? '0.1'
: opacity < 0.375 : opacity < 0.375
? '0.25' ? '0.25'
: opacity < 0.625 : opacity < 0.625
? '0.5' ? '0.5'
: opacity < 0.875 : opacity < 0.875
? '0.75' ? '0.75'
: '1', : '1',
}, },
} }
}, },

View file

@ -121,14 +121,14 @@ export const arrowShapeMigrations = defineMigrations({
isPrecise: !( isPrecise: !(
start.normalizedAnchor.x === 0.5 && start.normalizedAnchor.y === 0.5 start.normalizedAnchor.x === 0.5 && start.normalizedAnchor.y === 0.5
), ),
} }
: start, : start,
end: end:
(end as TLArrowShapeTerminal).type === 'binding' (end as TLArrowShapeTerminal).type === 'binding'
? { ? {
...end, ...end,
isPrecise: !(end.normalizedAnchor.x === 0.5 && end.normalizedAnchor.y === 0.5), isPrecise: !(end.normalizedAnchor.x === 0.5 && end.normalizedAnchor.y === 0.5),
} }
: end, : end,
}, },
} }

View file

@ -58,9 +58,11 @@ export function deepCopy<T = unknown>(obj: T): T {
* *
* @internal * @internal
*/ */
export function objectMapKeys<Key extends string>(object: { export function objectMapKeys<Key extends string>(
readonly [K in Key]: unknown object: {
}): Array<Key> { readonly [K in Key]: unknown
}
): Array<Key> {
return Object.keys(object) as Key[] return Object.keys(object) as Key[]
} }
@ -70,9 +72,11 @@ export function objectMapKeys<Key extends string>(object: {
* *
* @internal * @internal
*/ */
export function objectMapValues<Key extends string, Value>(object: { export function objectMapValues<Key extends string, Value>(
[K in Key]: Value object: {
}): Array<Value> { [K in Key]: Value
}
): Array<Value> {
return Object.values(object) as Value[] return Object.values(object) as Value[]
} }
@ -82,9 +86,11 @@ export function objectMapValues<Key extends string, Value>(object: {
* *
* @internal * @internal
*/ */
export function objectMapEntries<Key extends string, Value>(object: { export function objectMapEntries<Key extends string, Value>(
[K in Key]: Value object: {
}): Array<[Key, Value]> { [K in Key]: Value
}
): Array<[Key, Value]> {
return Object.entries(object) as [Key, Value][] return Object.entries(object) as [Key, Value][]
} }

View file

@ -242,9 +242,11 @@ export class ObjectValidator<Shape extends object> extends Validator<Shape> {
* }) * })
* ``` * ```
*/ */
extend<Extension extends Record<string, unknown>>(extension: { extend<Extension extends Record<string, unknown>>(
readonly [K in keyof Extension]: Validatable<Extension[K]> extension: {
}): ObjectValidator<Shape & Extension> { readonly [K in keyof Extension]: Validatable<Extension[K]>
}
): ObjectValidator<Shape & Extension> {
return new ObjectValidator({ ...this.config, ...extension }) as ObjectValidator< return new ObjectValidator({ ...this.config, ...extension }) as ObjectValidator<
Shape & Extension Shape & Extension
> >
@ -470,9 +472,11 @@ export const unknownObject = new Validator<Record<string, unknown>>((value) => {
* *
* @public * @public
*/ */
export function object<Shape extends object>(config: { export function object<Shape extends object>(
readonly [K in keyof Shape]: Validatable<Shape[K]> config: {
}): ObjectValidator<Shape> { readonly [K in keyof Shape]: Validatable<Shape[K]>
}
): ObjectValidator<Shape> {
return new ObjectValidator(config) return new ObjectValidator(config)
} }

View file

@ -10,7 +10,7 @@ async function main() {
const nextVersion = latestVersion.prerelease.length const nextVersion = latestVersion.prerelease.length
? // if the package is in prerelease mode, we want to release a canary for the current version rather than bumping ? // if the package is in prerelease mode, we want to release a canary for the current version rather than bumping
latestVersion latestVersion
: latestVersion?.inc(bump) : latestVersion?.inc(bump)
const versionString = `${nextVersion.major}.${nextVersion.minor}.${nextVersion.patch}-canary.${sha}` const versionString = `${nextVersion.major}.${nextVersion.minor}.${nextVersion.patch}-canary.${sha}`

View file

@ -46,7 +46,7 @@ async function main() {
const nextVersion = prereleaseTag const nextVersion = prereleaseTag
? `${latestVersion.major}.${latestVersion.minor}.${latestVersion.patch}-${prereleaseTag}.${ ? `${latestVersion.major}.${latestVersion.minor}.${latestVersion.patch}-${prereleaseTag}.${
Number(prereleaseNumber) + 1 Number(prereleaseNumber) + 1
}` }`
: latestVersion.inc(bump).format() : latestVersion.inc(bump).format()
setAllVersions(nextVersion) setAllVersions(nextVersion)