canvasengine 2.0.0-beta.42 → 2.0.0-beta.43

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.
Files changed (49) hide show
  1. package/dist/{DebugRenderer-BosXI2Pd.js → DebugRenderer-K2IZBznP.js} +2 -2
  2. package/dist/{DebugRenderer-BosXI2Pd.js.map → DebugRenderer-K2IZBznP.js.map} +1 -1
  3. package/dist/components/Button.d.ts +3 -0
  4. package/dist/components/Button.d.ts.map +1 -1
  5. package/dist/components/DOMElement.d.ts.map +1 -1
  6. package/dist/components/Graphic.d.ts +1 -1
  7. package/dist/components/Graphic.d.ts.map +1 -1
  8. package/dist/components/index.d.ts +1 -0
  9. package/dist/components/index.d.ts.map +1 -1
  10. package/dist/components/types/DisplayObject.d.ts +12 -16
  11. package/dist/components/types/DisplayObject.d.ts.map +1 -1
  12. package/dist/directives/FocusNavigation.d.ts +71 -0
  13. package/dist/directives/FocusNavigation.d.ts.map +1 -0
  14. package/dist/directives/KeyboardControls.d.ts.map +1 -1
  15. package/dist/directives/ViewportFollow.d.ts.map +1 -1
  16. package/dist/engine/FocusManager.d.ts +174 -0
  17. package/dist/engine/FocusManager.d.ts.map +1 -0
  18. package/dist/engine/reactive.d.ts.map +1 -1
  19. package/dist/hooks/useFocus.d.ts +61 -0
  20. package/dist/hooks/useFocus.d.ts.map +1 -0
  21. package/dist/{index-DNwqVzaq.js → index-B4hYyfVE.js} +5469 -4676
  22. package/dist/index-B4hYyfVE.js.map +1 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.global.js +7 -7
  26. package/dist/index.global.js.map +1 -1
  27. package/dist/index.js +66 -60
  28. package/package.json +2 -2
  29. package/src/components/Button.ts +7 -4
  30. package/src/components/Canvas.ts +1 -1
  31. package/src/components/DOMContainer.ts +27 -2
  32. package/src/components/DOMElement.ts +37 -29
  33. package/src/components/DisplayObject.ts +15 -3
  34. package/src/components/FocusContainer.ts +372 -0
  35. package/src/components/Graphic.ts +43 -48
  36. package/src/components/Sprite.ts +4 -2
  37. package/src/components/Viewport.ts +65 -26
  38. package/src/components/index.ts +2 -1
  39. package/src/components/types/DisplayObject.ts +7 -4
  40. package/src/directives/Controls.ts +1 -1
  41. package/src/directives/ControlsBase.ts +1 -1
  42. package/src/directives/FocusNavigation.ts +252 -0
  43. package/src/directives/KeyboardControls.ts +12 -8
  44. package/src/directives/ViewportFollow.ts +8 -5
  45. package/src/engine/FocusManager.ts +495 -0
  46. package/src/engine/reactive.ts +20 -19
  47. package/src/hooks/useFocus.ts +94 -0
  48. package/src/index.ts +2 -0
  49. package/dist/index-DNwqVzaq.js.map +0 -1
@@ -0,0 +1,372 @@
1
+ import { Container as PixiContainer } from "pixi.js";
2
+ import { createComponent, registerComponent, Element } from "../engine/reactive";
3
+ import { applyDirective } from "../engine/directive";
4
+ import { ComponentInstance, DisplayObject } from "./DisplayObject";
5
+ import { ComponentFunction, h } from "../engine/signal";
6
+ import { DisplayObjectProps } from "./types/DisplayObject";
7
+ import { Container } from "./Container";
8
+ import { focusManager, ScrollOptions } from "../engine/FocusManager";
9
+ import { signal, Signal, isSignal } from "@signe/reactive";
10
+ import { CanvasViewport } from "./Viewport";
11
+ import { Controls } from "../directives/ControlsBase";
12
+ // Import FocusNavigation directive to ensure it's registered
13
+ import "../directives/FocusNavigation";
14
+
15
+ /**
16
+ * Properties for FocusContainer component
17
+ *
18
+ * @property tabindex - Focus index for the container (default: 0 if present)
19
+ * @property controls - Controls configuration for automatic navigation
20
+ * @property onFocusChange - Callback when focus changes
21
+ * @property autoScroll - Enable automatic scrolling to focused element (default: false)
22
+ * @property viewport - Viewport instance to use for scrolling (optional, uses context viewport by default)
23
+ */
24
+ export interface FocusContainerProps extends DisplayObjectProps {
25
+ tabindex?: number;
26
+ controls?: Controls | Signal<Controls>;
27
+ onFocusChange?: (index: number, element: Element | null) => void;
28
+ autoScroll?: boolean | ScrollOptions;
29
+ viewport?: CanvasViewport;
30
+ throttle?: number;
31
+ }
32
+
33
+ /**
34
+ * FocusContainer component for managing focus navigation
35
+ *
36
+ * This component provides a container that manages focus navigation between
37
+ * focusable child elements. It supports automatic navigation via Controls
38
+ * (keyboard/gamepad) and automatic scrolling with Viewport.
39
+ *
40
+ * ## Features
41
+ *
42
+ * - **Focus Management**: Automatically registers focusable children
43
+ * - **Navigation**: Supports keyboard/gamepad navigation via Controls
44
+ * - **Auto-scroll**: Automatically scrolls viewport to show focused element
45
+ * - **Hooks**: Provides reactive signals for focus state
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * // Basic usage
50
+ * <FocusContainer tabindex={0}>
51
+ * <Button tabindex={0} text="Button 1" />
52
+ * <Button tabindex={1} text="Button 2" />
53
+ * </FocusContainer>
54
+ *
55
+ * // With Controls
56
+ * <FocusContainer tabindex={0} controls={controlsConfig}>
57
+ * <Button tabindex={0} text="Button 1" />
58
+ * <Button tabindex={1} text="Button 2" />
59
+ * </FocusContainer>
60
+ *
61
+ * // With auto-scroll
62
+ * <Viewport worldWidth={2000} worldHeight={5000}>
63
+ * <FocusContainer tabindex={0} autoScroll={true}>
64
+ * <Button tabindex={0} y={0} text="Item 1" />
65
+ * <Button tabindex={1} y={100} text="Item 2" />
66
+ * </FocusContainer>
67
+ * </Viewport>
68
+ * ```
69
+ */
70
+ export class CanvasFocusContainer extends DisplayObject(PixiContainer) {
71
+ private containerId: string = '';
72
+ private currentIndexSignal: Signal<number | null> | null = null;
73
+ private focusedElementSignal: Signal<Element | null> | null = null;
74
+ private registeredFocusables: Set<number> = new Set();
75
+
76
+ /**
77
+ * Initialize the focus container
78
+ *
79
+ * @param props - Component properties
80
+ */
81
+ onInit(props: FocusContainerProps) {
82
+ super.onInit(props);
83
+
84
+ // Generate unique container ID
85
+ this.containerId = `focus-container-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
86
+
87
+ // Create signals for current index and focused element
88
+ const currentIndex = signal<number | null>(null);
89
+ const focusedElement = signal<Element | null>(null);
90
+
91
+ this.currentIndexSignal = currentIndex;
92
+ this.focusedElementSignal = focusedElement;
93
+
94
+ // Get viewport from context or props
95
+ const viewport = props.viewport || (props.context?.viewport as CanvasViewport | undefined);
96
+
97
+ // Register container with FocusManager
98
+ focusManager.registerContainer(this.containerId, {
99
+ focusables: new Map(),
100
+ currentIndex,
101
+ focusedElement,
102
+ onFocusChange: props.onFocusChange,
103
+ autoScroll: props.autoScroll,
104
+ viewport,
105
+ throttle: props.throttle ?? 150
106
+ });
107
+ }
108
+
109
+ /**
110
+ * Mount hook - register focusable children
111
+ *
112
+ * @param element - The element being mounted
113
+ */
114
+ async onMount(element: Element<CanvasFocusContainer>): Promise<void> {
115
+ await super.onMount(element, undefined);
116
+
117
+ // Update container with element reference for freeze checking
118
+ focusManager.updateContainer(this.containerId, { element });
119
+
120
+ // Apply focusNavigation directive if controls are provided
121
+ if (element.props.controls) {
122
+ const focusNavDirective = applyDirective(element, 'focusNavigation');
123
+ if (focusNavDirective && !element.directives) {
124
+ element.directives = {};
125
+ }
126
+ if (focusNavDirective) {
127
+ element.directives.focusNavigation = focusNavDirective;
128
+ // Initialize the directive
129
+ focusNavDirective.onInit(element);
130
+ focusNavDirective.onMount(element);
131
+ }
132
+ }
133
+
134
+ // Subscribe to allElements to detect when children are mounted
135
+ if (element.allElements) {
136
+ const subscription = element.allElements.subscribe(() => {
137
+ // Register children when they are mounted
138
+ this.registerChildren(element);
139
+ });
140
+ // Store subscription for cleanup
141
+ if (!element.effectSubscriptions) {
142
+ element.effectSubscriptions = [];
143
+ }
144
+ element.effectSubscriptions.push(subscription);
145
+ }
146
+
147
+ // if (element.propObservables.tabindex) {
148
+ // const subscription = element.propObservables.tabindex.observable.subscribe((value: any) => {
149
+ // console.log("tabindex changed", value);
150
+ // if (value !== null) {
151
+ // // focusManager.setIndex(this.containerId, value);
152
+ // }
153
+ // });
154
+ // element.effectSubscriptions.push(subscription);
155
+ // }
156
+
157
+ focusManager.setTabindex(this.containerId, element.propObservables.tabindex);
158
+
159
+ // Register all focusable children initially
160
+ // Use setTimeout to ensure children are mounted
161
+ setTimeout(() => {
162
+ this.registerChildren(element);
163
+ }, 0);
164
+ }
165
+
166
+ /**
167
+ * Update hook - handle prop changes
168
+ *
169
+ * @param props - Updated properties
170
+ */
171
+ onUpdate(props: FocusContainerProps) {
172
+ super.onUpdate(props);
173
+
174
+ // Update viewport if changed
175
+ const viewport = props.viewport || (props.context?.viewport as CanvasViewport | undefined);
176
+ focusManager.updateContainer(this.containerId, {
177
+ viewport,
178
+ autoScroll: props.autoScroll,
179
+ onFocusChange: props.onFocusChange,
180
+ throttle: props.throttle ?? 150
181
+ });
182
+ }
183
+
184
+ /**
185
+ * Destroy hook - cleanup
186
+ *
187
+ * @param parent - Parent element
188
+ * @param afterDestroy - Callback after destruction
189
+ */
190
+ async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {
191
+ // Unregister all focusables
192
+ for (const index of this.registeredFocusables) {
193
+ focusManager.unregisterFocusable(this.containerId, index);
194
+ }
195
+ this.registeredFocusables.clear();
196
+
197
+ // Unregister container
198
+ focusManager.unregisterContainer(this.containerId);
199
+
200
+ await super.onDestroy(parent, afterDestroy);
201
+ }
202
+
203
+ /**
204
+ * Register focusable children from element
205
+ *
206
+ * @param element - Container element
207
+ */
208
+ private registerChildren(element: Element<CanvasFocusContainer>) {
209
+ if (!element.props.children) return;
210
+
211
+
212
+ let registeredCount = 0;
213
+ const processChildren = (children: any[]) => {
214
+ for (const child of children) {
215
+ if (!child) continue;
216
+
217
+ // Handle signals/observables
218
+ if (isSignal(child) || (child && typeof child.subscribe === 'function')) {
219
+
220
+ // Subscribe to changes
221
+ const subscription = (isSignal(child) ? child.observable : child).subscribe((value: any) => {
222
+ // Handle FlowObservable result (from loop, cond, etc.) - has 'elements' property
223
+ if (value && typeof value === 'object' && 'elements' in value) {
224
+ const elements = value.elements || [];
225
+ if (Array.isArray(elements)) {
226
+ processChildren(elements);
227
+ }
228
+ } else if (Array.isArray(value)) {
229
+ processChildren(value);
230
+ } else if (value) {
231
+ processChild(value);
232
+ }
233
+ });
234
+ // Note: We should track subscriptions for cleanup, but for now this works
235
+ continue;
236
+ }
237
+
238
+ // Handle arrays
239
+ if (Array.isArray(child)) {
240
+ processChildren(child);
241
+ continue;
242
+ }
243
+
244
+ // Handle single element
245
+ processChild(child);
246
+ }
247
+ };
248
+
249
+ const processChild = (child: Element) => {
250
+ if (!child || !child.componentInstance) return;
251
+
252
+ // Check for tabindex in props
253
+ let tabindex: number | undefined = undefined;
254
+
255
+ // For DOMElement/DOMContainer, check attrs.tabindex
256
+ if (child.props?.attrs?.tabindex !== undefined) {
257
+ const tabindexValue = child.props.attrs.tabindex;
258
+ tabindex = isSignal(tabindexValue) ? tabindexValue() : tabindexValue;
259
+ }
260
+ // For other components, check tabindex prop directly
261
+ else if (child.props?.tabindex !== undefined) {
262
+ const tabindexValue = child.props.tabindex;
263
+ tabindex = isSignal(tabindexValue) ? tabindexValue() : tabindexValue;
264
+ }
265
+
266
+ // Register if tabindex >= 0
267
+ if (tabindex !== undefined && tabindex >= 0) {
268
+ if (!this.registeredFocusables.has(tabindex)) {
269
+ focusManager.registerFocusable(this.containerId, child, tabindex);
270
+ this.registeredFocusables.add(tabindex);
271
+ registeredCount++;
272
+ }
273
+ }
274
+
275
+ // Recursively process children
276
+ if (child.props && child.props.children) {
277
+ if (Array.isArray(child.props.children)) {
278
+ processChildren(child.props.children);
279
+ } else if (isSignal(child.props.children) || (child.props.children && typeof child.props.children.subscribe === 'function')) {
280
+ const subscription = (isSignal(child.props.children) ? child.props.children.observable : child.props.children).subscribe((value: any) => {
281
+ // Handle FlowObservable result (from loop, cond, etc.) - has 'elements' property
282
+ if (value && typeof value === 'object' && 'elements' in value) {
283
+ const elements = value.elements || [];
284
+ if (Array.isArray(elements)) {
285
+ processChildren(elements);
286
+ }
287
+ } else if (Array.isArray(value)) {
288
+ processChildren(value);
289
+ } else if (value) {
290
+ processChild(value);
291
+ }
292
+ });
293
+ // Store subscription for cleanup if child has effectSubscriptions
294
+ if (child.effectSubscriptions) {
295
+ child.effectSubscriptions.push(subscription);
296
+ }
297
+ } else {
298
+ processChild(child.props.children as any);
299
+ }
300
+ }
301
+ };
302
+
303
+ if (Array.isArray(element.props.children)) {
304
+ processChildren(element.props.children);
305
+ } else if (element.props.children) {
306
+ if (isSignal(element.props.children) || (element.props.children && typeof element.props.children.subscribe === 'function')) {
307
+ const subscription = (isSignal(element.props.children) ? element.props.children.observable : element.props.children).subscribe((value: any) => {
308
+ // Handle FlowObservable result (from loop, cond, etc.) - has 'elements' property
309
+ if (value && typeof value === 'object' && 'elements' in value) {
310
+ const elements = value.elements || [];
311
+ if (Array.isArray(elements)) {
312
+ processChildren(elements);
313
+ }
314
+ } else if (Array.isArray(value)) {
315
+ processChildren(value);
316
+ } else if (value) {
317
+ processChild(value);
318
+ }
319
+ });
320
+ // Store subscription for cleanup
321
+ if (!element.effectSubscriptions) {
322
+ element.effectSubscriptions = [];
323
+ }
324
+ element.effectSubscriptions.push(subscription);
325
+ } else {
326
+ processChild(element.props.children as any);
327
+ }
328
+ }
329
+ }
330
+
331
+ /**
332
+ * Get the container ID
333
+ *
334
+ * @returns Container identifier
335
+ */
336
+ getContainerId(): string {
337
+ return this.containerId;
338
+ }
339
+
340
+ /**
341
+ * Get current index signal
342
+ *
343
+ * @returns Signal for current focus index
344
+ */
345
+ getCurrentIndexSignal(): Signal<number | null> | null {
346
+ return this.currentIndexSignal;
347
+ }
348
+
349
+ /**
350
+ * Get focused element signal
351
+ *
352
+ * @returns Signal for current focused element
353
+ */
354
+ getFocusedElementSignal(): Signal<Element | null> | null {
355
+ return this.focusedElementSignal;
356
+ }
357
+ }
358
+
359
+ export interface CanvasFocusContainer extends DisplayObjectProps { }
360
+
361
+ registerComponent("FocusContainer", CanvasFocusContainer);
362
+
363
+ /**
364
+ * FocusContainer component function
365
+ *
366
+ * @param props - Component properties
367
+ * @returns FocusContainer element
368
+ */
369
+ export const FocusContainer: ComponentFunction<FocusContainerProps> = (props) => {
370
+ return createComponent("FocusContainer", props);
371
+ };
372
+
@@ -1,14 +1,15 @@
1
1
  import { Effect, effect, isSignal, signal, Signal, WritableSignal } from "@signe/reactive";
2
- import { Assets, Graphics as PixiGraphics } from "pixi.js";
2
+ import { Assets, ObservablePoint, Graphics as PixiGraphics } from "pixi.js";
3
3
  import { createComponent, Element, registerComponent } from "../engine/reactive";
4
4
  import { ComponentInstance, DisplayObject } from "./DisplayObject";
5
5
  import { DisplayObjectProps } from "./types/DisplayObject";
6
6
  import { useProps } from "../hooks/useProps";
7
7
  import { SignalOrPrimitive } from "./types";
8
8
  import { isPercent } from "../utils/functions";
9
+ import { setObservablePoint } from "../engine/utils";
9
10
 
10
11
  interface GraphicsProps extends DisplayObjectProps {
11
- draw?: (graphics: PixiGraphics, width: number, height: number) => void;
12
+ draw?: (graphics: PixiGraphics, width: number, height: number, anchor?: [number, number]) => void;
12
13
  }
13
14
 
14
15
  interface RectProps extends DisplayObjectProps {
@@ -42,6 +43,8 @@ class CanvasGraphics extends DisplayObject(PixiGraphics) {
42
43
  clearEffect: Effect;
43
44
  _width: WritableSignal<number>;
44
45
  _height: WritableSignal<number>;
46
+
47
+ isCustomAnchor = true;
45
48
 
46
49
  /**
47
50
  * Initializes the graphics component with reactive width and height handling.
@@ -74,6 +77,7 @@ class CanvasGraphics extends DisplayObject(PixiGraphics) {
74
77
  */
75
78
  async onInit(props) {
76
79
  await super.onInit(props);
80
+ this.setObjectFit('none');
77
81
  }
78
82
 
79
83
  /**
@@ -89,6 +93,7 @@ class CanvasGraphics extends DisplayObject(PixiGraphics) {
89
93
  // Use original signals from propObservables if available, otherwise create new ones
90
94
  const width = (isSignal(propObservables?.width) ? propObservables.width : signal(props.width || 0)) as WritableSignal<number>;
91
95
  const height = (isSignal(propObservables?.height) ? propObservables.height : signal(props.height || 0)) as WritableSignal<number>;
96
+ const anchor = (isSignal(propObservables?.anchor) ? propObservables.anchor : signal(props.anchor || [0, 0])) as WritableSignal<[number, number]>;
92
97
 
93
98
  // Store as class properties for access in other methods
94
99
  this._width = width;
@@ -102,11 +107,12 @@ class CanvasGraphics extends DisplayObject(PixiGraphics) {
102
107
  this.clearEffect = effect(() => {
103
108
  const w = width();
104
109
  const h = height();
110
+ const a = anchor();
105
111
  if (typeof w == 'string' || typeof h == 'string') {
106
112
  return
107
113
  }
108
114
  this.clear();
109
- props.draw?.(this, w, h);
115
+ props.draw?.(this, w, h, a);
110
116
  this.subjectInit.next(this)
111
117
  });
112
118
  }
@@ -169,6 +175,15 @@ export function Graphics(props: GraphicsProps) {
169
175
  return createComponent("Graphics", props);
170
176
  }
171
177
 
178
+ const graphicsAnchor = (anchor, width, height) => {
179
+ const observableAnchor = new ObservablePoint({ _onUpdate: () => {} }, 0, 0);
180
+ setObservablePoint(observableAnchor, anchor);
181
+ const ax = observableAnchor.x;
182
+ const ay = observableAnchor.y;
183
+
184
+ return { x: -ax * width, y: -ay * height };
185
+ }
186
+
172
187
  export function Rect(props: RectProps) {
173
188
  const { color, borderRadius, border } = useProps(props, {
174
189
  borderRadius: null,
@@ -176,11 +191,12 @@ export function Rect(props: RectProps) {
176
191
  })
177
192
 
178
193
  return Graphics({
179
- draw: (g, width, height) => {
194
+ draw: (g, width, height, anchor) => {
195
+ const { x, y } = graphicsAnchor(anchor, width, height);
180
196
  if (borderRadius()) {
181
- g.roundRect(0, 0, width, height, borderRadius());
197
+ g.roundRect(x, y, width, height, borderRadius());
182
198
  } else {
183
- g.rect(0, 0, width, height);
199
+ g.rect(x, y, width, height);
184
200
  }
185
201
  if (border) {
186
202
  g.stroke(border);
@@ -191,45 +207,19 @@ export function Rect(props: RectProps) {
191
207
  })
192
208
  }
193
209
 
194
- function drawShape(g: PixiGraphics, shape: 'circle' | 'ellipse', props: {
195
- radius: Signal<number>;
196
- color: Signal<string>;
197
- border: Signal<number>;
198
- } | {
199
- width: Signal<number>;
200
- height: Signal<number>;
201
- color: Signal<string>;
202
- border: Signal<number>;
203
- }) {
204
- const { color, border } = props;
205
- if ('radius' in props) {
206
- g.circle(0, 0, props.radius());
207
- } else {
208
- g.ellipse(0, 0, props.width() / 2, props.height() / 2);
209
- }
210
- if (border()) {
211
- g.stroke(border());
212
- }
213
- g.fill(color());
214
- }
215
-
216
210
  export function Circle(props: CircleProps) {
217
- const { radius, color, border } = useProps(props, {
218
- border: null
219
- })
220
- return Graphics({
221
- draw: (g) => drawShape(g, 'circle', { radius, color, border }),
222
- ...props
223
- })
224
- }
225
-
226
- export function Ellipse(props: EllipseProps) {
227
- const { width, height, color, border } = useProps(props, {
228
- border: null
211
+ const { color, border, radius } = useProps(props, {
212
+ border: null,
213
+ radius: null
229
214
  })
230
215
  return Graphics({
231
- draw: (g, gWidth, gHeight) => {
232
- g.ellipse(0, 0, gWidth / 2, gHeight / 2);
216
+ draw: (g, width, height, anchor) => {
217
+ const { x, y } = graphicsAnchor(anchor, width, height);
218
+ if (width == height || height == 0) {
219
+ g.circle(x, y, radius() || width);
220
+ } else {
221
+ g.ellipse(x, y, width, height);
222
+ }
233
223
  if (border()) {
234
224
  g.stroke(border());
235
225
  }
@@ -239,17 +229,22 @@ export function Ellipse(props: EllipseProps) {
239
229
  })
240
230
  }
241
231
 
232
+ export function Ellipse(props: EllipseProps) {
233
+ return Circle(props as CircleProps);
234
+ }
235
+
242
236
  export function Triangle(props: TriangleProps) {
243
- const { width, height, color, border } = useProps(props, {
237
+ const { color, border } = useProps(props, {
244
238
  border: null,
245
239
  color: '#000'
246
240
  })
247
241
  return Graphics({
248
- draw: (g, gWidth, gHeight) => {
249
- g.moveTo(0, gHeight);
250
- g.lineTo(gWidth / 2, 0);
251
- g.lineTo(gWidth, gHeight);
252
- g.lineTo(0, gHeight);
242
+ draw: (g, gWidth, gHeight, anchor) => {
243
+ const { x, y } = graphicsAnchor(anchor, gWidth, gHeight);
244
+ g.moveTo(x, y + gHeight);
245
+ g.lineTo(x + gWidth / 2, y);
246
+ g.lineTo(x + gWidth, y + gHeight);
247
+ g.lineTo(x, y + gHeight);
253
248
  g.fill(color());
254
249
  if (border) {
255
250
  g.stroke(border);
@@ -319,7 +319,8 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
319
319
  this.update(value);
320
320
  });
321
321
  if (definition) {
322
- this.spritesheet = definition.value ?? definition;
322
+ const resolvedDefinition = definition instanceof Promise ? await definition : definition;
323
+ this.spritesheet = resolvedDefinition.value ?? resolvedDefinition;
323
324
  await this.createAnimations();
324
325
  }
325
326
  if (sheet.params) {
@@ -420,7 +421,8 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
420
421
  const definition = props.sheet?.definition ?? {};
421
422
 
422
423
  if (definition?.type === 'reset') {
423
- this.spritesheet = definition.value ?? definition;
424
+ const resolvedValue = definition.value instanceof Promise ? await definition.value : definition.value;
425
+ this.spritesheet = resolvedValue ?? definition;
424
426
  await this.resetAnimations();
425
427
  }
426
428