@energy8platform/game-engine 0.11.0 → 0.13.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/index.d.ts CHANGED
@@ -1265,13 +1265,20 @@ declare class SpriteAnimation {
1265
1265
  type FlexDirection = 'row' | 'column';
1266
1266
  type JustifyContent = 'start' | 'center' | 'end' | 'space-between' | 'space-around';
1267
1267
  type AlignItems = 'start' | 'center' | 'end' | 'stretch';
1268
+ type AlignSelf = 'auto' | 'start' | 'center' | 'end' | 'stretch';
1268
1269
  interface FlexItemConfig {
1269
1270
  /** Flex grow factor (0 = fixed size) */
1270
1271
  flexGrow?: number;
1272
+ /** Flex shrink factor (0 = don't shrink, default: 1) */
1273
+ flexShrink?: number;
1271
1274
  /** Explicit width override for layout calculations */
1272
1275
  layoutWidth?: number;
1273
1276
  /** Explicit height override for layout calculations */
1274
1277
  layoutHeight?: number;
1278
+ /** Override parent's alignItems for this child */
1279
+ alignSelf?: AlignSelf;
1280
+ /** Exclude from flex layout (acts like position: absolute) */
1281
+ flexExclude?: boolean;
1275
1282
  }
1276
1283
  interface FlexContainerConfig {
1277
1284
  /** Layout direction (default: 'row') */
package/dist/index.esm.js CHANGED
@@ -2965,6 +2965,37 @@ function layoutLine(items, isRow, mainSize, justify, align, gap, crossOffset, cr
2965
2965
  }
2966
2966
  }
2967
2967
  }
2968
+ // Shrink: if content overflows and mainSize is finite, shrink eligible items
2969
+ if (totalGrow === 0 && mainSize > 0) {
2970
+ const overflow = totalFixed + totalGap - mainSize;
2971
+ if (overflow > 0) {
2972
+ let totalShrinkable = 0;
2973
+ for (const item of items) {
2974
+ const shrink = item.child._flexConfig?.flexShrink ?? 1;
2975
+ if (shrink > 0) {
2976
+ totalShrinkable += isRow ? item.w : item.h;
2977
+ }
2978
+ }
2979
+ if (totalShrinkable > 0) {
2980
+ for (const item of items) {
2981
+ const shrink = item.child._flexConfig?.flexShrink ?? 1;
2982
+ if (shrink > 0) {
2983
+ const itemMain = isRow ? item.w : item.h;
2984
+ const reduction = overflow * (itemMain / totalShrinkable);
2985
+ const newSize = Math.max(0, itemMain - reduction);
2986
+ if (isRow) {
2987
+ item.w = newSize;
2988
+ item.child.width = newSize;
2989
+ }
2990
+ else {
2991
+ item.h = newSize;
2992
+ item.child.height = newSize;
2993
+ }
2994
+ }
2995
+ }
2996
+ }
2997
+ }
2998
+ }
2968
2999
  // Calculate total main size after flex
2969
3000
  let totalMain = totalGap;
2970
3001
  for (const item of items) {
@@ -3001,9 +3032,12 @@ function layoutLine(items, isRow, mainSize, justify, align, gap, crossOffset, cr
3001
3032
  for (const item of items) {
3002
3033
  const mainDim = isRow ? item.w : item.h;
3003
3034
  const crossDim = isRow ? item.h : item.w;
3004
- // Cross-axis alignment
3035
+ // Cross-axis alignment (alignSelf overrides align)
3036
+ const effectiveAlign = (item.child._flexConfig?.alignSelf && item.child._flexConfig.alignSelf !== 'auto')
3037
+ ? item.child._flexConfig.alignSelf
3038
+ : align;
3005
3039
  let crossPos = crossOffset;
3006
- switch (align) {
3040
+ switch (effectiveAlign) {
3007
3041
  case 'start':
3008
3042
  break;
3009
3043
  case 'center':
@@ -3187,11 +3221,14 @@ class FlexContainer extends Container {
3187
3221
  const contentH = this._explicitHeight > 0 ? this._explicitHeight - pt - pb : Infinity;
3188
3222
  const mainLimit = isRow ? contentW : contentH;
3189
3223
  const crossLimit = isRow ? contentH : contentW;
3190
- // Measure children
3191
- const measured = this._layoutChildren.map((child) => {
3224
+ // Measure children (skip flexExclude — they position themselves)
3225
+ const measured = [];
3226
+ for (const child of this._layoutChildren) {
3227
+ if (child._flexConfig?.flexExclude)
3228
+ continue;
3192
3229
  const { w, h, ox, oy } = measureChild(child);
3193
- return { child, w, h, ox, oy };
3194
- });
3230
+ measured.push({ child, w, h, ox, oy });
3231
+ }
3195
3232
  // Split into lines (if wrapping)
3196
3233
  const lines = [];
3197
3234
  if (flexWrap && mainLimit < Infinity) {
@@ -3234,7 +3271,12 @@ class FlexContainer extends Container {
3234
3271
  const mainStart = isRow ? pl : pt;
3235
3272
  // Offset items by padding
3236
3273
  const tempItems = line.map((item) => ({ ...item }));
3237
- layoutLine(tempItems, isRow, mainLimit < Infinity ? mainLimit : 0, mainLimit < Infinity ? justifyContent : 'start', alignItems, gap, crossOffset, crossLimit < Infinity ? Math.min(lineCross, crossLimit) : lineCross);
3274
+ // For single-line layouts, use the full available cross space for alignment;
3275
+ // for multi-line (wrapping), each line gets its own measured cross size.
3276
+ const effectiveCross = lines.length === 1 && crossLimit < Infinity
3277
+ ? crossLimit
3278
+ : (crossLimit < Infinity ? Math.min(lineCross, crossLimit) : lineCross);
3279
+ layoutLine(tempItems, isRow, mainLimit < Infinity ? mainLimit : 0, mainLimit < Infinity ? justifyContent : 'start', alignItems, gap, crossOffset, effectiveCross);
3238
3280
  // Apply main-axis padding offset
3239
3281
  for (const item of tempItems) {
3240
3282
  const origChild = line.find((l) => l.child === item.child);