pixifact 0.1.3 → 0.1.4

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.
Files changed (185) hide show
  1. package/README.md +3 -3
  2. package/dist/builtin-scenes/CenterContainer.d.ts +13 -0
  3. package/dist/builtin-scenes/CenterContainer.js +71 -0
  4. package/dist/builtin-scenes/CenterContainer.scene +3 -0
  5. package/dist/builtin-scenes/CenterContainer.ts +77 -0
  6. package/dist/builtin-scenes/Control.d.ts +44 -0
  7. package/dist/builtin-scenes/Control.js +206 -0
  8. package/dist/builtin-scenes/Control.scene +3 -0
  9. package/dist/builtin-scenes/Control.ts +233 -0
  10. package/dist/builtin-scenes/FlexItem.d.ts +45 -0
  11. package/dist/builtin-scenes/FlexItem.js +164 -0
  12. package/dist/builtin-scenes/FlexItem.scene +3 -0
  13. package/dist/builtin-scenes/FlexItem.ts +180 -0
  14. package/dist/builtin-scenes/FlexLayout.d.ts +29 -0
  15. package/dist/builtin-scenes/FlexLayout.js +358 -0
  16. package/dist/builtin-scenes/FlexLayout.scene +3 -0
  17. package/dist/builtin-scenes/FlexLayout.ts +409 -0
  18. package/dist/builtin-scenes/HBoxContainer.d.ts +15 -0
  19. package/dist/builtin-scenes/HBoxContainer.js +70 -0
  20. package/dist/builtin-scenes/HBoxContainer.scene +3 -0
  21. package/dist/builtin-scenes/HBoxContainer.ts +75 -0
  22. package/dist/builtin-scenes/MarginContainer.d.ts +23 -0
  23. package/dist/builtin-scenes/MarginContainer.js +131 -0
  24. package/dist/builtin-scenes/MarginContainer.scene +3 -0
  25. package/dist/builtin-scenes/MarginContainer.ts +139 -0
  26. package/dist/builtin-scenes/VBoxContainer.d.ts +15 -0
  27. package/dist/builtin-scenes/VBoxContainer.js +70 -0
  28. package/dist/builtin-scenes/VBoxContainer.scene +3 -0
  29. package/dist/builtin-scenes/VBoxContainer.ts +75 -0
  30. package/dist/builtin-scenes/controlLayout.d.ts +57 -0
  31. package/dist/builtin-scenes/controlLayout.js +202 -0
  32. package/dist/builtin-scenes/controlLayout.ts +270 -0
  33. package/dist/compiler/builtinScenes.d.ts +14 -0
  34. package/dist/compiler/builtinScenes.js +62 -0
  35. package/dist/compiler/compileScenes.js +126 -19
  36. package/dist/compiler/decorators.js +3 -0
  37. package/dist/compiler/index.d.ts +1 -0
  38. package/dist/compiler/index.js +1 -0
  39. package/dist/compiler/sceneAssetPair.js +19 -0
  40. package/dist/compiler/sceneRuntime.d.ts +5 -4
  41. package/dist/compiler/scriptInterfaceExtractor.d.ts +5 -0
  42. package/dist/compiler/scriptInterfaceExtractor.js +214 -8
  43. package/dist/compiler/spec.d.ts +2 -0
  44. package/dist/compiler/templateParser.js +4 -3
  45. package/dist/compiler/templateSerializer.js +2 -1
  46. package/dist/compiler/typescriptCompiler.js +87 -13
  47. package/dist/compiler-node/builtinSceneAssets.d.ts +8 -0
  48. package/dist/compiler-node/builtinSceneAssets.js +57 -0
  49. package/dist/compiler-node/index.d.ts +1 -0
  50. package/dist/compiler-node/index.js +1 -0
  51. package/dist/errors.d.ts +1 -0
  52. package/dist/errors.js +24 -0
  53. package/dist/index.d.ts +2 -5
  54. package/dist/index.js +2 -5
  55. package/dist/{authoring/ProjectConfig.d.ts → project/index.d.ts} +7 -0
  56. package/dist/{authoring/ProjectConfig.js → project/index.js} +22 -0
  57. package/dist/runtime/Group.d.ts +18 -0
  58. package/dist/runtime/Group.js +45 -0
  59. package/dist/runtime/index.d.ts +1 -9
  60. package/dist/runtime/index.js +1 -9
  61. package/package.json +4 -26
  62. package/dist/authoring/ActionRegistry.d.ts +0 -10
  63. package/dist/authoring/ActionRegistry.js +0 -26
  64. package/dist/authoring/ComponentPalette.d.ts +0 -16
  65. package/dist/authoring/ComponentPalette.js +0 -50
  66. package/dist/authoring/DesignToken.d.ts +0 -16
  67. package/dist/authoring/DesignToken.js +0 -33
  68. package/dist/authoring/DiffModel.d.ts +0 -10
  69. package/dist/authoring/DiffModel.js +0 -104
  70. package/dist/authoring/InspectorModel.d.ts +0 -27
  71. package/dist/authoring/InspectorModel.js +0 -139
  72. package/dist/authoring/LogicGraph.d.ts +0 -66
  73. package/dist/authoring/LogicGraph.js +0 -184
  74. package/dist/authoring/OverrideJournal.d.ts +0 -18
  75. package/dist/authoring/OverrideJournal.js +0 -23
  76. package/dist/authoring/PreferenceMemory.d.ts +0 -21
  77. package/dist/authoring/PreferenceMemory.js +0 -39
  78. package/dist/authoring/RuntimePreview.d.ts +0 -11
  79. package/dist/authoring/RuntimePreview.js +0 -25
  80. package/dist/authoring/SceneDocument.d.ts +0 -74
  81. package/dist/authoring/SceneDocument.js +0 -332
  82. package/dist/authoring/SceneProjectState.d.ts +0 -20
  83. package/dist/authoring/SceneProjectState.js +0 -8
  84. package/dist/authoring/SceneSelection.d.ts +0 -11
  85. package/dist/authoring/SceneSelection.js +0 -1
  86. package/dist/authoring/index.d.ts +0 -13
  87. package/dist/authoring/index.js +0 -13
  88. package/dist/commands/Command.d.ts +0 -63
  89. package/dist/commands/Command.js +0 -1
  90. package/dist/commands/CommandStack.d.ts +0 -14
  91. package/dist/commands/CommandStack.js +0 -45
  92. package/dist/commands/applyCommand.d.ts +0 -23
  93. package/dist/commands/applyCommand.js +0 -316
  94. package/dist/commands/index.d.ts +0 -4
  95. package/dist/commands/index.js +0 -4
  96. package/dist/commands/utils.d.ts +0 -17
  97. package/dist/commands/utils.js +0 -77
  98. package/dist/commands/validateCommand.d.ts +0 -12
  99. package/dist/commands/validateCommand.js +0 -285
  100. package/dist/nodes/Input.d.ts +0 -91
  101. package/dist/nodes/Input.js +0 -352
  102. package/dist/nodes/Textarea.d.ts +0 -10
  103. package/dist/nodes/Textarea.js +0 -38
  104. package/dist/nodes/components/Button.d.ts +0 -8
  105. package/dist/nodes/components/Button.js +0 -45
  106. package/dist/nodes/components/InputField.d.ts +0 -12
  107. package/dist/nodes/components/InputField.js +0 -53
  108. package/dist/nodes/components/ProgressBar.d.ts +0 -14
  109. package/dist/nodes/components/ProgressBar.js +0 -66
  110. package/dist/nodes/components/ScrollRect.d.ts +0 -23
  111. package/dist/nodes/components/ScrollRect.js +0 -108
  112. package/dist/nodes/components/Selectable.d.ts +0 -32
  113. package/dist/nodes/components/Selectable.js +0 -153
  114. package/dist/nodes/components/index.d.ts +0 -5
  115. package/dist/nodes/components/index.js +0 -5
  116. package/dist/nodes/graphics/Graphic.d.ts +0 -14
  117. package/dist/nodes/graphics/Graphic.js +0 -47
  118. package/dist/nodes/graphics/ImageGraphic.d.ts +0 -9
  119. package/dist/nodes/graphics/ImageGraphic.js +0 -42
  120. package/dist/nodes/graphics/RoundedRectGraphic.d.ts +0 -13
  121. package/dist/nodes/graphics/RoundedRectGraphic.js +0 -65
  122. package/dist/nodes/graphics/TextGraphic.d.ts +0 -13
  123. package/dist/nodes/graphics/TextGraphic.js +0 -70
  124. package/dist/nodes/graphics/index.d.ts +0 -4
  125. package/dist/nodes/graphics/index.js +0 -4
  126. package/dist/nodes/index.d.ts +0 -3
  127. package/dist/nodes/index.js +0 -3
  128. package/dist/runtime/Application.d.ts +0 -15
  129. package/dist/runtime/Application.js +0 -67
  130. package/dist/runtime/GameObject.d.ts +0 -100
  131. package/dist/runtime/GameObject.js +0 -297
  132. package/dist/runtime/GameObjectEvent.d.ts +0 -52
  133. package/dist/runtime/GameObjectEvent.js +0 -38
  134. package/dist/runtime/Transform.d.ts +0 -32
  135. package/dist/runtime/Transform.js +0 -157
  136. package/dist/runtime/component/Component.d.ts +0 -13
  137. package/dist/runtime/component/Component.js +0 -13
  138. package/dist/runtime/component/ComponentRegistry.d.ts +0 -49
  139. package/dist/runtime/component/ComponentRegistry.js +0 -25
  140. package/dist/runtime/component/Flex.d.ts +0 -6
  141. package/dist/runtime/component/Flex.js +0 -15
  142. package/dist/runtime/component/FlexGroup.d.ts +0 -26
  143. package/dist/runtime/component/FlexGroup.js +0 -136
  144. package/dist/runtime/component/GridLayout.d.ts +0 -47
  145. package/dist/runtime/component/GridLayout.js +0 -129
  146. package/dist/runtime/component/Layout.d.ts +0 -104
  147. package/dist/runtime/component/Layout.js +0 -248
  148. package/dist/runtime/component/decorators.d.ts +0 -4
  149. package/dist/runtime/component/decorators.js +0 -52
  150. package/dist/runtime/component/index.d.ts +0 -7
  151. package/dist/runtime/component/index.js +0 -7
  152. package/dist/runtime/graphics/index.d.ts +0 -11
  153. package/dist/runtime/graphics/index.js +0 -29
  154. package/dist/runtime/group/index.d.ts +0 -39
  155. package/dist/runtime/group/index.js +0 -102
  156. package/dist/runtime/image/Image.d.ts +0 -19
  157. package/dist/runtime/image/Image.js +0 -60
  158. package/dist/runtime/image/NineSliceImage.d.ts +0 -23
  159. package/dist/runtime/image/NineSliceImage.js +0 -64
  160. package/dist/runtime/image/index.d.ts +0 -2
  161. package/dist/runtime/image/index.js +0 -2
  162. package/dist/runtime/label/Label.d.ts +0 -11
  163. package/dist/runtime/label/Label.js +0 -26
  164. package/dist/runtime/label/LabelStyle.d.ts +0 -3
  165. package/dist/runtime/label/LabelStyle.js +0 -3
  166. package/dist/runtime/label/index.d.ts +0 -2
  167. package/dist/runtime/label/index.js +0 -2
  168. package/dist/runtime/utils/index.d.ts +0 -1
  169. package/dist/runtime/utils/index.js +0 -1
  170. package/dist/runtime/utils/onlyOnceQueueMicrotask.d.ts +0 -1
  171. package/dist/runtime/utils/onlyOnceQueueMicrotask.js +0 -12
  172. package/dist/runtime/utils/setProps.d.ts +0 -10
  173. package/dist/runtime/utils/setProps.js +0 -17
  174. package/dist/scene/dsl.d.ts +0 -25
  175. package/dist/scene/dsl.js +0 -112
  176. package/dist/scene/index.d.ts +0 -5
  177. package/dist/scene/index.js +0 -5
  178. package/dist/scene/instantiate.d.ts +0 -8
  179. package/dist/scene/instantiate.js +0 -208
  180. package/dist/scene/nodesDsl.d.ts +0 -42
  181. package/dist/scene/nodesDsl.js +0 -169
  182. package/dist/scene/spec.d.ts +0 -100
  183. package/dist/scene/spec.js +0 -1
  184. package/dist/scene/templates.d.ts +0 -21
  185. package/dist/scene/templates.js +0 -239
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Pixifact is a Bun-first framework for AI-editable 2D game UI, HUDs, menus, and lightweight scenes on top of PixiJS v8.
4
4
 
5
- Use `pixifact` for runtime APIs, Scene instantiation, compiler APIs, and generated Scene runtime support.
5
+ Use `pixifact` for project config helpers, the `Group` runtime node, compiler APIs, and generated Scene runtime support.
6
6
 
7
7
  ## Install
8
8
 
@@ -13,8 +13,8 @@ bun add pixifact pixi.js
13
13
  ## Usage
14
14
 
15
15
  ```ts
16
- import { Application } from 'pixifact/runtime';
17
- import { scene, container, text } from 'pixifact/scene';
16
+ import { parseSceneTemplate } from 'pixifact/compiler';
17
+ import { Group } from 'pixifact/runtime';
18
18
  ```
19
19
 
20
20
  Compiler Scene projects usually also install the CLI:
@@ -0,0 +1,13 @@
1
+ import { Container } from 'pixi.js';
2
+ import { Control } from './Control.js';
3
+ import { type Size } from './controlLayout.js';
4
+ export declare class CenterContainer extends Control {
5
+ #private;
6
+ readonly default: Container;
7
+ get alignX(): string;
8
+ set alignX(value: string);
9
+ get alignY(): string;
10
+ set alignY(value: string);
11
+ layout(): void;
12
+ measureControlNaturalSize(): Size;
13
+ }
@@ -0,0 +1,71 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { prop, scene, slot } from 'pixifact/compiler';
8
+ import { Control } from './Control.js';
9
+ import { alignOffset, controlChildProps, controlMinSize, fillOrExpand, parseAlign, setControlChildBox, } from './controlLayout.js';
10
+ let CenterContainer = class CenterContainer extends Control {
11
+ #alignX = 'center';
12
+ #alignY = 'center';
13
+ #baseSizes = new WeakMap();
14
+ get alignX() {
15
+ return this.#alignX;
16
+ }
17
+ set alignX(value) {
18
+ this.#alignX = parseAlign(value);
19
+ this.layout();
20
+ }
21
+ get alignY() {
22
+ return this.#alignY;
23
+ }
24
+ set alignY(value) {
25
+ this.#alignY = parseAlign(value);
26
+ this.layout();
27
+ }
28
+ layout() {
29
+ const size = this.syncControlBoxSize();
30
+ const children = this.default?.children;
31
+ if (!children || children.length === 0) {
32
+ return;
33
+ }
34
+ for (const child of children) {
35
+ const props = controlChildProps(child);
36
+ const childSize = controlMinSize(child, this.#baseSizes);
37
+ const childWidth = fillOrExpand(props.hSize) ? size.width : childSize.width;
38
+ const childHeight = fillOrExpand(props.vSize) ? size.height : childSize.height;
39
+ setControlChildBox(child, {
40
+ x: alignOffset(this.#alignX, Math.max(0, size.width - childWidth)),
41
+ y: alignOffset(this.#alignY, Math.max(0, size.height - childHeight)),
42
+ width: childWidth,
43
+ height: childHeight,
44
+ });
45
+ }
46
+ }
47
+ measureControlNaturalSize() {
48
+ const children = this.default?.children;
49
+ if (!children || children.length === 0) {
50
+ return { width: 0, height: 0 };
51
+ }
52
+ const sizes = children.map((child) => controlMinSize(child, this.#baseSizes));
53
+ return {
54
+ width: sizes.reduce((max, size) => Math.max(max, size.width), 0),
55
+ height: sizes.reduce((max, size) => Math.max(max, size.height), 0),
56
+ };
57
+ }
58
+ };
59
+ __decorate([
60
+ slot()
61
+ ], CenterContainer.prototype, "default", void 0);
62
+ __decorate([
63
+ prop({ type: String, default: 'center' })
64
+ ], CenterContainer.prototype, "alignX", null);
65
+ __decorate([
66
+ prop({ type: String, default: 'center' })
67
+ ], CenterContainer.prototype, "alignY", null);
68
+ CenterContainer = __decorate([
69
+ scene()
70
+ ], CenterContainer);
71
+ export { CenterContainer };
@@ -0,0 +1,3 @@
1
+ <Scene name="CenterContainer">
2
+ <slot name="default" />
3
+ </Scene>
@@ -0,0 +1,77 @@
1
+ import { Container } from 'pixi.js';
2
+ import { prop, scene, slot } from 'pixifact/compiler';
3
+ import { Control } from './Control';
4
+ import {
5
+ alignOffset,
6
+ controlChildProps,
7
+ controlMinSize,
8
+ fillOrExpand,
9
+ parseAlign,
10
+ setControlChildBox,
11
+ type ControlAlign,
12
+ type ControlLayoutChild,
13
+ type Size,
14
+ } from './controlLayout';
15
+
16
+ @scene()
17
+ export class CenterContainer extends Control {
18
+ @slot()
19
+ declare readonly default: Container;
20
+
21
+ #alignX: ControlAlign = 'center';
22
+ #alignY: ControlAlign = 'center';
23
+ #baseSizes = new WeakMap<object, Size>();
24
+
25
+ get alignX() {
26
+ return this.#alignX;
27
+ }
28
+
29
+ @prop({ type: String, default: 'center' })
30
+ set alignX(value: string) {
31
+ this.#alignX = parseAlign(value);
32
+ this.layout();
33
+ }
34
+
35
+ get alignY() {
36
+ return this.#alignY;
37
+ }
38
+
39
+ @prop({ type: String, default: 'center' })
40
+ set alignY(value: string) {
41
+ this.#alignY = parseAlign(value);
42
+ this.layout();
43
+ }
44
+
45
+ override layout() {
46
+ const size = this.syncControlBoxSize();
47
+ const children = this.default?.children as ControlLayoutChild[] | undefined;
48
+ if (!children || children.length === 0) {
49
+ return;
50
+ }
51
+
52
+ for (const child of children) {
53
+ const props = controlChildProps(child);
54
+ const childSize = controlMinSize(child, this.#baseSizes);
55
+ const childWidth = fillOrExpand(props.hSize) ? size.width : childSize.width;
56
+ const childHeight = fillOrExpand(props.vSize) ? size.height : childSize.height;
57
+ setControlChildBox(child, {
58
+ x: alignOffset(this.#alignX, Math.max(0, size.width - childWidth)),
59
+ y: alignOffset(this.#alignY, Math.max(0, size.height - childHeight)),
60
+ width: childWidth,
61
+ height: childHeight,
62
+ });
63
+ }
64
+ }
65
+
66
+ override measureControlNaturalSize(): Size {
67
+ const children = this.default?.children as ControlLayoutChild[] | undefined;
68
+ if (!children || children.length === 0) {
69
+ return { width: 0, height: 0 };
70
+ }
71
+ const sizes = children.map((child) => controlMinSize(child, this.#baseSizes));
72
+ return {
73
+ width: sizes.reduce((max, size) => Math.max(max, size.width), 0),
74
+ height: sizes.reduce((max, size) => Math.max(max, size.height), 0),
75
+ };
76
+ }
77
+ }
@@ -0,0 +1,44 @@
1
+ import { Container } from 'pixi.js';
2
+ import { Group } from 'pixifact/runtime';
3
+ import { type ControlLayoutProps, type Size } from './controlLayout.js';
4
+ export declare class Control extends Group {
5
+ #private;
6
+ readonly default: Container;
7
+ get width(): number;
8
+ set width(value: number);
9
+ get height(): number;
10
+ set height(value: number);
11
+ getSize(out?: Size): Size;
12
+ setSize(value: number | {
13
+ width: number;
14
+ height?: number;
15
+ }, height?: number): void;
16
+ get minWidth(): number;
17
+ set minWidth(value: number);
18
+ get minHeight(): number;
19
+ set minHeight(value: number);
20
+ get hSize(): string;
21
+ set hSize(value: string);
22
+ get vSize(): string;
23
+ set vSize(value: string);
24
+ get stretch(): number;
25
+ set stretch(value: number);
26
+ get alignX(): string;
27
+ set alignX(value: string);
28
+ get alignY(): string;
29
+ set alignY(value: string);
30
+ onMounted(): void;
31
+ getControlLayoutProps(): ControlLayoutProps;
32
+ measureControlNaturalSize(): Size;
33
+ setControlLayoutBox(x: number, y: number, width: number, height: number): void;
34
+ layout(): void;
35
+ protected layoutDefaultSlot(size?: Size): void;
36
+ protected syncControlBoxSize(): Size;
37
+ protected getControlBoxSize(): Size;
38
+ protected getAssignedControlBoxSize(): {
39
+ width: number | undefined;
40
+ height: number | undefined;
41
+ };
42
+ protected refreshControlLayout(): void;
43
+ protected requestParentLayout(): void;
44
+ }
@@ -0,0 +1,206 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { prop, scene, slot } from 'pixifact/compiler';
8
+ import { Group } from 'pixifact/runtime';
9
+ import { alignOffset, boxSize, defaultControlLayoutProps, finiteNumber, measureChildren, measureChildrenBounds, parseAlign, parseSizeMode, } from './controlLayout.js';
10
+ let Control = class Control extends Group {
11
+ default;
12
+ #explicitWidth;
13
+ #explicitHeight;
14
+ #layoutWidth;
15
+ #layoutHeight;
16
+ #minWidth = 0;
17
+ #minHeight = 0;
18
+ #hSize = 'content';
19
+ #vSize = 'content';
20
+ #stretch = 1;
21
+ #alignX = 'start';
22
+ #alignY = 'start';
23
+ get width() {
24
+ return this.getControlBoxSize().width;
25
+ }
26
+ set width(value) {
27
+ this.#explicitWidth = Math.max(0, finiteNumber(value, 0));
28
+ this.refreshControlLayout();
29
+ }
30
+ get height() {
31
+ return this.getControlBoxSize().height;
32
+ }
33
+ set height(value) {
34
+ this.#explicitHeight = Math.max(0, finiteNumber(value, 0));
35
+ this.refreshControlLayout();
36
+ }
37
+ getSize(out = { width: 0, height: 0 }) {
38
+ out.width = this.width;
39
+ out.height = this.height;
40
+ return out;
41
+ }
42
+ setSize(value, height) {
43
+ const size = boxSize(value, height);
44
+ this.#explicitWidth = size.width;
45
+ this.#explicitHeight = size.height;
46
+ this.refreshControlLayout();
47
+ }
48
+ get minWidth() {
49
+ return this.#minWidth;
50
+ }
51
+ set minWidth(value) {
52
+ this.#minWidth = Math.max(0, finiteNumber(value, 0));
53
+ this.refreshControlLayout();
54
+ }
55
+ get minHeight() {
56
+ return this.#minHeight;
57
+ }
58
+ set minHeight(value) {
59
+ this.#minHeight = Math.max(0, finiteNumber(value, 0));
60
+ this.refreshControlLayout();
61
+ }
62
+ get hSize() {
63
+ return this.#hSize;
64
+ }
65
+ set hSize(value) {
66
+ this.#hSize = parseSizeMode(value);
67
+ this.requestParentLayout();
68
+ }
69
+ get vSize() {
70
+ return this.#vSize;
71
+ }
72
+ set vSize(value) {
73
+ this.#vSize = parseSizeMode(value);
74
+ this.requestParentLayout();
75
+ }
76
+ get stretch() {
77
+ return this.#stretch;
78
+ }
79
+ set stretch(value) {
80
+ this.#stretch = Math.max(0, finiteNumber(value, 1));
81
+ this.requestParentLayout();
82
+ }
83
+ get alignX() {
84
+ return this.#alignX;
85
+ }
86
+ set alignX(value) {
87
+ this.#alignX = parseAlign(value);
88
+ this.layout();
89
+ }
90
+ get alignY() {
91
+ return this.#alignY;
92
+ }
93
+ set alignY(value) {
94
+ this.#alignY = parseAlign(value);
95
+ this.layout();
96
+ }
97
+ onMounted() {
98
+ this.default.on('childAdded', this.#refreshFromChildren, this);
99
+ this.default.on('childRemoved', this.#refreshFromChildren, this);
100
+ this.once('destroyed', this.#unmountLayout, this);
101
+ this.layout();
102
+ }
103
+ #unmountLayout() {
104
+ this.default.off('childAdded', this.#refreshFromChildren, this);
105
+ this.default.off('childRemoved', this.#refreshFromChildren, this);
106
+ }
107
+ #refreshFromChildren() {
108
+ this.refreshControlLayout();
109
+ }
110
+ getControlLayoutProps() {
111
+ return {
112
+ ...defaultControlLayoutProps,
113
+ minWidth: this.#minWidth,
114
+ minHeight: this.#minHeight,
115
+ hSize: this.#hSize,
116
+ vSize: this.#vSize,
117
+ stretch: this.#stretch,
118
+ };
119
+ }
120
+ measureControlNaturalSize() {
121
+ const contentSize = this.default ? measureChildren(this.default) : { width: 0, height: 0 };
122
+ return {
123
+ width: Math.max(this.#minWidth, contentSize.width),
124
+ height: Math.max(this.#minHeight, contentSize.height),
125
+ };
126
+ }
127
+ setControlLayoutBox(x, y, width, height) {
128
+ this.position.set(x, y);
129
+ this.#layoutWidth = Math.max(0, finiteNumber(width, 0));
130
+ this.#layoutHeight = Math.max(0, finiteNumber(height, 0));
131
+ this.layout();
132
+ }
133
+ layout() {
134
+ const size = this.syncControlBoxSize();
135
+ this.layoutDefaultSlot(size);
136
+ }
137
+ layoutDefaultSlot(size = this.getControlBoxSize()) {
138
+ if (!this.default) {
139
+ return;
140
+ }
141
+ const bounds = measureChildrenBounds(this.default);
142
+ const offsetX = alignOffset(this.#alignX, Math.max(0, size.width - bounds.width)) - bounds.x;
143
+ const offsetY = alignOffset(this.#alignY, Math.max(0, size.height - bounds.height)) - bounds.y;
144
+ this.default.position.set(offsetX, offsetY);
145
+ }
146
+ syncControlBoxSize() {
147
+ const size = this.getControlBoxSize();
148
+ super.setSize(Math.max(0, finiteNumber(size.width, 0)), Math.max(0, finiteNumber(size.height, 0)));
149
+ return size;
150
+ }
151
+ getControlBoxSize() {
152
+ const natural = this.measureControlNaturalSize();
153
+ return {
154
+ width: this.#layoutWidth ?? this.#explicitWidth ?? natural.width,
155
+ height: this.#layoutHeight ?? this.#explicitHeight ?? natural.height,
156
+ };
157
+ }
158
+ getAssignedControlBoxSize() {
159
+ return {
160
+ width: this.#layoutWidth ?? this.#explicitWidth,
161
+ height: this.#layoutHeight ?? this.#explicitHeight,
162
+ };
163
+ }
164
+ refreshControlLayout() {
165
+ this.layout();
166
+ this.requestParentLayout();
167
+ }
168
+ requestParentLayout() {
169
+ let parent = this.parent;
170
+ while (parent) {
171
+ if (typeof parent.layout === 'function') {
172
+ parent.layout();
173
+ return;
174
+ }
175
+ parent = parent.parent;
176
+ }
177
+ }
178
+ };
179
+ __decorate([
180
+ slot()
181
+ ], Control.prototype, "default", void 0);
182
+ __decorate([
183
+ prop({ type: Number, default: 0 })
184
+ ], Control.prototype, "minWidth", null);
185
+ __decorate([
186
+ prop({ type: Number, default: 0 })
187
+ ], Control.prototype, "minHeight", null);
188
+ __decorate([
189
+ prop({ type: String, default: 'content' })
190
+ ], Control.prototype, "hSize", null);
191
+ __decorate([
192
+ prop({ type: String, default: 'content' })
193
+ ], Control.prototype, "vSize", null);
194
+ __decorate([
195
+ prop({ type: Number, default: 1 })
196
+ ], Control.prototype, "stretch", null);
197
+ __decorate([
198
+ prop({ type: String, default: 'start' })
199
+ ], Control.prototype, "alignX", null);
200
+ __decorate([
201
+ prop({ type: String, default: 'start' })
202
+ ], Control.prototype, "alignY", null);
203
+ Control = __decorate([
204
+ scene()
205
+ ], Control);
206
+ export { Control };
@@ -0,0 +1,3 @@
1
+ <Scene name="Control">
2
+ <slot name="default" />
3
+ </Scene>
@@ -0,0 +1,233 @@
1
+ import { Container } from 'pixi.js';
2
+ import { prop, scene, slot } from 'pixifact/compiler';
3
+ import { Group } from 'pixifact/runtime';
4
+ import {
5
+ alignOffset,
6
+ boxSize,
7
+ defaultControlLayoutProps,
8
+ finiteNumber,
9
+ measureChildren,
10
+ measureChildrenBounds,
11
+ parseAlign,
12
+ parseSizeMode,
13
+ type ControlAlign,
14
+ type ControlLayoutProps,
15
+ type ControlSizeMode,
16
+ type Size,
17
+ } from './controlLayout';
18
+
19
+ @scene()
20
+ export class Control extends Group {
21
+ @slot()
22
+ readonly default!: Container;
23
+
24
+ #explicitWidth: number | undefined;
25
+ #explicitHeight: number | undefined;
26
+ #layoutWidth: number | undefined;
27
+ #layoutHeight: number | undefined;
28
+ #minWidth = 0;
29
+ #minHeight = 0;
30
+ #hSize: ControlSizeMode = 'content';
31
+ #vSize: ControlSizeMode = 'content';
32
+ #stretch = 1;
33
+ #alignX: ControlAlign = 'start';
34
+ #alignY: ControlAlign = 'start';
35
+
36
+ override get width() {
37
+ return this.getControlBoxSize().width;
38
+ }
39
+
40
+ override set width(value: number) {
41
+ this.#explicitWidth = Math.max(0, finiteNumber(value, 0));
42
+ this.refreshControlLayout();
43
+ }
44
+
45
+ override get height() {
46
+ return this.getControlBoxSize().height;
47
+ }
48
+
49
+ override set height(value: number) {
50
+ this.#explicitHeight = Math.max(0, finiteNumber(value, 0));
51
+ this.refreshControlLayout();
52
+ }
53
+
54
+ override getSize(out: Size = { width: 0, height: 0 }) {
55
+ out.width = this.width;
56
+ out.height = this.height;
57
+ return out;
58
+ }
59
+
60
+ override setSize(value: number | { width: number; height?: number }, height?: number) {
61
+ const size = boxSize(value, height);
62
+ this.#explicitWidth = size.width;
63
+ this.#explicitHeight = size.height;
64
+ this.refreshControlLayout();
65
+ }
66
+
67
+ get minWidth() {
68
+ return this.#minWidth;
69
+ }
70
+
71
+ @prop({ type: Number, default: 0 })
72
+ set minWidth(value: number) {
73
+ this.#minWidth = Math.max(0, finiteNumber(value, 0));
74
+ this.refreshControlLayout();
75
+ }
76
+
77
+ get minHeight() {
78
+ return this.#minHeight;
79
+ }
80
+
81
+ @prop({ type: Number, default: 0 })
82
+ set minHeight(value: number) {
83
+ this.#minHeight = Math.max(0, finiteNumber(value, 0));
84
+ this.refreshControlLayout();
85
+ }
86
+
87
+ get hSize() {
88
+ return this.#hSize;
89
+ }
90
+
91
+ @prop({ type: String, default: 'content' })
92
+ set hSize(value: string) {
93
+ this.#hSize = parseSizeMode(value);
94
+ this.requestParentLayout();
95
+ }
96
+
97
+ get vSize() {
98
+ return this.#vSize;
99
+ }
100
+
101
+ @prop({ type: String, default: 'content' })
102
+ set vSize(value: string) {
103
+ this.#vSize = parseSizeMode(value);
104
+ this.requestParentLayout();
105
+ }
106
+
107
+ get stretch() {
108
+ return this.#stretch;
109
+ }
110
+
111
+ @prop({ type: Number, default: 1 })
112
+ set stretch(value: number) {
113
+ this.#stretch = Math.max(0, finiteNumber(value, 1));
114
+ this.requestParentLayout();
115
+ }
116
+
117
+ get alignX() {
118
+ return this.#alignX;
119
+ }
120
+
121
+ @prop({ type: String, default: 'start' })
122
+ set alignX(value: string) {
123
+ this.#alignX = parseAlign(value);
124
+ this.layout();
125
+ }
126
+
127
+ get alignY() {
128
+ return this.#alignY;
129
+ }
130
+
131
+ @prop({ type: String, default: 'start' })
132
+ set alignY(value: string) {
133
+ this.#alignY = parseAlign(value);
134
+ this.layout();
135
+ }
136
+
137
+ onMounted() {
138
+ this.default.on('childAdded', this.#refreshFromChildren, this);
139
+ this.default.on('childRemoved', this.#refreshFromChildren, this);
140
+ this.once('destroyed', this.#unmountLayout, this);
141
+ this.layout();
142
+ }
143
+
144
+ #unmountLayout() {
145
+ this.default.off('childAdded', this.#refreshFromChildren, this);
146
+ this.default.off('childRemoved', this.#refreshFromChildren, this);
147
+ }
148
+
149
+ #refreshFromChildren() {
150
+ this.refreshControlLayout();
151
+ }
152
+
153
+ getControlLayoutProps(): ControlLayoutProps {
154
+ return {
155
+ ...defaultControlLayoutProps,
156
+ minWidth: this.#minWidth,
157
+ minHeight: this.#minHeight,
158
+ hSize: this.#hSize,
159
+ vSize: this.#vSize,
160
+ stretch: this.#stretch,
161
+ };
162
+ }
163
+
164
+ measureControlNaturalSize(): Size {
165
+ const contentSize = this.default ? measureChildren(this.default) : { width: 0, height: 0 };
166
+ return {
167
+ width: Math.max(this.#minWidth, contentSize.width),
168
+ height: Math.max(this.#minHeight, contentSize.height),
169
+ };
170
+ }
171
+
172
+ setControlLayoutBox(x: number, y: number, width: number, height: number) {
173
+ this.position.set(x, y);
174
+ this.#layoutWidth = Math.max(0, finiteNumber(width, 0));
175
+ this.#layoutHeight = Math.max(0, finiteNumber(height, 0));
176
+ this.layout();
177
+ }
178
+
179
+ layout() {
180
+ const size = this.syncControlBoxSize();
181
+ this.layoutDefaultSlot(size);
182
+ }
183
+
184
+ protected layoutDefaultSlot(size: Size = this.getControlBoxSize()) {
185
+ if (!this.default) {
186
+ return;
187
+ }
188
+ const bounds = measureChildrenBounds(this.default);
189
+ const offsetX = alignOffset(this.#alignX, Math.max(0, size.width - bounds.width)) - bounds.x;
190
+ const offsetY = alignOffset(this.#alignY, Math.max(0, size.height - bounds.height)) - bounds.y;
191
+ this.default.position.set(offsetX, offsetY);
192
+ }
193
+
194
+ protected syncControlBoxSize() {
195
+ const size = this.getControlBoxSize();
196
+ super.setSize(
197
+ Math.max(0, finiteNumber(size.width, 0)),
198
+ Math.max(0, finiteNumber(size.height, 0)),
199
+ );
200
+ return size;
201
+ }
202
+
203
+ protected getControlBoxSize(): Size {
204
+ const natural = this.measureControlNaturalSize();
205
+ return {
206
+ width: this.#layoutWidth ?? this.#explicitWidth ?? natural.width,
207
+ height: this.#layoutHeight ?? this.#explicitHeight ?? natural.height,
208
+ };
209
+ }
210
+
211
+ protected getAssignedControlBoxSize() {
212
+ return {
213
+ width: this.#layoutWidth ?? this.#explicitWidth,
214
+ height: this.#layoutHeight ?? this.#explicitHeight,
215
+ };
216
+ }
217
+
218
+ protected refreshControlLayout() {
219
+ this.layout();
220
+ this.requestParentLayout();
221
+ }
222
+
223
+ protected requestParentLayout() {
224
+ let parent = this.parent as (Container & { layout?: () => void }) | null;
225
+ while (parent) {
226
+ if (typeof parent.layout === 'function') {
227
+ parent.layout();
228
+ return;
229
+ }
230
+ parent = parent.parent as (Container & { layout?: () => void }) | null;
231
+ }
232
+ }
233
+ }