@ankhorage/zora-game 0.1.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/CHANGELOG.md +11 -0
- package/LICENSE +21 -0
- package/README.md +19 -0
- package/dist/ZORA_GAME_COMPONENT_META.d.ts +224 -0
- package/dist/ZORA_GAME_COMPONENT_META.d.ts.map +1 -0
- package/dist/ZORA_GAME_COMPONENT_META.js +10 -0
- package/dist/ZORA_GAME_COMPONENT_META.js.map +1 -0
- package/dist/ZORA_GAME_PLUGIN.d.ts +247 -0
- package/dist/ZORA_GAME_PLUGIN.d.ts.map +1 -0
- package/dist/ZORA_GAME_PLUGIN.js +14 -0
- package/dist/ZORA_GAME_PLUGIN.js.map +1 -0
- package/dist/ZORA_PLUGIN_METADATA.d.ts +239 -0
- package/dist/ZORA_PLUGIN_METADATA.d.ts.map +1 -0
- package/dist/ZORA_PLUGIN_METADATA.js +23 -0
- package/dist/ZORA_PLUGIN_METADATA.js.map +1 -0
- package/dist/features/game-presentation/adapters/inbound/GameEntity.d.ts +4 -0
- package/dist/features/game-presentation/adapters/inbound/GameEntity.d.ts.map +1 -0
- package/dist/features/game-presentation/adapters/inbound/GameEntity.js +39 -0
- package/dist/features/game-presentation/adapters/inbound/GameEntity.js.map +1 -0
- package/dist/features/game-presentation/adapters/inbound/GameField.d.ts +4 -0
- package/dist/features/game-presentation/adapters/inbound/GameField.d.ts.map +1 -0
- package/dist/features/game-presentation/adapters/inbound/GameField.js +28 -0
- package/dist/features/game-presentation/adapters/inbound/GameField.js.map +1 -0
- package/dist/features/game-presentation/adapters/inbound/GameOverlay.d.ts +4 -0
- package/dist/features/game-presentation/adapters/inbound/GameOverlay.d.ts.map +1 -0
- package/dist/features/game-presentation/adapters/inbound/GameOverlay.js +39 -0
- package/dist/features/game-presentation/adapters/inbound/GameOverlay.js.map +1 -0
- package/dist/features/game-presentation/meta/gameEntityMeta.d.ts +119 -0
- package/dist/features/game-presentation/meta/gameEntityMeta.d.ts.map +1 -0
- package/dist/features/game-presentation/meta/gameEntityMeta.js +90 -0
- package/dist/features/game-presentation/meta/gameEntityMeta.js.map +1 -0
- package/dist/features/game-presentation/meta/gameFieldMeta.d.ts +52 -0
- package/dist/features/game-presentation/meta/gameFieldMeta.d.ts.map +1 -0
- package/dist/features/game-presentation/meta/gameFieldMeta.js +41 -0
- package/dist/features/game-presentation/meta/gameFieldMeta.js.map +1 -0
- package/dist/features/game-presentation/meta/gameOverlayMeta.d.ts +55 -0
- package/dist/features/game-presentation/meta/gameOverlayMeta.d.ts.map +1 -0
- package/dist/features/game-presentation/meta/gameOverlayMeta.js +65 -0
- package/dist/features/game-presentation/meta/gameOverlayMeta.js.map +1 -0
- package/dist/features/game-presentation/public.d.ts +5 -0
- package/dist/features/game-presentation/public.d.ts.map +1 -0
- package/dist/features/game-presentation/public.js +4 -0
- package/dist/features/game-presentation/public.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata.d.ts +3 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +3 -0
- package/dist/metadata.js.map +1 -0
- package/dist/types/gamePresentation.d.ts +37 -0
- package/dist/types/gamePresentation.d.ts.map +1 -0
- package/dist/types/gamePresentation.js +2 -0
- package/dist/types/gamePresentation.js.map +1 -0
- package/package.json +95 -0
- package/src/ZORA_GAME_COMPONENT_META.ts +10 -0
- package/src/ZORA_GAME_PLUGIN.ts +14 -0
- package/src/ZORA_PLUGIN_METADATA.test.ts +24 -0
- package/src/ZORA_PLUGIN_METADATA.ts +25 -0
- package/src/features/game-presentation/adapters/inbound/GameEntity.tsx +88 -0
- package/src/features/game-presentation/adapters/inbound/GameField.tsx +44 -0
- package/src/features/game-presentation/adapters/inbound/GameOverlay.tsx +57 -0
- package/src/features/game-presentation/meta/gameEntityMeta.ts +91 -0
- package/src/features/game-presentation/meta/gameFieldMeta.ts +42 -0
- package/src/features/game-presentation/meta/gameOverlayMeta.ts +66 -0
- package/src/features/game-presentation/public.ts +10 -0
- package/src/index.ts +9 -0
- package/src/metadata.ts +2 -0
- package/src/types/gamePresentation.ts +41 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { View } from '@ankhorage/zora';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import type { GameFieldProps } from '../../../../types/gamePresentation';
|
|
5
|
+
|
|
6
|
+
/*** Render a bounded relative-positioning surface for game presentation content. */
|
|
7
|
+
export function GameField({
|
|
8
|
+
children,
|
|
9
|
+
aspectRatio,
|
|
10
|
+
minHeight = 240,
|
|
11
|
+
clip = true,
|
|
12
|
+
accessibilityLabel,
|
|
13
|
+
testID,
|
|
14
|
+
}: GameFieldProps) {
|
|
15
|
+
return (
|
|
16
|
+
<View
|
|
17
|
+
{...(accessibilityLabel === undefined ? {} : { accessibilityLabel })}
|
|
18
|
+
{...(testID === undefined ? {} : { testID })}
|
|
19
|
+
style={[
|
|
20
|
+
styles.root,
|
|
21
|
+
clip ? styles.clipped : styles.overflowVisible,
|
|
22
|
+
{
|
|
23
|
+
...(aspectRatio === undefined ? {} : { aspectRatio }),
|
|
24
|
+
minHeight,
|
|
25
|
+
},
|
|
26
|
+
]}
|
|
27
|
+
>
|
|
28
|
+
{children}
|
|
29
|
+
</View>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const styles = StyleSheet.create({
|
|
34
|
+
clipped: {
|
|
35
|
+
overflow: 'hidden',
|
|
36
|
+
},
|
|
37
|
+
overflowVisible: {
|
|
38
|
+
overflow: 'visible',
|
|
39
|
+
},
|
|
40
|
+
root: {
|
|
41
|
+
position: 'relative',
|
|
42
|
+
width: '100%',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { View } from '@ankhorage/zora';
|
|
2
|
+
import { StyleSheet, type ViewStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import type { GameOverlayPlacement, GameOverlayProps } from '../../../../types/gamePresentation';
|
|
5
|
+
|
|
6
|
+
/*** Render an absolute game presentation layer for HUD, feedback, and phase content. */
|
|
7
|
+
export function GameOverlay({
|
|
8
|
+
children,
|
|
9
|
+
placement = 'fill',
|
|
10
|
+
blocking = false,
|
|
11
|
+
padding = 0,
|
|
12
|
+
accessibilityLabel,
|
|
13
|
+
testID,
|
|
14
|
+
}: GameOverlayProps) {
|
|
15
|
+
return (
|
|
16
|
+
<View
|
|
17
|
+
{...(accessibilityLabel === undefined ? {} : { accessibilityLabel })}
|
|
18
|
+
{...(testID === undefined ? {} : { testID })}
|
|
19
|
+
pointerEvents={blocking ? 'auto' : 'box-none'}
|
|
20
|
+
style={[styles.root, resolvePlacementStyle(placement), { padding }]}
|
|
21
|
+
>
|
|
22
|
+
{children}
|
|
23
|
+
</View>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/*** Resolve overlay alignment without coupling layout to any game genre or rule. */
|
|
28
|
+
function resolvePlacementStyle(placement: GameOverlayPlacement): ViewStyle {
|
|
29
|
+
switch (placement) {
|
|
30
|
+
case 'center':
|
|
31
|
+
return { alignItems: 'center', justifyContent: 'center' };
|
|
32
|
+
case 'top':
|
|
33
|
+
return { alignItems: 'center', justifyContent: 'flex-start' };
|
|
34
|
+
case 'bottom':
|
|
35
|
+
return { alignItems: 'center', justifyContent: 'flex-end' };
|
|
36
|
+
case 'top-left':
|
|
37
|
+
return { alignItems: 'flex-start', justifyContent: 'flex-start' };
|
|
38
|
+
case 'top-right':
|
|
39
|
+
return { alignItems: 'flex-end', justifyContent: 'flex-start' };
|
|
40
|
+
case 'bottom-left':
|
|
41
|
+
return { alignItems: 'flex-start', justifyContent: 'flex-end' };
|
|
42
|
+
case 'bottom-right':
|
|
43
|
+
return { alignItems: 'flex-end', justifyContent: 'flex-end' };
|
|
44
|
+
case 'fill':
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const styles = StyleSheet.create({
|
|
50
|
+
root: {
|
|
51
|
+
bottom: 0,
|
|
52
|
+
left: 0,
|
|
53
|
+
position: 'absolute',
|
|
54
|
+
right: 0,
|
|
55
|
+
top: 0,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { ZoraComponentMeta } from '@ankhorage/zora/metadata';
|
|
2
|
+
|
|
3
|
+
/*** Describe one positioned generic game entity for ZORA authoring tools. */
|
|
4
|
+
export const gameEntityMeta = {
|
|
5
|
+
name: 'GameEntity',
|
|
6
|
+
category: 'component',
|
|
7
|
+
description: 'Positions arbitrary visual content inside a GameField without owning game rules.',
|
|
8
|
+
directManifestNode: true,
|
|
9
|
+
allowedChildren: ['Badge', 'Icon', 'Image', 'Text', 'View'],
|
|
10
|
+
blueprint: {
|
|
11
|
+
label: 'Game entity',
|
|
12
|
+
defaultProps: { x: 0, y: 0, opacity: 1, scale: 1, rotation: 0, zIndex: 0 },
|
|
13
|
+
},
|
|
14
|
+
props: {
|
|
15
|
+
x: {
|
|
16
|
+
type: 'number',
|
|
17
|
+
category: 'Position',
|
|
18
|
+
label: 'X (%)',
|
|
19
|
+
default: 0,
|
|
20
|
+
authoring: { authority: 'instance' },
|
|
21
|
+
},
|
|
22
|
+
y: {
|
|
23
|
+
type: 'number',
|
|
24
|
+
category: 'Position',
|
|
25
|
+
label: 'Y (%)',
|
|
26
|
+
default: 0,
|
|
27
|
+
authoring: { authority: 'instance' },
|
|
28
|
+
},
|
|
29
|
+
width: {
|
|
30
|
+
type: 'number',
|
|
31
|
+
category: 'Size',
|
|
32
|
+
label: 'Width',
|
|
33
|
+
authoring: { authority: 'instance' },
|
|
34
|
+
},
|
|
35
|
+
height: {
|
|
36
|
+
type: 'number',
|
|
37
|
+
category: 'Size',
|
|
38
|
+
label: 'Height',
|
|
39
|
+
authoring: { authority: 'instance' },
|
|
40
|
+
},
|
|
41
|
+
opacity: {
|
|
42
|
+
type: 'number',
|
|
43
|
+
category: 'Appearance',
|
|
44
|
+
label: 'Opacity',
|
|
45
|
+
default: 1,
|
|
46
|
+
authoring: { authority: 'instance' },
|
|
47
|
+
},
|
|
48
|
+
scale: {
|
|
49
|
+
type: 'number',
|
|
50
|
+
category: 'Transform',
|
|
51
|
+
label: 'Scale',
|
|
52
|
+
default: 1,
|
|
53
|
+
authoring: { authority: 'instance' },
|
|
54
|
+
},
|
|
55
|
+
rotation: {
|
|
56
|
+
type: 'number',
|
|
57
|
+
category: 'Transform',
|
|
58
|
+
label: 'Rotation',
|
|
59
|
+
default: 0,
|
|
60
|
+
authoring: { authority: 'instance' },
|
|
61
|
+
},
|
|
62
|
+
zIndex: {
|
|
63
|
+
type: 'number',
|
|
64
|
+
category: 'Position',
|
|
65
|
+
label: 'Z index',
|
|
66
|
+
default: 0,
|
|
67
|
+
authoring: { authority: 'instance' },
|
|
68
|
+
},
|
|
69
|
+
hidden: {
|
|
70
|
+
type: 'boolean',
|
|
71
|
+
category: 'State',
|
|
72
|
+
label: 'Hidden',
|
|
73
|
+
default: false,
|
|
74
|
+
authoring: { authority: 'instance' },
|
|
75
|
+
},
|
|
76
|
+
pointerEvents: {
|
|
77
|
+
type: 'enum',
|
|
78
|
+
category: 'Interaction',
|
|
79
|
+
label: 'Pointer events',
|
|
80
|
+
enum: ['auto', 'box-none', 'box-only', 'none'],
|
|
81
|
+
default: 'auto',
|
|
82
|
+
authoring: { authority: 'instance' },
|
|
83
|
+
},
|
|
84
|
+
accessibilityLabel: {
|
|
85
|
+
type: 'string',
|
|
86
|
+
category: 'Accessibility',
|
|
87
|
+
label: 'Accessibility label',
|
|
88
|
+
authoring: { authority: 'instance' },
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
} as const satisfies ZoraComponentMeta;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ZoraComponentMeta } from '@ankhorage/zora/metadata';
|
|
2
|
+
|
|
3
|
+
/*** Describe the embeddable game field for ZORA authoring tools. */
|
|
4
|
+
export const gameFieldMeta = {
|
|
5
|
+
name: 'GameField',
|
|
6
|
+
category: 'layout',
|
|
7
|
+
description: 'Relative positioning surface for embeddable game presentation content.',
|
|
8
|
+
directManifestNode: true,
|
|
9
|
+
allowedChildren: ['GameEntity', 'GameOverlay', 'Gradient', 'Image', 'View'],
|
|
10
|
+
blueprint: {
|
|
11
|
+
label: 'Game field',
|
|
12
|
+
defaultProps: { minHeight: 320, clip: true },
|
|
13
|
+
},
|
|
14
|
+
props: {
|
|
15
|
+
aspectRatio: {
|
|
16
|
+
type: 'number',
|
|
17
|
+
category: 'Layout',
|
|
18
|
+
label: 'Aspect ratio',
|
|
19
|
+
authoring: { authority: 'instance' },
|
|
20
|
+
},
|
|
21
|
+
minHeight: {
|
|
22
|
+
type: 'number',
|
|
23
|
+
category: 'Layout',
|
|
24
|
+
label: 'Minimum height',
|
|
25
|
+
default: 320,
|
|
26
|
+
authoring: { authority: 'instance' },
|
|
27
|
+
},
|
|
28
|
+
clip: {
|
|
29
|
+
type: 'boolean',
|
|
30
|
+
category: 'Layout',
|
|
31
|
+
label: 'Clip overflow',
|
|
32
|
+
default: true,
|
|
33
|
+
authoring: { authority: 'instance' },
|
|
34
|
+
},
|
|
35
|
+
accessibilityLabel: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
category: 'Accessibility',
|
|
38
|
+
label: 'Accessibility label',
|
|
39
|
+
authoring: { authority: 'instance' },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
} as const satisfies ZoraComponentMeta;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ZoraComponentMeta } from '@ankhorage/zora/metadata';
|
|
2
|
+
|
|
3
|
+
/*** Describe a generic absolute game layer for HUD, feedback, and phase content. */
|
|
4
|
+
export const gameOverlayMeta = {
|
|
5
|
+
name: 'GameOverlay',
|
|
6
|
+
category: 'layout',
|
|
7
|
+
description: 'Absolute presentation layer for HUD, feedback, controls, and phase content.',
|
|
8
|
+
directManifestNode: true,
|
|
9
|
+
allowedChildren: [
|
|
10
|
+
'Badge',
|
|
11
|
+
'Button',
|
|
12
|
+
'ButtonGroup',
|
|
13
|
+
'Card',
|
|
14
|
+
'GameEntity',
|
|
15
|
+
'Heading',
|
|
16
|
+
'Icon',
|
|
17
|
+
'Image',
|
|
18
|
+
'Progress',
|
|
19
|
+
'ProgressRing',
|
|
20
|
+
'Text',
|
|
21
|
+
'View',
|
|
22
|
+
],
|
|
23
|
+
blueprint: {
|
|
24
|
+
label: 'Game overlay',
|
|
25
|
+
defaultProps: { placement: 'fill', blocking: false, padding: 0 },
|
|
26
|
+
},
|
|
27
|
+
props: {
|
|
28
|
+
placement: {
|
|
29
|
+
type: 'enum',
|
|
30
|
+
category: 'Layout',
|
|
31
|
+
label: 'Placement',
|
|
32
|
+
enum: [
|
|
33
|
+
'fill',
|
|
34
|
+
'center',
|
|
35
|
+
'top',
|
|
36
|
+
'bottom',
|
|
37
|
+
'top-left',
|
|
38
|
+
'top-right',
|
|
39
|
+
'bottom-left',
|
|
40
|
+
'bottom-right',
|
|
41
|
+
],
|
|
42
|
+
default: 'fill',
|
|
43
|
+
authoring: { authority: 'instance' },
|
|
44
|
+
},
|
|
45
|
+
blocking: {
|
|
46
|
+
type: 'boolean',
|
|
47
|
+
category: 'Interaction',
|
|
48
|
+
label: 'Block pointer input',
|
|
49
|
+
default: false,
|
|
50
|
+
authoring: { authority: 'instance' },
|
|
51
|
+
},
|
|
52
|
+
padding: {
|
|
53
|
+
type: 'number',
|
|
54
|
+
category: 'Layout',
|
|
55
|
+
label: 'Padding',
|
|
56
|
+
default: 0,
|
|
57
|
+
authoring: { authority: 'instance' },
|
|
58
|
+
},
|
|
59
|
+
accessibilityLabel: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
category: 'Accessibility',
|
|
62
|
+
label: 'Accessibility label',
|
|
63
|
+
authoring: { authority: 'instance' },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
} as const satisfies ZoraComponentMeta;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
GameEntityProps,
|
|
3
|
+
GameFieldProps,
|
|
4
|
+
GameOverlayPlacement,
|
|
5
|
+
GameOverlayProps,
|
|
6
|
+
GamePointerEvents,
|
|
7
|
+
} from '../../types/gamePresentation';
|
|
8
|
+
export { GameEntity } from './adapters/inbound/GameEntity';
|
|
9
|
+
export { GameField } from './adapters/inbound/GameField';
|
|
10
|
+
export { GameOverlay } from './adapters/inbound/GameOverlay';
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
GameEntityProps,
|
|
3
|
+
GameFieldProps,
|
|
4
|
+
GameOverlayPlacement,
|
|
5
|
+
GameOverlayProps,
|
|
6
|
+
GamePointerEvents,
|
|
7
|
+
} from './features/game-presentation/public';
|
|
8
|
+
export { GameEntity, GameField, GameOverlay } from './features/game-presentation/public';
|
|
9
|
+
export { ZORA_GAME_PLUGIN } from './ZORA_GAME_PLUGIN';
|
package/src/metadata.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
|
|
3
|
+
type GameOverlayCornerPlacement = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
4
|
+
|
|
5
|
+
export type GamePointerEvents = 'auto' | 'box-none' | 'box-only' | 'none';
|
|
6
|
+
export type GameOverlayPlacement =
|
|
7
|
+
'fill' | 'center' | 'top' | 'bottom' | GameOverlayCornerPlacement;
|
|
8
|
+
|
|
9
|
+
export interface GameFieldProps {
|
|
10
|
+
readonly children?: React.ReactNode;
|
|
11
|
+
readonly aspectRatio?: number;
|
|
12
|
+
readonly minHeight?: number;
|
|
13
|
+
readonly clip?: boolean;
|
|
14
|
+
readonly accessibilityLabel?: string;
|
|
15
|
+
readonly testID?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface GameEntityProps {
|
|
19
|
+
readonly children?: React.ReactNode;
|
|
20
|
+
readonly x?: number;
|
|
21
|
+
readonly y?: number;
|
|
22
|
+
readonly width?: number;
|
|
23
|
+
readonly height?: number;
|
|
24
|
+
readonly opacity?: number;
|
|
25
|
+
readonly scale?: number;
|
|
26
|
+
readonly rotation?: number;
|
|
27
|
+
readonly zIndex?: number;
|
|
28
|
+
readonly hidden?: boolean;
|
|
29
|
+
readonly pointerEvents?: GamePointerEvents;
|
|
30
|
+
readonly accessibilityLabel?: string;
|
|
31
|
+
readonly testID?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface GameOverlayProps {
|
|
35
|
+
readonly children?: React.ReactNode;
|
|
36
|
+
readonly placement?: GameOverlayPlacement;
|
|
37
|
+
readonly blocking?: boolean;
|
|
38
|
+
readonly padding?: number;
|
|
39
|
+
readonly accessibilityLabel?: string;
|
|
40
|
+
readonly testID?: string;
|
|
41
|
+
}
|