@energy8platform/game-engine 0.14.10 → 0.15.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/dist/audio.cjs.js +6 -1
- package/dist/audio.cjs.js.map +1 -1
- package/dist/audio.esm.js +6 -1
- package/dist/audio.esm.js.map +1 -1
- package/dist/core.cjs.js +6 -1
- package/dist/core.cjs.js.map +1 -1
- package/dist/core.esm.js +6 -1
- package/dist/core.esm.js.map +1 -1
- package/dist/index.cjs.js +23 -9
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +24 -5
- package/dist/index.esm.js +23 -9
- package/dist/index.esm.js.map +1 -1
- package/dist/react-jsx.cjs.js +3 -0
- package/dist/react-jsx.cjs.js.map +1 -0
- package/dist/react-jsx.d.ts +582 -0
- package/dist/react-jsx.esm.js +2 -0
- package/dist/react-jsx.esm.js.map +1 -0
- package/dist/react.cjs.js +141 -11
- package/dist/react.cjs.js.map +1 -1
- package/dist/react.esm.js +141 -11
- package/dist/react.esm.js.map +1 -1
- package/dist/ui.cjs.js +109 -8
- package/dist/ui.cjs.js.map +1 -1
- package/dist/ui.d.ts +82 -7
- package/dist/ui.esm.js +109 -9
- package/dist/ui.esm.js.map +1 -1
- package/package.json +6 -1
- package/src/audio/AudioManager.ts +6 -1
- package/src/react/applyProps.ts +32 -1
- package/src/react/extendAll.ts +2 -2
- package/src/react/{jsx.d.ts → jsx-runtime.ts} +48 -8
- package/src/react/reconciler.ts +1 -1
- package/src/ui/FlexContainer.ts +39 -11
- package/src/ui/LabelValue.ts +122 -0
- package/src/ui/index.ts +2 -0
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* JSX IntrinsicElements
|
|
2
|
+
* Ambient JSX IntrinsicElements declarations for the PixiJS React reconciler.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* -
|
|
4
|
+
* Consumer apps opt in once (e.g. from an app-level `vite-env.d.ts`):
|
|
5
|
+
*
|
|
6
|
+
* import '@energy8platform/game-engine/react-jsx';
|
|
7
|
+
*
|
|
8
|
+
* After that, TypeScript recognises `<flexContainer>`, `<button>`, `<label>` etc.
|
|
9
|
+
* with fully-typed props — no need to hand-maintain a local `pixi-jsx.d.ts`.
|
|
10
|
+
*
|
|
11
|
+
* The JS entry for this subpath is intentionally empty: this module exists
|
|
12
|
+
* solely to carry type declarations that side-effect the global `JSX` namespace.
|
|
7
13
|
*
|
|
8
14
|
* Dash-notation is supported for nested config objects:
|
|
9
15
|
* <button colors-default={0xff0000} colors-hover={0x00ff00} />
|
|
10
16
|
*/
|
|
11
17
|
|
|
12
|
-
import type {
|
|
18
|
+
import type { Texture, TextStyle } from 'pixi.js';
|
|
13
19
|
import type { ViewInput } from '../ui/view';
|
|
14
20
|
import type { ButtonConfig, ButtonState } from '../ui/Button';
|
|
15
21
|
import type { LabelConfig } from '../ui/Label';
|
|
22
|
+
import type { LabelValueConfig } from '../ui/LabelValue';
|
|
16
23
|
import type { PanelConfig } from '../ui/Panel';
|
|
17
|
-
import type { FlexContainerConfig,
|
|
24
|
+
import type { FlexContainerConfig, AlignSelf, AlignContent } from '../ui/FlexContainer';
|
|
18
25
|
import type { ProgressBarConfig } from '../ui/ProgressBar';
|
|
19
26
|
import type { ScrollContainerConfig } from '../ui/ScrollContainer';
|
|
20
27
|
import type { ModalConfig } from '../ui/Modal';
|
|
@@ -90,11 +97,18 @@ interface BaseProps extends PixiEventProps {
|
|
|
90
97
|
layoutHeight?: number | string;
|
|
91
98
|
alignSelf?: AlignSelf;
|
|
92
99
|
flexExclude?: boolean;
|
|
93
|
-
// Absolute positioning for flexExclude children
|
|
100
|
+
// Absolute positioning for flexExclude children.
|
|
101
|
+
// Values describe the visual bounding rectangle (top-left of the rendered
|
|
102
|
+
// frame), so elements with centered origin like Button/Label are positioned
|
|
103
|
+
// intuitively — (left: 100, top: 50) puts the visible corner at (100, 50).
|
|
94
104
|
top?: number;
|
|
95
105
|
right?: number;
|
|
96
106
|
bottom?: number;
|
|
97
107
|
left?: number;
|
|
108
|
+
/** X coordinate of the visual center within parent (px or `'50%'`). Overrides left/right. */
|
|
109
|
+
centerX?: number | string;
|
|
110
|
+
/** Y coordinate of the visual center within parent (px or `'50%'`). Overrides top/bottom. */
|
|
111
|
+
centerY?: number | string;
|
|
98
112
|
}
|
|
99
113
|
|
|
100
114
|
// ─── PixiJS primitive elements ───────────────────────────
|
|
@@ -120,6 +134,14 @@ interface TextProps extends BaseProps {
|
|
|
120
134
|
interface GraphicsProps extends BaseProps {
|
|
121
135
|
/** Draw function: receives the Graphics instance, called on mount and updates */
|
|
122
136
|
draw?: (g: any) => void;
|
|
137
|
+
/**
|
|
138
|
+
* Layout size hint (pixels). For Graphics, `width`/`height` do NOT apply a scale
|
|
139
|
+
* transform (unlike Container.width). They're forwarded to the parent
|
|
140
|
+
* FlexContainer as `layoutWidth`/`layoutHeight` so layout measures the element
|
|
141
|
+
* at the requested size while the actual geometry stays in the `draw` callback.
|
|
142
|
+
*/
|
|
143
|
+
width?: number;
|
|
144
|
+
height?: number;
|
|
123
145
|
}
|
|
124
146
|
|
|
125
147
|
// ─── Engine UI component props ───────────────────────────
|
|
@@ -157,11 +179,28 @@ interface LabelComponentProps extends BaseProps, Omit<LabelConfig, 'style'> {
|
|
|
157
179
|
'style-letterSpacing'?: number;
|
|
158
180
|
}
|
|
159
181
|
|
|
182
|
+
interface LabelValueComponentProps extends Omit<BaseProps, 'width' | 'height' | 'label'>,
|
|
183
|
+
Omit<LabelValueConfig, 'labelStyle' | 'valueStyle'> {
|
|
184
|
+
labelStyle?: Partial<TextStyle>;
|
|
185
|
+
valueStyle?: Partial<TextStyle>;
|
|
186
|
+
width?: number | string;
|
|
187
|
+
height?: number | string;
|
|
188
|
+
// Dash-notation for nested styles
|
|
189
|
+
'labelStyle-fontSize'?: number;
|
|
190
|
+
'labelStyle-fill'?: number | string;
|
|
191
|
+
'labelStyle-fontFamily'?: string;
|
|
192
|
+
'labelStyle-fontWeight'?: string;
|
|
193
|
+
'valueStyle-fontSize'?: number;
|
|
194
|
+
'valueStyle-fill'?: number | string;
|
|
195
|
+
'valueStyle-fontFamily'?: string;
|
|
196
|
+
'valueStyle-fontWeight'?: string;
|
|
197
|
+
}
|
|
198
|
+
|
|
160
199
|
interface PanelComponentProps extends BaseProps, Omit<PanelConfig, 'layout'> {
|
|
161
200
|
layout?: Partial<FlexContainerConfig>;
|
|
162
201
|
}
|
|
163
202
|
|
|
164
|
-
interface FlexContainerComponentProps extends BaseProps, FlexContainerConfig {
|
|
203
|
+
interface FlexContainerComponentProps extends Omit<BaseProps, 'width' | 'height'>, FlexContainerConfig {
|
|
165
204
|
padding?: number | [number, number, number, number];
|
|
166
205
|
paddingTop?: number;
|
|
167
206
|
paddingRight?: number;
|
|
@@ -243,6 +282,7 @@ declare global {
|
|
|
243
282
|
// Engine UI components
|
|
244
283
|
button: ButtonComponentProps;
|
|
245
284
|
label: LabelComponentProps;
|
|
285
|
+
labelValue: LabelValueComponentProps;
|
|
246
286
|
panel: PanelComponentProps;
|
|
247
287
|
flexContainer: FlexContainerComponentProps;
|
|
248
288
|
progressBar: ProgressBarComponentProps;
|
package/src/react/reconciler.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { FlexContainer } from '../ui/FlexContainer';
|
|
|
7
7
|
import type { FlexItemConfig } from '../ui/FlexContainer';
|
|
8
8
|
|
|
9
9
|
/** Flex item prop names that should be forwarded to _flexConfig on the child */
|
|
10
|
-
const FLEX_ITEM_PROPS = ['flexGrow', 'flexShrink', 'layoutWidth', 'layoutHeight', 'alignSelf', 'flexExclude', 'top', 'right', 'bottom', 'left'] as const;
|
|
10
|
+
const FLEX_ITEM_PROPS = ['flexGrow', 'flexShrink', 'layoutWidth', 'layoutHeight', 'alignSelf', 'flexExclude', 'top', 'right', 'bottom', 'left', 'centerX', 'centerY'] as const;
|
|
11
11
|
|
|
12
12
|
/** Any component with suspendLayout/resumeLayout (FlexContainer, Panel, etc.) */
|
|
13
13
|
interface Suspendable {
|
package/src/ui/FlexContainer.ts
CHANGED
|
@@ -20,16 +20,35 @@ export interface FlexItemConfig {
|
|
|
20
20
|
layoutHeight?: number | string;
|
|
21
21
|
/** Override parent's alignItems for this child */
|
|
22
22
|
alignSelf?: AlignSelf;
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Exclude from flex layout (acts like position: absolute).
|
|
25
|
+
*
|
|
26
|
+
* Positioning props (`top`/`right`/`bottom`/`left`/`centerX`/`centerY`) describe
|
|
27
|
+
* the **visual bounding rectangle**, so children with a centered internal
|
|
28
|
+
* origin (Button, Label — `anchor = 0.5`) are positioned intuitively.
|
|
29
|
+
* `left: 100` places the visible left edge at 100px, regardless of origin.
|
|
30
|
+
*/
|
|
24
31
|
flexExclude?: boolean;
|
|
25
|
-
/**
|
|
32
|
+
/** Distance from top edge of parent content area to the child's visual top */
|
|
26
33
|
top?: number;
|
|
27
|
-
/**
|
|
34
|
+
/** Distance from right edge of parent content area to the child's visual right */
|
|
28
35
|
right?: number;
|
|
29
|
-
/**
|
|
36
|
+
/** Distance from bottom edge of parent content area to the child's visual bottom */
|
|
30
37
|
bottom?: number;
|
|
31
|
-
/**
|
|
38
|
+
/** Distance from left edge of parent content area to the child's visual left */
|
|
32
39
|
left?: number;
|
|
40
|
+
/**
|
|
41
|
+
* X coordinate of the child's visual center within parent content area.
|
|
42
|
+
* Accepts pixels (`200`) or a percentage of parent content width (`'50%'`).
|
|
43
|
+
* Takes precedence over `left`/`right`.
|
|
44
|
+
*/
|
|
45
|
+
centerX?: number | string;
|
|
46
|
+
/**
|
|
47
|
+
* Y coordinate of the child's visual center within parent content area.
|
|
48
|
+
* Accepts pixels or a percentage of parent content height (`'50%'`).
|
|
49
|
+
* Takes precedence over `top`/`bottom`.
|
|
50
|
+
*/
|
|
51
|
+
centerY?: number | string;
|
|
33
52
|
}
|
|
34
53
|
|
|
35
54
|
export interface FlexContainerConfig {
|
|
@@ -679,17 +698,26 @@ export class FlexContainer extends Container {
|
|
|
679
698
|
this._computedHeight = this._explicitHeight > 0 ? this._explicitHeight : (pt + naturalMainSize + pb);
|
|
680
699
|
}
|
|
681
700
|
|
|
682
|
-
// Position flexExclude children (absolute positioning)
|
|
701
|
+
// Position flexExclude children (absolute positioning).
|
|
702
|
+
// All position props describe the visual (bounds) rectangle, so we subtract
|
|
703
|
+
// `ox/oy` to compensate for children with a centered origin (Button, Label).
|
|
704
|
+
// `centerX/centerY` take precedence over `left/right` / `top/bottom` on each axis.
|
|
683
705
|
for (const child of this._layoutChildren) {
|
|
684
706
|
if (!child._flexConfig?.flexExclude) continue;
|
|
685
707
|
const cfg = child._flexConfig;
|
|
686
|
-
const { w, h } = measureChild(child, pctRefW, pctRefH);
|
|
708
|
+
const { w, h, ox, oy } = measureChild(child, pctRefW, pctRefH);
|
|
687
709
|
const cw = this._computedWidth;
|
|
688
710
|
const ch = this._computedHeight;
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
if (
|
|
692
|
-
else if (cfg.
|
|
711
|
+
|
|
712
|
+
const centerX = resolveDimension(cfg.centerX, pctRefW);
|
|
713
|
+
if (centerX !== undefined) child.x = centerX - w / 2 - ox;
|
|
714
|
+
else if (cfg.left !== undefined) child.x = cfg.left - ox;
|
|
715
|
+
else if (cfg.right !== undefined) child.x = cw - w - cfg.right - ox;
|
|
716
|
+
|
|
717
|
+
const centerY = resolveDimension(cfg.centerY, pctRefH);
|
|
718
|
+
if (centerY !== undefined) child.y = centerY - h / 2 - oy;
|
|
719
|
+
else if (cfg.top !== undefined) child.y = cfg.top - oy;
|
|
720
|
+
else if (cfg.bottom !== undefined) child.y = ch - h - cfg.bottom - oy;
|
|
693
721
|
}
|
|
694
722
|
}
|
|
695
723
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { TextStyle } from 'pixi.js';
|
|
2
|
+
import { FlexContainer, type FlexContainerConfig } from './FlexContainer';
|
|
3
|
+
import { Label } from './Label';
|
|
4
|
+
|
|
5
|
+
export type LabelValueAlign = 'start' | 'center' | 'end';
|
|
6
|
+
|
|
7
|
+
export interface LabelValueConfig {
|
|
8
|
+
/** Caption text (top row, typically smaller/muted) */
|
|
9
|
+
label?: string;
|
|
10
|
+
/** Value text (bottom row, typically larger/prominent) */
|
|
11
|
+
value?: string;
|
|
12
|
+
/** Style for the caption Label */
|
|
13
|
+
labelStyle?: Partial<TextStyle>;
|
|
14
|
+
/** Style for the value Label */
|
|
15
|
+
valueStyle?: Partial<TextStyle>;
|
|
16
|
+
/** Gap in pixels between caption and value (default: 4) */
|
|
17
|
+
gap?: number;
|
|
18
|
+
/** Horizontal alignment of both rows (default: 'center') */
|
|
19
|
+
align?: LabelValueAlign;
|
|
20
|
+
/** Maximum width — value will be auto-scaled to fit when exceeded */
|
|
21
|
+
maxWidth?: number;
|
|
22
|
+
/** Optional padding (forwarded to the underlying FlexContainer) */
|
|
23
|
+
padding?: FlexContainerConfig['padding'];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Two-row text cell with a muted caption above and a prominent value below —
|
|
28
|
+
* the archetypal casino UI pattern (BALANCE/€500, BET/€1, WIN/€0.00).
|
|
29
|
+
*
|
|
30
|
+
* Extends FlexContainer, so it participates in parent flex layouts directly
|
|
31
|
+
* (you can pass `flexGrow`, `alignSelf`, etc. when it's a child of another
|
|
32
|
+
* FlexContainer) and auto-sizes to its contents when no explicit size is set.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* <labelValue
|
|
37
|
+
* label="BALANCE"
|
|
38
|
+
* value={`€${balance.toFixed(2)}`}
|
|
39
|
+
* labelStyle={{ fontSize: 12, fill: 0x888888 }}
|
|
40
|
+
* valueStyle={{ fontSize: 22, fill: 0xffffff, fontWeight: 'bold' }}
|
|
41
|
+
* gap={6}
|
|
42
|
+
* align="center"
|
|
43
|
+
* />
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export class LabelValue extends FlexContainer {
|
|
47
|
+
private readonly _labelEl: Label;
|
|
48
|
+
private readonly _valueEl: Label;
|
|
49
|
+
private _valueMaxWidth: number;
|
|
50
|
+
|
|
51
|
+
constructor(config: LabelValueConfig = {}) {
|
|
52
|
+
super({
|
|
53
|
+
direction: 'column',
|
|
54
|
+
alignItems: toAlignItems(config.align ?? 'center'),
|
|
55
|
+
gap: config.gap ?? 4,
|
|
56
|
+
padding: config.padding,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
this._valueMaxWidth = config.maxWidth ?? Infinity;
|
|
60
|
+
|
|
61
|
+
this._labelEl = new Label({
|
|
62
|
+
text: config.label ?? '',
|
|
63
|
+
style: config.labelStyle,
|
|
64
|
+
});
|
|
65
|
+
this._valueEl = new Label({
|
|
66
|
+
text: config.value ?? '',
|
|
67
|
+
style: config.valueStyle,
|
|
68
|
+
maxWidth: config.maxWidth,
|
|
69
|
+
autoFit: config.maxWidth !== undefined,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
this.addFlexChild(this._labelEl);
|
|
73
|
+
this.addFlexChild(this._valueEl);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Get the caption Label (for advanced styling / animation) */
|
|
77
|
+
get labelElement(): Label {
|
|
78
|
+
return this._labelEl;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Get the value Label */
|
|
82
|
+
get valueElement(): Label {
|
|
83
|
+
return this._valueEl;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Update caption text */
|
|
87
|
+
setLabel(text: string): void {
|
|
88
|
+
this._labelEl.text = text;
|
|
89
|
+
this.updateLayout();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Update value text */
|
|
93
|
+
setValue(text: string): void {
|
|
94
|
+
this._valueEl.text = text;
|
|
95
|
+
this.updateLayout();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** React reconciler update hook */
|
|
99
|
+
override updateConfig(changed: Record<string, any>): void {
|
|
100
|
+
if ('label' in changed) this._labelEl.text = changed.label ?? '';
|
|
101
|
+
if ('value' in changed) this._valueEl.text = changed.value ?? '';
|
|
102
|
+
if ('labelStyle' in changed && typeof changed.labelStyle === 'object') {
|
|
103
|
+
Object.assign(this._labelEl.style, changed.labelStyle);
|
|
104
|
+
}
|
|
105
|
+
if ('valueStyle' in changed && typeof changed.valueStyle === 'object') {
|
|
106
|
+
Object.assign(this._valueEl.style, changed.valueStyle);
|
|
107
|
+
}
|
|
108
|
+
if ('maxWidth' in changed) {
|
|
109
|
+
this._valueMaxWidth = changed.maxWidth ?? Infinity;
|
|
110
|
+
this._valueEl.maxWidth = this._valueMaxWidth;
|
|
111
|
+
}
|
|
112
|
+
if ('gap' in changed) this.setGap(changed.gap);
|
|
113
|
+
if ('align' in changed) this.setAlignItems(toAlignItems(changed.align));
|
|
114
|
+
|
|
115
|
+
// Forward remaining FlexContainer props (e.g. padding, width, height)
|
|
116
|
+
super.updateConfig(changed);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function toAlignItems(align: LabelValueAlign): 'start' | 'center' | 'end' {
|
|
121
|
+
return align;
|
|
122
|
+
}
|
package/src/ui/index.ts
CHANGED
|
@@ -11,6 +11,8 @@ export { ProgressBar } from './ProgressBar';
|
|
|
11
11
|
export type { ProgressBarConfig } from './ProgressBar';
|
|
12
12
|
export { Label } from './Label';
|
|
13
13
|
export type { LabelConfig } from './Label';
|
|
14
|
+
export { LabelValue } from './LabelValue';
|
|
15
|
+
export type { LabelValueConfig, LabelValueAlign } from './LabelValue';
|
|
14
16
|
export { Panel } from './Panel';
|
|
15
17
|
export type { PanelConfig } from './Panel';
|
|
16
18
|
export { BalanceDisplay } from './BalanceDisplay';
|