pixi-watchface-engine 0.1.8 → 0.2.0
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/API.md +29 -0
- package/dist/elements/TextElement.d.ts +36 -2
- package/dist/elements/TextElement.d.ts.map +1 -1
- package/dist/geometry/DisplayGeometry.d.ts +46 -0
- package/dist/geometry/DisplayGeometry.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +356 -15
- package/package.json +2 -1
package/API.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
5. [Plugins](#plugins)
|
|
10
10
|
6. [Events](#events)
|
|
11
11
|
7. [Types](#types)
|
|
12
|
+
8. [Display Geometry](#display-geometry)
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
@@ -734,6 +735,34 @@ interface Bounds {
|
|
|
734
735
|
|
|
735
736
|
---
|
|
736
737
|
|
|
738
|
+
## Display Geometry
|
|
739
|
+
|
|
740
|
+
Display geometry describes the face's logical shape and dimensions separately
|
|
741
|
+
from the editor's pixel dimensions. The geometry helpers are device-independent;
|
|
742
|
+
they accept circular and rectangular profiles without inferring a shape.
|
|
743
|
+
|
|
744
|
+
```typescript
|
|
745
|
+
const geometry = { shape: 'rectangle', width: 448, height: 486 } as const;
|
|
746
|
+
const fitted = fitDisplayGeometry(geometry, {
|
|
747
|
+
x: 0, y: 0, width: 600, height: 600, // editor bounds, not logical face size
|
|
748
|
+
});
|
|
749
|
+
const editorPoint = displayToViewportPoint(
|
|
750
|
+
{ x: 224, y: 243 }, geometry, fitted,
|
|
751
|
+
);
|
|
752
|
+
const hit = isPointInDisplay({ x: 0, y: 0 }, geometry); // true for rectangles
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
`fitDisplayGeometry` centers the logical display in editor bounds and uses one
|
|
756
|
+
uniform scale. `displayToViewportPoint` and `viewportToDisplayPoint` convert
|
|
757
|
+
coordinates while preserving either the default `top-left` or `center` origin.
|
|
758
|
+
`isPointInDisplay` uses rectangular bounds or the circular visible boundary.
|
|
759
|
+
`createDisplayMask` creates a Pixi `Graphics` mask for the same shape;
|
|
760
|
+
`applyDisplayMask` attaches one to a container and returns it for cleanup.
|
|
761
|
+
Circular profiles must have equal positive width and height. Invalid dimensions
|
|
762
|
+
and unknown shapes throw instead of silently selecting a default.
|
|
763
|
+
|
|
764
|
+
---
|
|
765
|
+
|
|
737
766
|
## Complete Example
|
|
738
767
|
|
|
739
768
|
```typescript
|
|
@@ -7,17 +7,34 @@ export interface TextElementStyle {
|
|
|
7
7
|
fontWeight?: TextStyleFontWeight;
|
|
8
8
|
align?: TextStyleAlign;
|
|
9
9
|
color?: number;
|
|
10
|
+
lineHeight?: number | null;
|
|
11
|
+
letterSpacing?: number;
|
|
12
|
+
boxWidth?: number | null;
|
|
13
|
+
breakWords?: boolean;
|
|
14
|
+
textTransform?: TextTransform;
|
|
15
|
+
maxLines?: number | null;
|
|
16
|
+
truncationCharacter?: string;
|
|
10
17
|
}
|
|
11
18
|
type TextStyleAlign = 'left' | 'center' | 'right';
|
|
19
|
+
type TextTransform = 'none' | 'uppercase' | 'lowercase' | 'capitalize';
|
|
12
20
|
export declare class TextElement extends BaseElement {
|
|
13
21
|
private pixiText;
|
|
14
22
|
private charSprites;
|
|
23
|
+
private boxProxy;
|
|
24
|
+
private _boxWidth;
|
|
25
|
+
private _boxHeight;
|
|
15
26
|
private _text;
|
|
16
27
|
private _fontFamily;
|
|
17
28
|
private _fontSize;
|
|
18
29
|
private _fontWeight;
|
|
19
30
|
private _align;
|
|
20
31
|
private _color;
|
|
32
|
+
private _lineHeight;
|
|
33
|
+
private _letterSpacing;
|
|
34
|
+
private _breakWords;
|
|
35
|
+
private _textTransform;
|
|
36
|
+
private _maxLines;
|
|
37
|
+
private _truncationCharacter;
|
|
21
38
|
private _arcPath;
|
|
22
39
|
constructor(text: string, x: number, y: number, style?: TextElementStyle);
|
|
23
40
|
get arcPath(): ArcPath | null;
|
|
@@ -34,13 +51,30 @@ export declare class TextElement extends BaseElement {
|
|
|
34
51
|
set align(value: TextStyleAlign);
|
|
35
52
|
get color(): number;
|
|
36
53
|
set color(value: number);
|
|
54
|
+
get lineHeight(): number | null;
|
|
55
|
+
set lineHeight(value: number | null);
|
|
56
|
+
get letterSpacing(): number;
|
|
57
|
+
set letterSpacing(value: number);
|
|
58
|
+
get boxWidth(): number | null;
|
|
59
|
+
set boxWidth(value: number | null);
|
|
60
|
+
get breakWords(): boolean;
|
|
61
|
+
set breakWords(value: boolean);
|
|
62
|
+
get textTransform(): TextTransform;
|
|
63
|
+
set textTransform(value: TextTransform);
|
|
64
|
+
get maxLines(): number | null;
|
|
65
|
+
set maxLines(value: number | null);
|
|
66
|
+
get truncationCharacter(): string;
|
|
67
|
+
set truncationCharacter(value: string);
|
|
37
68
|
get width(): number;
|
|
38
|
-
set width(
|
|
69
|
+
set width(value: number);
|
|
39
70
|
get height(): number;
|
|
40
|
-
set height(
|
|
71
|
+
set height(value: number);
|
|
41
72
|
protected redraw(): void;
|
|
42
73
|
private drawNormalText;
|
|
43
74
|
private drawArcText;
|
|
75
|
+
private displayText;
|
|
76
|
+
private transformText;
|
|
77
|
+
private makeTextStyle;
|
|
44
78
|
private makeText;
|
|
45
79
|
private applyStyleToAll;
|
|
46
80
|
toJSON(): SerializedElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextElement.d.ts","sourceRoot":"","sources":["../../src/elements/TextElement.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"TextElement.d.ts","sourceRoot":"","sources":["../../src/elements/TextElement.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Container, Graphics } from 'pixi.js';
|
|
2
|
+
import type { Bounds, CoordinateOrigin } from '../types.ts';
|
|
3
|
+
/** Display shape supported by watch-face geometry. */
|
|
4
|
+
export type DisplayShape = 'circle' | 'rectangle';
|
|
5
|
+
/** Logical display dimensions, independent of an editor's pixel dimensions. */
|
|
6
|
+
export interface DisplayGeometry {
|
|
7
|
+
shape: DisplayShape;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}
|
|
11
|
+
export interface DisplayPoint {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
}
|
|
15
|
+
/** A display's fitted rectangle in the editor, plus its uniform scale. */
|
|
16
|
+
export interface DisplayViewport extends Bounds {
|
|
17
|
+
scale: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Check and narrow geometry received from saved data or device integrations.
|
|
21
|
+
* Circular displays use a square logical coordinate space.
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateDisplayGeometry(value: unknown): asserts value is DisplayGeometry;
|
|
24
|
+
/** Return logical display bounds for the requested coordinate origin. */
|
|
25
|
+
export declare function getDisplayBounds(geometry: DisplayGeometry, coordinateOrigin?: CoordinateOrigin): Bounds;
|
|
26
|
+
/**
|
|
27
|
+
* Fit a logical display inside an editor-space rectangle without distortion.
|
|
28
|
+
* The returned bounds are centered in the editor rectangle; the editor
|
|
29
|
+
* rectangle is never interpreted as the face's logical dimensions.
|
|
30
|
+
*/
|
|
31
|
+
export declare function fitDisplayGeometry(geometry: DisplayGeometry, editorBounds: Bounds): DisplayViewport;
|
|
32
|
+
/** Convert a logical face coordinate to the fitted editor viewport. */
|
|
33
|
+
export declare function displayToViewportPoint(point: DisplayPoint, geometry: DisplayGeometry, viewport: DisplayViewport, coordinateOrigin?: CoordinateOrigin): DisplayPoint;
|
|
34
|
+
/** Convert a fitted editor-space point to logical face coordinates. */
|
|
35
|
+
export declare function viewportToDisplayPoint(point: DisplayPoint, geometry: DisplayGeometry, viewport: DisplayViewport, coordinateOrigin?: CoordinateOrigin): DisplayPoint;
|
|
36
|
+
/** Test whether a logical coordinate falls inside the visible display shape. */
|
|
37
|
+
export declare function isPointInDisplay(point: DisplayPoint, geometry: DisplayGeometry, coordinateOrigin?: CoordinateOrigin): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Create a Pixi mask matching the visible display shape. Add the returned
|
|
40
|
+
* Graphics to the masked container (or a sibling in the same coordinate
|
|
41
|
+
* space) and assign it as that container's mask.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createDisplayMask(geometry: DisplayGeometry, coordinateOrigin?: CoordinateOrigin): Graphics;
|
|
44
|
+
/** Attach a shape-aware Pixi mask and return it for later removal/destruction. */
|
|
45
|
+
export declare function applyDisplayMask(target: Container, geometry: DisplayGeometry, coordinateOrigin?: CoordinateOrigin): Graphics;
|
|
46
|
+
//# sourceMappingURL=DisplayGeometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DisplayGeometry.d.ts","sourceRoot":"","sources":["../../src/geometry/DisplayGeometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE5D,sDAAsD;AACtD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElD,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,0EAA0E;AAC1E,MAAM,WAAW,eAAgB,SAAQ,MAAM;IAC7C,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,eAAe,CAkBxF;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EACzB,gBAAgB,GAAE,gBAA6B,GAC9C,MAAM,CASR;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,eAAe,EACzB,YAAY,EAAE,MAAM,GACnB,eAAe,CAcjB;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,eAAe,EACzB,gBAAgB,GAAE,gBAA6B,GAC9C,YAAY,CASd;AAED,uEAAuE;AACvE,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,eAAe,EACzB,gBAAgB,GAAE,gBAA6B,GAC9C,YAAY,CASd;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,eAAe,EACzB,gBAAgB,GAAE,gBAA6B,GAC9C,OAAO,CAcT;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,eAAe,EACzB,gBAAgB,GAAE,gBAA6B,GAC9C,QAAQ,CAUV;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,eAAe,EACzB,gBAAgB,GAAE,gBAA6B,GAC9C,QAAQ,CAKV"}
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export { ZOrderManager } from "./managers/ZOrderManager.ts";
|
|
|
25
25
|
export { SelectionManager } from "./selection/SelectionManager.ts";
|
|
26
26
|
export { SerializationManager } from "./managers/SerializationManager.ts";
|
|
27
27
|
export type { FillDirection, ShapeType, LineCap, ArcPath, ElementType, CoordinateOrigin, SerializedElement, WatchfaceState, UndoableAction, HandleConfig, Bounds, } from "./types.ts";
|
|
28
|
+
export { applyDisplayMask, createDisplayMask, displayToViewportPoint, fitDisplayGeometry, getDisplayBounds, isPointInDisplay, validateDisplayGeometry, viewportToDisplayPoint, } from "./geometry/DisplayGeometry.ts";
|
|
29
|
+
export type { DisplayGeometry, DisplayPoint, DisplayShape, DisplayViewport, } from "./geometry/DisplayGeometry.ts";
|
|
28
30
|
export { EventBus } from "./EventBus.ts";
|
|
29
31
|
export type { EngineEventMap } from "./EventBus.ts";
|
|
30
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAGhE,YAAY,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,YAAY,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAGvF,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAG1E,YAAY,EACV,aAAa,EACb,SAAS,EACT,OAAO,EACP,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,MAAM,GACP,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAGhE,YAAY,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,YAAY,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAGvF,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAG1E,YAAY,EACV,aAAa,EACb,SAAS,EACT,OAAO,EACP,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,MAAM,GACP,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -30734,6 +30734,7 @@ init_textureFrom();
|
|
|
30734
30734
|
init_Container();
|
|
30735
30735
|
init_Graphics();
|
|
30736
30736
|
init_Sprite();
|
|
30737
|
+
init_CanvasTextMetrics();
|
|
30737
30738
|
init_TextStyle();
|
|
30738
30739
|
init_Ticker();
|
|
30739
30740
|
init_eventemitter3();
|
|
@@ -31101,12 +31102,21 @@ class BaseElement {
|
|
|
31101
31102
|
class TextElement extends BaseElement {
|
|
31102
31103
|
pixiText;
|
|
31103
31104
|
charSprites = [];
|
|
31105
|
+
boxProxy;
|
|
31106
|
+
_boxWidth = null;
|
|
31107
|
+
_boxHeight = null;
|
|
31104
31108
|
_text;
|
|
31105
31109
|
_fontFamily;
|
|
31106
31110
|
_fontSize;
|
|
31107
31111
|
_fontWeight;
|
|
31108
31112
|
_align;
|
|
31109
31113
|
_color;
|
|
31114
|
+
_lineHeight;
|
|
31115
|
+
_letterSpacing;
|
|
31116
|
+
_breakWords;
|
|
31117
|
+
_textTransform;
|
|
31118
|
+
_maxLines;
|
|
31119
|
+
_truncationCharacter;
|
|
31110
31120
|
_arcPath = null;
|
|
31111
31121
|
constructor(text, x2, y2, style) {
|
|
31112
31122
|
super("text");
|
|
@@ -31116,10 +31126,20 @@ class TextElement extends BaseElement {
|
|
|
31116
31126
|
this._fontWeight = style?.fontWeight ?? "normal";
|
|
31117
31127
|
this._align = style?.align ?? "left";
|
|
31118
31128
|
this._color = style?.color ?? 16777215;
|
|
31119
|
-
this.
|
|
31129
|
+
this._lineHeight = style?.lineHeight ?? null;
|
|
31130
|
+
this._letterSpacing = style?.letterSpacing ?? 0;
|
|
31131
|
+
this._boxWidth = style?.boxWidth ?? null;
|
|
31132
|
+
this._breakWords = style?.breakWords ?? false;
|
|
31133
|
+
this._textTransform = style?.textTransform ?? "none";
|
|
31134
|
+
this._maxLines = style?.maxLines ?? null;
|
|
31135
|
+
this._truncationCharacter = style?.truncationCharacter ?? "…";
|
|
31136
|
+
this.pixiText = this.makeText(this.displayText(this._text));
|
|
31120
31137
|
this.container.addChild(this.pixiText);
|
|
31138
|
+
this.boxProxy = new Graphics;
|
|
31139
|
+
this.container.addChild(this.boxProxy);
|
|
31121
31140
|
this.x = x2;
|
|
31122
31141
|
this.y = y2;
|
|
31142
|
+
this.redraw();
|
|
31123
31143
|
}
|
|
31124
31144
|
get arcPath() {
|
|
31125
31145
|
return this._arcPath;
|
|
@@ -31190,6 +31210,7 @@ class TextElement extends BaseElement {
|
|
|
31190
31210
|
this._align = value;
|
|
31191
31211
|
if (this.pixiText)
|
|
31192
31212
|
this.pixiText.style.align = value;
|
|
31213
|
+
this.redraw();
|
|
31193
31214
|
this.emitChange("align", old, value);
|
|
31194
31215
|
}
|
|
31195
31216
|
get color() {
|
|
@@ -31205,18 +31226,124 @@ class TextElement extends BaseElement {
|
|
|
31205
31226
|
});
|
|
31206
31227
|
this.emitChange("color", old, value);
|
|
31207
31228
|
}
|
|
31229
|
+
get lineHeight() {
|
|
31230
|
+
return this._lineHeight;
|
|
31231
|
+
}
|
|
31232
|
+
set lineHeight(value) {
|
|
31233
|
+
const old = this._lineHeight;
|
|
31234
|
+
if (old === value)
|
|
31235
|
+
return;
|
|
31236
|
+
this._lineHeight = value;
|
|
31237
|
+
this.applyStyleToAll((s2) => {
|
|
31238
|
+
if (value != null)
|
|
31239
|
+
s2.lineHeight = value;
|
|
31240
|
+
});
|
|
31241
|
+
this.redraw();
|
|
31242
|
+
this.emitChange("lineHeight", old, value);
|
|
31243
|
+
}
|
|
31244
|
+
get letterSpacing() {
|
|
31245
|
+
return this._letterSpacing;
|
|
31246
|
+
}
|
|
31247
|
+
set letterSpacing(value) {
|
|
31248
|
+
const old = this._letterSpacing;
|
|
31249
|
+
if (old === value)
|
|
31250
|
+
return;
|
|
31251
|
+
this._letterSpacing = value;
|
|
31252
|
+
this.applyStyleToAll((s2) => {
|
|
31253
|
+
s2.letterSpacing = value;
|
|
31254
|
+
});
|
|
31255
|
+
this.emitChange("letterSpacing", old, value);
|
|
31256
|
+
}
|
|
31257
|
+
get boxWidth() {
|
|
31258
|
+
return this._boxWidth;
|
|
31259
|
+
}
|
|
31260
|
+
set boxWidth(value) {
|
|
31261
|
+
const old = this._boxWidth;
|
|
31262
|
+
if (old === value)
|
|
31263
|
+
return;
|
|
31264
|
+
this._boxWidth = value;
|
|
31265
|
+
this.applyStyleToAll((s2) => {
|
|
31266
|
+
s2.wordWrap = value != null;
|
|
31267
|
+
s2.wordWrapWidth = value ?? 100;
|
|
31268
|
+
});
|
|
31269
|
+
this.emitChange("boxWidth", old, value);
|
|
31270
|
+
}
|
|
31271
|
+
get breakWords() {
|
|
31272
|
+
return this._breakWords;
|
|
31273
|
+
}
|
|
31274
|
+
set breakWords(value) {
|
|
31275
|
+
const old = this._breakWords;
|
|
31276
|
+
if (old === value)
|
|
31277
|
+
return;
|
|
31278
|
+
this._breakWords = value;
|
|
31279
|
+
this.applyStyleToAll((s2) => {
|
|
31280
|
+
s2.breakWords = value;
|
|
31281
|
+
});
|
|
31282
|
+
this.emitChange("breakWords", old, value);
|
|
31283
|
+
}
|
|
31284
|
+
get textTransform() {
|
|
31285
|
+
return this._textTransform;
|
|
31286
|
+
}
|
|
31287
|
+
set textTransform(value) {
|
|
31288
|
+
const old = this._textTransform;
|
|
31289
|
+
if (old === value)
|
|
31290
|
+
return;
|
|
31291
|
+
this._textTransform = value;
|
|
31292
|
+
this.redraw();
|
|
31293
|
+
this.emitChange("textTransform", old, value);
|
|
31294
|
+
}
|
|
31295
|
+
get maxLines() {
|
|
31296
|
+
return this._maxLines;
|
|
31297
|
+
}
|
|
31298
|
+
set maxLines(value) {
|
|
31299
|
+
const old = this._maxLines;
|
|
31300
|
+
if (old === value)
|
|
31301
|
+
return;
|
|
31302
|
+
this._maxLines = value;
|
|
31303
|
+
this.redraw();
|
|
31304
|
+
this.emitChange("maxLines", old, value);
|
|
31305
|
+
}
|
|
31306
|
+
get truncationCharacter() {
|
|
31307
|
+
return this._truncationCharacter;
|
|
31308
|
+
}
|
|
31309
|
+
set truncationCharacter(value) {
|
|
31310
|
+
const old = this._truncationCharacter;
|
|
31311
|
+
if (old === value)
|
|
31312
|
+
return;
|
|
31313
|
+
this._truncationCharacter = value;
|
|
31314
|
+
this.redraw();
|
|
31315
|
+
this.emitChange("truncationCharacter", old, value);
|
|
31316
|
+
}
|
|
31208
31317
|
get width() {
|
|
31209
31318
|
if (this._arcPath)
|
|
31210
31319
|
return this._arcPath.radius * 2;
|
|
31211
|
-
return this.pixiText?.width ?? 0;
|
|
31320
|
+
return this._boxWidth ?? this.pixiText?.width ?? 0;
|
|
31321
|
+
}
|
|
31322
|
+
set width(value) {
|
|
31323
|
+
if (this._arcPath)
|
|
31324
|
+
return;
|
|
31325
|
+
const old = this.width;
|
|
31326
|
+
if (old === value)
|
|
31327
|
+
return;
|
|
31328
|
+
this._boxWidth = value;
|
|
31329
|
+
this.redraw();
|
|
31330
|
+
this.emitChange("width", old, value);
|
|
31212
31331
|
}
|
|
31213
|
-
set width(_value) {}
|
|
31214
31332
|
get height() {
|
|
31215
31333
|
if (this._arcPath)
|
|
31216
31334
|
return this._arcPath.radius * 2;
|
|
31217
|
-
return this.pixiText?.height ?? 0;
|
|
31335
|
+
return this._boxHeight ?? this.pixiText?.height ?? 0;
|
|
31336
|
+
}
|
|
31337
|
+
set height(value) {
|
|
31338
|
+
if (this._arcPath)
|
|
31339
|
+
return;
|
|
31340
|
+
const old = this.height;
|
|
31341
|
+
if (old === value)
|
|
31342
|
+
return;
|
|
31343
|
+
this._boxHeight = value;
|
|
31344
|
+
this.redraw();
|
|
31345
|
+
this.emitChange("height", old, value);
|
|
31218
31346
|
}
|
|
31219
|
-
set height(_value) {}
|
|
31220
31347
|
redraw() {
|
|
31221
31348
|
if (this._arcPath) {
|
|
31222
31349
|
this.drawArcText();
|
|
@@ -31231,15 +31358,25 @@ class TextElement extends BaseElement {
|
|
|
31231
31358
|
}
|
|
31232
31359
|
this.charSprites = [];
|
|
31233
31360
|
if (!this.pixiText) {
|
|
31234
|
-
this.pixiText = this.makeText(this._text);
|
|
31361
|
+
this.pixiText = this.makeText(this.displayText(this._text));
|
|
31235
31362
|
this.container.addChild(this.pixiText);
|
|
31236
31363
|
} else {
|
|
31237
|
-
this.pixiText.text = this._text;
|
|
31364
|
+
this.pixiText.text = this.displayText(this._text);
|
|
31238
31365
|
this.pixiText.visible = true;
|
|
31239
31366
|
}
|
|
31367
|
+
const text = this.pixiText;
|
|
31368
|
+
const bw = this._boxWidth ?? text.width;
|
|
31369
|
+
const bh = this._boxHeight ?? text.height;
|
|
31370
|
+
this.boxProxy.clear();
|
|
31371
|
+
this.boxProxy.rect(0, 0, bw, bh);
|
|
31372
|
+
this.boxProxy.fill({ color: 16777215, alpha: 0 });
|
|
31373
|
+
text.position.y = bh / 2;
|
|
31374
|
+
const tw = text.width;
|
|
31375
|
+
text.position.x = this._align === "left" ? tw / 2 : this._align === "right" ? bw - tw / 2 : bw / 2;
|
|
31240
31376
|
}
|
|
31241
31377
|
drawArcText() {
|
|
31242
31378
|
const arc = this._arcPath;
|
|
31379
|
+
this.boxProxy.clear();
|
|
31243
31380
|
if (this.pixiText) {
|
|
31244
31381
|
this.pixiText.visible = false;
|
|
31245
31382
|
}
|
|
@@ -31271,17 +31408,61 @@ class TextElement extends BaseElement {
|
|
|
31271
31408
|
angle += halfAngular * Math.sign(span);
|
|
31272
31409
|
}
|
|
31273
31410
|
}
|
|
31411
|
+
displayText(value) {
|
|
31412
|
+
const transformed = this.transformText(value);
|
|
31413
|
+
if (!this._maxLines || this._maxLines <= 0)
|
|
31414
|
+
return transformed;
|
|
31415
|
+
const style = this.makeTextStyle();
|
|
31416
|
+
const lines = CanvasTextMetrics.measureText(transformed, style).lines;
|
|
31417
|
+
const maxLines = Math.floor(this._maxLines);
|
|
31418
|
+
if (lines.length <= maxLines)
|
|
31419
|
+
return transformed;
|
|
31420
|
+
const visibleLines = lines.slice(0, maxLines);
|
|
31421
|
+
let lastLine = visibleLines[visibleLines.length - 1]?.replace(/\s+$/, "") ?? "";
|
|
31422
|
+
if (this._boxWidth != null) {
|
|
31423
|
+
while (lastLine && CanvasTextMetrics.measureText(`${lastLine}${this._truncationCharacter}`, style, undefined, false).width > this._boxWidth) {
|
|
31424
|
+
lastLine = lastLine.slice(0, -1);
|
|
31425
|
+
}
|
|
31426
|
+
}
|
|
31427
|
+
visibleLines[visibleLines.length - 1] = `${lastLine}${this._truncationCharacter}`;
|
|
31428
|
+
return visibleLines.join(`
|
|
31429
|
+
`);
|
|
31430
|
+
}
|
|
31431
|
+
transformText(value) {
|
|
31432
|
+
if (this._textTransform === "uppercase")
|
|
31433
|
+
return value.toUpperCase();
|
|
31434
|
+
if (this._textTransform === "lowercase")
|
|
31435
|
+
return value.toLowerCase();
|
|
31436
|
+
if (this._textTransform === "capitalize") {
|
|
31437
|
+
return value.replace(/\p{L}[\p{L}\p{M}'’-]*/gu, (word) => {
|
|
31438
|
+
const first = word[0];
|
|
31439
|
+
return first ? first.toUpperCase() + word.slice(1).toLowerCase() : word;
|
|
31440
|
+
});
|
|
31441
|
+
}
|
|
31442
|
+
return value;
|
|
31443
|
+
}
|
|
31444
|
+
makeTextStyle() {
|
|
31445
|
+
const style = new TextStyle({
|
|
31446
|
+
fontFamily: this._fontFamily,
|
|
31447
|
+
fontSize: this._fontSize,
|
|
31448
|
+
fontWeight: this._fontWeight,
|
|
31449
|
+
fill: this._color,
|
|
31450
|
+
align: this._align,
|
|
31451
|
+
letterSpacing: this._letterSpacing,
|
|
31452
|
+
wordWrap: this._boxWidth != null,
|
|
31453
|
+
wordWrapWidth: this._boxWidth ?? 100,
|
|
31454
|
+
breakWords: this._breakWords
|
|
31455
|
+
});
|
|
31456
|
+
if (this._lineHeight != null)
|
|
31457
|
+
style.lineHeight = this._lineHeight;
|
|
31458
|
+
return style;
|
|
31459
|
+
}
|
|
31274
31460
|
makeText(content) {
|
|
31461
|
+
const style = this.makeTextStyle();
|
|
31275
31462
|
return new Text({
|
|
31276
31463
|
text: content,
|
|
31277
31464
|
anchor: 0.5,
|
|
31278
|
-
style
|
|
31279
|
-
fontFamily: this._fontFamily,
|
|
31280
|
-
fontSize: this._fontSize,
|
|
31281
|
-
fontWeight: this._fontWeight,
|
|
31282
|
-
fill: this._color,
|
|
31283
|
-
align: this._align
|
|
31284
|
-
})
|
|
31465
|
+
style
|
|
31285
31466
|
});
|
|
31286
31467
|
}
|
|
31287
31468
|
applyStyleToAll(mutate) {
|
|
@@ -31299,6 +31480,13 @@ class TextElement extends BaseElement {
|
|
|
31299
31480
|
fontWeight: this._fontWeight,
|
|
31300
31481
|
align: this._align,
|
|
31301
31482
|
color: this._color,
|
|
31483
|
+
lineHeight: this._lineHeight,
|
|
31484
|
+
letterSpacing: this._letterSpacing,
|
|
31485
|
+
boxWidth: this._boxWidth,
|
|
31486
|
+
breakWords: this._breakWords,
|
|
31487
|
+
textTransform: this._textTransform,
|
|
31488
|
+
maxLines: this._maxLines,
|
|
31489
|
+
truncationCharacter: this._truncationCharacter,
|
|
31302
31490
|
arcPath: this._arcPath ?? undefined
|
|
31303
31491
|
};
|
|
31304
31492
|
}
|
|
@@ -31315,8 +31503,26 @@ class TextElement extends BaseElement {
|
|
|
31315
31503
|
this.align = data.align;
|
|
31316
31504
|
if (data.color !== undefined)
|
|
31317
31505
|
this.color = data.color;
|
|
31506
|
+
if (data.lineHeight !== undefined)
|
|
31507
|
+
this.lineHeight = data.lineHeight;
|
|
31508
|
+
if (data.letterSpacing !== undefined)
|
|
31509
|
+
this.letterSpacing = data.letterSpacing;
|
|
31510
|
+
if (data.boxWidth !== undefined)
|
|
31511
|
+
this.boxWidth = data.boxWidth;
|
|
31512
|
+
if (data.breakWords !== undefined)
|
|
31513
|
+
this.breakWords = data.breakWords;
|
|
31514
|
+
if (data.textTransform !== undefined)
|
|
31515
|
+
this.textTransform = data.textTransform;
|
|
31516
|
+
if (data.maxLines !== undefined)
|
|
31517
|
+
this.maxLines = data.maxLines;
|
|
31518
|
+
if (data.truncationCharacter !== undefined)
|
|
31519
|
+
this.truncationCharacter = data.truncationCharacter;
|
|
31318
31520
|
if ("arcPath" in data)
|
|
31319
31521
|
this.arcPath = data.arcPath ?? null;
|
|
31522
|
+
if (data.width !== undefined)
|
|
31523
|
+
this.width = data.width;
|
|
31524
|
+
if (data.height !== undefined)
|
|
31525
|
+
this.height = data.height;
|
|
31320
31526
|
this.x = data.x;
|
|
31321
31527
|
this.y = data.y;
|
|
31322
31528
|
this.rotation = data.rotation;
|
|
@@ -31331,10 +31537,21 @@ class TextElement extends BaseElement {
|
|
|
31331
31537
|
fontSize: data.fontSize,
|
|
31332
31538
|
fontWeight: data.fontWeight,
|
|
31333
31539
|
align: data.align,
|
|
31334
|
-
color: data.color
|
|
31540
|
+
color: data.color,
|
|
31541
|
+
lineHeight: data.lineHeight,
|
|
31542
|
+
letterSpacing: data.letterSpacing,
|
|
31543
|
+
boxWidth: data.boxWidth,
|
|
31544
|
+
breakWords: data.breakWords,
|
|
31545
|
+
textTransform: data.textTransform,
|
|
31546
|
+
maxLines: data.maxLines,
|
|
31547
|
+
truncationCharacter: data.truncationCharacter
|
|
31335
31548
|
});
|
|
31336
31549
|
if (data.arcPath)
|
|
31337
31550
|
el.arcPath = data.arcPath;
|
|
31551
|
+
if (data.width !== undefined)
|
|
31552
|
+
el.width = data.width;
|
|
31553
|
+
if (data.height !== undefined)
|
|
31554
|
+
el.height = data.height;
|
|
31338
31555
|
el.rotation = data.rotation;
|
|
31339
31556
|
el.zIndex = data.zIndex;
|
|
31340
31557
|
el.visible = data.visible;
|
|
@@ -34579,7 +34796,131 @@ class AlignmentGuidesPlugin {
|
|
|
34579
34796
|
this.graphics.destroy();
|
|
34580
34797
|
}
|
|
34581
34798
|
}
|
|
34799
|
+
// src/geometry/DisplayGeometry.ts
|
|
34800
|
+
function validateDisplayGeometry(value) {
|
|
34801
|
+
if (typeof value !== "object" || value === null) {
|
|
34802
|
+
throw new TypeError("Display geometry must be an object.");
|
|
34803
|
+
}
|
|
34804
|
+
const geometry = value;
|
|
34805
|
+
if (geometry.shape !== "circle" && geometry.shape !== "rectangle") {
|
|
34806
|
+
throw new TypeError(`Unsupported display shape: ${String(geometry.shape)}.`);
|
|
34807
|
+
}
|
|
34808
|
+
if (typeof geometry.width !== "number" || !Number.isFinite(geometry.width) || geometry.width <= 0) {
|
|
34809
|
+
throw new RangeError("Display geometry width must be a positive finite number.");
|
|
34810
|
+
}
|
|
34811
|
+
if (typeof geometry.height !== "number" || !Number.isFinite(geometry.height) || geometry.height <= 0) {
|
|
34812
|
+
throw new RangeError("Display geometry height must be a positive finite number.");
|
|
34813
|
+
}
|
|
34814
|
+
if (geometry.shape === "circle" && geometry.width !== geometry.height) {
|
|
34815
|
+
throw new RangeError("Circular display geometry must have equal width and height.");
|
|
34816
|
+
}
|
|
34817
|
+
}
|
|
34818
|
+
function getDisplayBounds(geometry, coordinateOrigin = "top-left") {
|
|
34819
|
+
validateDisplayGeometry(geometry);
|
|
34820
|
+
validateCoordinateOrigin(coordinateOrigin);
|
|
34821
|
+
return {
|
|
34822
|
+
x: coordinateOrigin === "center" ? -geometry.width / 2 : 0,
|
|
34823
|
+
y: coordinateOrigin === "center" ? -geometry.height / 2 : 0,
|
|
34824
|
+
width: geometry.width,
|
|
34825
|
+
height: geometry.height
|
|
34826
|
+
};
|
|
34827
|
+
}
|
|
34828
|
+
function fitDisplayGeometry(geometry, editorBounds) {
|
|
34829
|
+
validateDisplayGeometry(geometry);
|
|
34830
|
+
validateBounds(editorBounds, "Editor bounds");
|
|
34831
|
+
const scale = Math.min(editorBounds.width / geometry.width, editorBounds.height / geometry.height);
|
|
34832
|
+
const width = geometry.width * scale;
|
|
34833
|
+
const height = geometry.height * scale;
|
|
34834
|
+
return {
|
|
34835
|
+
x: editorBounds.x + (editorBounds.width - width) / 2,
|
|
34836
|
+
y: editorBounds.y + (editorBounds.height - height) / 2,
|
|
34837
|
+
width,
|
|
34838
|
+
height,
|
|
34839
|
+
scale
|
|
34840
|
+
};
|
|
34841
|
+
}
|
|
34842
|
+
function displayToViewportPoint(point, geometry, viewport, coordinateOrigin = "top-left") {
|
|
34843
|
+
validateDisplayGeometry(geometry);
|
|
34844
|
+
validateViewport(viewport);
|
|
34845
|
+
validatePoint(point, "Display point");
|
|
34846
|
+
const bounds = getDisplayBounds(geometry, coordinateOrigin);
|
|
34847
|
+
return {
|
|
34848
|
+
x: viewport.x + (point.x - bounds.x) * viewport.scale,
|
|
34849
|
+
y: viewport.y + (point.y - bounds.y) * viewport.scale
|
|
34850
|
+
};
|
|
34851
|
+
}
|
|
34852
|
+
function viewportToDisplayPoint(point, geometry, viewport, coordinateOrigin = "top-left") {
|
|
34853
|
+
validateDisplayGeometry(geometry);
|
|
34854
|
+
validateViewport(viewport);
|
|
34855
|
+
validatePoint(point, "Viewport point");
|
|
34856
|
+
const bounds = getDisplayBounds(geometry, coordinateOrigin);
|
|
34857
|
+
return {
|
|
34858
|
+
x: bounds.x + (point.x - viewport.x) / viewport.scale,
|
|
34859
|
+
y: bounds.y + (point.y - viewport.y) / viewport.scale
|
|
34860
|
+
};
|
|
34861
|
+
}
|
|
34862
|
+
function isPointInDisplay(point, geometry, coordinateOrigin = "top-left") {
|
|
34863
|
+
validateDisplayGeometry(geometry);
|
|
34864
|
+
validatePoint(point, "Display point");
|
|
34865
|
+
const bounds = getDisplayBounds(geometry, coordinateOrigin);
|
|
34866
|
+
if (geometry.shape === "rectangle") {
|
|
34867
|
+
return point.x >= bounds.x && point.x <= bounds.x + bounds.width && point.y >= bounds.y && point.y <= bounds.y + bounds.height;
|
|
34868
|
+
}
|
|
34869
|
+
const centerX = bounds.x + bounds.width / 2;
|
|
34870
|
+
const centerY = bounds.y + bounds.height / 2;
|
|
34871
|
+
const radius = geometry.width / 2;
|
|
34872
|
+
return (point.x - centerX) ** 2 + (point.y - centerY) ** 2 <= radius ** 2;
|
|
34873
|
+
}
|
|
34874
|
+
function createDisplayMask(geometry, coordinateOrigin = "top-left") {
|
|
34875
|
+
const bounds = getDisplayBounds(geometry, coordinateOrigin);
|
|
34876
|
+
const mask = new Graphics;
|
|
34877
|
+
if (geometry.shape === "circle") {
|
|
34878
|
+
mask.circle(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2, bounds.width / 2);
|
|
34879
|
+
} else {
|
|
34880
|
+
mask.rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
|
34881
|
+
}
|
|
34882
|
+
mask.fill({ color: 16777215 });
|
|
34883
|
+
return mask;
|
|
34884
|
+
}
|
|
34885
|
+
function applyDisplayMask(target, geometry, coordinateOrigin = "top-left") {
|
|
34886
|
+
const mask = createDisplayMask(geometry, coordinateOrigin);
|
|
34887
|
+
target.addChild(mask);
|
|
34888
|
+
target.mask = mask;
|
|
34889
|
+
return mask;
|
|
34890
|
+
}
|
|
34891
|
+
function validateCoordinateOrigin(value) {
|
|
34892
|
+
if (value !== "top-left" && value !== "center") {
|
|
34893
|
+
throw new TypeError(`Unsupported coordinate origin: ${String(value)}.`);
|
|
34894
|
+
}
|
|
34895
|
+
}
|
|
34896
|
+
function validatePoint(point, label) {
|
|
34897
|
+
if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) {
|
|
34898
|
+
throw new RangeError(`${label} coordinates must be finite numbers.`);
|
|
34899
|
+
}
|
|
34900
|
+
}
|
|
34901
|
+
function validateBounds(bounds, label) {
|
|
34902
|
+
if (!Number.isFinite(bounds.x) || !Number.isFinite(bounds.y)) {
|
|
34903
|
+
throw new RangeError(`${label} position must use finite numbers.`);
|
|
34904
|
+
}
|
|
34905
|
+
if (!Number.isFinite(bounds.width) || bounds.width <= 0 || !Number.isFinite(bounds.height) || bounds.height <= 0) {
|
|
34906
|
+
throw new RangeError(`${label} width and height must be positive finite numbers.`);
|
|
34907
|
+
}
|
|
34908
|
+
}
|
|
34909
|
+
function validateViewport(viewport) {
|
|
34910
|
+
validateBounds(viewport, "Viewport bounds");
|
|
34911
|
+
if (!Number.isFinite(viewport.scale) || viewport.scale <= 0) {
|
|
34912
|
+
throw new RangeError("Viewport scale must be a positive finite number.");
|
|
34913
|
+
}
|
|
34914
|
+
}
|
|
34582
34915
|
export {
|
|
34916
|
+
viewportToDisplayPoint,
|
|
34917
|
+
validateDisplayGeometry,
|
|
34918
|
+
isPointInDisplay,
|
|
34919
|
+
getDisplayBounds,
|
|
34920
|
+
fitDisplayGeometry,
|
|
34921
|
+
displayToViewportPoint,
|
|
34922
|
+
createDisplayMask,
|
|
34923
|
+
applyDisplayMask,
|
|
34583
34924
|
ZOrderManager,
|
|
34584
34925
|
WatchfaceEngine,
|
|
34585
34926
|
ViewportPlugin,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixi-watchface-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A PixiJS v8 watchface editor engine with visual editor, plugin system, and intuitive API",
|
|
5
5
|
"author": "Eric Schmar (ericschmar@gmail.com)",
|
|
6
6
|
"type": "module",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"LICENSE"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
+
"test": "bun test",
|
|
23
24
|
"typecheck": "tsc --noEmit",
|
|
24
25
|
"build": "bun build src/index.ts --outdir dist --target browser && tsc --emitDeclarationOnly --declaration",
|
|
25
26
|
"prepublishOnly": "bun run typecheck && bun run build"
|