@ankhorage/zora-game 0.2.0 → 0.3.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +2 -1
  3. package/dist/ZORA_GAME_COMPONENT_META.d.ts +111 -1
  4. package/dist/ZORA_GAME_COMPONENT_META.d.ts.map +1 -1
  5. package/dist/ZORA_GAME_COMPONENT_META.js +2 -0
  6. package/dist/ZORA_GAME_COMPONENT_META.js.map +1 -1
  7. package/dist/ZORA_GAME_PLUGIN.d.ts +117 -2
  8. package/dist/ZORA_GAME_PLUGIN.d.ts.map +1 -1
  9. package/dist/ZORA_GAME_PLUGIN.js +2 -0
  10. package/dist/ZORA_GAME_PLUGIN.js.map +1 -1
  11. package/dist/ZORA_PLUGIN_METADATA.d.ts +115 -2
  12. package/dist/ZORA_PLUGIN_METADATA.d.ts.map +1 -1
  13. package/dist/ZORA_PLUGIN_METADATA.js +5 -1
  14. package/dist/ZORA_PLUGIN_METADATA.js.map +1 -1
  15. package/dist/features/game-presentation/adapters/inbound/GameEntity.d.ts.map +1 -1
  16. package/dist/features/game-presentation/adapters/inbound/GameEntity.js +4 -11
  17. package/dist/features/game-presentation/adapters/inbound/GameEntity.js.map +1 -1
  18. package/dist/features/game-presentation/adapters/inbound/GameInputZone.d.ts +4 -0
  19. package/dist/features/game-presentation/adapters/inbound/GameInputZone.d.ts.map +1 -0
  20. package/dist/features/game-presentation/adapters/inbound/GameInputZone.js +35 -0
  21. package/dist/features/game-presentation/adapters/inbound/GameInputZone.js.map +1 -0
  22. package/dist/features/game-presentation/adapters/inbound/createGamePointerEvent.d.ts +17 -0
  23. package/dist/features/game-presentation/adapters/inbound/createGamePointerEvent.d.ts.map +1 -0
  24. package/dist/features/game-presentation/adapters/inbound/createGamePointerEvent.js +20 -0
  25. package/dist/features/game-presentation/adapters/inbound/createGamePointerEvent.js.map +1 -0
  26. package/dist/features/game-presentation/adapters/inbound/useGameInputZoneResponder.d.ts +9 -0
  27. package/dist/features/game-presentation/adapters/inbound/useGameInputZoneResponder.d.ts.map +1 -0
  28. package/dist/features/game-presentation/adapters/inbound/useGameInputZoneResponder.js +37 -0
  29. package/dist/features/game-presentation/adapters/inbound/useGameInputZoneResponder.js.map +1 -0
  30. package/dist/features/game-presentation/meta/gameInputZoneMeta.d.ts +112 -0
  31. package/dist/features/game-presentation/meta/gameInputZoneMeta.d.ts.map +1 -0
  32. package/dist/features/game-presentation/meta/gameInputZoneMeta.js +92 -0
  33. package/dist/features/game-presentation/meta/gameInputZoneMeta.js.map +1 -0
  34. package/dist/features/game-presentation/meta/gameMeta.d.ts +1 -1
  35. package/dist/features/game-presentation/meta/gameMeta.js +1 -1
  36. package/dist/features/game-presentation/meta/gameMeta.js.map +1 -1
  37. package/dist/features/game-presentation/public.d.ts +2 -1
  38. package/dist/features/game-presentation/public.d.ts.map +1 -1
  39. package/dist/features/game-presentation/public.js +1 -0
  40. package/dist/features/game-presentation/public.js.map +1 -1
  41. package/dist/features/game-presentation/utils/clampGamePercentage.d.ts +3 -0
  42. package/dist/features/game-presentation/utils/clampGamePercentage.d.ts.map +1 -0
  43. package/dist/features/game-presentation/utils/clampGamePercentage.js +5 -0
  44. package/dist/features/game-presentation/utils/clampGamePercentage.js.map +1 -0
  45. package/dist/features/game-presentation/utils/toGamePercentage.d.ts +3 -0
  46. package/dist/features/game-presentation/utils/toGamePercentage.d.ts.map +1 -0
  47. package/dist/features/game-presentation/utils/toGamePercentage.js +6 -0
  48. package/dist/features/game-presentation/utils/toGamePercentage.js.map +1 -0
  49. package/dist/index.d.ts +2 -2
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +1 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/types/gamePresentation.d.ts +13 -0
  54. package/dist/types/gamePresentation.d.ts.map +1 -1
  55. package/dist/types/gamePresentation.js.map +1 -1
  56. package/package.json +1 -1
  57. package/src/ZORA_GAME_COMPONENT_META.ts +2 -0
  58. package/src/ZORA_GAME_PLUGIN.ts +2 -0
  59. package/src/ZORA_PLUGIN_METADATA.test.ts +11 -0
  60. package/src/ZORA_PLUGIN_METADATA.ts +5 -1
  61. package/src/features/game-presentation/adapters/inbound/GameEntity.tsx +4 -13
  62. package/src/features/game-presentation/adapters/inbound/GameInputZone.tsx +70 -0
  63. package/src/features/game-presentation/adapters/inbound/createGamePointerEvent.test.ts +56 -0
  64. package/src/features/game-presentation/adapters/inbound/createGamePointerEvent.ts +39 -0
  65. package/src/features/game-presentation/adapters/inbound/useGameInputZoneResponder.ts +49 -0
  66. package/src/features/game-presentation/meta/gameInputZoneMeta.ts +94 -0
  67. package/src/features/game-presentation/meta/gameMeta.ts +1 -1
  68. package/src/features/game-presentation/public.ts +2 -0
  69. package/src/features/game-presentation/utils/clampGamePercentage.ts +4 -0
  70. package/src/features/game-presentation/utils/toGamePercentage.ts +6 -0
  71. package/src/index.ts +8 -1
  72. package/src/types/gamePresentation.ts +14 -0
@@ -1,6 +1,7 @@
1
1
  import { Game } from './features/game-presentation/adapters/inbound/Game';
2
2
  import { GameEntity } from './features/game-presentation/adapters/inbound/GameEntity';
3
3
  import { GameField } from './features/game-presentation/adapters/inbound/GameField';
4
+ import { GameInputZone } from './features/game-presentation/adapters/inbound/GameInputZone';
4
5
  import { GameOverlay } from './features/game-presentation/adapters/inbound/GameOverlay';
5
6
  import { ZORA_PLUGIN_METADATA } from './ZORA_PLUGIN_METADATA';
6
7
 
@@ -11,6 +12,7 @@ export const ZORA_GAME_PLUGIN = {
11
12
  Game,
12
13
  GameEntity,
13
14
  GameField,
15
+ GameInputZone,
14
16
  GameOverlay,
15
17
  },
16
18
  } as const;
@@ -18,9 +18,20 @@ describe('ZORA game plugin metadata', () => {
18
18
  expect(gameField.allowedChildren).toContain('GameEntity');
19
19
  expect(gameField.allowedChildren).toContain('GameOverlay');
20
20
  expect(game.allowedChildren).toContain('GameEntity');
21
+ expect(game.allowedChildren).toContain('GameInputZone');
21
22
  expect(game.allowedChildren).toContain('GameOverlay');
22
23
  });
23
24
 
25
+ test('keeps Game input zones scoped to runtime-owning Game parents', () => {
26
+ const catalog = composeZoraPluginMetadata([ZORA_CORE_PLUGIN_METADATA, ZORA_PLUGIN_METADATA]);
27
+ const gameInputZone = readComponentMeta(catalog.componentMeta.GameInputZone, 'GameInputZone');
28
+
29
+ expect(gameInputZone.props.eventType?.type).toBe('string');
30
+ expect(gameInputZone.props.continuous?.type).toBe('boolean');
31
+ expect(catalog.componentMeta.Game?.allowedChildren).toContain('GameInputZone');
32
+ expect(catalog.componentMeta.GameField?.allowedChildren).not.toContain('GameInputZone');
33
+ });
34
+
24
35
  test('describes bindable Game inputs and domain-neutral outputs', () => {
25
36
  const catalog = composeZoraPluginMetadata([ZORA_CORE_PLUGIN_METADATA, ZORA_PLUGIN_METADATA]);
26
37
  const game = readComponentMeta(catalog.componentMeta.Game, 'Game');
@@ -7,7 +7,7 @@ export const ZORA_PLUGIN_METADATA = {
7
7
  packageName: '@ankhorage/zora-game',
8
8
  displayName: 'ZORA Game',
9
9
  componentMeta: ZORA_GAME_COMPONENT_META,
10
- extensionHosts: ['Game', 'GameField', 'GameEntity', 'GameOverlay'],
10
+ extensionHosts: ['Game', 'GameEntity', 'GameField', 'GameInputZone', 'GameOverlay'],
11
11
  placements: [
12
12
  {
13
13
  child: 'Game',
@@ -21,6 +21,10 @@ export const ZORA_PLUGIN_METADATA = {
21
21
  child: 'GameEntity',
22
22
  parents: ['Game', 'GameField', 'GameOverlay'],
23
23
  },
24
+ {
25
+ child: 'GameInputZone',
26
+ parents: ['Game'],
27
+ },
24
28
  {
25
29
  child: 'GameOverlay',
26
30
  parents: ['Game', 'GameField'],
@@ -2,6 +2,7 @@ import { View } from '@ankhorage/zora';
2
2
  import { StyleSheet, type ViewStyle } from 'react-native';
3
3
 
4
4
  import type { GameEntityProps } from '../../../../types/gamePresentation';
5
+ import { toGamePercentage } from '../../utils/toGamePercentage';
5
6
 
6
7
  /*** Render one generic positioned game entity without owning gameplay semantics. */
7
8
  export function GameEntity({
@@ -60,10 +61,10 @@ function createEntityStyle({
60
61
  }: GameEntityStyleInput): ViewStyle {
61
62
  return {
62
63
  display: hidden ? 'none' : 'flex',
63
- left: toPercent(x),
64
- opacity: clamp(opacity, 0, 1),
64
+ left: toGamePercentage(x),
65
+ opacity: Math.min(1, Math.max(0, opacity)),
65
66
  position: 'absolute',
66
- top: toPercent(y),
67
+ top: toGamePercentage(y),
67
68
  transform: [{ scale }, { rotate: `${rotation}deg` }],
68
69
  zIndex,
69
70
  ...(height === undefined ? {} : { height }),
@@ -71,16 +72,6 @@ function createEntityStyle({
71
72
  };
72
73
  }
73
74
 
74
- /*** Convert a bounded percentage number to React Native percentage syntax. */
75
- function toPercent(value: number): `${number}%` {
76
- return `${clamp(value, 0, 100)}%`;
77
- }
78
-
79
- /*** Clamp one numeric presentation value to an inclusive range. */
80
- function clamp(value: number, minimum: number, maximum: number): number {
81
- return Math.min(maximum, Math.max(minimum, value));
82
- }
83
-
84
75
  const styles = StyleSheet.create({
85
76
  root: {
86
77
  position: 'absolute',
@@ -0,0 +1,70 @@
1
+ import { StyleSheet, View, type ViewStyle } from 'react-native';
2
+
3
+ import type { GameInputZoneProps } from '../../../../types/gamePresentation';
4
+ import { toGamePercentage } from '../../utils/toGamePercentage';
5
+ import { useGameInputZoneResponder } from './useGameInputZoneResponder';
6
+
7
+ /*** Capture pointer/touch geometry and dispatch only normalized generic Game events. */
8
+ export function GameInputZone({
9
+ x = 0,
10
+ y = 0,
11
+ width = 100,
12
+ height = 100,
13
+ zIndex = 0,
14
+ enabled = true,
15
+ continuous = true,
16
+ accessibilityLabel,
17
+ testID,
18
+ ...inputProps
19
+ }: GameInputZoneProps) {
20
+ const { dispatchPointer, handleLayout, shouldSetResponder } = useGameInputZoneResponder({
21
+ ...inputProps,
22
+ x,
23
+ y,
24
+ width,
25
+ height,
26
+ enabled,
27
+ continuous,
28
+ });
29
+
30
+ return (
31
+ <View
32
+ {...(accessibilityLabel === undefined ? {} : { accessibilityLabel })}
33
+ {...(testID === undefined ? {} : { testID })}
34
+ {...(continuous
35
+ ? { onResponderGrant: dispatchPointer, onResponderMove: dispatchPointer }
36
+ : { onResponderRelease: dispatchPointer })}
37
+ collapsable={false}
38
+ onLayout={handleLayout}
39
+ onStartShouldSetResponder={shouldSetResponder}
40
+ pointerEvents={enabled ? 'auto' : 'none'}
41
+ style={createInputZoneStyle({ x, y, width, height, zIndex })}
42
+ />
43
+ );
44
+ }
45
+
46
+ interface InputZoneStyleInput {
47
+ readonly x: number;
48
+ readonly y: number;
49
+ readonly width: number;
50
+ readonly height: number;
51
+ readonly zIndex: number;
52
+ }
53
+
54
+ /*** Convert field-relative input-zone props into one absolute React Native style. */
55
+ function createInputZoneStyle({ x, y, width, height, zIndex }: InputZoneStyleInput): ViewStyle {
56
+ return {
57
+ left: toGamePercentage(x),
58
+ top: toGamePercentage(y),
59
+ width: toGamePercentage(width),
60
+ height: toGamePercentage(height),
61
+ zIndex,
62
+ ...styles.root,
63
+ };
64
+ }
65
+
66
+ const styles = StyleSheet.create({
67
+ root: {
68
+ position: 'absolute',
69
+ },
70
+ });
@@ -0,0 +1,56 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+
3
+ import { createGamePointerEvent } from './createGamePointerEvent';
4
+
5
+ describe('createGamePointerEvent', () => {
6
+ test('maps zone-local pointer coordinates into field percentages', () => {
7
+ expect(
8
+ createGamePointerEvent({
9
+ eventType: 'player.move',
10
+ entityId: 'player',
11
+ localX: 100,
12
+ localY: 25,
13
+ measuredWidth: 200,
14
+ measuredHeight: 100,
15
+ zoneX: 10,
16
+ zoneY: 60,
17
+ zoneWidth: 80,
18
+ zoneHeight: 30,
19
+ }),
20
+ ).toEqual({
21
+ type: 'player.move',
22
+ entityId: 'player',
23
+ payload: { x: 50, y: 67.5 },
24
+ });
25
+ });
26
+
27
+ test('clamps out-of-bounds native coordinates and rejects unmeasured zones', () => {
28
+ expect(
29
+ createGamePointerEvent({
30
+ eventType: 'pointer.move',
31
+ localX: 500,
32
+ localY: -20,
33
+ measuredWidth: 100,
34
+ measuredHeight: 100,
35
+ zoneX: 20,
36
+ zoneY: 20,
37
+ zoneWidth: 50,
38
+ zoneHeight: 50,
39
+ }),
40
+ ).toEqual({ type: 'pointer.move', payload: { x: 70, y: 20 } });
41
+
42
+ expect(
43
+ createGamePointerEvent({
44
+ eventType: 'pointer.move',
45
+ localX: 0,
46
+ localY: 0,
47
+ measuredWidth: 0,
48
+ measuredHeight: 100,
49
+ zoneX: 0,
50
+ zoneY: 0,
51
+ zoneWidth: 100,
52
+ zoneHeight: 100,
53
+ }),
54
+ ).toBeUndefined();
55
+ });
56
+ });
@@ -0,0 +1,39 @@
1
+ import type { GameEvent } from '@ankhorage/game';
2
+
3
+ import { clampGamePercentage } from '../../utils/clampGamePercentage';
4
+
5
+ interface GamePointerEventInput {
6
+ readonly eventType: string;
7
+ readonly entityId?: string;
8
+ readonly localX: number;
9
+ readonly localY: number;
10
+ readonly measuredWidth: number;
11
+ readonly measuredHeight: number;
12
+ readonly zoneX: number;
13
+ readonly zoneY: number;
14
+ readonly zoneWidth: number;
15
+ readonly zoneHeight: number;
16
+ }
17
+
18
+ /*** Normalize one measured pointer/touch position into a field-relative generic Game event. */
19
+ export function createGamePointerEvent(input: GamePointerEventInput): GameEvent | undefined {
20
+ if (
21
+ !Number.isFinite(input.measuredWidth) ||
22
+ !Number.isFinite(input.measuredHeight) ||
23
+ input.measuredWidth <= 0 ||
24
+ input.measuredHeight <= 0
25
+ ) {
26
+ return undefined;
27
+ }
28
+
29
+ const localX = clampGamePercentage((input.localX / input.measuredWidth) * 100);
30
+ const localY = clampGamePercentage((input.localY / input.measuredHeight) * 100);
31
+ const x = clampGamePercentage(input.zoneX + (localX * input.zoneWidth) / 100);
32
+ const y = clampGamePercentage(input.zoneY + (localY * input.zoneHeight) / 100);
33
+
34
+ return {
35
+ type: input.eventType,
36
+ ...(input.entityId === undefined ? {} : { entityId: input.entityId }),
37
+ payload: { x, y },
38
+ };
39
+ }
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import type { GestureResponderEvent, LayoutChangeEvent } from 'react-native';
3
+
4
+ import type { GameInputZoneProps } from '../../../../types/gamePresentation';
5
+ import { GameRuntimeContext } from '../../composition/GameRuntimeContext';
6
+ import { createGamePointerEvent } from './createGamePointerEvent';
7
+
8
+ interface MeasuredSize {
9
+ readonly width: number;
10
+ readonly height: number;
11
+ }
12
+
13
+ /*** Own React Native responder measurement and event dispatch for one Game input zone. */
14
+ export function useGameInputZoneResponder(props: GameInputZoneProps) {
15
+ const runtime = React.useContext(GameRuntimeContext);
16
+ if (runtime === null) throw new Error('GameInputZone must be rendered inside Game.');
17
+
18
+ const measuredSizeRef = React.useRef<MeasuredSize>({ width: 0, height: 0 });
19
+ const handleLayout = React.useCallback((event: LayoutChangeEvent) => {
20
+ const { width, height } = event.nativeEvent.layout;
21
+ measuredSizeRef.current = { width, height };
22
+ }, []);
23
+
24
+ const dispatchPointer = React.useCallback(
25
+ (event: GestureResponderEvent) => {
26
+ const measured = measuredSizeRef.current;
27
+ const gameEvent = createGamePointerEvent({
28
+ eventType: props.eventType,
29
+ ...(props.entityId === undefined ? {} : { entityId: props.entityId }),
30
+ localX: event.nativeEvent.locationX,
31
+ localY: event.nativeEvent.locationY,
32
+ measuredWidth: measured.width,
33
+ measuredHeight: measured.height,
34
+ zoneX: props.x ?? 0,
35
+ zoneY: props.y ?? 0,
36
+ zoneWidth: props.width ?? 100,
37
+ zoneHeight: props.height ?? 100,
38
+ });
39
+ if (gameEvent !== undefined) runtime.dispatch(gameEvent);
40
+ },
41
+ [props.entityId, props.eventType, props.height, props.width, props.x, props.y, runtime],
42
+ );
43
+
44
+ return {
45
+ dispatchPointer,
46
+ handleLayout,
47
+ shouldSetResponder: () => props.enabled ?? true,
48
+ };
49
+ }
@@ -0,0 +1,94 @@
1
+ import type { ZoraComponentMeta } from '@ankhorage/zora/metadata';
2
+
3
+ /*** Describe a field-relative pointer/touch input adapter for one embeddable Game session. */
4
+ export const gameInputZoneMeta = {
5
+ name: 'GameInputZone',
6
+ category: 'component',
7
+ description:
8
+ 'Normalizes pointer and touch positions into field-relative percentages and dispatches a generic game event.',
9
+ directManifestNode: true,
10
+ allowedChildren: [],
11
+ blueprint: {
12
+ label: 'Game input zone',
13
+ defaultProps: {
14
+ eventType: 'game.pointer',
15
+ x: 0,
16
+ y: 0,
17
+ width: 100,
18
+ height: 100,
19
+ zIndex: 1,
20
+ enabled: true,
21
+ continuous: true,
22
+ },
23
+ },
24
+ props: {
25
+ eventType: {
26
+ type: 'string',
27
+ category: 'Input',
28
+ label: 'Game event type',
29
+ default: 'game.pointer',
30
+ authoring: { authority: 'instance' },
31
+ },
32
+ entityId: {
33
+ type: 'string',
34
+ category: 'Input',
35
+ label: 'Entity id',
36
+ authoring: { authority: 'instance' },
37
+ },
38
+ x: {
39
+ type: 'number',
40
+ category: 'Position',
41
+ label: 'X (%)',
42
+ default: 0,
43
+ authoring: { authority: 'instance' },
44
+ },
45
+ y: {
46
+ type: 'number',
47
+ category: 'Position',
48
+ label: 'Y (%)',
49
+ default: 0,
50
+ authoring: { authority: 'instance' },
51
+ },
52
+ width: {
53
+ type: 'number',
54
+ category: 'Size',
55
+ label: 'Width (%)',
56
+ default: 100,
57
+ authoring: { authority: 'instance' },
58
+ },
59
+ height: {
60
+ type: 'number',
61
+ category: 'Size',
62
+ label: 'Height (%)',
63
+ default: 100,
64
+ authoring: { authority: 'instance' },
65
+ },
66
+ zIndex: {
67
+ type: 'number',
68
+ category: 'Position',
69
+ label: 'Z index',
70
+ default: 1,
71
+ authoring: { authority: 'instance' },
72
+ },
73
+ enabled: {
74
+ type: 'boolean',
75
+ category: 'State',
76
+ label: 'Enabled',
77
+ default: true,
78
+ authoring: { authority: 'instance' },
79
+ },
80
+ continuous: {
81
+ type: 'boolean',
82
+ category: 'Input',
83
+ label: 'Dispatch while moving',
84
+ default: true,
85
+ authoring: { authority: 'instance' },
86
+ },
87
+ accessibilityLabel: {
88
+ type: 'string',
89
+ category: 'Accessibility',
90
+ label: 'Accessibility label',
91
+ authoring: { authority: 'instance' },
92
+ },
93
+ },
94
+ } as const satisfies ZoraComponentMeta;
@@ -7,7 +7,7 @@ export const gameMeta = {
7
7
  description:
8
8
  'Embeds one config-driven game session inside ordinary ZORA layout and emits domain-neutral game outputs.',
9
9
  directManifestNode: true,
10
- allowedChildren: ['GameEntity', 'GameOverlay', 'Gradient', 'Image', 'View'],
10
+ allowedChildren: ['GameEntity', 'GameInputZone', 'GameOverlay', 'Gradient', 'Image', 'View'],
11
11
  blueprint: {
12
12
  label: 'Game',
13
13
  defaultProps: {
@@ -1,6 +1,7 @@
1
1
  export type {
2
2
  GameEntityProps,
3
3
  GameFieldProps,
4
+ GameInputZoneProps,
4
5
  GameOverlayPlacement,
5
6
  GameOverlayProps,
6
7
  GamePointerEvents,
@@ -9,4 +10,5 @@ export type {
9
10
  export { Game } from './adapters/inbound/Game';
10
11
  export { GameEntity } from './adapters/inbound/GameEntity';
11
12
  export { GameField } from './adapters/inbound/GameField';
13
+ export { GameInputZone } from './adapters/inbound/GameInputZone';
12
14
  export { GameOverlay } from './adapters/inbound/GameOverlay';
@@ -0,0 +1,4 @@
1
+ /*** Clamp one game presentation coordinate to the inclusive field-percentage range. */
2
+ export function clampGamePercentage(value: number): number {
3
+ return Math.min(100, Math.max(0, value));
4
+ }
@@ -0,0 +1,6 @@
1
+ import { clampGamePercentage } from './clampGamePercentage';
2
+
3
+ /*** Convert one game percentage coordinate to React Native percentage style syntax. */
4
+ export function toGamePercentage(value: number): `${number}%` {
5
+ return `${clampGamePercentage(value)}%`;
6
+ }
package/src/index.ts CHANGED
@@ -1,10 +1,17 @@
1
1
  export type {
2
2
  GameEntityProps,
3
3
  GameFieldProps,
4
+ GameInputZoneProps,
4
5
  GameOverlayPlacement,
5
6
  GameOverlayProps,
6
7
  GamePointerEvents,
7
8
  GameProps,
8
9
  } from './features/game-presentation/public';
9
- export { Game, GameEntity, GameField, GameOverlay } from './features/game-presentation/public';
10
+ export {
11
+ Game,
12
+ GameEntity,
13
+ GameField,
14
+ GameInputZone,
15
+ GameOverlay,
16
+ } from './features/game-presentation/public';
10
17
  export { ZORA_GAME_PLUGIN } from './ZORA_GAME_PLUGIN';
@@ -32,6 +32,20 @@ export interface GameEntityProps {
32
32
  readonly testID?: string;
33
33
  }
34
34
 
35
+ export interface GameInputZoneProps {
36
+ readonly eventType: string;
37
+ readonly entityId?: string;
38
+ readonly x?: number;
39
+ readonly y?: number;
40
+ readonly width?: number;
41
+ readonly height?: number;
42
+ readonly zIndex?: number;
43
+ readonly enabled?: boolean;
44
+ readonly continuous?: boolean;
45
+ readonly accessibilityLabel?: string;
46
+ readonly testID?: string;
47
+ }
48
+
35
49
  export interface GameOverlayProps {
36
50
  readonly children?: React.ReactNode;
37
51
  readonly placement?: GameOverlayPlacement;