@dcl/react-ecs 7.0.6-3807227301.commit-1045452 → 7.0.6-3808564125.commit-7a2650b
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/components/Button/index.d.ts +7 -0
- package/dist/components/Button/index.js +39 -0
- package/dist/components/Button/types.d.ts +7 -0
- package/dist/components/Button/types.js +1 -0
- package/dist/components/Dropdown/index.d.ts +7 -0
- package/dist/components/Dropdown/index.js +26 -0
- package/dist/components/Dropdown/types.d.ts +7 -0
- package/dist/components/Dropdown/types.js +1 -0
- package/dist/components/Input/index.d.ts +7 -0
- package/dist/components/Input/index.js +24 -0
- package/dist/components/Input/types.d.ts +7 -0
- package/dist/components/Input/types.js +1 -0
- package/dist/components/Label/index.d.ts +7 -0
- package/dist/components/Label/index.js +16 -0
- package/dist/components/Label/types.d.ts +5 -0
- package/dist/components/Label/types.js +1 -0
- package/dist/components/index.d.ts +9 -2
- package/dist/components/index.js +13 -7
- package/dist/components/listeners/types.d.ts +4 -3
- package/dist/components/listeners/types.js +2 -1
- package/dist/components/types.d.ts +5 -5
- package/dist/components/uiBackground/index.d.ts +6 -0
- package/dist/components/uiBackground/index.js +40 -0
- package/dist/components/uiBackground/types.d.ts +21 -0
- package/dist/components/uiBackground/types.js +1 -0
- package/dist/components/uiTransform/index.js +20 -19
- package/dist/components/uiTransform/types.d.ts +1 -1
- package/dist/components/utils.d.ts +1 -0
- package/dist/components/utils.js +17 -0
- package/dist/react-ecs.d.ts +9 -8
- package/dist/reconciler/index.d.ts +1 -1
- package/dist/reconciler/index.js +68 -36
- package/dist/reconciler/utils.d.ts +2 -2
- package/dist/reconciler/utils.js +32 -3
- package/package.json +2 -2
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ReactEcs } from '../../react-ecs';
|
|
2
|
+
import { parseUiBackground } from '../uiBackground';
|
|
3
|
+
import { parseUiTransform } from '../uiTransform';
|
|
4
|
+
function getButtonProps(props) {
|
|
5
|
+
if (props.type === 'primary') {
|
|
6
|
+
return {
|
|
7
|
+
uiBackground: { color: { r: 0.98, g: 0.17, b: 0.33, a: 1 } },
|
|
8
|
+
uiText: { color: { r: 1, g: 1, b: 1, a: 1 } }
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
if (props.type === 'secondary') {
|
|
12
|
+
return {
|
|
13
|
+
uiBackground: { color: { r: 1, g: 1, b: 1, a: 1 } },
|
|
14
|
+
uiText: { color: { r: 0.98, g: 0.17, b: 0.33, a: 1 } }
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
/*#__PURE__*/
|
|
23
|
+
export function Button(props) {
|
|
24
|
+
const { uiTransform, uiBackground, onMouseDown, onMouseUp, ...uiTextProps } = props;
|
|
25
|
+
const buttonProps = getButtonProps(props);
|
|
26
|
+
const uiBackgroundProps = parseUiBackground({
|
|
27
|
+
...buttonProps.uiBackground,
|
|
28
|
+
...uiBackground
|
|
29
|
+
});
|
|
30
|
+
const textProps = {
|
|
31
|
+
...buttonProps.uiText,
|
|
32
|
+
...uiTextProps
|
|
33
|
+
};
|
|
34
|
+
const uiTransformProps = parseUiTransform({
|
|
35
|
+
height: 36,
|
|
36
|
+
...uiTransform
|
|
37
|
+
});
|
|
38
|
+
return (ReactEcs.createElement("entity", { onMouseDown: onMouseDown, onMouseUp: onMouseUp, uiTransform: uiTransformProps, uiText: textProps, uiBackground: uiBackgroundProps }));
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { parseProps } from '../utils';
|
|
2
|
+
import { ReactEcs } from '../../react-ecs';
|
|
3
|
+
function parseUiDropdown(props) {
|
|
4
|
+
return {
|
|
5
|
+
acceptEmpty: false,
|
|
6
|
+
options: [],
|
|
7
|
+
selectedIndex: props.acceptEmpty ? -1 : 0,
|
|
8
|
+
disabled: false,
|
|
9
|
+
...props
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
/*#__PURE__*/
|
|
16
|
+
export function Dropdown(props) {
|
|
17
|
+
const { uiTransform, uiBackground, onMouseDown, onMouseUp, ...otherProps } = props;
|
|
18
|
+
const dropdownProps = parseUiDropdown(otherProps);
|
|
19
|
+
const commonProps = parseProps({
|
|
20
|
+
uiTransform,
|
|
21
|
+
uiBackground,
|
|
22
|
+
onMouseDown,
|
|
23
|
+
onMouseUp
|
|
24
|
+
});
|
|
25
|
+
return ReactEcs.createElement("entity", { ...commonProps, uiDropdown: dropdownProps });
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { parseProps } from '../utils';
|
|
2
|
+
import { ReactEcs } from '../../react-ecs';
|
|
3
|
+
function parseUiInput(props) {
|
|
4
|
+
return {
|
|
5
|
+
disabled: false,
|
|
6
|
+
placeholder: '',
|
|
7
|
+
...props
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
/*#__PURE__*/
|
|
14
|
+
export function Input(props) {
|
|
15
|
+
const { uiTransform, uiBackground, onMouseDown, onMouseUp, ...otherProps } = props;
|
|
16
|
+
const inputProps = parseUiInput(otherProps);
|
|
17
|
+
const commonProps = parseProps({
|
|
18
|
+
uiTransform,
|
|
19
|
+
uiBackground,
|
|
20
|
+
onMouseDown,
|
|
21
|
+
onMouseUp
|
|
22
|
+
});
|
|
23
|
+
return ReactEcs.createElement("entity", { ...commonProps, uiInput: inputProps });
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { parseProps } from '../utils';
|
|
2
|
+
import { ReactEcs } from '../../react-ecs';
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
/*#__PURE__*/
|
|
7
|
+
export function Label(props) {
|
|
8
|
+
const { uiTransform, uiBackground, onMouseDown, onMouseUp, ...uiTextProps } = props;
|
|
9
|
+
const commonProps = parseProps({
|
|
10
|
+
uiTransform,
|
|
11
|
+
uiBackground,
|
|
12
|
+
onMouseDown,
|
|
13
|
+
onMouseUp
|
|
14
|
+
});
|
|
15
|
+
return ReactEcs.createElement("entity", { ...commonProps, uiText: uiTextProps });
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -5,9 +5,16 @@ export * from './types';
|
|
|
5
5
|
export { CANVAS_ROOT_ENTITY };
|
|
6
6
|
export * from './uiTransform/types';
|
|
7
7
|
export * from './listeners/types';
|
|
8
|
+
export * from './Input/types';
|
|
9
|
+
export * from './uiBackground/types';
|
|
10
|
+
export * from './Dropdown/types';
|
|
11
|
+
export * from './Label/types';
|
|
12
|
+
export * from './Button/types';
|
|
13
|
+
export { Dropdown } from './Dropdown';
|
|
14
|
+
export { Input } from './Input';
|
|
15
|
+
export { Label } from './Label';
|
|
16
|
+
export { Button } from './Button';
|
|
8
17
|
/**
|
|
9
18
|
* @public
|
|
10
19
|
*/
|
|
11
20
|
export declare function UiEntity(props: EntityPropTypes & Partial<CommonProps>): ReactEcs.JSX.Element;
|
|
12
|
-
export declare type ContainerPropTypes = Partial<CommonProps> & EntityPropTypes['uiTransform'];
|
|
13
|
-
export declare function Container({ width, height, children }: ContainerPropTypes): ReactEcs.JSX.Element;
|
package/dist/components/index.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { ReactEcs } from '../react-ecs';
|
|
2
|
-
import {
|
|
2
|
+
import { CANVAS_ROOT_ENTITY } from './uiTransform';
|
|
3
|
+
import { parseProps } from './utils';
|
|
3
4
|
export * from './types';
|
|
4
5
|
export { CANVAS_ROOT_ENTITY };
|
|
5
6
|
export * from './uiTransform/types';
|
|
6
7
|
export * from './listeners/types';
|
|
8
|
+
export * from './Input/types';
|
|
9
|
+
export * from './uiBackground/types';
|
|
10
|
+
export * from './Dropdown/types';
|
|
11
|
+
export * from './Label/types';
|
|
12
|
+
export * from './Button/types';
|
|
13
|
+
export { Dropdown } from './Dropdown';
|
|
14
|
+
export { Input } from './Input';
|
|
15
|
+
export { Label } from './Label';
|
|
16
|
+
export { Button } from './Button';
|
|
7
17
|
/**
|
|
8
18
|
* @public
|
|
9
19
|
*/
|
|
20
|
+
/*#__PURE__*/
|
|
10
21
|
export function UiEntity(props) {
|
|
11
|
-
|
|
12
|
-
const uiTransformProps = parseUiTransform(uiTransform);
|
|
13
|
-
return ReactEcs.createElement("entity", { uiTransform: uiTransformProps, ...otherProps });
|
|
14
|
-
}
|
|
15
|
-
export function Container({ width, height, children }) {
|
|
16
|
-
return (ReactEcs.createElement(UiEntity, { uiTransform: { width, height, display: 0 /* YGDisplay.YGD_FLEX */ } }, children));
|
|
22
|
+
return ReactEcs.createElement("entity", { ...parseProps(props) });
|
|
17
23
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
export declare type Callback = () => void;
|
|
2
2
|
export declare type Listeners = {
|
|
3
|
-
|
|
3
|
+
onMouseDown?: Callback;
|
|
4
|
+
onMouseUp?: Callback;
|
|
4
5
|
};
|
|
5
|
-
export declare const isListener: (key: string) => key is
|
|
6
|
+
export declare const isListener: (key: string) => key is keyof Listeners;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Listeners } from './listeners/types';
|
|
2
|
+
import { UiBackgroundProps } from './uiBackground/types';
|
|
2
3
|
import { UiTransformProps } from './uiTransform/types';
|
|
3
4
|
/**
|
|
4
5
|
* @public
|
|
5
6
|
*/
|
|
6
7
|
export declare type EntityPropTypes = {
|
|
7
8
|
uiTransform?: UiTransformProps;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
9
|
+
uiBackground?: UiBackgroundProps;
|
|
10
|
+
} & Listeners;
|
|
11
11
|
export declare type Key = number | string;
|
|
12
|
-
export declare type Children =
|
|
12
|
+
export declare type Children = unknown;
|
|
13
13
|
export declare type CommonProps = {
|
|
14
14
|
key: Key;
|
|
15
15
|
children: Children;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function isAvatarTexture(props) {
|
|
2
|
+
return !!props.avatarTexture;
|
|
3
|
+
}
|
|
4
|
+
function isTexture(props) {
|
|
5
|
+
return !!props.texture;
|
|
6
|
+
}
|
|
7
|
+
function getTexture(props) {
|
|
8
|
+
if (isTexture(props) && props.texture) {
|
|
9
|
+
return {
|
|
10
|
+
tex: {
|
|
11
|
+
$case: 'texture',
|
|
12
|
+
texture: props.texture
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (isAvatarTexture(props) && props.avatarTexture) {
|
|
17
|
+
return {
|
|
18
|
+
tex: {
|
|
19
|
+
$case: 'avatarTexture',
|
|
20
|
+
avatarTexture: props.avatarTexture
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
/*#__PURE__*/
|
|
30
|
+
export function parseUiBackground(props) {
|
|
31
|
+
if (!props || !Object.keys(props).length)
|
|
32
|
+
return undefined;
|
|
33
|
+
const texture = getTexture(props);
|
|
34
|
+
return {
|
|
35
|
+
...props,
|
|
36
|
+
uvs: props.uvs ?? [],
|
|
37
|
+
texture,
|
|
38
|
+
textureMode: props.textureMode ?? 1 /* BackgroundTextureMode.CENTER */
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PBUiBackground, Texture, AvatarTexture } from '@dcl/ecs';
|
|
2
|
+
/**
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export declare type UiBackgroundProps = Partial<Omit<PBUiBackground, 'texture'>> & UiTextureUnion;
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export declare type UiTextureUnion = UiAvatarTexture | UiTexture;
|
|
10
|
+
/**
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export declare type UiAvatarTexture = {
|
|
14
|
+
avatarTexture?: AvatarTexture;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export declare type UiTexture = {
|
|
20
|
+
texture?: Texture;
|
|
21
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,24 +1,5 @@
|
|
|
1
1
|
import { parsePosition, parseSize } from './utils';
|
|
2
2
|
export const CANVAS_ROOT_ENTITY = 0;
|
|
3
|
-
/**
|
|
4
|
-
* @public
|
|
5
|
-
*/
|
|
6
|
-
export function parseUiTransform(props = {}) {
|
|
7
|
-
const { position, padding, margin, height, minHeight, maxHeight, width, maxWidth, minWidth, ...otherProps } = props;
|
|
8
|
-
return {
|
|
9
|
-
...defaultUiTransform,
|
|
10
|
-
...otherProps,
|
|
11
|
-
...parsePosition(position, 'position'),
|
|
12
|
-
...parsePosition(margin, 'margin'),
|
|
13
|
-
...parsePosition(padding, 'padding'),
|
|
14
|
-
...parseSize(height, 'height'),
|
|
15
|
-
...parseSize(minHeight, 'minHeight'),
|
|
16
|
-
...parseSize(maxHeight, 'maxHeight'),
|
|
17
|
-
...parseSize(width, 'width'),
|
|
18
|
-
...parseSize(minWidth, 'minWidth'),
|
|
19
|
-
...parseSize(maxWidth, 'maxWidth')
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
3
|
const defaultUiTransform = {
|
|
23
4
|
parent: CANVAS_ROOT_ENTITY,
|
|
24
5
|
rightOf: 0,
|
|
@@ -68,3 +49,23 @@ const defaultUiTransform = {
|
|
|
68
49
|
widthUnit: 0 /* YGUnit.YGU_UNDEFINED */,
|
|
69
50
|
heightUnit: 0 /* YGUnit.YGU_UNDEFINED */
|
|
70
51
|
};
|
|
52
|
+
/**
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
55
|
+
/*#__PURE__*/
|
|
56
|
+
export function parseUiTransform(props = {}) {
|
|
57
|
+
const { position, padding, margin, height, minHeight, maxHeight, width, maxWidth, minWidth, ...otherProps } = props;
|
|
58
|
+
return {
|
|
59
|
+
...defaultUiTransform,
|
|
60
|
+
...otherProps,
|
|
61
|
+
...parsePosition(position, 'position'),
|
|
62
|
+
...parsePosition(margin, 'margin'),
|
|
63
|
+
...parsePosition(padding, 'padding'),
|
|
64
|
+
...parseSize(height, 'height'),
|
|
65
|
+
...parseSize(minHeight, 'minHeight'),
|
|
66
|
+
...parseSize(maxHeight, 'maxHeight'),
|
|
67
|
+
...parseSize(width, 'width'),
|
|
68
|
+
...parseSize(minWidth, 'minWidth'),
|
|
69
|
+
...parseSize(maxWidth, 'maxWidth')
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { YGAlign, YGDisplay, YGFlexDirection, YGJustify, YGOverflow, YGPositionType, YGWrap } from '@dcl/ecs
|
|
1
|
+
import { YGAlign, YGDisplay, YGFlexDirection, YGJustify, YGOverflow, YGPositionType, YGWrap } from '@dcl/ecs';
|
|
2
2
|
export declare type PositionUnit = `${number}px` | `${number}%` | number;
|
|
3
3
|
/**
|
|
4
4
|
* @public
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { parseUiBackground } from './uiBackground';
|
|
2
|
+
import { parseUiTransform } from './uiTransform';
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export function parseProps(props) {
|
|
7
|
+
const { uiTransform, uiBackground, ...otherProps } = props;
|
|
8
|
+
const uiTransformProps = parseUiTransform(uiTransform);
|
|
9
|
+
const uiBackgroundProps = uiBackground
|
|
10
|
+
? { uiBackground: parseUiBackground(uiBackground) }
|
|
11
|
+
: undefined;
|
|
12
|
+
return {
|
|
13
|
+
...otherProps,
|
|
14
|
+
uiTransform: uiTransformProps,
|
|
15
|
+
...uiBackgroundProps
|
|
16
|
+
};
|
|
17
|
+
}
|
package/dist/react-ecs.d.ts
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { PBUiBackground, PBUiText, PBUiTransform, PBUiInput, PBUiDropdown } from '@dcl/ecs';
|
|
2
|
+
import { Callback } from './components';
|
|
3
3
|
import { CommonProps } from './components/types';
|
|
4
4
|
export declare type EcsElements = {
|
|
5
|
-
entity: Partial<
|
|
5
|
+
entity: Partial<EntityComponents & CommonProps>;
|
|
6
6
|
};
|
|
7
7
|
export declare type EntityComponents = {
|
|
8
8
|
uiTransform: PBUiTransform;
|
|
9
9
|
uiText: PBUiText;
|
|
10
10
|
uiBackground: PBUiBackground;
|
|
11
|
-
|
|
11
|
+
uiInput: PBUiInput;
|
|
12
|
+
uiDropdown: PBUiDropdown;
|
|
13
|
+
onMouseDown: Callback;
|
|
14
|
+
onMouseUp: Callback;
|
|
12
15
|
};
|
|
13
16
|
export declare namespace JSX {
|
|
14
|
-
|
|
15
|
-
}
|
|
17
|
+
type Element = {} | null;
|
|
16
18
|
type IntrinsicElements = EcsElements;
|
|
17
19
|
interface Component {
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
export declare namespace ReactEcs {
|
|
21
23
|
namespace JSX {
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
+
type Element = {} | null;
|
|
24
25
|
type IntrinsicElements = EcsElements;
|
|
25
26
|
interface Component {
|
|
26
27
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IEngine, PointerEventsSystem } from '@dcl/ecs';
|
|
2
2
|
import { JSX } from '../react-ecs';
|
|
3
|
-
export declare function createReconciler(engine: Pick<IEngine, 'getComponent' | 'addEntity' | 'removeEntity' | 'defineComponentFromSchema'>, pointerEvents: PointerEventsSystem): {
|
|
3
|
+
export declare function createReconciler(engine: Pick<IEngine, 'getComponent' | 'addEntity' | 'removeEntity' | 'defineComponentFromSchema' | 'getEntitiesWith'>, pointerEvents: PointerEventsSystem): {
|
|
4
4
|
update: (component: JSX.Element) => number;
|
|
5
5
|
getEntities: () => unknown[];
|
|
6
6
|
};
|
package/dist/reconciler/index.js
CHANGED
|
@@ -2,62 +2,56 @@ import * as components from '@dcl/ecs/dist/components';
|
|
|
2
2
|
import Reconciler from 'react-reconciler';
|
|
3
3
|
import { isListener } from '../components';
|
|
4
4
|
import { CANVAS_ROOT_ENTITY } from '../components/uiTransform';
|
|
5
|
-
import { componentKeys,
|
|
6
|
-
function propsChanged(component, prevProps, nextProps) {
|
|
7
|
-
if (prevProps && !nextProps) {
|
|
8
|
-
return { type: 'delete', component };
|
|
9
|
-
}
|
|
10
|
-
if (!nextProps) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
if (!prevProps && nextProps) {
|
|
14
|
-
return { type: 'add', props: nextProps, component };
|
|
15
|
-
}
|
|
16
|
-
if (isListener(component)) {
|
|
17
|
-
if (!isEqual(prevProps, nextProps)) {
|
|
18
|
-
return { type: 'put', component, props: nextProps };
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
const changes = {};
|
|
22
|
-
for (const k in prevProps) {
|
|
23
|
-
const propKey = k;
|
|
24
|
-
if (!isEqual(prevProps[propKey], nextProps[propKey])) {
|
|
25
|
-
changes[propKey] = nextProps[propKey];
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
if (!Object.keys(changes).length) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
return { type: 'put', props: changes, component };
|
|
32
|
-
}
|
|
5
|
+
import { componentKeys, isNotUndefined, noopConfig, propsChanged } from './utils';
|
|
33
6
|
export function createReconciler(engine, pointerEvents) {
|
|
7
|
+
// Store all the entities so when we destroy the UI we can also destroy them
|
|
34
8
|
const entities = new Set();
|
|
9
|
+
// Store the onChange callbacks to be runned every time a Result has changed
|
|
10
|
+
const changeEvents = new Map();
|
|
11
|
+
// Initialize components
|
|
35
12
|
const UiTransform = components.UiTransform(engine);
|
|
36
13
|
const UiText = components.UiText(engine);
|
|
37
14
|
const UiBackground = components.UiBackground(engine);
|
|
15
|
+
const UiInput = components.UiInput(engine);
|
|
16
|
+
const UiInputResult = components.UiInputResult(engine);
|
|
17
|
+
const UiDropdown = components.UiDropdown(engine);
|
|
18
|
+
const UiDropdownResult = components.UiDropdownResult(engine);
|
|
19
|
+
// Component ID Helper
|
|
38
20
|
const getComponentId = {
|
|
39
21
|
uiTransform: UiTransform._id,
|
|
40
22
|
uiText: UiText._id,
|
|
41
|
-
uiBackground: UiBackground._id
|
|
23
|
+
uiBackground: UiBackground._id,
|
|
24
|
+
uiInput: UiInput._id,
|
|
25
|
+
uiDropdown: UiDropdown._id
|
|
42
26
|
};
|
|
43
27
|
function updateTree(instance, props) {
|
|
44
28
|
upsertComponent(instance, props, 'uiTransform');
|
|
45
29
|
}
|
|
46
30
|
function upsertListener(instance, update) {
|
|
47
|
-
// TODO: This handles only onClick listener for the moment
|
|
48
31
|
if (update.type === 'delete' || !update.props) {
|
|
49
|
-
|
|
32
|
+
if (update.component === 'onMouseDown') {
|
|
33
|
+
pointerEvents.removeOnPointerDown(instance.entity);
|
|
34
|
+
}
|
|
35
|
+
else if (update.component === 'onMouseUp') {
|
|
36
|
+
pointerEvents.removeOnPointerUp(instance.entity);
|
|
37
|
+
}
|
|
50
38
|
return;
|
|
51
39
|
}
|
|
52
40
|
if (update.props) {
|
|
53
|
-
|
|
41
|
+
const pointerEvent = update.component === 'onMouseDown'
|
|
42
|
+
? pointerEvents.onPointerDown
|
|
43
|
+
: pointerEvents.onPointerUp;
|
|
44
|
+
pointerEvent(instance.entity, update.props, {
|
|
54
45
|
button: 0 /* InputAction.IA_POINTER */,
|
|
55
|
-
|
|
46
|
+
// We add this showFeedBack so the pointerEventSystem creates a PointerEvent component with our entity
|
|
47
|
+
// This is needed for the renderer to know which entities are clickeables
|
|
48
|
+
showFeedback: true
|
|
56
49
|
});
|
|
57
50
|
}
|
|
58
51
|
}
|
|
59
52
|
function removeComponent(instance, component) {
|
|
60
|
-
const
|
|
53
|
+
const componentId = getComponentId[component];
|
|
54
|
+
const Component = engine.getComponent(componentId);
|
|
61
55
|
Component.deleteFrom(instance.entity);
|
|
62
56
|
}
|
|
63
57
|
function upsertComponent(instance, props, componentName) {
|
|
@@ -67,10 +61,18 @@ export function createReconciler(engine, pointerEvents) {
|
|
|
67
61
|
Component.create(instance.entity);
|
|
68
62
|
for (const key in props) {
|
|
69
63
|
const keyProp = key;
|
|
70
|
-
|
|
64
|
+
if (key === 'onChange') {
|
|
65
|
+
const onChange = props[keyProp];
|
|
66
|
+
updateOnChange(instance.entity, componentId, { fn: onChange });
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
;
|
|
70
|
+
component[keyProp] = props[keyProp];
|
|
71
|
+
}
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
function removeChildEntity(instance) {
|
|
75
|
+
changeEvents.delete(instance.entity);
|
|
74
76
|
engine.removeEntity(instance.entity);
|
|
75
77
|
for (const child of instance._child) {
|
|
76
78
|
removeChildEntity(child);
|
|
@@ -116,6 +118,14 @@ export function createReconciler(engine, pointerEvents) {
|
|
|
116
118
|
parentInstance._child.splice(childIndex, 1);
|
|
117
119
|
removeChildEntity(child);
|
|
118
120
|
}
|
|
121
|
+
function updateOnChange(entity, componentId, state) {
|
|
122
|
+
const event = changeEvents.get(entity) ||
|
|
123
|
+
changeEvents.set(entity, new Map()).get(entity);
|
|
124
|
+
const oldState = event.get(componentId);
|
|
125
|
+
const fn = state?.fn;
|
|
126
|
+
const value = state?.value ?? oldState?.value;
|
|
127
|
+
event.set(componentId, { fn, value });
|
|
128
|
+
}
|
|
119
129
|
const hostConfig = {
|
|
120
130
|
...noopConfig,
|
|
121
131
|
createInstance(type, props) {
|
|
@@ -154,7 +164,7 @@ export function createReconciler(engine, pointerEvents) {
|
|
|
154
164
|
.map((component) => propsChanged(component, oldProps[component], newProps[component]))
|
|
155
165
|
.filter(isNotUndefined);
|
|
156
166
|
},
|
|
157
|
-
commitUpdate(instance, updatePayload, _type,
|
|
167
|
+
commitUpdate(instance, updatePayload, _type, _prevProps, _nextProps, _internalHandle) {
|
|
158
168
|
for (const update of updatePayload) {
|
|
159
169
|
if (isListener(update.component)) {
|
|
160
170
|
upsertListener(instance, update);
|
|
@@ -180,14 +190,36 @@ export function createReconciler(engine, pointerEvents) {
|
|
|
180
190
|
child.parent = parentInstance.entity;
|
|
181
191
|
updateTree(child, { rightOf: child.rightOf, parent: child.parent });
|
|
182
192
|
updateTree(beforeChild, { rightOf: beforeChild.rightOf });
|
|
193
|
+
},
|
|
194
|
+
removeChildFromContainer(parenInstance, child) {
|
|
195
|
+
removeChildEntity(child);
|
|
183
196
|
}
|
|
184
197
|
};
|
|
185
198
|
const reconciler = Reconciler(hostConfig);
|
|
186
199
|
const root = reconciler.createContainer({}, 0, null, false, null, '',
|
|
187
200
|
/* istanbul ignore next */
|
|
188
201
|
function () { }, null);
|
|
202
|
+
// Maybe this could be something similar to Input system, but since we
|
|
203
|
+
// are going to use this only here, i prefer to scope it here.
|
|
204
|
+
function handleOnChange(componentId, resultComponent) {
|
|
205
|
+
for (const [entity, Result] of engine.getEntitiesWith(resultComponent)) {
|
|
206
|
+
const entityState = changeEvents.get(entity)?.get(componentId);
|
|
207
|
+
if (entityState?.fn && Result.value !== entityState.value) {
|
|
208
|
+
// Call onChange callback and update internal timestamp
|
|
209
|
+
entityState.fn(Result.value);
|
|
210
|
+
updateOnChange(entity, componentId, {
|
|
211
|
+
fn: entityState.fn,
|
|
212
|
+
value: Result.value
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
189
217
|
return {
|
|
190
218
|
update: function (component) {
|
|
219
|
+
if (changeEvents.size) {
|
|
220
|
+
handleOnChange(UiInput._id, UiInputResult);
|
|
221
|
+
handleOnChange(UiDropdown._id, UiDropdownResult);
|
|
222
|
+
}
|
|
191
223
|
return reconciler.updateContainer(component, root, null);
|
|
192
224
|
},
|
|
193
225
|
getEntities: () => Array.from(entities)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EntityComponents } from '../react-ecs';
|
|
2
|
-
import { Container, HostContext, Instance, OpaqueHandle, Props, PublicInstance, SuspenseInstance, TextInstance, TimeoutHandle, Type } from './types';
|
|
2
|
+
import { Changes, Container, HostContext, Instance, OpaqueHandle, Props, PublicInstance, SuspenseInstance, TextInstance, TimeoutHandle, Type } from './types';
|
|
3
|
+
export declare function propsChanged<K extends keyof EntityComponents>(component: K, prevProps: Partial<EntityComponents[K]>, nextProps: Partial<EntityComponents[K]>): Changes<K> | undefined;
|
|
3
4
|
export declare const componentKeys: (keyof EntityComponents)[];
|
|
4
5
|
export declare function isEqual<T = unknown>(val1: T, val2: T): boolean;
|
|
5
6
|
export declare const isNotUndefined: <T>(val: T | undefined) => val is T;
|
|
@@ -22,7 +23,6 @@ export declare const noopConfig: {
|
|
|
22
23
|
afterActiveInstanceBlur(): void;
|
|
23
24
|
prepareScopeUpdate(): void;
|
|
24
25
|
getInstanceFromScope(): null;
|
|
25
|
-
removeChildFromContainer(): void;
|
|
26
26
|
commitMount(_instance: Instance, _type: Type, _props: Props, _internalInstanceHandle: OpaqueHandle): void;
|
|
27
27
|
resetTextContent(_instance: Instance): void;
|
|
28
28
|
commitTextUpdate(_textInstance: TextInstance, _oldText: string, _newText: string): void;
|
package/dist/reconciler/utils.js
CHANGED
|
@@ -1,9 +1,40 @@
|
|
|
1
|
+
import { isListener } from '../components';
|
|
2
|
+
export function propsChanged(component, prevProps, nextProps) {
|
|
3
|
+
if (prevProps && !nextProps) {
|
|
4
|
+
return { type: 'delete', component };
|
|
5
|
+
}
|
|
6
|
+
if (!nextProps) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (!prevProps && nextProps) {
|
|
10
|
+
return { type: 'add', props: nextProps, component };
|
|
11
|
+
}
|
|
12
|
+
if (isListener(component)) {
|
|
13
|
+
if (!isEqual(prevProps, nextProps)) {
|
|
14
|
+
return { type: 'put', component, props: nextProps };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const changes = {};
|
|
18
|
+
for (const k in prevProps) {
|
|
19
|
+
const propKey = k;
|
|
20
|
+
if (!isEqual(prevProps[propKey], nextProps[propKey])) {
|
|
21
|
+
changes[propKey] = nextProps[propKey];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!Object.keys(changes).length) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
return { type: 'put', props: changes, component };
|
|
28
|
+
}
|
|
1
29
|
// as any HACK so every time we add a new component, we must add also the component here.
|
|
2
30
|
const entityComponent = {
|
|
3
31
|
uiText: undefined,
|
|
4
32
|
uiBackground: undefined,
|
|
5
33
|
uiTransform: undefined,
|
|
6
|
-
|
|
34
|
+
onMouseDown: undefined,
|
|
35
|
+
onMouseUp: undefined,
|
|
36
|
+
uiInput: undefined,
|
|
37
|
+
uiDropdown: undefined
|
|
7
38
|
};
|
|
8
39
|
export const componentKeys = Object.keys(entityComponent);
|
|
9
40
|
export function isEqual(val1, val2) {
|
|
@@ -85,8 +116,6 @@ export const noopConfig = {
|
|
|
85
116
|
return null;
|
|
86
117
|
},
|
|
87
118
|
/* istanbul ignore next */
|
|
88
|
-
removeChildFromContainer() { },
|
|
89
|
-
/* istanbul ignore next */
|
|
90
119
|
commitMount(_instance, _type, _props, _internalInstanceHandle) { },
|
|
91
120
|
/* istanbul ignore next */
|
|
92
121
|
resetTextContent(_instance) { },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcl/react-ecs",
|
|
3
|
-
"version": "7.0.6-
|
|
3
|
+
"version": "7.0.6-3808564125.commit-7a2650b",
|
|
4
4
|
"description": "Decentraland ECS",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
"dist",
|
|
37
37
|
"tsconfig.json"
|
|
38
38
|
],
|
|
39
|
-
"commit": "
|
|
39
|
+
"commit": "7a2650b741ac5f5a5d3f00ac1c955e5f773d679a"
|
|
40
40
|
}
|