@tldraw/editor 3.14.0-canary.e0ab6f4c80f9 → 3.14.0-canary.e34e46232a4e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +129 -107
- package/dist-cjs/index.js +8 -8
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js +1 -12
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +3 -3
- package/dist-cjs/lib/editor/Editor.js +76 -78
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/bindingsIndex.js +22 -22
- package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +16 -20
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js +16 -16
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
- package/dist-cjs/lib/editor/managers/{ClickManager.js → ClickManager/ClickManager.js} +1 -1
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{EdgeScrollManager.js → EdgeScrollManager/EdgeScrollManager.js} +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{FocusManager.js → FocusManager/FocusManager.js} +2 -0
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{FontManager.js → FontManager/FontManager.js} +4 -1
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{HistoryManager.js → HistoryManager/HistoryManager.js} +64 -6
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{ScribbleManager.js → ScribbleManager/ScribbleManager.js} +1 -1
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{TextManager.js → TextManager/TextManager.js} +73 -42
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{TickManager.js → TickManager/TickManager.js} +1 -1
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{UserPreferencesManager.js → UserPreferencesManager/UserPreferencesManager.js} +1 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +7 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +8 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +6 -0
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js.map +1 -1
- package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +33 -33
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +18 -13
- package/dist-cjs/lib/primitives/Vec.js.map +3 -3
- package/dist-cjs/lib/primitives/geometry/Arc2d.js +41 -21
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +11 -11
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +13 -16
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +4 -4
- package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Edge2d.js +14 -21
- package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +10 -10
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +5 -0
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Point2d.js +6 -6
- package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Polygon2d.js +3 -0
- package/dist-cjs/lib/primitives/geometry/Polygon2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js +8 -5
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Rectangle2d.js +22 -11
- package/dist-cjs/lib/primitives/geometry/Rectangle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js +22 -22
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
- package/dist-cjs/lib/utils/reorderShapes.js +11 -10
- package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
- package/dist-cjs/lib/utils/richText.js +7 -2
- package/dist-cjs/lib/utils/richText.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +129 -107
- package/dist-esm/index.mjs +15 -9
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +1 -1
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +76 -78
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/bindingsIndex.mjs +22 -22
- package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +16 -20
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +16 -16
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/{ClickManager.mjs → ClickManager/ClickManager.mjs} +1 -1
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{EdgeScrollManager.mjs → EdgeScrollManager/EdgeScrollManager.mjs} +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{FocusManager.mjs → FocusManager/FocusManager.mjs} +2 -0
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{FontManager.mjs → FontManager/FontManager.mjs} +4 -1
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{HistoryManager.mjs → HistoryManager/HistoryManager.mjs} +60 -2
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{ScribbleManager.mjs → ScribbleManager/ScribbleManager.mjs} +1 -1
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{TextManager.mjs → TextManager/TextManager.mjs} +73 -42
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{TickManager.mjs → TickManager/TickManager.mjs} +1 -1
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{UserPreferencesManager.mjs → UserPreferencesManager/UserPreferencesManager.mjs} +1 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +7 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +8 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +6 -0
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +1 -1
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +33 -33
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +19 -14
- package/dist-esm/lib/primitives/Vec.mjs.map +3 -3
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs +41 -21
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +11 -11
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +13 -16
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +4 -4
- package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs +14 -21
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +11 -11
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +7 -1
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Point2d.mjs +6 -6
- package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Polygon2d.mjs +3 -0
- package/dist-esm/lib/primitives/geometry/Polygon2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +8 -5
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs +22 -11
- package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +22 -22
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
- package/dist-esm/lib/utils/reorderShapes.mjs +11 -10
- package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
- package/dist-esm/lib/utils/richText.mjs +8 -3
- package/dist-esm/lib/utils/richText.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +433 -482
- package/package.json +8 -9
- package/src/index.ts +19 -8
- package/src/lib/config/TLSessionStateSnapshot.ts +1 -1
- package/src/lib/editor/Editor.test.ts +252 -3
- package/src/lib/editor/Editor.ts +77 -76
- package/src/lib/editor/bindings/BindingUtil.ts +6 -0
- package/src/lib/editor/derivations/bindingsIndex.ts +27 -26
- package/src/lib/editor/derivations/notVisibleShapes.ts +24 -25
- package/src/lib/editor/derivations/parentsToChildren.ts +28 -25
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +442 -0
- package/src/lib/editor/managers/{ClickManager.ts → ClickManager/ClickManager.ts} +3 -3
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +374 -0
- package/src/lib/editor/managers/{EdgeScrollManager.ts → EdgeScrollManager/EdgeScrollManager.ts} +3 -3
- package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +455 -0
- package/src/lib/editor/managers/{FocusManager.ts → FocusManager/FocusManager.ts} +3 -1
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +263 -0
- package/src/lib/editor/managers/{FontManager.ts → FontManager/FontManager.ts} +5 -2
- package/src/lib/editor/managers/{HistoryManager.test.ts → HistoryManager/HistoryManager.test.ts} +388 -1
- package/src/lib/editor/managers/{HistoryManager.ts → HistoryManager/HistoryManager.ts} +73 -2
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +624 -0
- package/src/lib/editor/managers/{ScribbleManager.ts → ScribbleManager/ScribbleManager.ts} +2 -2
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +485 -0
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +407 -0
- package/src/lib/editor/managers/{TextManager.ts → TextManager/TextManager.ts} +119 -87
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +314 -0
- package/src/lib/editor/managers/{TickManager.ts → TickManager/TickManager.ts} +2 -2
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +591 -0
- package/src/lib/editor/managers/{UserPreferencesManager.ts → UserPreferencesManager/UserPreferencesManager.ts} +2 -2
- package/src/lib/editor/shapes/ShapeUtil.ts +11 -1
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +8 -0
- package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +5 -2
- package/src/lib/editor/tools/StateNode.ts +3 -3
- package/src/lib/editor/types/external-content.ts +11 -2
- package/src/lib/exports/getSvgJsx.tsx +1 -1
- package/src/lib/hooks/useCanvasEvents.ts +0 -1
- package/src/lib/primitives/Box.test.ts +588 -7
- package/src/lib/primitives/Box.ts +33 -33
- package/src/lib/primitives/Vec.test.ts +2 -2
- package/src/lib/primitives/Vec.ts +15 -10
- package/src/lib/primitives/geometry/Arc2d.ts +42 -23
- package/src/lib/primitives/geometry/Circle2d.ts +12 -12
- package/src/lib/primitives/geometry/CubicBezier2d.test.ts +5 -0
- package/src/lib/primitives/geometry/CubicBezier2d.ts +13 -17
- package/src/lib/primitives/geometry/CubicSpline2d.ts +5 -5
- package/src/lib/primitives/geometry/Edge2d.ts +14 -25
- package/src/lib/primitives/geometry/Ellipse2d.ts +12 -13
- package/src/lib/primitives/geometry/Geometry2d.ts +6 -0
- package/src/lib/primitives/geometry/Point2d.ts +6 -6
- package/src/lib/primitives/geometry/Polygon2d.ts +4 -0
- package/src/lib/primitives/geometry/Polyline2d.ts +10 -7
- package/src/lib/primitives/geometry/Rectangle2d.ts +24 -11
- package/src/lib/primitives/geometry/Stadium2d.ts +22 -23
- package/src/lib/utils/reorderShapes.ts +10 -13
- package/src/lib/utils/richText.ts +10 -4
- package/src/version.ts +3 -3
- package/dist-cjs/lib/editor/managers/ClickManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/EdgeScrollManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/FocusManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/FontManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/HistoryManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/ScribbleManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/Stack.js +0 -82
- package/dist-cjs/lib/editor/managers/Stack.js.map +0 -7
- package/dist-cjs/lib/editor/managers/TextManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/TickManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +0 -7
- package/dist-esm/lib/editor/managers/ClickManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/EdgeScrollManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/FocusManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/FontManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/HistoryManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/ScribbleManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/Stack.mjs +0 -62
- package/dist-esm/lib/editor/managers/Stack.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/TextManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/TickManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +0 -7
- package/src/lib/editor/managers/ScribbleManager.test.ts +0 -32
- package/src/lib/editor/managers/Stack.ts +0 -71
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TLAssetId } from '@tldraw/tlschema'
|
|
1
|
+
import { TLAssetId, TLShapeId } from '@tldraw/tlschema'
|
|
2
2
|
import { VecLike } from '../../primitives/Vec'
|
|
3
3
|
import { TLContent } from './clipboard-types'
|
|
4
4
|
|
|
@@ -52,7 +52,15 @@ export interface TLTextExternalContent extends TLBaseExternalContent {
|
|
|
52
52
|
export interface TLFilesExternalContent extends TLBaseExternalContent {
|
|
53
53
|
type: 'files'
|
|
54
54
|
files: File[]
|
|
55
|
-
ignoreParent
|
|
55
|
+
ignoreParent?: boolean
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** @public */
|
|
59
|
+
export interface TLFileReplaceExternalContent extends TLBaseExternalContent {
|
|
60
|
+
type: 'file-replace'
|
|
61
|
+
file: File
|
|
62
|
+
shapeId: TLShapeId
|
|
63
|
+
isImage: boolean
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
/** @public */
|
|
@@ -90,6 +98,7 @@ export interface TLExcalidrawExternalContent extends TLBaseExternalContent {
|
|
|
90
98
|
export type TLExternalContent<EmbedDefinition> =
|
|
91
99
|
| TLTextExternalContent
|
|
92
100
|
| TLFilesExternalContent
|
|
101
|
+
| TLFileReplaceExternalContent
|
|
93
102
|
| TLUrlExternalContent
|
|
94
103
|
| TLSvgTextExternalContent
|
|
95
104
|
| TLEmbedExternalContent<EmbedDefinition>
|
|
@@ -21,7 +21,7 @@ import { flushSync } from 'react-dom'
|
|
|
21
21
|
import { ErrorBoundary } from '../components/ErrorBoundary'
|
|
22
22
|
import { InnerShape, InnerShapeBackground } from '../components/Shape'
|
|
23
23
|
import { Editor, TLRenderingShape } from '../editor/Editor'
|
|
24
|
-
import { TLFontFace } from '../editor/managers/FontManager'
|
|
24
|
+
import { TLFontFace } from '../editor/managers/FontManager/FontManager'
|
|
25
25
|
import { ShapeUtil } from '../editor/shapes/ShapeUtil'
|
|
26
26
|
import {
|
|
27
27
|
SvgExportContext,
|
|
@@ -2,9 +2,15 @@ import { Box } from './Box'
|
|
|
2
2
|
import { Vec } from './Vec'
|
|
3
3
|
|
|
4
4
|
describe('Box', () => {
|
|
5
|
+
let box: Box
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
box = new Box(10, 20, 100, 200)
|
|
9
|
+
})
|
|
10
|
+
|
|
5
11
|
it('Creates a box', () => {
|
|
6
|
-
const
|
|
7
|
-
expect(
|
|
12
|
+
const newBox = new Box(0, 0, 100, 100)
|
|
13
|
+
expect(newBox).toMatchObject({
|
|
8
14
|
x: 0,
|
|
9
15
|
y: 0,
|
|
10
16
|
w: 100,
|
|
@@ -12,13 +18,588 @@ describe('Box', () => {
|
|
|
12
18
|
})
|
|
13
19
|
})
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
describe('Box.point', () => {
|
|
22
|
+
it('gets the point as a Vec', () => {
|
|
23
|
+
expect(box.point).toEqual(new Vec(10, 20))
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('sets the point with a Vec', () => {
|
|
27
|
+
box.point = new Vec(50, 60)
|
|
28
|
+
expect(box.x).toBe(50)
|
|
29
|
+
expect(box.y).toBe(60)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('Box.minX', () => {
|
|
34
|
+
it('gets the minimum X value', () => {
|
|
35
|
+
expect(box.minX).toBe(10)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('sets the minimum X value', () => {
|
|
39
|
+
box.minX = 30
|
|
40
|
+
expect(box.x).toBe(30)
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
describe('Box.left', () => {
|
|
45
|
+
it('gets the left edge', () => {
|
|
46
|
+
expect(box.left).toBe(10)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
describe('Box.midX', () => {
|
|
51
|
+
it('gets the middle X value', () => {
|
|
52
|
+
expect(box.midX).toBe(60) // 10 + 100/2
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
describe('Box.maxX', () => {
|
|
57
|
+
it('gets the maximum X value', () => {
|
|
58
|
+
expect(box.maxX).toBe(110) // 10 + 100
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
describe('Box.right', () => {
|
|
63
|
+
it('gets the right edge', () => {
|
|
64
|
+
expect(box.right).toBe(110) // 10 + 100
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
describe('Box.minY', () => {
|
|
69
|
+
it('gets the minimum Y value', () => {
|
|
70
|
+
expect(box.minY).toBe(20)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('sets the minimum Y value', () => {
|
|
74
|
+
box.minY = 40
|
|
75
|
+
expect(box.y).toBe(40)
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
describe('Box.top', () => {
|
|
80
|
+
it('gets the top edge', () => {
|
|
81
|
+
expect(box.top).toBe(20)
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
describe('Box.midY', () => {
|
|
86
|
+
it('gets the middle Y value', () => {
|
|
87
|
+
expect(box.midY).toBe(120) // 20 + 200/2
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
describe('Box.maxY', () => {
|
|
92
|
+
it('gets the maximum Y value', () => {
|
|
93
|
+
expect(box.maxY).toBe(220) // 20 + 200
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
describe('Box.bottom', () => {
|
|
98
|
+
it('gets the bottom edge', () => {
|
|
99
|
+
expect(box.bottom).toBe(220) // 20 + 200
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
describe('Box.width', () => {
|
|
104
|
+
it('gets the width', () => {
|
|
105
|
+
expect(box.width).toBe(100)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('sets the width', () => {
|
|
109
|
+
box.width = 150
|
|
110
|
+
expect(box.w).toBe(150)
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
describe('Box.height', () => {
|
|
115
|
+
it('gets the height', () => {
|
|
116
|
+
expect(box.height).toBe(200)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('sets the height', () => {
|
|
120
|
+
box.height = 250
|
|
121
|
+
expect(box.h).toBe(250)
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
describe('Box.aspectRatio', () => {
|
|
126
|
+
it('gets the aspect ratio', () => {
|
|
127
|
+
expect(box.aspectRatio).toBe(0.5) // 100/200
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
describe('Box.center', () => {
|
|
132
|
+
it('gets the center point', () => {
|
|
133
|
+
expect(box.center).toEqual(new Vec(60, 120))
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('sets the center point', () => {
|
|
137
|
+
box.center = new Vec(100, 150)
|
|
138
|
+
expect(box.x).toBe(50) // 100 - 100/2
|
|
139
|
+
expect(box.y).toBe(50) // 150 - 200/2
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
describe('Box.corners', () => {
|
|
144
|
+
it('gets the corners', () => {
|
|
145
|
+
const corners = box.corners
|
|
146
|
+
expect(corners).toEqual([
|
|
147
|
+
new Vec(10, 20), // top-left
|
|
148
|
+
new Vec(110, 20), // top-right (fixed from buggy bottom-right)
|
|
149
|
+
new Vec(110, 220), // bottom-right
|
|
150
|
+
new Vec(10, 220), // bottom-left
|
|
151
|
+
])
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
describe('Box.cornersAndCenter', () => {
|
|
156
|
+
it('gets the corners and center', () => {
|
|
157
|
+
const cornersAndCenter = box.cornersAndCenter
|
|
158
|
+
expect(cornersAndCenter).toEqual([
|
|
159
|
+
new Vec(10, 20), // top-left
|
|
160
|
+
new Vec(110, 20), // top-right (fixed from buggy bottom-right)
|
|
161
|
+
new Vec(110, 220), // bottom-right
|
|
162
|
+
new Vec(10, 220), // bottom-left
|
|
163
|
+
new Vec(60, 120), // center
|
|
164
|
+
])
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
describe('Box.sides', () => {
|
|
169
|
+
it('gets the sides as pairs of vectors', () => {
|
|
170
|
+
const sides = box.sides
|
|
171
|
+
const corners = box.corners
|
|
172
|
+
expect(sides).toEqual([
|
|
173
|
+
[corners[0], corners[1]],
|
|
174
|
+
[corners[1], corners[2]],
|
|
175
|
+
[corners[2], corners[3]],
|
|
176
|
+
[corners[3], corners[0]],
|
|
177
|
+
])
|
|
178
|
+
})
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
describe('Box.size', () => {
|
|
182
|
+
it('gets the size as a Vec', () => {
|
|
183
|
+
expect(box.size).toEqual(new Vec(100, 200))
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
describe('Box.toFixed', () => {
|
|
188
|
+
it('applies precision to all values', () => {
|
|
189
|
+
const impreciseBox = new Box(10.123456789, 20.987654321, 100.555555, 200.777777)
|
|
190
|
+
const result = impreciseBox.toFixed()
|
|
191
|
+
expect(result.x).toBeCloseTo(10.123456789, 6)
|
|
192
|
+
expect(result.y).toBeCloseTo(20.987654321, 6)
|
|
193
|
+
expect(result.w).toBeCloseTo(100.555555, 6)
|
|
194
|
+
expect(result.h).toBeCloseTo(200.777777, 6)
|
|
195
|
+
expect(result).toBe(impreciseBox) // returns self
|
|
196
|
+
})
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
describe('Box.setTo', () => {
|
|
200
|
+
it('copies values from another box', () => {
|
|
201
|
+
const otherBox = new Box(50, 60, 150, 250)
|
|
202
|
+
const result = box.setTo(otherBox)
|
|
203
|
+
expect(box.x).toBe(50)
|
|
204
|
+
expect(box.y).toBe(60)
|
|
205
|
+
expect(box.w).toBe(150)
|
|
206
|
+
expect(box.h).toBe(250)
|
|
207
|
+
expect(result).toBe(box) // returns self
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
describe('Box.set', () => {
|
|
212
|
+
it('sets all values', () => {
|
|
213
|
+
const result = box.set(30, 40, 120, 180)
|
|
214
|
+
expect(box.x).toBe(30)
|
|
215
|
+
expect(box.y).toBe(40)
|
|
216
|
+
expect(box.w).toBe(120)
|
|
217
|
+
expect(box.h).toBe(180)
|
|
218
|
+
expect(result).toBe(box) // returns self
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
it('uses default values when no parameters provided', () => {
|
|
222
|
+
const result = box.set()
|
|
223
|
+
expect(box.x).toBe(0)
|
|
224
|
+
expect(box.y).toBe(0)
|
|
225
|
+
expect(box.w).toBe(0)
|
|
226
|
+
expect(box.h).toBe(0)
|
|
227
|
+
expect(result).toBe(box) // returns self
|
|
228
|
+
})
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
describe('Box.expand', () => {
|
|
232
|
+
it('expands to include another box', () => {
|
|
233
|
+
const otherBox = new Box(5, 15, 120, 240) // overlaps and extends
|
|
234
|
+
const result = box.expand(otherBox)
|
|
235
|
+
expect(box.x).toBe(5) // min of 10 and 5
|
|
236
|
+
expect(box.y).toBe(15) // min of 20 and 15
|
|
237
|
+
expect(box.w).toBe(120) // max(110, 125) - min(10, 5) = 125 - 5
|
|
238
|
+
expect(box.h).toBe(240) // max(220, 255) - min(20, 15) = 255 - 15
|
|
239
|
+
expect(result).toBe(box) // returns self
|
|
240
|
+
})
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
describe('Box.expandBy', () => {
|
|
244
|
+
it('expands by a given amount', () => {
|
|
245
|
+
const result = box.expandBy(10)
|
|
246
|
+
expect(box.x).toBe(0) // 10 - 10
|
|
247
|
+
expect(box.y).toBe(10) // 20 - 10
|
|
248
|
+
expect(box.w).toBe(120) // 100 + 10*2
|
|
249
|
+
expect(box.h).toBe(220) // 200 + 10*2
|
|
250
|
+
expect(result).toBe(box) // returns self
|
|
251
|
+
})
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
describe('Box.scale', () => {
|
|
255
|
+
it('scales the box by a factor', () => {
|
|
256
|
+
const result = box.scale(2)
|
|
257
|
+
expect(box.x).toBe(5) // 10/2
|
|
258
|
+
expect(box.y).toBe(10) // 20/2
|
|
259
|
+
expect(box.w).toBe(50) // 100/2
|
|
260
|
+
expect(box.h).toBe(100) // 200/2
|
|
261
|
+
expect(result).toBe(box) // returns self
|
|
262
|
+
})
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
describe('Box.clone', () => {
|
|
266
|
+
it('creates a copy of the box', () => {
|
|
267
|
+
const cloned = box.clone()
|
|
268
|
+
expect(cloned).toEqual(box)
|
|
269
|
+
expect(cloned).not.toBe(box) // different object
|
|
270
|
+
})
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
describe('Box.translate', () => {
|
|
274
|
+
it('translates the box by a delta', () => {
|
|
275
|
+
const delta = new Vec(5, 10)
|
|
276
|
+
const result = box.translate(delta)
|
|
277
|
+
expect(box.x).toBe(15) // 10 + 5
|
|
278
|
+
expect(box.y).toBe(30) // 20 + 10
|
|
279
|
+
expect(box.w).toBe(100) // unchanged
|
|
280
|
+
expect(box.h).toBe(200) // unchanged
|
|
281
|
+
expect(result).toBe(box) // returns self
|
|
282
|
+
})
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
describe('Box.snapToGrid', () => {
|
|
286
|
+
it('snaps the box to a grid', () => {
|
|
287
|
+
const testBox = new Box(12, 18, 95, 185)
|
|
288
|
+
testBox.snapToGrid(10)
|
|
289
|
+
expect(testBox.minX).toBe(10) // rounded to nearest 10
|
|
290
|
+
expect(testBox.minY).toBe(20) // rounded to nearest 10
|
|
291
|
+
expect(testBox.width).toBe(100) // snapped width
|
|
292
|
+
expect(testBox.height).toBe(180) // snapped height
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('ensures minimum size of 1', () => {
|
|
296
|
+
const testBox = new Box(0, 0, 3, 3)
|
|
297
|
+
testBox.snapToGrid(10)
|
|
298
|
+
expect(testBox.width).toBe(1) // minimum 1
|
|
299
|
+
expect(testBox.height).toBe(1) // minimum 1
|
|
300
|
+
})
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
describe('Box.collides', () => {
|
|
304
|
+
it('returns true when boxes collide', () => {
|
|
305
|
+
const otherBox = new Box(50, 100, 100, 100) // overlaps
|
|
306
|
+
expect(box.collides(otherBox)).toBe(true)
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
it('returns false when boxes do not collide', () => {
|
|
310
|
+
const otherBox = new Box(200, 300, 100, 100) // no overlap
|
|
311
|
+
expect(box.collides(otherBox)).toBe(false)
|
|
312
|
+
})
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
describe('Box.contains', () => {
|
|
316
|
+
it('returns true when this box contains the other', () => {
|
|
317
|
+
const otherBox = new Box(20, 30, 50, 100) // inside box
|
|
318
|
+
expect(box.contains(otherBox)).toBe(true)
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
it('returns false when this box does not contain the other', () => {
|
|
322
|
+
const otherBox = new Box(5, 5, 200, 300) // larger than box
|
|
323
|
+
expect(box.contains(otherBox)).toBe(false)
|
|
324
|
+
})
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
describe('Box.includes', () => {
|
|
328
|
+
it('returns true when boxes collide or contain', () => {
|
|
329
|
+
const collidingBox = new Box(50, 100, 100, 100)
|
|
330
|
+
const containedBox = new Box(20, 30, 50, 100)
|
|
331
|
+
expect(box.includes(collidingBox)).toBe(true)
|
|
332
|
+
expect(box.includes(containedBox)).toBe(true)
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
it('returns false when boxes do not interact', () => {
|
|
336
|
+
const separateBox = new Box(200, 300, 100, 100)
|
|
337
|
+
expect(box.includes(separateBox)).toBe(false)
|
|
338
|
+
})
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
describe('Box.containsPoint', () => {
|
|
342
|
+
it('returns true when point is inside', () => {
|
|
343
|
+
const point = new Vec(50, 100)
|
|
344
|
+
expect(box.containsPoint(point)).toBe(true)
|
|
345
|
+
})
|
|
17
346
|
|
|
18
|
-
|
|
347
|
+
it('returns false when point is outside', () => {
|
|
348
|
+
const point = new Vec(150, 300)
|
|
349
|
+
expect(box.containsPoint(point)).toBe(false)
|
|
350
|
+
})
|
|
19
351
|
|
|
20
|
-
|
|
352
|
+
it('respects margin', () => {
|
|
353
|
+
const point = new Vec(5, 15) // just outside
|
|
354
|
+
expect(box.containsPoint(point)).toBe(false)
|
|
355
|
+
expect(box.containsPoint(point, 10)).toBe(true) // with margin
|
|
356
|
+
})
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
describe('Box.getHandlePoint', () => {
|
|
360
|
+
it('returns correct points for corners', () => {
|
|
361
|
+
expect(box.getHandlePoint('top_left')).toEqual(new Vec(10, 20))
|
|
362
|
+
expect(box.getHandlePoint('top_right')).toEqual(new Vec(110, 20))
|
|
363
|
+
expect(box.getHandlePoint('bottom_left')).toEqual(new Vec(10, 220))
|
|
364
|
+
expect(box.getHandlePoint('bottom_right')).toEqual(new Vec(110, 220))
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
it('returns correct points for edges', () => {
|
|
368
|
+
expect(box.getHandlePoint('top')).toEqual(new Vec(60, 20))
|
|
369
|
+
expect(box.getHandlePoint('right')).toEqual(new Vec(110, 120))
|
|
370
|
+
expect(box.getHandlePoint('bottom')).toEqual(new Vec(60, 220))
|
|
371
|
+
expect(box.getHandlePoint('left')).toEqual(new Vec(10, 120))
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
describe('Box.toJson', () => {
|
|
376
|
+
it('returns box model object', () => {
|
|
377
|
+
expect(box.toJson()).toEqual({
|
|
378
|
+
x: 10,
|
|
379
|
+
y: 20,
|
|
380
|
+
w: 100,
|
|
381
|
+
h: 200,
|
|
382
|
+
})
|
|
383
|
+
})
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
describe('Box.resize', () => {
|
|
387
|
+
it('resizes from top-left handle', () => {
|
|
388
|
+
box.resize('top_left', 10, 20)
|
|
389
|
+
expect(box.minX).toBe(20) // moved right
|
|
390
|
+
expect(box.minY).toBe(40) // moved down
|
|
391
|
+
expect(box.width).toBe(90) // reduced width
|
|
392
|
+
expect(box.height).toBe(180) // reduced height
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
it('resizes from bottom-right handle', () => {
|
|
396
|
+
box.resize('bottom_right', 10, 20)
|
|
397
|
+
expect(box.minX).toBe(10) // unchanged
|
|
398
|
+
expect(box.minY).toBe(20) // unchanged
|
|
399
|
+
expect(box.width).toBe(110) // increased width
|
|
400
|
+
expect(box.height).toBe(220) // increased height
|
|
401
|
+
})
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
describe('Box.union', () => {
|
|
405
|
+
it('creates union with another box', () => {
|
|
406
|
+
const otherBox = { x: 5, y: 15, w: 120, h: 240 }
|
|
407
|
+
const result = box.union(otherBox)
|
|
408
|
+
expect(box.x).toBe(5)
|
|
409
|
+
expect(box.y).toBe(15)
|
|
410
|
+
expect(box.width).toBe(120) // max(110, 125) - min(10, 5)
|
|
411
|
+
expect(box.height).toBe(240) // max(220, 255) - min(20, 15)
|
|
412
|
+
expect(result).toBe(box) // returns self
|
|
413
|
+
})
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
describe('Box.equals', () => {
|
|
417
|
+
it('returns true for equal boxes', () => {
|
|
418
|
+
const otherBox = new Box(10, 20, 100, 200)
|
|
419
|
+
expect(box.equals(otherBox)).toBe(true)
|
|
420
|
+
})
|
|
421
|
+
|
|
422
|
+
it('returns false for different boxes', () => {
|
|
423
|
+
const otherBox = new Box(10, 20, 100, 201)
|
|
424
|
+
expect(box.equals(otherBox)).toBe(false)
|
|
425
|
+
})
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
describe('Box.zeroFix', () => {
|
|
429
|
+
it('ensures minimum size of 1', () => {
|
|
430
|
+
const zeroBox = new Box(0, 0, 0, 0)
|
|
431
|
+
const result = zeroBox.zeroFix()
|
|
432
|
+
expect(zeroBox.w).toBe(1)
|
|
433
|
+
expect(zeroBox.h).toBe(1)
|
|
434
|
+
expect(result).toBe(zeroBox) // returns self
|
|
435
|
+
})
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
// Static method tests
|
|
439
|
+
describe('Box.From', () => {
|
|
440
|
+
it('creates box from box model', () => {
|
|
441
|
+
const boxModel = { x: 5, y: 10, w: 50, h: 100 }
|
|
442
|
+
const result = Box.From(boxModel)
|
|
443
|
+
expect(result).toEqual(new Box(5, 10, 50, 100))
|
|
444
|
+
})
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
describe('Box.FromCenter', () => {
|
|
448
|
+
it('creates box from center and size', () => {
|
|
449
|
+
const center = new Vec(50, 100)
|
|
450
|
+
const size = new Vec(20, 40)
|
|
451
|
+
const result = Box.FromCenter(center, size)
|
|
452
|
+
expect(result).toEqual(new Box(40, 80, 20, 40))
|
|
453
|
+
})
|
|
454
|
+
})
|
|
21
455
|
|
|
22
|
-
|
|
456
|
+
describe('Box.FromPoints', () => {
|
|
457
|
+
it('creates box from array of points', () => {
|
|
458
|
+
const points = [new Vec(10, 20), new Vec(110, 220), new Vec(50, 100)]
|
|
459
|
+
const result = Box.FromPoints(points)
|
|
460
|
+
expect(result).toEqual(new Box(10, 20, 100, 200))
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
it('returns empty box for empty array', () => {
|
|
464
|
+
const result = Box.FromPoints([])
|
|
465
|
+
expect(result).toEqual(new Box())
|
|
466
|
+
})
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
describe('Box.Expand', () => {
|
|
470
|
+
it('creates expanded box from two boxes', () => {
|
|
471
|
+
const boxA = new Box(10, 20, 100, 200)
|
|
472
|
+
const boxB = new Box(5, 15, 120, 240)
|
|
473
|
+
const result = Box.Expand(boxA, boxB)
|
|
474
|
+
expect(result).toEqual(new Box(5, 15, 120, 240))
|
|
475
|
+
})
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
describe('Box.ExpandBy', () => {
|
|
479
|
+
it('creates expanded box by amount', () => {
|
|
480
|
+
const result = Box.ExpandBy(box, 10)
|
|
481
|
+
expect(result).toEqual(new Box(0, 10, 120, 220))
|
|
482
|
+
})
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
describe('Box.Collides', () => {
|
|
486
|
+
it('returns true when boxes collide', () => {
|
|
487
|
+
const boxA = new Box(0, 0, 50, 50)
|
|
488
|
+
const boxB = new Box(25, 25, 50, 50)
|
|
489
|
+
expect(Box.Collides(boxA, boxB)).toBe(true)
|
|
490
|
+
})
|
|
491
|
+
|
|
492
|
+
it('returns false when boxes do not collide', () => {
|
|
493
|
+
const boxA = new Box(0, 0, 50, 50)
|
|
494
|
+
const boxB = new Box(100, 100, 50, 50)
|
|
495
|
+
expect(Box.Collides(boxA, boxB)).toBe(false)
|
|
496
|
+
})
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
describe('Box.Contains', () => {
|
|
500
|
+
it('returns true when first box contains second', () => {
|
|
501
|
+
const boxA = new Box(0, 0, 100, 100)
|
|
502
|
+
const boxB = new Box(10, 10, 50, 50)
|
|
503
|
+
expect(Box.Contains(boxA, boxB)).toBe(true)
|
|
504
|
+
})
|
|
505
|
+
|
|
506
|
+
it('returns false when first box does not contain second', () => {
|
|
507
|
+
const boxA = new Box(0, 0, 50, 50)
|
|
508
|
+
const boxB = new Box(10, 10, 100, 100)
|
|
509
|
+
expect(Box.Contains(boxA, boxB)).toBe(false)
|
|
510
|
+
})
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
describe('Box.Includes', () => {
|
|
514
|
+
it('returns true when boxes collide or contain', () => {
|
|
515
|
+
const boxA = new Box(0, 0, 50, 50)
|
|
516
|
+
const boxB = new Box(25, 25, 50, 50) // colliding
|
|
517
|
+
const boxC = new Box(10, 10, 20, 20) // contained
|
|
518
|
+
expect(Box.Includes(boxA, boxB)).toBe(true)
|
|
519
|
+
expect(Box.Includes(boxA, boxC)).toBe(true)
|
|
520
|
+
})
|
|
521
|
+
|
|
522
|
+
it('returns false when boxes do not interact', () => {
|
|
523
|
+
const boxA = new Box(0, 0, 50, 50)
|
|
524
|
+
const boxB = new Box(100, 100, 50, 50)
|
|
525
|
+
expect(Box.Includes(boxA, boxB)).toBe(false)
|
|
526
|
+
})
|
|
527
|
+
})
|
|
528
|
+
|
|
529
|
+
describe('Box.ContainsPoint', () => {
|
|
530
|
+
it('returns true when point is inside box', () => {
|
|
531
|
+
const testBox = new Box(0, 0, 100, 100)
|
|
532
|
+
const point = new Vec(50, 50)
|
|
533
|
+
expect(Box.ContainsPoint(testBox, point)).toBe(true)
|
|
534
|
+
})
|
|
535
|
+
|
|
536
|
+
it('returns false when point is outside box', () => {
|
|
537
|
+
const testBox = new Box(0, 0, 100, 100)
|
|
538
|
+
const point = new Vec(150, 150)
|
|
539
|
+
expect(Box.ContainsPoint(testBox, point)).toBe(false)
|
|
540
|
+
})
|
|
541
|
+
|
|
542
|
+
it('respects margin parameter', () => {
|
|
543
|
+
const testBox = new Box(0, 0, 100, 100)
|
|
544
|
+
const point = new Vec(-5, -5)
|
|
545
|
+
expect(Box.ContainsPoint(testBox, point)).toBe(false)
|
|
546
|
+
expect(Box.ContainsPoint(testBox, point, 10)).toBe(true)
|
|
547
|
+
})
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
describe('Box.Common', () => {
|
|
551
|
+
it('creates bounding box of multiple boxes', () => {
|
|
552
|
+
const boxes = [new Box(0, 0, 50, 50), new Box(75, 75, 50, 50), new Box(25, 25, 50, 50)]
|
|
553
|
+
const result = Box.Common(boxes)
|
|
554
|
+
expect(result).toEqual(new Box(0, 0, 125, 125))
|
|
555
|
+
})
|
|
556
|
+
})
|
|
557
|
+
|
|
558
|
+
describe('Box.Sides', () => {
|
|
559
|
+
it('returns sides as corner pairs', () => {
|
|
560
|
+
const testBox = new Box(0, 0, 100, 100)
|
|
561
|
+
const sides = Box.Sides(testBox)
|
|
562
|
+
expect(sides).toHaveLength(4)
|
|
563
|
+
expect(sides[0]).toEqual([new Vec(0, 0), new Vec(100, 0)])
|
|
564
|
+
})
|
|
565
|
+
})
|
|
566
|
+
|
|
567
|
+
describe('Box.Resize', () => {
|
|
568
|
+
it('resizes box and returns scaling info', () => {
|
|
569
|
+
const testBox = new Box(0, 0, 100, 100)
|
|
570
|
+
const result = Box.Resize(testBox, 'bottom_right', 50, 50)
|
|
571
|
+
expect(result.box).toEqual(new Box(0, 0, 150, 150))
|
|
572
|
+
expect(result.scaleX).toBe(1.5)
|
|
573
|
+
expect(result.scaleY).toBe(1.5)
|
|
574
|
+
})
|
|
575
|
+
|
|
576
|
+
it('handles aspect ratio locking', () => {
|
|
577
|
+
const testBox = new Box(0, 0, 100, 100)
|
|
578
|
+
const result = Box.Resize(testBox, 'bottom_right', 50, 25, true)
|
|
579
|
+
expect(result.box.width).toBeCloseTo(result.box.height) // maintains aspect ratio
|
|
580
|
+
})
|
|
581
|
+
})
|
|
582
|
+
|
|
583
|
+
describe('Box.Equals', () => {
|
|
584
|
+
it('returns true for equal boxes', () => {
|
|
585
|
+
const boxA = new Box(10, 20, 100, 200)
|
|
586
|
+
const boxB = new Box(10, 20, 100, 200)
|
|
587
|
+
expect(Box.Equals(boxA, boxB)).toBe(true)
|
|
588
|
+
})
|
|
589
|
+
|
|
590
|
+
it('returns false for different boxes', () => {
|
|
591
|
+
const boxA = new Box(10, 20, 100, 200)
|
|
592
|
+
const boxB = new Box(10, 20, 100, 201)
|
|
593
|
+
expect(Box.Equals(boxA, boxB)).toBe(false)
|
|
594
|
+
})
|
|
595
|
+
})
|
|
596
|
+
|
|
597
|
+
describe('Box.ZeroFix', () => {
|
|
598
|
+
it('creates new box with minimum size of 1', () => {
|
|
599
|
+
const zeroBox = new Box(0, 0, 0, 0)
|
|
600
|
+
const result = Box.ZeroFix(zeroBox)
|
|
601
|
+
expect(result).toEqual(new Box(0, 0, 1, 1))
|
|
602
|
+
expect(result).not.toBe(zeroBox) // different object
|
|
603
|
+
})
|
|
23
604
|
})
|
|
24
605
|
})
|