@energy8platform/game-engine 0.14.5 → 0.14.7
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/index.cjs.js +4 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +4 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/react.cjs.js +96 -12
- package/dist/react.cjs.js.map +1 -1
- package/dist/react.esm.js +96 -12
- package/dist/react.esm.js.map +1 -1
- package/dist/ui.cjs.js +4 -3
- package/dist/ui.cjs.js.map +1 -1
- package/dist/ui.esm.js +4 -3
- package/dist/ui.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/react/applyProps.ts +47 -2
- package/src/react/reconciler.ts +35 -8
- package/src/ui/Modal.ts +3 -4
package/dist/react.cjs.js
CHANGED
|
@@ -25,6 +25,11 @@ function extend(components) {
|
|
|
25
25
|
const RESERVED = new Set(['children', 'key', 'ref']);
|
|
26
26
|
/** Props handled by the reconciler as flex item config, not forwarded to components */
|
|
27
27
|
const FLEX_ITEM_PROPS$1 = new Set(['flexGrow', 'flexShrink', 'layoutWidth', 'layoutHeight', 'alignSelf', 'flexExclude', 'top', 'right', 'bottom', 'left']);
|
|
28
|
+
/** Base Container props applied directly to the instance (not via config) */
|
|
29
|
+
const CONTAINER_PROPS = new Set([
|
|
30
|
+
'x', 'y', 'alpha', 'visible', 'rotation', 'angle', 'zIndex',
|
|
31
|
+
'label', 'cursor', 'eventMode',
|
|
32
|
+
]);
|
|
28
33
|
// ─── UI Component helpers ────────────────────────────────
|
|
29
34
|
/**
|
|
30
35
|
* Extract a config object from React props.
|
|
@@ -34,7 +39,7 @@ const FLEX_ITEM_PROPS$1 = new Set(['flexGrow', 'flexShrink', 'layoutWidth', 'lay
|
|
|
34
39
|
function extractConfig(props) {
|
|
35
40
|
const config = {};
|
|
36
41
|
for (const key in props) {
|
|
37
|
-
if (RESERVED.has(key) || FLEX_ITEM_PROPS$1.has(key) || isEventProp(key))
|
|
42
|
+
if (RESERVED.has(key) || FLEX_ITEM_PROPS$1.has(key) || CONTAINER_PROPS.has(key) || isEventProp(key))
|
|
38
43
|
continue;
|
|
39
44
|
if (key.includes('-')) {
|
|
40
45
|
const parts = key.split('-');
|
|
@@ -59,7 +64,7 @@ function diffConfig(newProps, oldProps) {
|
|
|
59
64
|
const changed = {};
|
|
60
65
|
// New or changed props
|
|
61
66
|
for (const key in newProps) {
|
|
62
|
-
if (RESERVED.has(key) || FLEX_ITEM_PROPS$1.has(key) || isEventProp(key))
|
|
67
|
+
if (RESERVED.has(key) || FLEX_ITEM_PROPS$1.has(key) || CONTAINER_PROPS.has(key) || isEventProp(key))
|
|
63
68
|
continue;
|
|
64
69
|
if (newProps[key] !== oldProps[key]) {
|
|
65
70
|
if (key.includes('-')) {
|
|
@@ -155,6 +160,50 @@ function setNestedValue(target, path, value) {
|
|
|
155
160
|
}
|
|
156
161
|
obj[path[path.length - 1]] = value;
|
|
157
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Apply base Container props (x, y, alpha, visible, etc.) directly to the instance.
|
|
165
|
+
* Called for ALL elements — both UI components and standard PixiJS elements.
|
|
166
|
+
* Also handles scale, pivot, position, anchor via dash-notation.
|
|
167
|
+
*/
|
|
168
|
+
function applyContainerProps(instance, newProps, oldProps = {}) {
|
|
169
|
+
for (const key of CONTAINER_PROPS) {
|
|
170
|
+
if (key in newProps && newProps[key] !== oldProps[key]) {
|
|
171
|
+
try {
|
|
172
|
+
instance[key] = newProps[key];
|
|
173
|
+
}
|
|
174
|
+
catch { /* read-only */ }
|
|
175
|
+
}
|
|
176
|
+
else if (key in oldProps && !(key in newProps)) {
|
|
177
|
+
// Prop removed — reset to undefined (PixiJS defaults)
|
|
178
|
+
try {
|
|
179
|
+
instance[key] = undefined;
|
|
180
|
+
}
|
|
181
|
+
catch { /* read-only */ }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// Handle scale as uniform number or {x,y} object
|
|
185
|
+
if ('scale' in newProps && newProps.scale !== oldProps.scale) {
|
|
186
|
+
const s = newProps.scale;
|
|
187
|
+
if (typeof s === 'number') {
|
|
188
|
+
instance.scale?.set?.(s, s);
|
|
189
|
+
}
|
|
190
|
+
else if (s && typeof s === 'object') {
|
|
191
|
+
instance.scale?.set?.(s.x ?? 1, s.y ?? 1);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Handle dash-notation container props: scale-x, scale-y, pivot-x, pivot-y, position-x, position-y, anchor-x, anchor-y
|
|
195
|
+
for (const key in newProps) {
|
|
196
|
+
if (!key.includes('-'))
|
|
197
|
+
continue;
|
|
198
|
+
const parts = key.split('-');
|
|
199
|
+
const root = parts[0];
|
|
200
|
+
if (root === 'scale' || root === 'pivot' || root === 'position' || root === 'anchor') {
|
|
201
|
+
if (newProps[key] !== oldProps[key]) {
|
|
202
|
+
setNestedValue(instance, parts, newProps[key]);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
158
207
|
function applyProps(instance, newProps, oldProps = {}) {
|
|
159
208
|
// Remove old props not in newProps
|
|
160
209
|
for (const key in oldProps) {
|
|
@@ -820,6 +869,17 @@ function isSuspendable(obj) {
|
|
|
820
869
|
}
|
|
821
870
|
/** Layout containers that need flush after commit phase */
|
|
822
871
|
const pendingLayoutFlush = new Set();
|
|
872
|
+
/** Suspend a layout container and all its suspendable ancestors, add them to pending flush */
|
|
873
|
+
function suspendWithAncestors(instance) {
|
|
874
|
+
let current = instance;
|
|
875
|
+
while (current) {
|
|
876
|
+
if (isSuspendable(current)) {
|
|
877
|
+
current.suspendLayout();
|
|
878
|
+
pendingLayoutFlush.add(current);
|
|
879
|
+
}
|
|
880
|
+
current = current.parent;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
823
883
|
/** Extract FlexItemConfig from props if any flex item props are present */
|
|
824
884
|
function extractFlexItemConfig(props) {
|
|
825
885
|
let config;
|
|
@@ -862,6 +922,7 @@ const hostConfig = {
|
|
|
862
922
|
// Config-based UI component: pass props as constructor config
|
|
863
923
|
const config = extractConfig(props);
|
|
864
924
|
instance = new Ctor(config);
|
|
925
|
+
applyContainerProps(instance, props);
|
|
865
926
|
applyEventProps(instance, props);
|
|
866
927
|
}
|
|
867
928
|
else {
|
|
@@ -967,11 +1028,18 @@ const hostConfig = {
|
|
|
967
1028
|
}
|
|
968
1029
|
},
|
|
969
1030
|
commitUpdate(instance, _updatePayload, _type, oldProps, newProps) {
|
|
1031
|
+
// Suspend this instance and ancestors before applying changes —
|
|
1032
|
+
// prevents intermediate relayouts with partially-updated tree
|
|
1033
|
+
const dimensionsChanged = newProps.width !== oldProps.width || newProps.height !== oldProps.height;
|
|
1034
|
+
if (isSuspendable(instance) || dimensionsChanged) {
|
|
1035
|
+
suspendWithAncestors(instance);
|
|
1036
|
+
}
|
|
970
1037
|
if (typeof instance.updateConfig === 'function') {
|
|
971
1038
|
const changed = diffConfig(newProps, oldProps);
|
|
972
1039
|
if (Object.keys(changed).length > 0) {
|
|
973
1040
|
instance.updateConfig(changed);
|
|
974
1041
|
}
|
|
1042
|
+
applyContainerProps(instance, newProps, oldProps);
|
|
975
1043
|
applyEventProps(instance, newProps, oldProps);
|
|
976
1044
|
}
|
|
977
1045
|
else {
|
|
@@ -994,11 +1062,9 @@ const hostConfig = {
|
|
|
994
1062
|
}
|
|
995
1063
|
}
|
|
996
1064
|
}
|
|
997
|
-
//
|
|
998
|
-
if (newFlexConfig || oldFlexConfig ||
|
|
999
|
-
|
|
1000
|
-
instance.parent.updateLayout();
|
|
1001
|
-
}
|
|
1065
|
+
// Mark ancestors dirty if flex config or dimensions changed
|
|
1066
|
+
if (newFlexConfig || oldFlexConfig || dimensionsChanged) {
|
|
1067
|
+
suspendWithAncestors(instance);
|
|
1002
1068
|
}
|
|
1003
1069
|
if (hasEventProps(newProps) && instance.eventMode === 'auto') {
|
|
1004
1070
|
instance.eventMode = 'static';
|
|
@@ -1030,8 +1096,25 @@ const hostConfig = {
|
|
|
1030
1096
|
return null;
|
|
1031
1097
|
},
|
|
1032
1098
|
resetAfterCommit() {
|
|
1033
|
-
|
|
1034
|
-
|
|
1099
|
+
if (pendingLayoutFlush.size === 0)
|
|
1100
|
+
return;
|
|
1101
|
+
// Sort by depth (deepest first) so children compute sizes before parents lay out
|
|
1102
|
+
const sorted = [...pendingLayoutFlush].sort((a, b) => {
|
|
1103
|
+
let da = 0;
|
|
1104
|
+
let n = a;
|
|
1105
|
+
while (n.parent) {
|
|
1106
|
+
da++;
|
|
1107
|
+
n = n.parent;
|
|
1108
|
+
}
|
|
1109
|
+
let db = 0;
|
|
1110
|
+
n = b;
|
|
1111
|
+
while (n.parent) {
|
|
1112
|
+
db++;
|
|
1113
|
+
n = n.parent;
|
|
1114
|
+
}
|
|
1115
|
+
return db - da; // deepest first
|
|
1116
|
+
});
|
|
1117
|
+
for (const fc of sorted) {
|
|
1035
1118
|
fc.resumeLayout();
|
|
1036
1119
|
}
|
|
1037
1120
|
pendingLayoutFlush.clear();
|
|
@@ -2188,10 +2271,11 @@ class Modal extends pixi_js.Container {
|
|
|
2188
2271
|
// Overlay
|
|
2189
2272
|
this._overlay = new pixi_js.Graphics();
|
|
2190
2273
|
this._overlay.eventMode = 'static';
|
|
2274
|
+
this._overlay.on('pointertap', () => {
|
|
2275
|
+
if (this._config.closeOnOverlay)
|
|
2276
|
+
this.hide();
|
|
2277
|
+
});
|
|
2191
2278
|
this.addChild(this._overlay);
|
|
2192
|
-
if (this._config.closeOnOverlay) {
|
|
2193
|
-
this._overlay.on('pointertap', () => this.hide());
|
|
2194
|
-
}
|
|
2195
2279
|
// Content container
|
|
2196
2280
|
this._contentContainer = new pixi_js.Container();
|
|
2197
2281
|
this.addChild(this._contentContainer);
|