snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,403 @@
|
||||
import { ElbowArrowRoute, ElbowArrowSide } from '../definitions'
|
||||
import { ElbowArrowRouteBuilder } from './ElbowArrowRouteBuilder'
|
||||
import { ElbowArrowTransform, ElbowArrowWorkingInfo } from './ElbowArrowWorkingInfo'
|
||||
|
||||
/**
|
||||
* Draw one of these arrows:
|
||||
*
|
||||
* ```
|
||||
* 1: 2: 3: 4: 5:
|
||||
* ┌───┐ ┌───┐ ┌───┐ ┌───────┐ ┌───────┐ ┌───┐
|
||||
* │ A ├─┐ │ A ├─┐ │ A ├───┐ │ ┌───┐ │ │ ┌───┐ │ │ A ├─┐
|
||||
* └───┘ │ ┌───┐ └───┘ │ └───┘ │ │ │ A ├─┘ └─► B │ │ └───┘ │
|
||||
* └─► B │ ┌────┘ ┌───┐ │ │ └───┘ └───┘ └───────┘
|
||||
* └───┘ │ ┌───┐ ┌►│ B │ │ │ ┌───┐
|
||||
* └─► B │ │ └───┘ │ └───► B │
|
||||
* └───┘ └───────┘ └───┘
|
||||
* ```
|
||||
*/
|
||||
export function routeRightToLeft(info: ElbowArrowWorkingInfo): ElbowArrowRoute | null {
|
||||
const aEdge = info.A.edges.right
|
||||
const bEdge = info.B.edges.left
|
||||
|
||||
// we can't draw this arrow if we don't have the proper edge we want:
|
||||
if (!aEdge || !bEdge) return null
|
||||
|
||||
// just so we get to handle less edge cases, flip the boxes if A is below B:
|
||||
if (aEdge.crossTarget > bEdge.crossTarget) {
|
||||
info.apply(ElbowArrowTransform.FlipY)
|
||||
}
|
||||
|
||||
if (info.gapX > 0 && info.midX !== null) {
|
||||
// Arrow 1:
|
||||
return new ElbowArrowRouteBuilder(info, 'to left 1')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(info.midX, aEdge.crossTarget)
|
||||
.add(info.midX, bEdge.crossTarget)
|
||||
.midpointHandle('x')
|
||||
.add(bEdge.value, bEdge.crossTarget)
|
||||
.build()
|
||||
}
|
||||
|
||||
if (aEdge.expanded === null || bEdge.expanded === null) return null
|
||||
|
||||
if (info.midY !== null) {
|
||||
// Arrow 2:
|
||||
return new ElbowArrowRouteBuilder(info, 'to left 2')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, info.midY)
|
||||
.add(bEdge.expanded, info.midY)
|
||||
.midpointHandle('y')
|
||||
.add(bEdge.expanded, bEdge.crossTarget)
|
||||
.add(bEdge.value, bEdge.crossTarget)
|
||||
.build()
|
||||
}
|
||||
|
||||
const arrow3Distance =
|
||||
Math.abs(aEdge.value - info.common.expanded.right) +
|
||||
Math.abs(aEdge.crossTarget - info.common.expanded.bottom) +
|
||||
Math.abs(info.common.expanded.right - bEdge.expanded) +
|
||||
Math.abs(info.common.expanded.bottom - bEdge.crossTarget) +
|
||||
info.options.expandElbowLegLength +
|
||||
6 // 6 points in this arrow
|
||||
|
||||
const arrow4Distance =
|
||||
info.options.expandElbowLegLength +
|
||||
Math.abs(aEdge.crossTarget - info.common.expanded.top) +
|
||||
Math.abs(aEdge.expanded - info.common.expanded.left) +
|
||||
Math.abs(info.common.expanded.top - bEdge.crossTarget) +
|
||||
Math.abs(info.common.expanded.left - bEdge.value) +
|
||||
// 6 points in this arrow, plus bias towards down/right:
|
||||
6 +
|
||||
info.bias.y
|
||||
|
||||
const arrow5Distance =
|
||||
info.gapX < 0 && info.midX !== null
|
||||
? info.options.expandElbowLegLength +
|
||||
Math.abs(aEdge.crossTarget - info.A.expanded.bottom) +
|
||||
info.common.expanded.width +
|
||||
Math.abs(info.A.expanded.bottom - info.B.expanded.top) +
|
||||
Math.abs(info.B.expanded.top - bEdge.crossTarget) +
|
||||
info.options.expandElbowLegLength +
|
||||
// 8 points in this arrow
|
||||
8
|
||||
: Infinity
|
||||
|
||||
if (arrow3Distance < arrow4Distance && arrow3Distance < arrow5Distance) {
|
||||
// Arrow 3:
|
||||
return new ElbowArrowRouteBuilder(info, 'to left 3')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(info.common.expanded.right, aEdge.crossTarget)
|
||||
.add(info.common.expanded.right, info.common.expanded.bottom)
|
||||
.add(bEdge.expanded, info.common.expanded.bottom)
|
||||
.add(bEdge.expanded, bEdge.crossTarget)
|
||||
.add(bEdge.value, bEdge.crossTarget)
|
||||
.build()
|
||||
}
|
||||
|
||||
if (arrow4Distance < arrow5Distance) {
|
||||
// Arrow 4:
|
||||
return new ElbowArrowRouteBuilder(info, 'to left 4')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, info.common.expanded.top)
|
||||
.add(info.common.expanded.left, info.common.expanded.top)
|
||||
.add(info.common.expanded.left, bEdge.crossTarget)
|
||||
.add(bEdge.value, bEdge.crossTarget)
|
||||
.build()
|
||||
}
|
||||
|
||||
if (info.midX !== null) {
|
||||
// Arrow 5:
|
||||
return new ElbowArrowRouteBuilder(info, 'to left 5')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, info.A.expanded.bottom)
|
||||
.add(info.midX, info.A.expanded.bottom)
|
||||
.add(info.midX, info.B.expanded.top)
|
||||
.midpointHandle('y')
|
||||
.add(bEdge.expanded, info.B.expanded.top)
|
||||
.add(bEdge.expanded, bEdge.crossTarget)
|
||||
.add(bEdge.value, bEdge.crossTarget)
|
||||
.build()
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw one of these arrows:
|
||||
* ```
|
||||
* 1: 2: 3:
|
||||
* ┌───┐ ┌───┐ ┌───┐
|
||||
* │ A ├─────┐ ┌───┐ │ ┌─▼─┐ │ A ├─┐
|
||||
* └───┘ │ │ A ├─┘ │ B │ └───┘ │
|
||||
* ┌─▼─┐ └───┘ └───┘ ┌───┘
|
||||
* │ B │ ┌─▼─┐
|
||||
* └───┘ │ B │
|
||||
* └───┘
|
||||
* 4: 5: 6:
|
||||
* ┌───┐ ┌───┐ ┌───┐ ┌───┐
|
||||
* ┌─▼─┐ │ │ ┌─▼─┐ ┌─▼─┐ │ │ A ├─┐
|
||||
* │ B │ │ │ │ B │ │ B │ │ └───┘ │
|
||||
* └───┘ │ │ └───┘ └───┘ └───────┘
|
||||
* ┌───┐ │ └───┐
|
||||
* │ A ├─┘ ┌───┐ │
|
||||
* └───┘ │ A ├─┘
|
||||
* └───┘
|
||||
* ```
|
||||
*/
|
||||
export function routeRightToTop(info: ElbowArrowWorkingInfo): ElbowArrowRoute | null {
|
||||
const aEdge = info.A.edges.right
|
||||
const bEdge = info.B.edges.top
|
||||
|
||||
if (!aEdge || !bEdge) return null
|
||||
|
||||
if (
|
||||
(aEdge.crossTarget < (bEdge.expanded ?? bEdge.value) &&
|
||||
bEdge.crossTarget > (aEdge.expanded ?? aEdge.value)) ||
|
||||
(info.A.isPoint && info.B.expanded.containsPoint(info.A.original.center))
|
||||
) {
|
||||
// Arrow 1:
|
||||
return new ElbowArrowRouteBuilder(info, 'to top 1')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(bEdge.crossTarget, aEdge.crossTarget)
|
||||
.add(bEdge.crossTarget, bEdge.value)
|
||||
.build()
|
||||
}
|
||||
|
||||
if (info.gapX > 0 && info.midX !== null && bEdge.expanded !== null) {
|
||||
// Arrow 2:
|
||||
return new ElbowArrowRouteBuilder(info, 'to top 2')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(info.midX, aEdge.crossTarget)
|
||||
.add(info.midX, bEdge.expanded)
|
||||
.midpointHandle('x')
|
||||
.add(bEdge.crossTarget, bEdge.expanded)
|
||||
.add(bEdge.crossTarget, bEdge.value)
|
||||
.build()
|
||||
}
|
||||
|
||||
if (
|
||||
info.gapY > 0 &&
|
||||
aEdge.expanded !== null &&
|
||||
bEdge.crossTarget < aEdge.expanded &&
|
||||
info.midY !== null
|
||||
) {
|
||||
// Arrow 3:
|
||||
return new ElbowArrowRouteBuilder(info, 'to top 3')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, info.midY)
|
||||
.add(bEdge.crossTarget, info.midY)
|
||||
.midpointHandle('y')
|
||||
.add(bEdge.crossTarget, bEdge.value)
|
||||
.build()
|
||||
}
|
||||
|
||||
const arrow4Length =
|
||||
Math.abs(aEdge.value - info.common.expanded.right) +
|
||||
Math.abs(aEdge.crossTarget - info.common.expanded.top) +
|
||||
Math.abs(bEdge.crossTarget - info.common.expanded.right) +
|
||||
Math.abs(bEdge.value - info.common.expanded.top)
|
||||
|
||||
const arrow5Length =
|
||||
aEdge.expanded !== null && info.midY !== null && bEdge.expanded !== null
|
||||
? Math.abs(aEdge.value - aEdge.expanded) +
|
||||
Math.abs(info.B.expanded.left - aEdge.expanded) +
|
||||
Math.abs(info.B.expanded.left - bEdge.crossTarget) +
|
||||
Math.abs(aEdge.crossTarget - info.B.expanded.top) +
|
||||
Math.abs(bEdge.value - bEdge.expanded)
|
||||
: Infinity
|
||||
|
||||
const arrow6Length =
|
||||
aEdge.expanded !== null && info.midX !== null && bEdge.expanded !== null
|
||||
? Math.abs(aEdge.value - info.common.expanded.right) +
|
||||
Math.abs(aEdge.crossTarget - info.A.expanded.bottom) +
|
||||
Math.abs(aEdge.expanded - bEdge.crossTarget) +
|
||||
Math.abs(info.A.expanded.bottom - bEdge.expanded) +
|
||||
Math.abs(bEdge.expanded - bEdge.value)
|
||||
: Infinity
|
||||
|
||||
if (arrow4Length < arrow5Length && arrow4Length < arrow6Length) {
|
||||
// Arrow 4:
|
||||
return new ElbowArrowRouteBuilder(info, 'to top 4')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(info.common.expanded.right, aEdge.crossTarget)
|
||||
.add(info.common.expanded.right, info.common.expanded.top)
|
||||
.add(bEdge.crossTarget, info.common.expanded.top)
|
||||
.add(bEdge.crossTarget, bEdge.value)
|
||||
.build()
|
||||
}
|
||||
|
||||
if (
|
||||
bEdge.expanded !== null &&
|
||||
aEdge.expanded !== null &&
|
||||
info.midY !== null &&
|
||||
arrow5Length < arrow6Length
|
||||
) {
|
||||
// Arrow 5:
|
||||
return new ElbowArrowRouteBuilder(info, 'to top 5')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, info.midY)
|
||||
.add(info.B.expanded.left, info.midY)
|
||||
.midpointHandle('y')
|
||||
.add(info.B.expanded.left, bEdge.expanded)
|
||||
.add(bEdge.crossTarget, bEdge.expanded)
|
||||
.add(bEdge.crossTarget, bEdge.value)
|
||||
.build()
|
||||
}
|
||||
|
||||
if (bEdge.expanded !== null && aEdge.expanded !== null && info.midX !== null) {
|
||||
// Arrow 6:
|
||||
return new ElbowArrowRouteBuilder(info, 'to top 6')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, info.A.expanded.bottom)
|
||||
.add(info.midX, info.A.expanded.bottom)
|
||||
.add(info.midX, bEdge.expanded)
|
||||
.midpointHandle('x')
|
||||
.add(bEdge.crossTarget, bEdge.expanded)
|
||||
.add(bEdge.crossTarget, bEdge.value)
|
||||
.build()
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* See `routeRightToTop`.
|
||||
*/
|
||||
export function routeRightToBottom(info: ElbowArrowWorkingInfo): ElbowArrowRoute | null {
|
||||
info.apply(ElbowArrowTransform.FlipY)
|
||||
return routeRightToTop(info)
|
||||
}
|
||||
|
||||
/**
|
||||
* Arrows may be mirrored - Y flipped
|
||||
* ```
|
||||
* 1: 2: 3:
|
||||
* ┌───┐ ┌───┐ ┌───────┐ ┌───┐
|
||||
* │ A ├─┐ │ A ├─┘ ┌───┐ │ ┌───┐ │ A ├─┐
|
||||
* └───┘ │ └───┘ │ B ◄─┘ │ B ◄─┐ └───┘ │
|
||||
* ┌───┐ │ └───┘ └───┘ └───────┘
|
||||
* │ B ◄─┘
|
||||
* └───┘
|
||||
* ```
|
||||
*/
|
||||
export function routeRightToRight(info: ElbowArrowWorkingInfo): ElbowArrowRoute | null {
|
||||
const aEdge = info.A.edges.right
|
||||
const bEdge = info.B.edges.right
|
||||
|
||||
if (!aEdge || !bEdge) return null
|
||||
|
||||
if (
|
||||
(info.gapX <= 0 ||
|
||||
aEdge.crossTarget > info.B.expanded.bottom ||
|
||||
aEdge.crossTarget < info.B.expanded.top) &&
|
||||
(bEdge.value > info.A.original.left ||
|
||||
bEdge.crossTarget > info.A.expanded.bottom ||
|
||||
bEdge.crossTarget < info.A.expanded.top)
|
||||
) {
|
||||
// Arrow 1
|
||||
return new ElbowArrowRouteBuilder(info, 'to right 1')
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(info.common.expanded.right, aEdge.crossTarget)
|
||||
.add(info.common.expanded.right, bEdge.crossTarget)
|
||||
.add(bEdge.value, bEdge.crossTarget)
|
||||
.build()
|
||||
}
|
||||
|
||||
if (info.midX === null) return null
|
||||
|
||||
if (bEdge.expanded !== null && info.gapX >= 0) {
|
||||
const viaBottomLength =
|
||||
Math.abs(bEdge.crossTarget - info.B.expanded.bottom) +
|
||||
Math.abs(aEdge.crossTarget - info.B.expanded.bottom)
|
||||
const viaTopLength =
|
||||
Math.abs(bEdge.crossTarget - info.B.expanded.top) +
|
||||
Math.abs(aEdge.crossTarget - info.B.expanded.top)
|
||||
|
||||
const topOrBottom = viaBottomLength < viaTopLength ? 'bottom' : 'top'
|
||||
// Arrow 2:
|
||||
return new ElbowArrowRouteBuilder(info, `to right 2 via ${topOrBottom}`)
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(info.midX, aEdge.crossTarget)
|
||||
.add(info.midX, info.B.expanded[topOrBottom])
|
||||
.midpointHandle('x')
|
||||
.add(bEdge.expanded, info.B.expanded[topOrBottom])
|
||||
.add(bEdge.expanded, bEdge.crossTarget)
|
||||
.add(bEdge.value, bEdge.crossTarget)
|
||||
.build()
|
||||
}
|
||||
|
||||
if (aEdge.expanded !== null && info.gapX <= 0) {
|
||||
const viaBottomLength =
|
||||
Math.abs(bEdge.crossTarget - info.A.expanded.bottom) +
|
||||
Math.abs(aEdge.crossTarget - info.A.expanded.bottom)
|
||||
const viaTopLength =
|
||||
Math.abs(bEdge.crossTarget - info.A.expanded.top) +
|
||||
Math.abs(aEdge.crossTarget - info.A.expanded.top)
|
||||
|
||||
const topOrBottom = viaBottomLength < viaTopLength ? 'bottom' : 'top'
|
||||
// Arrow 3:
|
||||
return new ElbowArrowRouteBuilder(info, `to right 3 via ${topOrBottom}`)
|
||||
.add(aEdge.value, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, aEdge.crossTarget)
|
||||
.add(aEdge.expanded, info.A.expanded[topOrBottom])
|
||||
.add(info.midX, info.A.expanded[topOrBottom])
|
||||
.add(info.midX, bEdge.crossTarget)
|
||||
.midpointHandle('x')
|
||||
.add(bEdge.value, bEdge.crossTarget)
|
||||
.build()
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const routes = {
|
||||
top: {
|
||||
top: [ElbowArrowTransform.Rotate270, routeRightToRight],
|
||||
left: [ElbowArrowTransform.Rotate270, routeRightToTop],
|
||||
bottom: [ElbowArrowTransform.Rotate270, routeRightToLeft],
|
||||
right: [ElbowArrowTransform.Rotate270, routeRightToBottom],
|
||||
},
|
||||
right: {
|
||||
top: [ElbowArrowTransform.Identity, routeRightToTop],
|
||||
right: [ElbowArrowTransform.Identity, routeRightToRight],
|
||||
bottom: [ElbowArrowTransform.Identity, routeRightToBottom],
|
||||
left: [ElbowArrowTransform.Identity, routeRightToLeft],
|
||||
},
|
||||
bottom: {
|
||||
top: [ElbowArrowTransform.Rotate90, routeRightToLeft],
|
||||
left: [ElbowArrowTransform.Rotate90, routeRightToBottom],
|
||||
bottom: [ElbowArrowTransform.Rotate90, routeRightToRight],
|
||||
right: [ElbowArrowTransform.Rotate90, routeRightToTop],
|
||||
},
|
||||
left: {
|
||||
top: [ElbowArrowTransform.Rotate180, routeRightToBottom],
|
||||
left: [ElbowArrowTransform.Rotate180, routeRightToRight],
|
||||
bottom: [ElbowArrowTransform.Rotate180, routeRightToTop],
|
||||
right: [ElbowArrowTransform.Rotate180, routeRightToLeft],
|
||||
},
|
||||
} satisfies Record<
|
||||
ElbowArrowSide,
|
||||
Record<
|
||||
ElbowArrowSide,
|
||||
[ElbowArrowTransform, (info: ElbowArrowWorkingInfo) => ElbowArrowRoute | null]
|
||||
>
|
||||
>
|
||||
|
||||
export function tryRouteArrow(
|
||||
info: ElbowArrowWorkingInfo,
|
||||
aEdge: ElbowArrowSide,
|
||||
bEdge: ElbowArrowSide
|
||||
): ElbowArrowRoute | null {
|
||||
const [transform, routeFn] = routes[aEdge][bEdge]
|
||||
info.apply(transform)
|
||||
const route = routeFn(info)
|
||||
info.reset()
|
||||
return route
|
||||
}
|
||||
Reference in New Issue
Block a user