@energy8platform/game-engine 0.15.0 → 0.15.2

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.
@@ -322,19 +322,28 @@ interface ToggleConfig {
322
322
  }
323
323
 
324
324
  /**
325
- * Ambient JSX IntrinsicElements declarations for the PixiJS React reconciler.
325
+ * JSX prop types for the PixiJS React reconciler.
326
326
  *
327
- * Consumer apps opt in once (e.g. from an app-level `vite-env.d.ts`):
327
+ * The engine auto-augments `react`'s module-scoped `JSX.IntrinsicElements`
328
+ * with every registered element (`<flexContainer>`, `<button>`, `<label>`,
329
+ * `<labelValue>`, etc). Because the augmentation is scoped to the `react`
330
+ * module (not the legacy global `JSX` namespace), it reliably wins over
331
+ * `@types/react`'s HTML defaults for colliding names like `<button>` / `<label>`.
328
332
  *
329
- * import '@energy8platform/game-engine/react-jsx';
333
+ * **Consumers don't need any shim.** Any import from `@energy8platform/game-engine/react`
334
+ * (e.g. `createPixiRoot`, `extendUIElements`, `ReactScene` — you're already
335
+ * importing these to boot the reconciler) pulls this module in and the JSX
336
+ * types activate automatically.
330
337
  *
331
- * After that, TypeScript recognises `<flexContainer>`, `<button>`, `<label>` etc.
332
- * with fully-typed props no need to hand-maintain a local `pixi-jsx.d.ts`.
338
+ * If a project imports only from `/ui` or `/core` and never touches `/react`,
339
+ * add a one-line side-effect import to trigger the augmentation:
333
340
  *
334
- * The JS entry for this subpath is intentionally empty: this module exists
335
- * solely to carry type declarations that side-effect the global `JSX` namespace.
341
+ * ```ts
342
+ * // app/src/pixi-jsx.d.ts
343
+ * import '@energy8platform/game-engine/react-jsx';
344
+ * ```
336
345
  *
337
- * Dash-notation is supported for nested config objects:
346
+ * Dash-notation for nested config objects is supported:
338
347
  * <button colors-default={0xff0000} colors-hover={0x00ff00} />
339
348
  */
340
349
 
@@ -435,6 +444,26 @@ interface GraphicsProps extends BaseProps {
435
444
  width?: number;
436
445
  height?: number;
437
446
  }
447
+ interface AnimatedSpriteProps extends BaseProps {
448
+ textures?: Texture[];
449
+ animationSpeed?: number;
450
+ loop?: boolean;
451
+ playing?: boolean;
452
+ }
453
+ interface NineSliceSpriteProps extends BaseProps {
454
+ texture?: string | Texture;
455
+ leftWidth?: number;
456
+ topHeight?: number;
457
+ rightWidth?: number;
458
+ bottomHeight?: number;
459
+ }
460
+ interface TilingSpriteProps extends BaseProps {
461
+ texture?: string | Texture;
462
+ tilePosition?: {
463
+ x: number;
464
+ y: number;
465
+ };
466
+ }
438
467
  interface ButtonComponentProps extends BaseProps, Omit<ButtonConfig, 'colors' | 'textStyle'> {
439
468
  colors?: Partial<Record<ButtonState, number>>;
440
469
  textStyle?: Record<string, unknown>;
@@ -536,47 +565,38 @@ interface ToggleComponentProps extends BaseProps, Omit<ToggleConfig, 'width' | '
536
565
  offView?: ViewInput;
537
566
  onChange?: (value: boolean) => void;
538
567
  }
539
- declare global {
568
+ /**
569
+ * Complete element → prop-type map for all engine-registered JSX elements.
570
+ * Also consumable directly for typing custom wrappers around engine elements.
571
+ */
572
+ interface EngineIntrinsicElements {
573
+ container: BaseProps;
574
+ sprite: SpriteProps;
575
+ text: TextProps;
576
+ graphics: GraphicsProps;
577
+ animatedSprite: AnimatedSpriteProps;
578
+ nineSliceSprite: NineSliceSpriteProps;
579
+ tilingSprite: TilingSpriteProps;
580
+ button: ButtonComponentProps;
581
+ label: LabelComponentProps;
582
+ labelValue: LabelValueComponentProps;
583
+ panel: PanelComponentProps;
584
+ flexContainer: FlexContainerComponentProps;
585
+ progressBar: ProgressBarComponentProps;
586
+ scrollContainer: ScrollContainerComponentProps;
587
+ modal: ModalComponentProps;
588
+ toast: ToastComponentProps;
589
+ balanceDisplay: BalanceDisplayComponentProps;
590
+ winDisplay: WinDisplayComponentProps;
591
+ layout: LayoutComponentProps;
592
+ slider: SliderComponentProps;
593
+ toggle: ToggleComponentProps;
594
+ }
595
+ declare module 'react' {
540
596
  namespace JSX {
541
- interface IntrinsicElements {
542
- container: BaseProps;
543
- sprite: SpriteProps;
544
- text: TextProps;
545
- graphics: GraphicsProps;
546
- animatedSprite: BaseProps & {
547
- textures?: Texture[];
548
- animationSpeed?: number;
549
- loop?: boolean;
550
- playing?: boolean;
551
- };
552
- nineSliceSprite: BaseProps & {
553
- texture?: string | Texture;
554
- leftWidth?: number;
555
- topHeight?: number;
556
- rightWidth?: number;
557
- bottomHeight?: number;
558
- };
559
- tilingSprite: BaseProps & {
560
- texture?: string | Texture;
561
- tilePosition?: {
562
- x: number;
563
- y: number;
564
- };
565
- };
566
- button: ButtonComponentProps;
567
- label: LabelComponentProps;
568
- labelValue: LabelValueComponentProps;
569
- panel: PanelComponentProps;
570
- flexContainer: FlexContainerComponentProps;
571
- progressBar: ProgressBarComponentProps;
572
- scrollContainer: ScrollContainerComponentProps;
573
- modal: ModalComponentProps;
574
- toast: ToastComponentProps;
575
- balanceDisplay: BalanceDisplayComponentProps;
576
- winDisplay: WinDisplayComponentProps;
577
- layout: LayoutComponentProps;
578
- slider: SliderComponentProps;
579
- toggle: ToggleComponentProps;
597
+ interface IntrinsicElements extends EngineIntrinsicElements {
580
598
  }
581
599
  }
582
600
  }
601
+
602
+ export type { AnimatedSpriteProps, BalanceDisplayComponentProps, BaseProps, ButtonComponentProps, EngineIntrinsicElements, FlexContainerComponentProps, GraphicsProps, LabelComponentProps, LabelValueComponentProps, LayoutComponentProps, ModalComponentProps, NineSliceSpriteProps, PanelComponentProps, PixiEventProps, ProgressBarComponentProps, ScrollContainerComponentProps, SliderComponentProps, SpriteProps, TextProps, TilingSpriteProps, ToastComponentProps, ToggleComponentProps, WinDisplayComponentProps };
package/dist/react.cjs.js CHANGED
@@ -314,24 +314,29 @@ function measureChild(child, parentContentW = 0, parentContentH = 0) {
314
314
  const cfg = child._flexConfig;
315
315
  const resolvedLW = resolveDimension(cfg?.layoutWidth, parentContentW);
316
316
  const resolvedLH = resolveDimension(cfg?.layoutHeight, parentContentH);
317
- if (resolvedLW !== undefined && resolvedLH !== undefined) {
318
- return { w: resolvedLW, h: resolvedLH, ox: 0, oy: 0 };
319
- }
320
- // For FlexContainers, use their explicit or computed size
317
+ // FlexContainer children are top-left origin by construction, so `ox/oy = 0`
318
+ // is correct and we can skip the `getLocalBounds()` call entirely.
321
319
  if (child instanceof FlexContainer) {
322
320
  const fc = child;
323
321
  const w = fc._explicitWidth > 0 ? fc._explicitWidth : (fc._computedWidth > 0 ? fc._computedWidth : undefined);
324
322
  const h = fc._explicitHeight > 0 ? fc._explicitHeight : (fc._computedHeight > 0 ? fc._computedHeight : undefined);
325
323
  if (w !== undefined && h !== undefined) {
326
- return { w, h, ox: 0, oy: 0 };
324
+ return { w: resolvedLW ?? w, h: resolvedLH ?? h, ox: 0, oy: 0 };
327
325
  }
328
326
  }
329
- // Use localBounds to get the true visual extent and origin offset.
330
- // This handles children with non-zero anchors (e.g. Button, Label with centered text).
327
+ // Use localBounds to get the true visual origin offset.
328
+ // We take `ox/oy` from bounds unconditionally a user-supplied `layoutWidth/Height`
329
+ // overrides the SIZE used by flex (protection against pre-paint bounds of 0), but
330
+ // it must NOT erase the center-anchor compensation: Button/Label views are drawn at
331
+ // `(-w/2..w/2)` and their bounds.x = -w/2 is what lets `layoutLine` place the
332
+ // visible rectangle where the layout intends.
331
333
  const bounds = child.getLocalBounds();
332
- const w = resolvedLW ?? bounds.width;
333
- const h = resolvedLH ?? bounds.height;
334
- return { w, h, ox: bounds.x, oy: bounds.y };
334
+ return {
335
+ w: resolvedLW ?? bounds.width,
336
+ h: resolvedLH ?? bounds.height,
337
+ ox: bounds.x,
338
+ oy: bounds.y,
339
+ };
335
340
  }
336
341
  /**
337
342
  * Set a child's main or cross dimension.
@@ -820,30 +825,35 @@ class FlexContainer extends pixi_js.Container {
820
825
  this._computedHeight = this._explicitHeight > 0 ? this._explicitHeight : (pt + naturalMainSize + pb);
821
826
  }
822
827
  // Position flexExclude children (absolute positioning).
823
- // All position props describe the visual (bounds) rectangle, so we subtract
824
- // `ox/oy` to compensate for children with a centered origin (Button, Label).
828
+ // All position props describe the visual (bounds) rectangle. We derive the
829
+ // visual rectangle directly from `getLocalBounds()` rather than the
830
+ // layout-config `w`/`h` returned by measureChild — those may differ from
831
+ // actual bounds when the user pins `layoutWidth`/`layoutHeight` to a value
832
+ // that doesn't match the child's real visual extent (e.g. a Button whose
833
+ // text overflows its configured `width`). Mixing layout size with real
834
+ // bounds-origin would shift the visual center off the requested point.
825
835
  // `centerX/centerY` take precedence over `left/right` / `top/bottom` on each axis.
826
836
  for (const child of this._layoutChildren) {
827
837
  if (!child._flexConfig?.flexExclude)
828
838
  continue;
829
839
  const cfg = child._flexConfig;
830
- const { w, h, ox, oy } = measureChild(child, pctRefW, pctRefH);
840
+ const bounds = child.getLocalBounds();
831
841
  const cw = this._computedWidth;
832
842
  const ch = this._computedHeight;
833
843
  const centerX = resolveDimension(cfg.centerX, pctRefW);
834
844
  if (centerX !== undefined)
835
- child.x = centerX - w / 2 - ox;
845
+ child.x = centerX - bounds.x - bounds.width / 2;
836
846
  else if (cfg.left !== undefined)
837
- child.x = cfg.left - ox;
847
+ child.x = cfg.left - bounds.x;
838
848
  else if (cfg.right !== undefined)
839
- child.x = cw - w - cfg.right - ox;
849
+ child.x = cw - cfg.right - bounds.x - bounds.width;
840
850
  const centerY = resolveDimension(cfg.centerY, pctRefH);
841
851
  if (centerY !== undefined)
842
- child.y = centerY - h / 2 - oy;
852
+ child.y = centerY - bounds.y - bounds.height / 2;
843
853
  else if (cfg.top !== undefined)
844
- child.y = cfg.top - oy;
854
+ child.y = cfg.top - bounds.y;
845
855
  else if (cfg.bottom !== undefined)
846
- child.y = ch - h - cfg.bottom - oy;
856
+ child.y = ch - cfg.bottom - bounds.y - bounds.height;
847
857
  }
848
858
  }
849
859
  /** Computed content size (after layout) */