hudini 0.2.1 → 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.
- package/README.md +187 -3
- package/dist/components/column/column.d.ts +88 -0
- package/dist/components/column/column.d.ts.map +1 -0
- package/dist/components/column/column.js +142 -0
- package/dist/components/column/column.js.map +1 -0
- package/dist/components/column/column.spec.d.ts +2 -0
- package/dist/components/column/column.spec.d.ts.map +1 -0
- package/dist/components/column/column.spec.js +147 -0
- package/dist/components/column/column.spec.js.map +1 -0
- package/dist/components/column/index.d.ts +2 -0
- package/dist/components/column/index.d.ts.map +1 -0
- package/dist/components/column/index.js +2 -0
- package/dist/components/column/index.js.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/layout/layout-utils.d.ts +13 -0
- package/dist/components/layout/layout-utils.d.ts.map +1 -0
- package/dist/components/layout/layout-utils.js +38 -0
- package/dist/components/layout/layout-utils.js.map +1 -0
- package/dist/components/layout/layout-utils.spec.d.ts +2 -0
- package/dist/components/layout/layout-utils.spec.d.ts.map +1 -0
- package/dist/components/layout/layout-utils.spec.js +70 -0
- package/dist/components/layout/layout-utils.spec.js.map +1 -0
- package/dist/components/row/index.d.ts +2 -0
- package/dist/components/row/index.d.ts.map +1 -0
- package/dist/components/row/index.js +2 -0
- package/dist/components/row/index.js.map +1 -0
- package/dist/components/row/row.d.ts +87 -0
- package/dist/components/row/row.d.ts.map +1 -0
- package/dist/components/row/row.js +139 -0
- package/dist/components/row/row.js.map +1 -0
- package/dist/components/row/row.spec.d.ts +2 -0
- package/dist/components/row/row.spec.d.ts.map +1 -0
- package/dist/components/row/row.spec.js +146 -0
- package/dist/components/row/row.spec.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<img src="data/hudini.png" alt="hudini" />
|
|
1
|
+
<img src="data/hudini.png" style="max-width: 500px" alt="hudini" />
|
|
2
2
|
|
|
3
3
|
# 🎩 Hudini
|
|
4
4
|
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
**Hudini** is a collection of reusable, themeable UI components for Phaser games. Named after the famous magician Houdini and HUD (Head-Up Display), it provides a magical toolkit for building consistent game interfaces.
|
|
8
8
|
|
|
9
|
+
> Important: Hudini is fully type‑safe. The entire library is written in TypeScript and uses strict, explicit types for all public APIs (components, layout options, and plugin configuration). You get compile‑time validation and rich IntelliSense everywhere—no runtime guessing.
|
|
10
|
+
|
|
9
11
|
## ✨ Features
|
|
10
12
|
|
|
11
13
|
- 🎨 **Themeable** - Dark/light themes with full customization
|
|
12
|
-
-
|
|
13
|
-
- 📦 **Zero Dependencies** - Only requires Phaser as peer dependency
|
|
14
|
+
- 📦 **Phaser-wind Dependency** - Only requires [Phaser-wind](https://github.com/renatocassino/phaser-toolkit/tree/main/packages/phaser-wind)
|
|
14
15
|
- 🎯 **TypeScript First** - Full type safety and IntelliSense
|
|
15
16
|
- 🧪 **Tested** - Comprehensive test coverage
|
|
16
17
|
|
|
@@ -23,3 +24,186 @@ yarn add hudini
|
|
|
23
24
|
# or
|
|
24
25
|
pnpm add hudini
|
|
25
26
|
```
|
|
27
|
+
|
|
28
|
+
## 🔌 Installation (Plugin Setup)
|
|
29
|
+
|
|
30
|
+
Hudini is built on top of `phaser-wind` for theming and UI primitives. The Hudini plugin will automatically install the `phaser-wind` plugin if it is not already registered. You only need to add Hudini to your Phaser game configuration.
|
|
31
|
+
|
|
32
|
+
Basic setup with the default light theme:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import Phaser from 'phaser';
|
|
36
|
+
import {
|
|
37
|
+
HudiniPlugin,
|
|
38
|
+
HUDINI_KEY,
|
|
39
|
+
HudiniPluginData,
|
|
40
|
+
createTheme,
|
|
41
|
+
} from 'hudini';
|
|
42
|
+
|
|
43
|
+
const theme = createTheme({
|
|
44
|
+
colors: {
|
|
45
|
+
primary: 'red-300',
|
|
46
|
+
secondary: 'blue-300',
|
|
47
|
+
},
|
|
48
|
+
// This theme is a phaser-wind theme conf. You can read more in https://github.com/renatocassino/phaser-toolkit/tree/main/packages/phaser-wind
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
type Theme = typeof theme;
|
|
52
|
+
|
|
53
|
+
new Phaser.Game({
|
|
54
|
+
type: Phaser.AUTO,
|
|
55
|
+
width: 800,
|
|
56
|
+
height: 600,
|
|
57
|
+
backgroundColor: '#1a1a1a',
|
|
58
|
+
plugins: {
|
|
59
|
+
global: [
|
|
60
|
+
{
|
|
61
|
+
key: HUDINI_KEY,
|
|
62
|
+
plugin: HudiniPlugin,
|
|
63
|
+
mapping: HUDINI_KEY,
|
|
64
|
+
data: {
|
|
65
|
+
theme,
|
|
66
|
+
} as HudiniPluginData<Theme>,
|
|
67
|
+
/**
|
|
68
|
+
* If you want to use a default theme, you can import "defaultLightTheme" from hudini
|
|
69
|
+
* data: {
|
|
70
|
+
* theme: defaultLightTheme,
|
|
71
|
+
* } as HudiniPluginData<Theme>
|
|
72
|
+
*/
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Notes:
|
|
80
|
+
|
|
81
|
+
- Hudini will ensure `phaser-wind` is available internally. If you prefer, you can also register `phaser-wind` explicitly before Hudini and pass a custom theme.
|
|
82
|
+
- You can pass `darkMode: true` (when no custom theme is provided) to use the default dark theme.
|
|
83
|
+
|
|
84
|
+
### Requirements
|
|
85
|
+
|
|
86
|
+
- Phaser (peer dependency)
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pnpm add phaser
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Import
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { Column, Row, IconButton } from 'hudini';
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Live examples
|
|
99
|
+
|
|
100
|
+
Check the Storybook for live, interactive examples: [Hudini on Storybook](https://renatocassino.github.io/phaser-toolkit/?path=/story/hudini--index)
|
|
101
|
+
|
|
102
|
+
## 🧩 Components
|
|
103
|
+
|
|
104
|
+
### Column
|
|
105
|
+
|
|
106
|
+
Stacks children vertically with spacing, horizontal alignment, and configurable vertical origin.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
// inside a Phaser.Scene (e.g., in create())
|
|
110
|
+
const spriteA = this.add.sprite(0, 0, 'player');
|
|
111
|
+
const spriteB = this.add.sprite(0, 0, 'enemy');
|
|
112
|
+
|
|
113
|
+
const column = new Column({
|
|
114
|
+
scene: this,
|
|
115
|
+
x: 400,
|
|
116
|
+
y: 300,
|
|
117
|
+
gap: 12, // default: 8
|
|
118
|
+
align: 'center', // 'left' | 'center' | 'right'
|
|
119
|
+
verticalOrigin: 'top', // 'top' | 'center' | 'bottom'
|
|
120
|
+
children: [spriteA, spriteB],
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Update layout options later
|
|
124
|
+
column.setGap(20);
|
|
125
|
+
column.setAlign('left');
|
|
126
|
+
|
|
127
|
+
// Add items dynamically
|
|
128
|
+
const spriteC = this.add.sprite(0, 0, 'coin');
|
|
129
|
+
column.addChild(spriteC); // triggers relayout by default
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Key points:
|
|
133
|
+
|
|
134
|
+
- Horizontal alignment aligns each child's left/center/right edge correctly, respecting per-child origin.
|
|
135
|
+
- `verticalOrigin` controls where the content starts from within the container.
|
|
136
|
+
- The container's position `(x, y)` is the center of the overall content area.
|
|
137
|
+
|
|
138
|
+
### Row
|
|
139
|
+
|
|
140
|
+
Arranges children horizontally with spacing, vertical alignment, and configurable horizontal origin.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// inside a Phaser.Scene (e.g., in create())
|
|
144
|
+
const heart = this.add.sprite(0, 0, 'heart');
|
|
145
|
+
const gem = this.add.sprite(0, 0, 'gem');
|
|
146
|
+
|
|
147
|
+
const row = new Row({
|
|
148
|
+
scene: this,
|
|
149
|
+
x: 400,
|
|
150
|
+
y: 80,
|
|
151
|
+
gap: 10, // default: 8
|
|
152
|
+
align: 'center', // 'top' | 'center' | 'bottom'
|
|
153
|
+
horizontalOrigin: 'center', // 'left' | 'center' | 'right'
|
|
154
|
+
children: [heart, gem],
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
row.setGap(16);
|
|
158
|
+
row.setAlign('top');
|
|
159
|
+
|
|
160
|
+
const star = this.add.sprite(0, 0, 'star');
|
|
161
|
+
row.addChild(star);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Key points:
|
|
165
|
+
|
|
166
|
+
- Vertical alignment aligns each child's top/center/bottom edge correctly, respecting per-child origin.
|
|
167
|
+
- `horizontalOrigin` controls where the content starts from within the container.
|
|
168
|
+
- The container's position `(x, y)` is the center of the overall content area.
|
|
169
|
+
|
|
170
|
+
### IconButton
|
|
171
|
+
|
|
172
|
+
An interactive circular icon button with hover and click animations, built on top of `phaser-wind` and `font-awesome-for-phaser`.
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
import { IconButton } from 'hudini';
|
|
176
|
+
// inside a Phaser.Scene (e.g., in create())
|
|
177
|
+
|
|
178
|
+
const btn = new IconButton({
|
|
179
|
+
scene: this,
|
|
180
|
+
x: 100,
|
|
181
|
+
y: 100,
|
|
182
|
+
icon: 'solid/heart', // any IconKey from font-awesome-for-phaser
|
|
183
|
+
size: 'lg', // FontSizeKey or a number (px)
|
|
184
|
+
color: 'red', // any base color from phaser-wind (except black/white)
|
|
185
|
+
onClick: () => {
|
|
186
|
+
// your click handler
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
this.add.existing(btn);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Notes:
|
|
194
|
+
|
|
195
|
+
- Hover scales the icon subtly, click animates press/release.
|
|
196
|
+
- Colors and sizes integrate with `phaser-wind` theme tokens.
|
|
197
|
+
|
|
198
|
+
## 📦 API Surfaces
|
|
199
|
+
|
|
200
|
+
- `Column` and `Row` are `Phaser.GameObjects.Container` subclasses. Useful methods:
|
|
201
|
+
- `setGap(gap: number): void`
|
|
202
|
+
- `setAlign(...)`: Column → `'left'|'center'|'right'`, Row → `'top'|'center'|'bottom'`
|
|
203
|
+
- `addChild(child, relayout = true): this`
|
|
204
|
+
- `addChildren(children, relayout = true): this`
|
|
205
|
+
- `IconButton` constructor accepts `{ scene, x, y, icon, size?, color?, onClick? }`.
|
|
206
|
+
|
|
207
|
+
## 🔗 Storybook
|
|
208
|
+
|
|
209
|
+
Explore all components and props in Storybook: [Hudini on Storybook](https://renatocassino.github.io/phaser-toolkit/?path=/story/hudini--index)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { GameObjects, Scene } from 'phaser';
|
|
2
|
+
/** Horizontal alignment options for column items */
|
|
3
|
+
export type HorizontalAlign = 'left' | 'center' | 'right';
|
|
4
|
+
/** Parameters for creating a Column container */
|
|
5
|
+
export type ColumnParams = {
|
|
6
|
+
/** The scene this column belongs to */
|
|
7
|
+
scene: Scene;
|
|
8
|
+
/** X coordinate of the column */
|
|
9
|
+
x: number;
|
|
10
|
+
/** Y coordinate of the column */
|
|
11
|
+
y: number;
|
|
12
|
+
/** Gap between elements in pixels */
|
|
13
|
+
gap?: number;
|
|
14
|
+
/** Horizontal alignment of elements */
|
|
15
|
+
align?: HorizontalAlign;
|
|
16
|
+
/** Initial child elements */
|
|
17
|
+
children?: GameObjects.GameObject[];
|
|
18
|
+
/** Vertical origin point of the column */
|
|
19
|
+
verticalOrigin?: 'top' | 'center' | 'bottom';
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Column is a layout container that stacks children vertically with a gap.
|
|
23
|
+
* The container position (x, y) represents the center of the whole column.
|
|
24
|
+
*/
|
|
25
|
+
export declare class Column extends GameObjects.Container {
|
|
26
|
+
/** Gap between elements in pixels */
|
|
27
|
+
private gap;
|
|
28
|
+
/** Horizontal alignment of elements */
|
|
29
|
+
private align;
|
|
30
|
+
/** Vertical origin point of the column */
|
|
31
|
+
private verticalOrigin;
|
|
32
|
+
/**
|
|
33
|
+
* Creates a new Column container
|
|
34
|
+
* @param params Configuration parameters for the column
|
|
35
|
+
*/
|
|
36
|
+
constructor({ scene, x, y, gap, align, children, verticalOrigin, }: ColumnParams);
|
|
37
|
+
/**
|
|
38
|
+
* Sets the spacing between children and relayouts
|
|
39
|
+
* @param gap Gap in pixels between elements
|
|
40
|
+
*/
|
|
41
|
+
setGap(gap: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* Sets the horizontal alignment and relayouts
|
|
44
|
+
* @param align New horizontal alignment
|
|
45
|
+
*/
|
|
46
|
+
setAlign(align: HorizontalAlign): void;
|
|
47
|
+
/**
|
|
48
|
+
* Adds a child game object to the column
|
|
49
|
+
* @param child Game object to add
|
|
50
|
+
* @param relayout Whether to relayout after adding (default: true)
|
|
51
|
+
* @returns This column instance for chaining
|
|
52
|
+
*/
|
|
53
|
+
addChild(child: GameObjects.GameObject, relayout?: boolean): this;
|
|
54
|
+
/**
|
|
55
|
+
* Adds multiple children to the column
|
|
56
|
+
* @param children Array of game objects to add
|
|
57
|
+
* @param relayout Whether to relayout after adding (default: true)
|
|
58
|
+
* @returns This column instance for chaining
|
|
59
|
+
*/
|
|
60
|
+
addChildren(children: GameObjects.GameObject[], relayout?: boolean): this;
|
|
61
|
+
/**
|
|
62
|
+
* Recomputes children's positions and updates this container size
|
|
63
|
+
* Positions are calculated based on alignment, origins and gaps
|
|
64
|
+
*/
|
|
65
|
+
layout(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Gets the display width of a game object
|
|
68
|
+
* @param child GameObject to measure
|
|
69
|
+
* @returns Display width in pixels
|
|
70
|
+
*/
|
|
71
|
+
getDisplayWidth(child: GameObjects.GameObject): number;
|
|
72
|
+
/**
|
|
73
|
+
* Gets the display height of a game object
|
|
74
|
+
* @param child GameObject to measure
|
|
75
|
+
* @returns Display height in pixels
|
|
76
|
+
*/
|
|
77
|
+
getDisplayHeight(child: GameObjects.GameObject): number;
|
|
78
|
+
/**
|
|
79
|
+
* Gets the normalized origin point of a game object
|
|
80
|
+
* @param child GameObject to get origin from
|
|
81
|
+
* @returns Object with normalized x,y coordinates of the origin point
|
|
82
|
+
*/
|
|
83
|
+
getNormalizedOrigin(child: GameObjects.GameObject): {
|
|
84
|
+
x: number;
|
|
85
|
+
y: number;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=column.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"column.d.ts","sourceRoot":"","sources":["../../../src/components/column/column.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAS5C,oDAAoD;AACpD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1D,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG;IACzB,uCAAuC;IACvC,KAAK,EAAE,KAAK,CAAC;IACb,iCAAiC;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,iCAAiC;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,qCAAqC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,EAAE,CAAC;IACpC,0CAA0C;IAC1C,cAAc,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAC9C,CAAC;AAEF;;;GAGG;AACH,qBAAa,MAAO,SAAQ,WAAW,CAAC,SAAS;IAC/C,qCAAqC;IACrC,OAAO,CAAC,GAAG,CAAS;IACpB,uCAAuC;IACvC,OAAO,CAAC,KAAK,CAAkB;IAC/B,0CAA0C;IAC1C,OAAO,CAAC,cAAc,CAA8B;IAEpD;;;OAGG;gBACS,EACV,KAAK,EACL,CAAC,EACD,CAAC,EACD,GAAiB,EACjB,KAAgB,EAChB,QAAa,EACb,cAAsB,GACvB,EAAE,YAAY;IAaf;;;OAGG;IACI,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKhC;;;OAGG;IACI,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAK7C;;;;;OAKG;IACI,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,EAAE,QAAQ,GAAE,OAAc,GAAG,IAAI;IAM9E;;;;;OAKG;IACI,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,UAAU,EAAE,EAAE,QAAQ,GAAE,OAAc,GAAG,IAAI;IAMtF;;;OAGG;IACI,MAAM,IAAI,IAAI;IAkDrB;;;;OAIG;IACI,eAAe,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,GAAG,MAAM;IAI7D;;;;OAIG;IACI,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,GAAG,MAAM;IAI9D;;;;OAIG;IACI,mBAAmB,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE;CAGpF"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/* eslint-disable complexity */
|
|
2
|
+
import { GameObjects } from 'phaser';
|
|
3
|
+
import { DEFAULT_GAP, getDisplayHeightOf, getDisplayWidthOf, getNormalizedOriginOf, } from '../layout/layout-utils';
|
|
4
|
+
/**
|
|
5
|
+
* Column is a layout container that stacks children vertically with a gap.
|
|
6
|
+
* The container position (x, y) represents the center of the whole column.
|
|
7
|
+
*/
|
|
8
|
+
export class Column extends GameObjects.Container {
|
|
9
|
+
/** Gap between elements in pixels */
|
|
10
|
+
gap;
|
|
11
|
+
/** Horizontal alignment of elements */
|
|
12
|
+
align;
|
|
13
|
+
/** Vertical origin point of the column */
|
|
14
|
+
verticalOrigin;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new Column container
|
|
17
|
+
* @param params Configuration parameters for the column
|
|
18
|
+
*/
|
|
19
|
+
constructor({ scene, x, y, gap = DEFAULT_GAP, align = 'center', children = [], verticalOrigin = 'top', }) {
|
|
20
|
+
super(scene, x, y);
|
|
21
|
+
this.gap = gap;
|
|
22
|
+
this.align = align;
|
|
23
|
+
this.verticalOrigin = verticalOrigin;
|
|
24
|
+
if (children.length > 0) {
|
|
25
|
+
this.add(children);
|
|
26
|
+
}
|
|
27
|
+
this.layout();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Sets the spacing between children and relayouts
|
|
31
|
+
* @param gap Gap in pixels between elements
|
|
32
|
+
*/
|
|
33
|
+
setGap(gap) {
|
|
34
|
+
this.gap = gap;
|
|
35
|
+
this.layout();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Sets the horizontal alignment and relayouts
|
|
39
|
+
* @param align New horizontal alignment
|
|
40
|
+
*/
|
|
41
|
+
setAlign(align) {
|
|
42
|
+
this.align = align;
|
|
43
|
+
this.layout();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Adds a child game object to the column
|
|
47
|
+
* @param child Game object to add
|
|
48
|
+
* @param relayout Whether to relayout after adding (default: true)
|
|
49
|
+
* @returns This column instance for chaining
|
|
50
|
+
*/
|
|
51
|
+
addChild(child, relayout = true) {
|
|
52
|
+
this.add(child);
|
|
53
|
+
if (relayout)
|
|
54
|
+
this.layout();
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Adds multiple children to the column
|
|
59
|
+
* @param children Array of game objects to add
|
|
60
|
+
* @param relayout Whether to relayout after adding (default: true)
|
|
61
|
+
* @returns This column instance for chaining
|
|
62
|
+
*/
|
|
63
|
+
addChildren(children, relayout = true) {
|
|
64
|
+
if (children.length > 0)
|
|
65
|
+
this.add(children);
|
|
66
|
+
if (relayout)
|
|
67
|
+
this.layout();
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Recomputes children's positions and updates this container size
|
|
72
|
+
* Positions are calculated based on alignment, origins and gaps
|
|
73
|
+
*/
|
|
74
|
+
layout() {
|
|
75
|
+
const children = this.list;
|
|
76
|
+
if (children.length === 0) {
|
|
77
|
+
// Reset size when empty
|
|
78
|
+
this.setSize(0, 0);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Measure sizes and origins
|
|
82
|
+
const entries = children.map((child) => ({
|
|
83
|
+
child,
|
|
84
|
+
width: this.getDisplayWidth(child),
|
|
85
|
+
height: this.getDisplayHeight(child),
|
|
86
|
+
origin: this.getNormalizedOrigin(child),
|
|
87
|
+
}));
|
|
88
|
+
const maxWidth = entries.reduce((m, s) => Math.max(m, s.width), 0);
|
|
89
|
+
const totalHeight = entries.reduce((sum, s) => sum + s.height, 0) + this.gap * (entries.length - 1);
|
|
90
|
+
// Determine top of content based on verticalOrigin
|
|
91
|
+
const contentTopY = this.verticalOrigin === 'top' ? 0 : this.verticalOrigin === 'center' ? -totalHeight / 2 : -totalHeight;
|
|
92
|
+
// Walk from top to bottom, aligning considering each child's origin
|
|
93
|
+
let cursorTopY = contentTopY;
|
|
94
|
+
for (const { child, width, height, origin } of entries) {
|
|
95
|
+
// Horizontal alignment: align left/right edges or centers correctly using origin
|
|
96
|
+
let x = 0;
|
|
97
|
+
if (this.align === 'left') {
|
|
98
|
+
// place child's left edge at content left
|
|
99
|
+
x = -maxWidth / 2 + origin.x * width;
|
|
100
|
+
}
|
|
101
|
+
else if (this.align === 'right') {
|
|
102
|
+
// place child's right edge at content right
|
|
103
|
+
x = maxWidth / 2 - (1 - origin.x) * width;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
// center alignment: center of child at 0 accounting for origin
|
|
107
|
+
x = (origin.x - 0.5) * width;
|
|
108
|
+
}
|
|
109
|
+
// Vertical position so that child's top is at cursorTopY
|
|
110
|
+
const y = cursorTopY + origin.y * height;
|
|
111
|
+
child.setPosition(x, y);
|
|
112
|
+
cursorTopY += height + this.gap;
|
|
113
|
+
}
|
|
114
|
+
// Update this container size to match content bounds
|
|
115
|
+
this.setSize(maxWidth, totalHeight);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Gets the display width of a game object
|
|
119
|
+
* @param child GameObject to measure
|
|
120
|
+
* @returns Display width in pixels
|
|
121
|
+
*/
|
|
122
|
+
getDisplayWidth(child) {
|
|
123
|
+
return getDisplayWidthOf(child);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Gets the display height of a game object
|
|
127
|
+
* @param child GameObject to measure
|
|
128
|
+
* @returns Display height in pixels
|
|
129
|
+
*/
|
|
130
|
+
getDisplayHeight(child) {
|
|
131
|
+
return getDisplayHeightOf(child);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Gets the normalized origin point of a game object
|
|
135
|
+
* @param child GameObject to get origin from
|
|
136
|
+
* @returns Object with normalized x,y coordinates of the origin point
|
|
137
|
+
*/
|
|
138
|
+
getNormalizedOrigin(child) {
|
|
139
|
+
return getNormalizedOriginOf(child);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=column.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"column.js","sourceRoot":"","sources":["../../../src/components/column/column.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"column.spec.d.ts","sourceRoot":"","sources":["../../../src/components/column/column.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/* eslint-disable no-magic-numbers */
|
|
2
|
+
/* eslint-disable max-lines-per-function */
|
|
3
|
+
import { Scene } from 'phaser';
|
|
4
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
// Mock to phaser with type to avoid canvas dependency in runtime
|
|
6
|
+
vi.mock('phaser', () => {
|
|
7
|
+
class Scene {
|
|
8
|
+
}
|
|
9
|
+
class Container {
|
|
10
|
+
list = [];
|
|
11
|
+
x;
|
|
12
|
+
y;
|
|
13
|
+
width = 0;
|
|
14
|
+
height = 0;
|
|
15
|
+
// scene is accepted but not used in the mock
|
|
16
|
+
constructor(_scene, x, y) {
|
|
17
|
+
this.x = x;
|
|
18
|
+
this.y = y;
|
|
19
|
+
}
|
|
20
|
+
add(child) {
|
|
21
|
+
if (Array.isArray(child)) {
|
|
22
|
+
this.list.push(...child);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
this.list.push(child);
|
|
26
|
+
}
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
setSize(width, height) {
|
|
30
|
+
this.width = width;
|
|
31
|
+
this.height = height;
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const GameObjects = { Container };
|
|
36
|
+
return { GameObjects, Scene };
|
|
37
|
+
});
|
|
38
|
+
import { Column } from './column';
|
|
39
|
+
class TestChild {
|
|
40
|
+
displayWidth;
|
|
41
|
+
width;
|
|
42
|
+
displayHeight;
|
|
43
|
+
height;
|
|
44
|
+
originX;
|
|
45
|
+
originY;
|
|
46
|
+
displayOriginX;
|
|
47
|
+
displayOriginY;
|
|
48
|
+
lastPosition = null;
|
|
49
|
+
constructor(params = {}) {
|
|
50
|
+
Object.assign(this, params);
|
|
51
|
+
}
|
|
52
|
+
setPosition(x, y) {
|
|
53
|
+
this.lastPosition = { x, y };
|
|
54
|
+
}
|
|
55
|
+
getBounds() {
|
|
56
|
+
return {
|
|
57
|
+
width: this.width ?? this.displayWidth ?? 0,
|
|
58
|
+
height: this.height ?? this.displayHeight ?? 0,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
let scene;
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
scene = new Scene();
|
|
65
|
+
});
|
|
66
|
+
describe('Column layout', () => {
|
|
67
|
+
it('centers children by default with verticalOrigin top', () => {
|
|
68
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
69
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
70
|
+
const col = new Column({ scene, x: 0, y: 0, gap: 10, align: 'center', verticalOrigin: 'top', children: [] });
|
|
71
|
+
col.addChildren([a, b]);
|
|
72
|
+
// After construction or addition, layout is applied
|
|
73
|
+
expect(a.lastPosition).toEqual({ x: 0, y: 25 }); // 0 + 0.5*50
|
|
74
|
+
expect(b.lastPosition).toEqual({ x: 0, y: 110 }); // (50 + 10) + 0.5*100
|
|
75
|
+
// width = max child width; height = sum + gaps
|
|
76
|
+
// maxWidth = 200; totalHeight = 50 + 100 + 10 = 160
|
|
77
|
+
expect(col.width).toBe(200);
|
|
78
|
+
expect(col.height).toBe(160);
|
|
79
|
+
});
|
|
80
|
+
it('align left positions children at content left edge', () => {
|
|
81
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
82
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
83
|
+
const col = new Column({ scene, x: 0, y: 0, gap: 10, align: 'left', verticalOrigin: 'top', children: [a, b] });
|
|
84
|
+
// maxWidth = 200
|
|
85
|
+
expect(a.lastPosition?.x).toBe(-50); // -maxWidth/2 + 0.5*100 = -100 + 50
|
|
86
|
+
expect(b.lastPosition?.x).toBe(0); // -100 + 0.5*200 = 0
|
|
87
|
+
expect(col.width).toBe(200);
|
|
88
|
+
expect(col.height).toBe(160);
|
|
89
|
+
});
|
|
90
|
+
it('align right positions children at content right edge', () => {
|
|
91
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
92
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
93
|
+
new Column({ scene, x: 0, y: 0, gap: 10, align: 'right', verticalOrigin: 'top', children: [a, b] });
|
|
94
|
+
expect(a.lastPosition?.x).toBe(50); // +maxWidth/2 - (1-0.5)*100 = 100 - 50
|
|
95
|
+
expect(b.lastPosition?.x).toBe(0); // 100 - (1-0.5)*200 = 0
|
|
96
|
+
});
|
|
97
|
+
it('verticalOrigin center shifts content up by half height', () => {
|
|
98
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
99
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
100
|
+
// totalHeight = 50 + 100 + 10 = 160; top starts at -80
|
|
101
|
+
new Column({ scene, x: 0, y: 0, gap: 10, align: 'center', verticalOrigin: 'center', children: [a, b] });
|
|
102
|
+
expect(a.lastPosition?.y).toBe(-80 + 0.5 * 50); // -55
|
|
103
|
+
expect(b.lastPosition?.y).toBe(-80 + 50 + 10 + 0.5 * 100); // -80 + 60 + 50 = 30
|
|
104
|
+
});
|
|
105
|
+
it('respects per-child origin when computing alignment and positions', () => {
|
|
106
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50, originX: 0.0, originY: 0.0 });
|
|
107
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100, originX: 1.0, originY: 1.0 });
|
|
108
|
+
// maxWidth = 200; totalHeight = 160; top = 0 (verticalOrigin top)
|
|
109
|
+
new Column({ scene, x: 0, y: 0, gap: 10, align: 'left', verticalOrigin: 'top', children: [a, b] });
|
|
110
|
+
// a: x = -100 + 0*100 = -100; y = 0 + 0*50 = 0
|
|
111
|
+
expect(a.lastPosition).toEqual({ x: -100, y: 0 });
|
|
112
|
+
// cursor = 50 + 10 = 60; b: x = -100 + 1*200 = 100; y = 60 + 1*100 = 160
|
|
113
|
+
expect(b.lastPosition).toEqual({ x: 100, y: 160 });
|
|
114
|
+
});
|
|
115
|
+
it('setGap and setAlign trigger relayout', () => {
|
|
116
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
117
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
118
|
+
const col = new Column({ scene, x: 0, y: 0, children: [a, b] }); // default gap=8, align=center, verticalOrigin=top
|
|
119
|
+
// Initial state with gap=8
|
|
120
|
+
expect(b.lastPosition?.y).toBe(50 + 8 + 50); // 108
|
|
121
|
+
col.setGap(20); // changes layout
|
|
122
|
+
expect(b.lastPosition?.y).toBe(50 + 20 + 50); // 120
|
|
123
|
+
col.setAlign('left');
|
|
124
|
+
// maxWidth=200 => a.x = -100 + 0.5*100 = -50; b.x = -100 + 0.5*200 = 0
|
|
125
|
+
expect(a.lastPosition?.x).toBe(-50);
|
|
126
|
+
expect(b.lastPosition?.x).toBe(0);
|
|
127
|
+
});
|
|
128
|
+
it('addChild/addChildren optionally avoid relayout when requested', () => {
|
|
129
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
130
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
131
|
+
const col = new Column({ scene, x: 0, y: 0, children: [a] });
|
|
132
|
+
// b added without relayout
|
|
133
|
+
col.addChild(b, false);
|
|
134
|
+
const before = b.lastPosition;
|
|
135
|
+
expect(before).toBeNull();
|
|
136
|
+
// When calling layout, positions are calculated
|
|
137
|
+
col.layout();
|
|
138
|
+
expect(b.lastPosition).not.toBeNull();
|
|
139
|
+
});
|
|
140
|
+
it('empty column has size 0,0', () => {
|
|
141
|
+
const col = new Column({ scene, x: 0, y: 0, children: [] });
|
|
142
|
+
// After constructor, layout runs and sizes to 0,0
|
|
143
|
+
expect(col.width).toBe(0);
|
|
144
|
+
expect(col.height).toBe(0);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=column.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"column.spec.js","sourceRoot":"","sources":["../../../src/components/column/column.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/column/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/column/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC"}
|
package/dist/components/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { GameObjects } from 'phaser';
|
|
2
|
+
/** Default gap between elements in pixels */
|
|
3
|
+
export declare const DEFAULT_GAP = 8;
|
|
4
|
+
/** Measures the display width of a game object, with fallbacks */
|
|
5
|
+
export declare const getDisplayWidthOf: (child: GameObjects.GameObject) => number;
|
|
6
|
+
/** Measures the display height of a game object, with fallbacks */
|
|
7
|
+
export declare const getDisplayHeightOf: (child: GameObjects.GameObject) => number;
|
|
8
|
+
/** Returns normalized origin (0..1) for a game object */
|
|
9
|
+
export declare const getNormalizedOriginOf: (child: GameObjects.GameObject) => {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=layout-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout-utils.d.ts","sourceRoot":"","sources":["../../../src/components/layout/layout-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,6CAA6C;AAC7C,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B,kEAAkE;AAClE,eAAO,MAAM,iBAAiB,GAAI,OAAO,WAAW,CAAC,UAAU,KAAG,MAUjE,CAAC;AAEF,mEAAmE;AACnE,eAAO,MAAM,kBAAkB,GAAI,OAAO,WAAW,CAAC,UAAU,KAAG,MAUlE,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,GAAI,OAAO,WAAW,CAAC,UAAU,KAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAwB3F,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Default gap between elements in pixels */
|
|
2
|
+
export const DEFAULT_GAP = 8;
|
|
3
|
+
/** Measures the display width of a game object, with fallbacks */
|
|
4
|
+
export const getDisplayWidthOf = (child) => {
|
|
5
|
+
const childTyped = child;
|
|
6
|
+
if (typeof childTyped.displayWidth === 'number')
|
|
7
|
+
return childTyped.displayWidth;
|
|
8
|
+
if (typeof childTyped.width === 'number')
|
|
9
|
+
return childTyped.width;
|
|
10
|
+
const bounds = childTyped.getBounds?.();
|
|
11
|
+
return bounds ? bounds.width : 0;
|
|
12
|
+
};
|
|
13
|
+
/** Measures the display height of a game object, with fallbacks */
|
|
14
|
+
export const getDisplayHeightOf = (child) => {
|
|
15
|
+
const childTyped = child;
|
|
16
|
+
if (typeof childTyped.displayHeight === 'number')
|
|
17
|
+
return childTyped.displayHeight;
|
|
18
|
+
if (typeof childTyped.height === 'number')
|
|
19
|
+
return childTyped.height;
|
|
20
|
+
const bounds = childTyped.getBounds?.();
|
|
21
|
+
return bounds ? bounds.height : 0;
|
|
22
|
+
};
|
|
23
|
+
/** Returns normalized origin (0..1) for a game object */
|
|
24
|
+
export const getNormalizedOriginOf = (child) => {
|
|
25
|
+
const width = getDisplayWidthOf(child);
|
|
26
|
+
const height = getDisplayHeightOf(child);
|
|
27
|
+
const childTyped = child;
|
|
28
|
+
let ox = typeof childTyped.originX === 'number' ? childTyped.originX : undefined;
|
|
29
|
+
let oy = typeof childTyped.originY === 'number' ? childTyped.originY : undefined;
|
|
30
|
+
if (ox === undefined && typeof childTyped.displayOriginX === 'number' && width > 0) {
|
|
31
|
+
ox = childTyped.displayOriginX / width;
|
|
32
|
+
}
|
|
33
|
+
if (oy === undefined && typeof childTyped.displayOriginY === 'number' && height > 0) {
|
|
34
|
+
oy = childTyped.displayOriginY / height;
|
|
35
|
+
}
|
|
36
|
+
return { x: ox ?? 0.5, y: oy ?? 0.5 };
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=layout-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout-utils.js","sourceRoot":"","sources":["../../../src/components/layout/layout-utils.ts"],"names":[],"mappings":"AAGA,6CAA6C;AAC7C,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAE7B,kEAAkE;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAA6B,EAAU,EAAE;IACzE,MAAM,UAAU,GAAG,KAIlB,CAAC;IACF,IAAI,OAAO,UAAU,CAAC,YAAY,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC,YAAY,CAAC;IAChF,IAAI,OAAO,UAAU,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC,KAAe,CAAC;IAC5E,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC;IACxC,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,mEAAmE;AACnE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAA6B,EAAU,EAAE;IAC1E,MAAM,UAAU,GAAG,KAIlB,CAAC;IACF,IAAI,OAAO,UAAU,CAAC,aAAa,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC,aAAa,CAAC;IAClF,IAAI,OAAO,UAAU,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC,MAAgB,CAAC;IAC9E,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC;IACxC,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF,yDAAyD;AACzD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAA6B,EAA4B,EAAE;IAC/F,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAEzC,MAAM,UAAU,GAAG,KAKlB,CAAC;IAEF,IAAI,EAAE,GACJ,OAAO,UAAU,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,IAAI,EAAE,GACJ,OAAO,UAAU,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAE1E,IAAI,EAAE,KAAK,SAAS,IAAI,OAAO,UAAU,CAAC,cAAc,KAAK,QAAQ,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACnF,EAAE,GAAG,UAAU,CAAC,cAAc,GAAG,KAAK,CAAC;IACzC,CAAC;IACD,IAAI,EAAE,KAAK,SAAS,IAAI,OAAO,UAAU,CAAC,cAAc,KAAK,QAAQ,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACpF,EAAE,GAAG,UAAU,CAAC,cAAc,GAAG,MAAM,CAAC;IAC1C,CAAC;IAED,OAAO,EAAE,CAAC,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC;AACxC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout-utils.spec.d.ts","sourceRoot":"","sources":["../../../src/components/layout/layout-utils.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { DEFAULT_GAP, getDisplayHeightOf, getDisplayWidthOf, getNormalizedOriginOf, } from './layout-utils';
|
|
3
|
+
// Helper to satisfy typing without importing Phaser types in tests
|
|
4
|
+
const asGO = (o) => o;
|
|
5
|
+
describe('layout-utils', () => {
|
|
6
|
+
it('DEFAULT_GAP should be 8', () => {
|
|
7
|
+
expect(DEFAULT_GAP).toBe(8);
|
|
8
|
+
});
|
|
9
|
+
describe('getDisplayWidthOf', () => {
|
|
10
|
+
it('prefers displayWidth when present', () => {
|
|
11
|
+
const obj = asGO({ displayWidth: 120, width: 200, getBounds: () => ({ width: 300 }) });
|
|
12
|
+
expect(getDisplayWidthOf(obj)).toBe(120);
|
|
13
|
+
});
|
|
14
|
+
it('falls back to width when displayWidth is absent', () => {
|
|
15
|
+
const obj = asGO({ width: 200, getBounds: () => ({ width: 300 }) });
|
|
16
|
+
expect(getDisplayWidthOf(obj)).toBe(200);
|
|
17
|
+
});
|
|
18
|
+
it('falls back to getBounds().width when both displayWidth and width are absent', () => {
|
|
19
|
+
const obj = asGO({ getBounds: () => ({ width: 300 }) });
|
|
20
|
+
expect(getDisplayWidthOf(obj)).toBe(300);
|
|
21
|
+
});
|
|
22
|
+
it('returns 0 when nothing is available', () => {
|
|
23
|
+
const obj = asGO({});
|
|
24
|
+
expect(getDisplayWidthOf(obj)).toBe(0);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('getDisplayHeightOf', () => {
|
|
28
|
+
it('prefers displayHeight when present', () => {
|
|
29
|
+
const obj = asGO({ displayHeight: 110, height: 210, getBounds: () => ({ height: 310 }) });
|
|
30
|
+
expect(getDisplayHeightOf(obj)).toBe(110);
|
|
31
|
+
});
|
|
32
|
+
it('falls back to height when displayHeight is absent', () => {
|
|
33
|
+
const obj = asGO({ height: 210, getBounds: () => ({ height: 310 }) });
|
|
34
|
+
expect(getDisplayHeightOf(obj)).toBe(210);
|
|
35
|
+
});
|
|
36
|
+
it('falls back to getBounds().height when both displayHeight and height are absent', () => {
|
|
37
|
+
const obj = asGO({ getBounds: () => ({ height: 310 }) });
|
|
38
|
+
expect(getDisplayHeightOf(obj)).toBe(310);
|
|
39
|
+
});
|
|
40
|
+
it('returns 0 when nothing is available', () => {
|
|
41
|
+
const obj = asGO({});
|
|
42
|
+
expect(getDisplayHeightOf(obj)).toBe(0);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe('getNormalizedOriginOf', () => {
|
|
46
|
+
it('returns originX/Y when provided', () => {
|
|
47
|
+
const obj = asGO({ originX: 0.2, originY: 0.8, displayWidth: 100, displayHeight: 100 });
|
|
48
|
+
expect(getNormalizedOriginOf(obj)).toEqual({ x: 0.2, y: 0.8 });
|
|
49
|
+
});
|
|
50
|
+
it('computes from displayOriginX/Y over displayWidth/Height when originX/Y absent', () => {
|
|
51
|
+
const obj = asGO({ displayOriginX: 25, displayOriginY: 50, displayWidth: 100, displayHeight: 200 });
|
|
52
|
+
// x = 25/100 = 0.25, y = 50/200 = 0.25
|
|
53
|
+
expect(getNormalizedOriginOf(obj)).toEqual({ x: 0.25, y: 0.25 });
|
|
54
|
+
});
|
|
55
|
+
it('defaults to 0.5 when origins are missing and size is zero', () => {
|
|
56
|
+
const obj = asGO({ displayOriginX: 10, displayOriginY: 10, displayWidth: 0, displayHeight: 0 });
|
|
57
|
+
expect(getNormalizedOriginOf(obj)).toEqual({ x: 0.5, y: 0.5 });
|
|
58
|
+
});
|
|
59
|
+
it('uses mixed fallbacks per axis independently', () => {
|
|
60
|
+
const obj = asGO({
|
|
61
|
+
originX: 0.1, // should take precedence on X
|
|
62
|
+
displayOriginY: 30,
|
|
63
|
+
displayHeight: 120, // Y should be 30/120 = 0.25
|
|
64
|
+
displayWidth: 400,
|
|
65
|
+
});
|
|
66
|
+
expect(getNormalizedOriginOf(obj)).toEqual({ x: 0.1, y: 0.25 });
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=layout-utils.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout-utils.spec.js","sourceRoot":"","sources":["../../../src/components/layout/layout-utils.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/row/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/row/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { GameObjects, Scene } from 'phaser';
|
|
2
|
+
/** Vertical alignment options for row items */
|
|
3
|
+
export type VerticalAlign = 'top' | 'center' | 'bottom';
|
|
4
|
+
/** Parameters for creating a Row container */
|
|
5
|
+
export type RowParams = {
|
|
6
|
+
/** The scene this row belongs to */
|
|
7
|
+
scene: Scene;
|
|
8
|
+
/** X coordinate of the row */
|
|
9
|
+
x: number;
|
|
10
|
+
/** Y coordinate of the row */
|
|
11
|
+
y: number;
|
|
12
|
+
/** Gap between elements in pixels */
|
|
13
|
+
gap?: number;
|
|
14
|
+
/** Vertical alignment of elements */
|
|
15
|
+
align?: VerticalAlign;
|
|
16
|
+
/** Initial child elements */
|
|
17
|
+
children?: GameObjects.GameObject[];
|
|
18
|
+
/** Horizontal origin point of the row */
|
|
19
|
+
horizontalOrigin?: 'left' | 'center' | 'right';
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Row is a layout container that arranges children horizontally with a gap.
|
|
23
|
+
* The container position (x, y) represents the center of the whole row.
|
|
24
|
+
*/
|
|
25
|
+
export declare class Row extends GameObjects.Container {
|
|
26
|
+
/** Gap between elements in pixels */
|
|
27
|
+
private gap;
|
|
28
|
+
/** Vertical alignment of elements */
|
|
29
|
+
private align;
|
|
30
|
+
/** Horizontal origin point of the row */
|
|
31
|
+
private horizontalOrigin;
|
|
32
|
+
/**
|
|
33
|
+
* Creates a new Row container
|
|
34
|
+
* @param params Configuration parameters for the row
|
|
35
|
+
*/
|
|
36
|
+
constructor({ scene, x, y, gap, align, children, horizontalOrigin, }: RowParams);
|
|
37
|
+
/**
|
|
38
|
+
* Sets the gap between elements and updates layout
|
|
39
|
+
* @param gap Gap size in pixels
|
|
40
|
+
*/
|
|
41
|
+
setGap(gap: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* Sets the vertical alignment and updates layout
|
|
44
|
+
* @param align New vertical alignment
|
|
45
|
+
*/
|
|
46
|
+
setAlign(align: VerticalAlign): void;
|
|
47
|
+
/**
|
|
48
|
+
* Adds a single child to the row
|
|
49
|
+
* @param child GameObject to add
|
|
50
|
+
* @param relayout Whether to update layout after adding
|
|
51
|
+
* @returns This row instance for chaining
|
|
52
|
+
*/
|
|
53
|
+
addChild(child: GameObjects.GameObject, relayout?: boolean): this;
|
|
54
|
+
/**
|
|
55
|
+
* Adds multiple children to the row
|
|
56
|
+
* @param children Array of GameObjects to add
|
|
57
|
+
* @param relayout Whether to update layout after adding
|
|
58
|
+
* @returns This row instance for chaining
|
|
59
|
+
*/
|
|
60
|
+
addChildren(children: GameObjects.GameObject[], relayout?: boolean): this;
|
|
61
|
+
/**
|
|
62
|
+
* Recomputes children's positions and updates this container size
|
|
63
|
+
*/
|
|
64
|
+
layout(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Gets the display width of a game object
|
|
67
|
+
* @param child GameObject to measure
|
|
68
|
+
* @returns Display width in pixels
|
|
69
|
+
*/
|
|
70
|
+
getDisplayWidth(child: GameObjects.GameObject): number;
|
|
71
|
+
/**
|
|
72
|
+
* Gets the display height of a game object
|
|
73
|
+
* @param child GameObject to measure
|
|
74
|
+
* @returns Display height in pixels
|
|
75
|
+
*/
|
|
76
|
+
getDisplayHeight(child: GameObjects.GameObject): number;
|
|
77
|
+
/**
|
|
78
|
+
* Gets the normalized origin point of a game object
|
|
79
|
+
* @param child GameObject to get origin from
|
|
80
|
+
* @returns Object with normalized x,y coordinates of the origin point
|
|
81
|
+
*/
|
|
82
|
+
getNormalizedOrigin(child: GameObjects.GameObject): {
|
|
83
|
+
x: number;
|
|
84
|
+
y: number;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row.d.ts","sourceRoot":"","sources":["../../../src/components/row/row.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAS5C,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAExD,8CAA8C;AAC9C,MAAM,MAAM,SAAS,GAAG;IACtB,oCAAoC;IACpC,KAAK,EAAE,KAAK,CAAC;IACb,8BAA8B;IAC9B,CAAC,EAAE,MAAM,CAAC;IACV,8BAA8B;IAC9B,CAAC,EAAE,MAAM,CAAC;IACV,qCAAqC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,EAAE,CAAC;IACpC,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CAChD,CAAC;AAEF;;;GAGG;AACH,qBAAa,GAAI,SAAQ,WAAW,CAAC,SAAS;IAC5C,qCAAqC;IACrC,OAAO,CAAC,GAAG,CAAS;IACpB,qCAAqC;IACrC,OAAO,CAAC,KAAK,CAAgB;IAC7B,yCAAyC;IACzC,OAAO,CAAC,gBAAgB,CAA8B;IAEtD;;;OAGG;gBACS,EACV,KAAK,EACL,CAAC,EACD,CAAC,EACD,GAAiB,EACjB,KAAgB,EAChB,QAAa,EACb,gBAA2B,GAC5B,EAAE,SAAS;IAcZ;;;OAGG;IACI,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKhC;;;OAGG;IACI,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAK3C;;;;;OAKG;IACI,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,EAAE,QAAQ,GAAE,OAAc,GAAG,IAAI;IAM9E;;;;;OAKG;IACI,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,UAAU,EAAE,EAAE,QAAQ,GAAE,OAAc,GAAG,IAAI;IAMtF;;OAEG;IACI,MAAM,IAAI,IAAI;IAgDrB;;;;OAIG;IACI,eAAe,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,GAAG,MAAM;IAI7D;;;;OAIG;IACI,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,GAAG,MAAM;IAI9D;;;;OAIG;IACI,mBAAmB,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE;CAGpF"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/* eslint-disable complexity */
|
|
2
|
+
import { GameObjects } from 'phaser';
|
|
3
|
+
import { DEFAULT_GAP, getDisplayHeightOf, getDisplayWidthOf, getNormalizedOriginOf, } from '../layout/layout-utils';
|
|
4
|
+
/**
|
|
5
|
+
* Row is a layout container that arranges children horizontally with a gap.
|
|
6
|
+
* The container position (x, y) represents the center of the whole row.
|
|
7
|
+
*/
|
|
8
|
+
export class Row extends GameObjects.Container {
|
|
9
|
+
/** Gap between elements in pixels */
|
|
10
|
+
gap;
|
|
11
|
+
/** Vertical alignment of elements */
|
|
12
|
+
align;
|
|
13
|
+
/** Horizontal origin point of the row */
|
|
14
|
+
horizontalOrigin;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new Row container
|
|
17
|
+
* @param params Configuration parameters for the row
|
|
18
|
+
*/
|
|
19
|
+
constructor({ scene, x, y, gap = DEFAULT_GAP, align = 'center', children = [], horizontalOrigin = 'center', }) {
|
|
20
|
+
super(scene, x, y);
|
|
21
|
+
this.gap = gap;
|
|
22
|
+
this.align = align;
|
|
23
|
+
this.horizontalOrigin = horizontalOrigin;
|
|
24
|
+
if (children.length > 0) {
|
|
25
|
+
this.add(children);
|
|
26
|
+
}
|
|
27
|
+
this.layout();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Sets the gap between elements and updates layout
|
|
31
|
+
* @param gap Gap size in pixels
|
|
32
|
+
*/
|
|
33
|
+
setGap(gap) {
|
|
34
|
+
this.gap = gap;
|
|
35
|
+
this.layout();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Sets the vertical alignment and updates layout
|
|
39
|
+
* @param align New vertical alignment
|
|
40
|
+
*/
|
|
41
|
+
setAlign(align) {
|
|
42
|
+
this.align = align;
|
|
43
|
+
this.layout();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Adds a single child to the row
|
|
47
|
+
* @param child GameObject to add
|
|
48
|
+
* @param relayout Whether to update layout after adding
|
|
49
|
+
* @returns This row instance for chaining
|
|
50
|
+
*/
|
|
51
|
+
addChild(child, relayout = true) {
|
|
52
|
+
this.add(child);
|
|
53
|
+
if (relayout)
|
|
54
|
+
this.layout();
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Adds multiple children to the row
|
|
59
|
+
* @param children Array of GameObjects to add
|
|
60
|
+
* @param relayout Whether to update layout after adding
|
|
61
|
+
* @returns This row instance for chaining
|
|
62
|
+
*/
|
|
63
|
+
addChildren(children, relayout = true) {
|
|
64
|
+
if (children.length > 0)
|
|
65
|
+
this.add(children);
|
|
66
|
+
if (relayout)
|
|
67
|
+
this.layout();
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Recomputes children's positions and updates this container size
|
|
72
|
+
*/
|
|
73
|
+
layout() {
|
|
74
|
+
const children = this.list;
|
|
75
|
+
if (children.length === 0) {
|
|
76
|
+
this.setSize(0, 0);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Measure sizes and origins
|
|
80
|
+
const entries = children.map((child) => ({
|
|
81
|
+
child,
|
|
82
|
+
width: this.getDisplayWidth(child),
|
|
83
|
+
height: this.getDisplayHeight(child),
|
|
84
|
+
origin: this.getNormalizedOrigin(child),
|
|
85
|
+
}));
|
|
86
|
+
const maxHeight = entries.reduce((m, s) => Math.max(m, s.height), 0);
|
|
87
|
+
const totalWidth = entries.reduce((sum, s) => sum + s.width, 0) + this.gap * (entries.length - 1);
|
|
88
|
+
// Determine left of content based on horizontalOrigin
|
|
89
|
+
const contentLeftX = this.horizontalOrigin === 'left' ? 0 : this.horizontalOrigin === 'center' ? -totalWidth / 2 : -totalWidth;
|
|
90
|
+
// Walk left to right, aligning considering each child's origin
|
|
91
|
+
let cursorLeftX = contentLeftX;
|
|
92
|
+
for (const { child, width, height, origin } of entries) {
|
|
93
|
+
// Vertical alignment: align top/bottom edges or centers correctly using origin
|
|
94
|
+
let y = 0;
|
|
95
|
+
if (this.align === 'top') {
|
|
96
|
+
// place child's top edge at content top
|
|
97
|
+
y = -maxHeight / 2 + origin.y * height;
|
|
98
|
+
}
|
|
99
|
+
else if (this.align === 'bottom') {
|
|
100
|
+
// place child's bottom edge at content bottom
|
|
101
|
+
y = maxHeight / 2 - (1 - origin.y) * height;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// center alignment
|
|
105
|
+
y = (origin.y - 0.5) * height;
|
|
106
|
+
}
|
|
107
|
+
// Horizontal position so that child's left is at cursorLeftX
|
|
108
|
+
const x = cursorLeftX + origin.x * width;
|
|
109
|
+
child.setPosition(x, y);
|
|
110
|
+
cursorLeftX += width + this.gap;
|
|
111
|
+
}
|
|
112
|
+
this.setSize(totalWidth, maxHeight);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Gets the display width of a game object
|
|
116
|
+
* @param child GameObject to measure
|
|
117
|
+
* @returns Display width in pixels
|
|
118
|
+
*/
|
|
119
|
+
getDisplayWidth(child) {
|
|
120
|
+
return getDisplayWidthOf(child);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Gets the display height of a game object
|
|
124
|
+
* @param child GameObject to measure
|
|
125
|
+
* @returns Display height in pixels
|
|
126
|
+
*/
|
|
127
|
+
getDisplayHeight(child) {
|
|
128
|
+
return getDisplayHeightOf(child);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Gets the normalized origin point of a game object
|
|
132
|
+
* @param child GameObject to get origin from
|
|
133
|
+
* @returns Object with normalized x,y coordinates of the origin point
|
|
134
|
+
*/
|
|
135
|
+
getNormalizedOrigin(child) {
|
|
136
|
+
return getNormalizedOriginOf(child);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row.js","sourceRoot":"","sources":["../../../src/components/row/row.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row.spec.d.ts","sourceRoot":"","sources":["../../../src/components/row/row.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/* eslint-disable no-magic-numbers */
|
|
2
|
+
/* eslint-disable max-lines-per-function */
|
|
3
|
+
import { Scene } from 'phaser';
|
|
4
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
// Typed mock of 'phaser' to avoid canvas dependency
|
|
6
|
+
vi.mock('phaser', () => {
|
|
7
|
+
class Scene {
|
|
8
|
+
}
|
|
9
|
+
class Container {
|
|
10
|
+
list = [];
|
|
11
|
+
x;
|
|
12
|
+
y;
|
|
13
|
+
width = 0;
|
|
14
|
+
height = 0;
|
|
15
|
+
constructor(_scene, x, y) {
|
|
16
|
+
this.x = x;
|
|
17
|
+
this.y = y;
|
|
18
|
+
}
|
|
19
|
+
add(child) {
|
|
20
|
+
if (Array.isArray(child)) {
|
|
21
|
+
this.list.push(...child);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
this.list.push(child);
|
|
25
|
+
}
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
setSize(width, height) {
|
|
29
|
+
this.width = width;
|
|
30
|
+
this.height = height;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const GameObjects = { Container };
|
|
35
|
+
return { GameObjects, Scene };
|
|
36
|
+
});
|
|
37
|
+
import { Row } from './row';
|
|
38
|
+
class TestChild {
|
|
39
|
+
displayWidth;
|
|
40
|
+
width;
|
|
41
|
+
displayHeight;
|
|
42
|
+
height;
|
|
43
|
+
originX;
|
|
44
|
+
originY;
|
|
45
|
+
displayOriginX;
|
|
46
|
+
displayOriginY;
|
|
47
|
+
lastPosition = null;
|
|
48
|
+
constructor(params = {}) {
|
|
49
|
+
Object.assign(this, params);
|
|
50
|
+
}
|
|
51
|
+
setPosition(x, y) {
|
|
52
|
+
this.lastPosition = { x, y };
|
|
53
|
+
}
|
|
54
|
+
getBounds() {
|
|
55
|
+
return {
|
|
56
|
+
width: this.width ?? this.displayWidth ?? 0,
|
|
57
|
+
height: this.height ?? this.displayHeight ?? 0,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
let scene;
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
scene = new Scene();
|
|
64
|
+
});
|
|
65
|
+
describe('Row layout', () => {
|
|
66
|
+
it('centers children by default with horizontalOrigin center', () => {
|
|
67
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
68
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
69
|
+
const row = new Row({ scene, x: 0, y: 0, gap: 10, align: 'center', horizontalOrigin: 'center', children: [] });
|
|
70
|
+
row.addChildren([a, b]);
|
|
71
|
+
// totalWidth = 100 + 200 + 10 = 310; contentLeft = -155
|
|
72
|
+
expect(a.lastPosition).toEqual({ x: -155 + 0.5 * 100, y: 0 }); // -105, 0
|
|
73
|
+
expect(b.lastPosition).toEqual({ x: -45 + 0.5 * 200, y: 0 }); // 55, 0
|
|
74
|
+
// width = totalWidth; height = max child height
|
|
75
|
+
expect(row.width).toBe(310);
|
|
76
|
+
expect(row.height).toBe(100);
|
|
77
|
+
});
|
|
78
|
+
it('align top positions children at content top edge', () => {
|
|
79
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
80
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
81
|
+
const row = new Row({ scene, x: 0, y: 0, gap: 10, align: 'top', horizontalOrigin: 'center', children: [a, b] });
|
|
82
|
+
// maxHeight = 100
|
|
83
|
+
expect(a.lastPosition?.y).toBe(-50 + 0.5 * 50); // -25
|
|
84
|
+
expect(b.lastPosition?.y).toBe(-50 + 0.5 * 100); // 0
|
|
85
|
+
expect(row.width).toBe(310);
|
|
86
|
+
expect(row.height).toBe(100);
|
|
87
|
+
});
|
|
88
|
+
it('align bottom positions children at content bottom edge', () => {
|
|
89
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
90
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
91
|
+
new Row({ scene, x: 0, y: 0, gap: 10, align: 'bottom', horizontalOrigin: 'center', children: [a, b] });
|
|
92
|
+
expect(a.lastPosition?.y).toBe(50 - (1 - 0.5) * 50); // 25
|
|
93
|
+
expect(b.lastPosition?.y).toBe(50 - (1 - 0.5) * 100); // 0
|
|
94
|
+
});
|
|
95
|
+
it('horizontalOrigin left places content starting at x=0', () => {
|
|
96
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
97
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
98
|
+
const row = new Row({ scene, x: 0, y: 0, gap: 10, align: 'center', horizontalOrigin: 'left', children: [a, b] });
|
|
99
|
+
expect(a.lastPosition?.x).toBe(0 + 0.5 * 100); // 50
|
|
100
|
+
expect(b.lastPosition?.x).toBe(110 + 0.5 * 200); // 210
|
|
101
|
+
expect(row.width).toBe(310);
|
|
102
|
+
expect(row.height).toBe(100);
|
|
103
|
+
});
|
|
104
|
+
it('respects per-child origin when computing alignment and positions', () => {
|
|
105
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50, originX: 0.0, originY: 0.0 });
|
|
106
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100, originX: 1.0, originY: 1.0 });
|
|
107
|
+
// totalWidth = 310; left = 0 (horizontalOrigin left); maxHeight = 100
|
|
108
|
+
new Row({ scene, x: 0, y: 0, gap: 10, align: 'top', horizontalOrigin: 'left', children: [a, b] });
|
|
109
|
+
// a: x = 0 + 0*100 = 0; y = -50 + 0*50 = -50
|
|
110
|
+
expect(a.lastPosition).toEqual({ x: 0, y: -50 });
|
|
111
|
+
// cursor = 0 + 100 + 10 = 110; b: x = 110 + 1*200 = 310; y = -50 + 1*100 = 50
|
|
112
|
+
expect(b.lastPosition).toEqual({ x: 310, y: 50 });
|
|
113
|
+
});
|
|
114
|
+
it('setGap and setAlign trigger relayout', () => {
|
|
115
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
116
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
117
|
+
const row = new Row({ scene, x: 0, y: 0, children: [a, b] }); // default gap=8, align=center, horizontalOrigin=center
|
|
118
|
+
// Initial container width with gap=8
|
|
119
|
+
const initialWidth = row.width;
|
|
120
|
+
row.setGap(20); // triggers layout
|
|
121
|
+
const afterWidth = row.width;
|
|
122
|
+
expect(afterWidth).toBe(initialWidth + (20 - 8));
|
|
123
|
+
row.setAlign('top');
|
|
124
|
+
// For align top, y positions as computed earlier with maxHeight=100
|
|
125
|
+
expect(a.lastPosition?.y).toBe(-50 + 0.5 * 50); // -25
|
|
126
|
+
expect(b.lastPosition?.y).toBe(-50 + 0.5 * 100); // 0
|
|
127
|
+
});
|
|
128
|
+
it('addChild/addChildren optionally avoid relayout when requested', () => {
|
|
129
|
+
const a = new TestChild({ displayWidth: 100, displayHeight: 50 });
|
|
130
|
+
const b = new TestChild({ displayWidth: 200, displayHeight: 100 });
|
|
131
|
+
const row = new Row({ scene, x: 0, y: 0, children: [a] });
|
|
132
|
+
// b added without relayout
|
|
133
|
+
row.addChild(b, false);
|
|
134
|
+
const before = b.lastPosition;
|
|
135
|
+
expect(before).toBeNull();
|
|
136
|
+
// layout computes positions
|
|
137
|
+
row.layout();
|
|
138
|
+
expect(b.lastPosition).not.toBeNull();
|
|
139
|
+
});
|
|
140
|
+
it('empty row has size 0,0', () => {
|
|
141
|
+
const row = new Row({ scene, x: 0, y: 0, children: [] });
|
|
142
|
+
expect(row.width).toBe(0);
|
|
143
|
+
expect(row.height).toBe(0);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=row.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row.spec.js","sourceRoot":"","sources":["../../../src/components/row/row.spec.ts"],"names":[],"mappings":"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"}
|