@dcl/react-ecs 7.7.10-13859848918.commit-407cb6b → 7.7.10-13934567813.commit-fb33ab1
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/README.md +1 -131
- package/dist/components/Button/index.js +2 -2
- package/dist/components/Dropdown/index.js +2 -5
- package/dist/components/Input/index.js +2 -5
- package/dist/components/Label/index.js +3 -8
- package/dist/components/Label/types.d.ts +0 -4
- package/dist/components/listeners/types.d.ts +0 -6
- package/dist/components/listeners/types.js +1 -4
- package/dist/components/uiBackground/types.d.ts +1 -12
- package/dist/components/uiBackground/utils.js +0 -8
- package/dist/components/uiTransform/index.d.ts +1 -1
- package/dist/components/uiTransform/index.js +4 -9
- package/dist/components/uiTransform/types.d.ts +0 -16
- package/dist/components/uiTransform/utils.js +0 -37
- package/dist/react-ecs.d.ts +0 -3
- package/dist/reconciler/index.d.ts +3 -4
- package/dist/reconciler/index.js +7 -44
- package/dist/reconciler/utils.js +0 -3
- package/dist/system.d.ts +0 -6
- package/dist/system.js +2 -17
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,131 +1 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
React bindings for Decentraland's Entity Component System (ECS), providing a declarative way to build UIs in Decentraland scenes using React's component model and JSX syntax.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Flexbox-based Layout**: Implements a subset of CSS Flexbox for powerful and intuitive UI layouts
|
|
8
|
-
- **React Components**: Familiar React-like component API for building UIs
|
|
9
|
-
- **Type Safety**: Full TypeScript support with proper type definitions
|
|
10
|
-
- **Event Handling**: Support for mouse events and user interactions
|
|
11
|
-
- **Performance**: Optimized reconciliation for minimal runtime overhead
|
|
12
|
-
- **Theme Support**: Built-in light and dark theme system with context-based switching
|
|
13
|
-
|
|
14
|
-
## Component Guidelines
|
|
15
|
-
|
|
16
|
-
All components in @dcl/react-ecs must:
|
|
17
|
-
|
|
18
|
-
- Return JSX.Elements for consistency and composability
|
|
19
|
-
- Support theme integration through context
|
|
20
|
-
- Be reusable and composable with other components
|
|
21
|
-
|
|
22
|
-
## Installation
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
npm install @dcl/react-ecs
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Basic Usage
|
|
29
|
-
|
|
30
|
-
```tsx
|
|
31
|
-
import { ReactEcs, UiEntity, Label, Button } from '@dcl/react-ecs'
|
|
32
|
-
|
|
33
|
-
export function MyUI() {
|
|
34
|
-
return (
|
|
35
|
-
<UiEntity
|
|
36
|
-
uiTransform={{
|
|
37
|
-
width: 300,
|
|
38
|
-
height: 100,
|
|
39
|
-
display: 'flex',
|
|
40
|
-
justifyContent: 'center',
|
|
41
|
-
alignItems: 'center'
|
|
42
|
-
}}
|
|
43
|
-
>
|
|
44
|
-
<Label value="Hello Decentraland!" />
|
|
45
|
-
<Button value="Click Me!" onMouseDown={() => console.log('clicked!')} />
|
|
46
|
-
</UiEntity>
|
|
47
|
-
)
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Theme System
|
|
52
|
-
|
|
53
|
-
The package includes a theme system for consistent UI styling:
|
|
54
|
-
|
|
55
|
-
```tsx
|
|
56
|
-
import { ReactEcs, ThemeProvider, Button } from '@dcl/react-ecs'
|
|
57
|
-
|
|
58
|
-
// Wrap your UI with ThemeProvider
|
|
59
|
-
export function MyUI() {
|
|
60
|
-
return (
|
|
61
|
-
<ThemeProvider>
|
|
62
|
-
<Button value="Theme-Aware Button" />
|
|
63
|
-
</ThemeProvider>
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Use themes in custom components
|
|
68
|
-
function CustomComponent() {
|
|
69
|
-
const { theme, toggleTheme } = React.useContext(ThemeContext)
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<UiEntity
|
|
73
|
-
uiBackground={{
|
|
74
|
-
color: theme === 'light' ? '#FFFFFF' : '#000000'
|
|
75
|
-
}}
|
|
76
|
-
onMouseDown={toggleTheme}
|
|
77
|
-
/>
|
|
78
|
-
)
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Components
|
|
83
|
-
|
|
84
|
-
### Core Components
|
|
85
|
-
|
|
86
|
-
- **UiEntity**: Base component for UI elements
|
|
87
|
-
- **Label**: Text display component
|
|
88
|
-
- **Button**: Interactive button component
|
|
89
|
-
- **Input**: Text input field
|
|
90
|
-
- **Dropdown**: Selection dropdown menu
|
|
91
|
-
|
|
92
|
-
### Layout System
|
|
93
|
-
|
|
94
|
-
The layout system is based on Flexbox and supports the following properties:
|
|
95
|
-
|
|
96
|
-
- `display: 'flex'`
|
|
97
|
-
- `flexDirection: 'row' | 'column'`
|
|
98
|
-
- `justifyContent: 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around'`
|
|
99
|
-
- `alignItems: 'flex-start' | 'center' | 'flex-end' | 'stretch'`
|
|
100
|
-
- `width`, `height`
|
|
101
|
-
- `margin`, `padding`
|
|
102
|
-
- `positionType: 'absolute' | 'relative'`
|
|
103
|
-
|
|
104
|
-
## Event Handling
|
|
105
|
-
|
|
106
|
-
Components support the following mouse events:
|
|
107
|
-
|
|
108
|
-
```tsx
|
|
109
|
-
<Button onMouseDown={() => {}} onMouseUp={() => {}} onMouseEnter={() => {}} onMouseLeave={() => {}} />
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Technical Details
|
|
113
|
-
|
|
114
|
-
The package implements a custom React reconciler that bridges React's component model with Decentraland's ECS. It:
|
|
115
|
-
|
|
116
|
-
1. Translates JSX into ECS entities and components
|
|
117
|
-
2. Manages component lifecycle and updates
|
|
118
|
-
3. Handles event delegation and bubbling
|
|
119
|
-
4. Provides a performant update mechanism
|
|
120
|
-
|
|
121
|
-
## Related Documentation
|
|
122
|
-
|
|
123
|
-
For more details about the UI system architecture and design decisions:
|
|
124
|
-
|
|
125
|
-
- [ADR-124: Implementing Flexbox-based UI](https://adr.decentraland.org/adr/ADR-124)
|
|
126
|
-
- [ADR-125: User Interface Components](https://adr.decentraland.org/adr/ADR-125)
|
|
127
|
-
- [ADR-237: SDK 7 Custom UI Components](https://adr.decentraland.org/adr/ADR-237)
|
|
128
|
-
|
|
129
|
-
## License
|
|
130
|
-
|
|
131
|
-
Apache 2.0
|
|
1
|
+
# React ECS
|
|
@@ -29,7 +29,7 @@ function getButtonProps(props) {
|
|
|
29
29
|
*/
|
|
30
30
|
/* @__PURE__ */
|
|
31
31
|
export function Button(props) {
|
|
32
|
-
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave,
|
|
32
|
+
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave, ...otherProps } = props;
|
|
33
33
|
const buttonProps = getButtonProps(props);
|
|
34
34
|
const uiBackgroundProps = parseUiBackground({
|
|
35
35
|
...buttonProps.uiBackground,
|
|
@@ -54,5 +54,5 @@ export function Button(props) {
|
|
|
54
54
|
if (uiBackgroundProps && uiBackgroundProps.color)
|
|
55
55
|
uiBackgroundProps.color.a /= 2;
|
|
56
56
|
}
|
|
57
|
-
return (ReactEcs.createElement("entity", { onMouseDown: !!props.disabled ? undefined : onMouseDown, onMouseUp: !!props.disabled ? undefined : onMouseUp, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave,
|
|
57
|
+
return (ReactEcs.createElement("entity", { onMouseDown: !!props.disabled ? undefined : onMouseDown, onMouseUp: !!props.disabled ? undefined : onMouseUp, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, uiTransform: uiTransformProps, uiText: textProps, uiBackground: uiBackgroundProps }));
|
|
58
58
|
}
|
|
@@ -34,7 +34,7 @@ function parseUiDropdown(props) {
|
|
|
34
34
|
*/
|
|
35
35
|
/* @__PURE__ */
|
|
36
36
|
export function Dropdown(props) {
|
|
37
|
-
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave,
|
|
37
|
+
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave, ...otherProps } = props;
|
|
38
38
|
const dropdownProps = parseUiDropdown(otherProps);
|
|
39
39
|
const commonProps = parseProps({
|
|
40
40
|
uiTransform,
|
|
@@ -42,10 +42,7 @@ export function Dropdown(props) {
|
|
|
42
42
|
onMouseDown,
|
|
43
43
|
onMouseUp,
|
|
44
44
|
onMouseEnter,
|
|
45
|
-
onMouseLeave
|
|
46
|
-
onMouseDrag,
|
|
47
|
-
onMouseDragLocked,
|
|
48
|
-
onMouseDragEnd
|
|
45
|
+
onMouseLeave
|
|
49
46
|
});
|
|
50
47
|
return ReactEcs.createElement("entity", { ...commonProps, uiDropdown: dropdownProps });
|
|
51
48
|
}
|
|
@@ -35,7 +35,7 @@ function parseUiInput(props) {
|
|
|
35
35
|
* @category Component
|
|
36
36
|
*/ /* @__PURE__ */
|
|
37
37
|
export function Input(props) {
|
|
38
|
-
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave,
|
|
38
|
+
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave, ...otherProps } = props;
|
|
39
39
|
const inputProps = parseUiInput(otherProps);
|
|
40
40
|
const commonProps = parseProps({
|
|
41
41
|
uiTransform,
|
|
@@ -43,10 +43,7 @@ export function Input(props) {
|
|
|
43
43
|
onMouseDown,
|
|
44
44
|
onMouseUp,
|
|
45
45
|
onMouseEnter,
|
|
46
|
-
onMouseLeave
|
|
47
|
-
onMouseDrag,
|
|
48
|
-
onMouseDragLocked,
|
|
49
|
-
onMouseDragEnd
|
|
46
|
+
onMouseLeave
|
|
50
47
|
});
|
|
51
48
|
return ReactEcs.createElement("entity", { ...commonProps, uiInput: inputProps });
|
|
52
49
|
}
|
|
@@ -16,17 +16,14 @@ export { scaleFontSize } from './utils';
|
|
|
16
16
|
*/
|
|
17
17
|
/* @__PURE__ */
|
|
18
18
|
export function Label(props) {
|
|
19
|
-
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave,
|
|
19
|
+
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave, ...uiTextProps } = props;
|
|
20
20
|
const commonProps = parseProps({
|
|
21
21
|
uiTransform,
|
|
22
22
|
uiBackground,
|
|
23
23
|
onMouseDown,
|
|
24
24
|
onMouseUp,
|
|
25
25
|
onMouseEnter,
|
|
26
|
-
onMouseLeave
|
|
27
|
-
onMouseDrag,
|
|
28
|
-
onMouseDragLocked,
|
|
29
|
-
onMouseDragEnd
|
|
26
|
+
onMouseLeave
|
|
30
27
|
});
|
|
31
28
|
const { font, textAlign, fontSize, textWrap, ...textProps } = uiTextProps;
|
|
32
29
|
const uiText = {
|
|
@@ -34,9 +31,7 @@ export function Label(props) {
|
|
|
34
31
|
...getFont(font),
|
|
35
32
|
...getTextAlign(textAlign),
|
|
36
33
|
...getFontSize(fontSize),
|
|
37
|
-
...getTextWrap(textWrap)
|
|
38
|
-
outlineWidth: props.outlineWidth,
|
|
39
|
-
outlineColor: props.outlineColor
|
|
34
|
+
...getTextWrap(textWrap)
|
|
40
35
|
};
|
|
41
36
|
return ReactEcs.createElement("entity", { ...commonProps, uiText: uiText });
|
|
42
37
|
}
|
|
@@ -15,10 +15,6 @@ export interface UiLabelProps {
|
|
|
15
15
|
textAlign?: TextAlignType | undefined;
|
|
16
16
|
/** Label font type. @defaultValue 'sans-serif' */
|
|
17
17
|
font?: UiFontType | undefined;
|
|
18
|
-
/** Outline width of the text. @defaultValue 0 */
|
|
19
|
-
outlineWidth?: number | undefined;
|
|
20
|
-
/** Outline color of the text. @defaultValue `{ r: 0, g: 0, b: 0, a: 1 }` */
|
|
21
|
-
outlineColor?: Color4 | undefined;
|
|
22
18
|
/** Behaviour when text reached. @defaultValue 'wrap' */
|
|
23
19
|
textWrap?: UiTextWrapType | undefined;
|
|
24
20
|
}
|
|
@@ -16,10 +16,4 @@ export type Listeners = {
|
|
|
16
16
|
onMouseEnter?: Callback;
|
|
17
17
|
/** triggered on mouse leave event */
|
|
18
18
|
onMouseLeave?: Callback;
|
|
19
|
-
/** triggered on mouse drag event */
|
|
20
|
-
onMouseDrag?: Callback;
|
|
21
|
-
/** triggered on mouse drag event */
|
|
22
|
-
onMouseDragLocked?: Callback;
|
|
23
|
-
/** triggered on mouse drag event */
|
|
24
|
-
onMouseDragEnd?: Callback;
|
|
25
19
|
};
|
|
@@ -2,10 +2,7 @@ const listeners = {
|
|
|
2
2
|
onMouseDown: undefined,
|
|
3
3
|
onMouseUp: undefined,
|
|
4
4
|
onMouseEnter: undefined,
|
|
5
|
-
onMouseLeave: undefined
|
|
6
|
-
onMouseDrag: undefined,
|
|
7
|
-
onMouseDragLocked: undefined,
|
|
8
|
-
onMouseDragEnd: undefined
|
|
5
|
+
onMouseLeave: undefined
|
|
9
6
|
};
|
|
10
7
|
const listenersKey = Object.keys(listeners);
|
|
11
8
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BorderRect
|
|
1
|
+
import { BorderRect } from '@dcl/ecs';
|
|
2
2
|
import { Color4 } from '@dcl/ecs/dist/components/generated/pb/decentraland/common/colors.gen';
|
|
3
3
|
/**
|
|
4
4
|
* @public
|
|
@@ -15,8 +15,6 @@ export interface UiBackgroundProps {
|
|
|
15
15
|
uvs?: number[];
|
|
16
16
|
/** AvatarTexture for the background */
|
|
17
17
|
avatarTexture?: UiAvatarTexture;
|
|
18
|
-
/** VideoTexture for the background */
|
|
19
|
-
videoTexture?: UiVideoTexture;
|
|
20
18
|
/** Texture for the background */
|
|
21
19
|
texture?: UiTexture;
|
|
22
20
|
}
|
|
@@ -29,15 +27,6 @@ export interface UiAvatarTexture {
|
|
|
29
27
|
wrapMode?: TextureWrapType;
|
|
30
28
|
filterMode?: TextureFilterType;
|
|
31
29
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Texture
|
|
34
|
-
* @public
|
|
35
|
-
*/
|
|
36
|
-
export interface UiVideoTexture {
|
|
37
|
-
videoPlayerEntity: Entity;
|
|
38
|
-
wrapMode?: TextureWrapType;
|
|
39
|
-
filterMode?: TextureFilterType;
|
|
40
|
-
}
|
|
41
30
|
/**
|
|
42
31
|
* Texture
|
|
43
32
|
* @public
|
|
@@ -30,14 +30,6 @@ export function getTexture(props) {
|
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
-
if (props.videoTexture) {
|
|
34
|
-
return {
|
|
35
|
-
tex: {
|
|
36
|
-
$case: 'videoTexture',
|
|
37
|
-
videoTexture: parseTexture(props.videoTexture)
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
33
|
return undefined;
|
|
42
34
|
}
|
|
43
35
|
function parseTexture(texture) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getAlign, getDisplay, getFlexDirection, getFlexWrap, getJustify, getOverflow, getPointerFilter, getPositionType,
|
|
1
|
+
import { getAlign, getDisplay, getFlexDirection, getFlexWrap, getJustify, getOverflow, getPointerFilter, getPositionType, parsePosition, parseSize } from './utils';
|
|
2
2
|
/**
|
|
3
3
|
* @internal
|
|
4
4
|
*/
|
|
@@ -51,16 +51,14 @@ const defaultUiTransform = {
|
|
|
51
51
|
flexBasisUnit: 0 /* YGUnit.YGU_UNDEFINED */,
|
|
52
52
|
widthUnit: 3 /* YGUnit.YGU_AUTO */,
|
|
53
53
|
heightUnit: 0 /* YGUnit.YGU_UNDEFINED */,
|
|
54
|
-
pointerFilter: 0 /* PointerFilterMode.PFM_NONE
|
|
55
|
-
opacity: 1,
|
|
56
|
-
zIndex: 0
|
|
54
|
+
pointerFilter: 0 /* PointerFilterMode.PFM_NONE */
|
|
57
55
|
};
|
|
58
56
|
/**
|
|
59
57
|
* @public
|
|
60
58
|
*/
|
|
61
59
|
/* @__PURE__ */
|
|
62
60
|
export function parseUiTransform(props = {}) {
|
|
63
|
-
const {
|
|
61
|
+
const { height, minHeight, maxHeight, width, minWidth, maxWidth, alignItems, alignContent, flexWrap, ...otherProps } = props;
|
|
64
62
|
return {
|
|
65
63
|
...defaultUiTransform,
|
|
66
64
|
...otherProps,
|
|
@@ -83,9 +81,6 @@ export function parseUiTransform(props = {}) {
|
|
|
83
81
|
// Optional values
|
|
84
82
|
...(alignContent && getAlign('alignContent', alignContent)),
|
|
85
83
|
...(alignItems && getAlign('alignItems', alignItems)),
|
|
86
|
-
...(flexWrap && getFlexWrap(flexWrap))
|
|
87
|
-
...(scrollPosition && getScrollPosition(scrollPosition)),
|
|
88
|
-
...(scrollVisible && getScrollVisible(scrollVisible)),
|
|
89
|
-
...(zIndex && { zIndex })
|
|
84
|
+
...(flexWrap && getFlexWrap(flexWrap))
|
|
90
85
|
};
|
|
91
86
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Vector2 } from '@dcl/ecs/dist/components/generated/pb/decentraland/common/vectors.gen';
|
|
2
1
|
import { ScaleUnit } from '../types';
|
|
3
2
|
/**
|
|
4
3
|
* unit value specified. i.e. 1 || '100%' || '1px' || '10vw'
|
|
@@ -63,11 +62,6 @@ export type PositionType = 'absolute' | 'relative';
|
|
|
63
62
|
* The pointer filter property determines if the ui element blocks the pointer or not (elements with pointer events always block the pointer regardless of this property)
|
|
64
63
|
*/
|
|
65
64
|
export type PointerFilterType = 'none' | 'block';
|
|
66
|
-
/**
|
|
67
|
-
* @public
|
|
68
|
-
* The scroll-visible determines if the scrollbars are shown when the scroll overflow is enabled
|
|
69
|
-
*/
|
|
70
|
-
export type ScrollVisibleType = 'horizontal' | 'vertical' | 'both' | 'hidden';
|
|
71
65
|
/**
|
|
72
66
|
* Layout props to position things in the canvas
|
|
73
67
|
* @public
|
|
@@ -119,14 +113,4 @@ export interface UiTransformProps {
|
|
|
119
113
|
overflow?: OverflowType;
|
|
120
114
|
/** The pointer filter property determines if the ui element blocks the pointer or not (elements with pointer events always block the pointer regardless of this property) **/
|
|
121
115
|
pointerFilter?: PointerFilterType;
|
|
122
|
-
/** The opacity property sets the opacity level for an element, it's accumulated across children @defaultValue 1 */
|
|
123
|
-
opacity?: number;
|
|
124
|
-
/** A reference value to identify the element, default empty */
|
|
125
|
-
elementId?: string;
|
|
126
|
-
/** default position=(0,0) if it aplies, a vector or a reference-id */
|
|
127
|
-
scrollPosition?: Vector2 | string;
|
|
128
|
-
/** default ShowScrollBar.SSB_BOTH */
|
|
129
|
-
scrollVisible?: ScrollVisibleType;
|
|
130
|
-
/** default 0 */
|
|
131
|
-
zIndex?: number;
|
|
132
116
|
}
|
|
@@ -184,40 +184,3 @@ const parsePointerFilter = {
|
|
|
184
184
|
none: 0 /* PointerFilterMode.PFM_NONE */,
|
|
185
185
|
block: 1 /* PointerFilterMode.PFM_BLOCK */
|
|
186
186
|
};
|
|
187
|
-
/**
|
|
188
|
-
* @internal
|
|
189
|
-
*/
|
|
190
|
-
export function getScrollPosition(scrollPosition) {
|
|
191
|
-
if (typeof scrollPosition === 'string') {
|
|
192
|
-
return {
|
|
193
|
-
scrollPosition: {
|
|
194
|
-
value: {
|
|
195
|
-
$case: 'reference',
|
|
196
|
-
reference: scrollPosition
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
return {
|
|
203
|
-
scrollPosition: {
|
|
204
|
-
value: {
|
|
205
|
-
$case: 'position',
|
|
206
|
-
position: scrollPosition
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
const parseScrollVisible = {
|
|
213
|
-
both: 0 /* ShowScrollBar.SSB_BOTH */,
|
|
214
|
-
hidden: 3 /* ShowScrollBar.SSB_HIDDEN */,
|
|
215
|
-
horizontal: 2 /* ShowScrollBar.SSB_ONLY_HORIZONTAL */,
|
|
216
|
-
vertical: 1 /* ShowScrollBar.SSB_ONLY_VERTICAL */
|
|
217
|
-
};
|
|
218
|
-
/**
|
|
219
|
-
* @internal
|
|
220
|
-
*/
|
|
221
|
-
export function getScrollVisible(scrollVisible) {
|
|
222
|
-
return { scrollVisible: parseScrollVisible[scrollVisible] };
|
|
223
|
-
}
|
package/dist/react-ecs.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Entity, IEngine, PointerEventsSystem } from '@dcl/ecs';
|
|
2
2
|
import { ReactEcs } from '../react-ecs';
|
|
3
|
-
export
|
|
4
|
-
update: (component: ReactEcs.JSX.ReactNode) =>
|
|
3
|
+
export declare function createReconciler(engine: Pick<IEngine, 'getComponent' | 'addEntity' | 'removeEntity' | 'defineComponentFromSchema' | 'getEntitiesWith'>, pointerEvents: PointerEventsSystem): {
|
|
4
|
+
update: (component: ReactEcs.JSX.ReactNode) => number;
|
|
5
5
|
getEntities: () => Entity[];
|
|
6
|
-
}
|
|
7
|
-
export declare function createReconciler(engine: Pick<IEngine, 'getComponent' | 'addEntity' | 'removeEntity' | 'defineComponentFromSchema' | 'getEntitiesWith'>, pointerEvents: PointerEventsSystem, rootEntity: Entity | undefined): DclReconciler;
|
|
6
|
+
};
|
package/dist/reconciler/index.js
CHANGED
|
@@ -8,14 +8,11 @@ function getPointerEnum(pointerKey) {
|
|
|
8
8
|
onMouseDown: 1 /* PointerEventType.PET_DOWN */,
|
|
9
9
|
onMouseUp: 0 /* PointerEventType.PET_UP */,
|
|
10
10
|
onMouseEnter: 2 /* PointerEventType.PET_HOVER_ENTER */,
|
|
11
|
-
onMouseLeave: 3 /* PointerEventType.PET_HOVER_LEAVE
|
|
12
|
-
onMouseDrag: 5 /* PointerEventType.PET_DRAG */,
|
|
13
|
-
onMouseDragLocked: 4 /* PointerEventType.PET_DRAG_LOCKED */,
|
|
14
|
-
onMouseDragEnd: 6 /* PointerEventType.PET_DRAG_END */
|
|
11
|
+
onMouseLeave: 3 /* PointerEventType.PET_HOVER_LEAVE */
|
|
15
12
|
};
|
|
16
13
|
return pointers[pointerKey];
|
|
17
14
|
}
|
|
18
|
-
export function createReconciler(engine, pointerEvents
|
|
15
|
+
export function createReconciler(engine, pointerEvents) {
|
|
19
16
|
// Store all the entities so when we destroy the UI we can also destroy them
|
|
20
17
|
const entities = new Set();
|
|
21
18
|
// Store the onChange callbacks to be runned every time a Result has changed
|
|
@@ -29,8 +26,6 @@ export function createReconciler(engine, pointerEvents, rootEntity) {
|
|
|
29
26
|
const UiInputResult = components.UiInputResult(engine);
|
|
30
27
|
const UiDropdown = components.UiDropdown(engine);
|
|
31
28
|
const UiDropdownResult = components.UiDropdownResult(engine);
|
|
32
|
-
const UiScrollResult = components.UiScrollResult(engine);
|
|
33
|
-
const Transform = components.Transform(engine);
|
|
34
29
|
// Component ID Helper
|
|
35
30
|
const getComponentId = {
|
|
36
31
|
uiTransform: UiTransform.componentId,
|
|
@@ -63,15 +58,6 @@ export function createReconciler(engine, pointerEvents, rootEntity) {
|
|
|
63
58
|
else if (update.component === 'onMouseLeave') {
|
|
64
59
|
pointerEvents.removeOnPointerHoverLeave(instance.entity);
|
|
65
60
|
}
|
|
66
|
-
else if (update.component === 'onMouseDrag') {
|
|
67
|
-
pointerEvents.removeOnPointerDrag(instance.entity);
|
|
68
|
-
}
|
|
69
|
-
else if (update.component === 'onMouseDragLocked') {
|
|
70
|
-
pointerEvents.removeOnPointerDragLocked(instance.entity);
|
|
71
|
-
}
|
|
72
|
-
else if (update.component === 'onMouseDragEnd') {
|
|
73
|
-
pointerEvents.removeOnPointerDragEnd(instance.entity);
|
|
74
|
-
}
|
|
75
61
|
return;
|
|
76
62
|
}
|
|
77
63
|
if (update.props) {
|
|
@@ -87,13 +73,7 @@ export function createReconciler(engine, pointerEvents, rootEntity) {
|
|
|
87
73
|
? pointerEvents.onPointerUp
|
|
88
74
|
: update.component === 'onMouseEnter'
|
|
89
75
|
? pointerEvents.onPointerHoverEnter
|
|
90
|
-
: update.component === 'onMouseLeave'
|
|
91
|
-
? pointerEvents.onPointerHoverLeave
|
|
92
|
-
: update.component === 'onMouseDrag'
|
|
93
|
-
? pointerEvents.onPointerDrag
|
|
94
|
-
: update.component === 'onMouseDragLocked'
|
|
95
|
-
? pointerEvents.onPointerDragLocked
|
|
96
|
-
: update.component === 'onMouseDragEnd' && pointerEvents.onPointerDragEnd;
|
|
76
|
+
: update.component === 'onMouseLeave' && pointerEvents.onPointerHoverLeave;
|
|
97
77
|
if (pointerEventSystem) {
|
|
98
78
|
pointerEventSystem({
|
|
99
79
|
entity: instance.entity,
|
|
@@ -144,7 +124,6 @@ export function createReconciler(engine, pointerEvents, rootEntity) {
|
|
|
144
124
|
}
|
|
145
125
|
function removeChildEntity(instance) {
|
|
146
126
|
changeEvents.delete(instance.entity);
|
|
147
|
-
clickEvents.delete(instance.entity);
|
|
148
127
|
engine.removeEntity(instance.entity);
|
|
149
128
|
for (const child of instance._child) {
|
|
150
129
|
removeChildEntity(child);
|
|
@@ -191,32 +170,18 @@ export function createReconciler(engine, pointerEvents, rootEntity) {
|
|
|
191
170
|
removeChildEntity(child);
|
|
192
171
|
}
|
|
193
172
|
function updateOnChange(entity, componentId, state) {
|
|
194
|
-
const hasEvent = changeEvents.has(entity);
|
|
195
173
|
const event = changeEvents.get(entity) || changeEvents.set(entity, new Map()).get(entity);
|
|
174
|
+
const oldState = event.get(componentId);
|
|
196
175
|
const onChangeCallback = state?.onChangeCallback;
|
|
197
176
|
const onSubmitCallback = state?.onSubmitCallback;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const resultComponentId = componentId === UiDropdown.componentId ? UiDropdownResult.componentId : UiInputResult.componentId;
|
|
202
|
-
engine.getComponent(resultComponentId).onChange(entity, (value) => {
|
|
203
|
-
if (value?.isSubmit) {
|
|
204
|
-
const onSubmit = changeEvents.get(entity)?.get(componentId)?.onSubmitCallback;
|
|
205
|
-
onSubmit && onSubmit(value?.value);
|
|
206
|
-
}
|
|
207
|
-
const onChange = changeEvents.get(entity)?.get(componentId)?.onChangeCallback;
|
|
208
|
-
onChange && onChange(value?.value);
|
|
209
|
-
});
|
|
210
|
-
}
|
|
177
|
+
const value = state?.value ?? oldState?.value;
|
|
178
|
+
const isSubmit = state?.isSubmit ?? oldState?.isSubmit;
|
|
179
|
+
event.set(componentId, { onChangeCallback, onSubmitCallback, value, isSubmit });
|
|
211
180
|
}
|
|
212
181
|
const hostConfig = {
|
|
213
182
|
...noopConfig,
|
|
214
183
|
createInstance(type, props) {
|
|
215
184
|
const entity = engine.addEntity();
|
|
216
|
-
// set root
|
|
217
|
-
if (rootEntity !== undefined) {
|
|
218
|
-
Transform.createOrReplace(entity, { parent: rootEntity });
|
|
219
|
-
}
|
|
220
185
|
entities.add(entity);
|
|
221
186
|
const instance = {
|
|
222
187
|
entity,
|
|
@@ -311,8 +276,6 @@ export function createReconciler(engine, pointerEvents, rootEntity) {
|
|
|
311
276
|
if (changeEvents.size) {
|
|
312
277
|
handleOnChange(UiInput.componentId, UiInputResult);
|
|
313
278
|
handleOnChange(UiDropdown.componentId, UiDropdownResult);
|
|
314
|
-
// TODO: maybe as componentId could be a virtual id since the scroll input doesn't exist
|
|
315
|
-
handleOnChange(UiTransform.componentId, UiScrollResult);
|
|
316
279
|
}
|
|
317
280
|
return reconciler.updateContainer(component, root, null);
|
|
318
281
|
},
|
package/dist/reconciler/utils.js
CHANGED
package/dist/system.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Entity, IEngine, PointerEventsSystem } from '@dcl/ecs';
|
|
2
1
|
import type { ReactEcs } from './react-ecs';
|
|
3
2
|
/**
|
|
4
3
|
* @public
|
|
@@ -10,9 +9,4 @@ export type UiComponent = () => ReactEcs.JSX.ReactNode;
|
|
|
10
9
|
export interface ReactBasedUiSystem {
|
|
11
10
|
destroy(): void;
|
|
12
11
|
setUiRenderer(ui: UiComponent): void;
|
|
13
|
-
setTextureRenderer(entity: Entity, ui: UiComponent): void;
|
|
14
12
|
}
|
|
15
|
-
/**
|
|
16
|
-
* @public
|
|
17
|
-
*/
|
|
18
|
-
export declare function createReactBasedUiSystem(engine: IEngine, pointerSystem: PointerEventsSystem): ReactBasedUiSystem;
|
package/dist/system.js
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { createReconciler } from './reconciler';
|
|
2
2
|
/**
|
|
3
|
-
* @
|
|
3
|
+
* @internal
|
|
4
4
|
*/
|
|
5
5
|
export function createReactBasedUiSystem(engine, pointerSystem) {
|
|
6
|
-
const renderer = createReconciler(engine, pointerSystem
|
|
6
|
+
const renderer = createReconciler(engine, pointerSystem);
|
|
7
7
|
let uiComponent = undefined;
|
|
8
|
-
const textureRenderersAndUis = [];
|
|
9
8
|
function ReactBasedUiSystem() {
|
|
10
9
|
if (uiComponent)
|
|
11
10
|
renderer.update(uiComponent());
|
|
12
|
-
for (const [textureRenderer, ui] of textureRenderersAndUis) {
|
|
13
|
-
textureRenderer.update(ui());
|
|
14
|
-
}
|
|
15
11
|
}
|
|
16
12
|
engine.addSystem(ReactBasedUiSystem, 100e3, '@dcl/react-ecs');
|
|
17
13
|
return {
|
|
@@ -20,20 +16,9 @@ export function createReactBasedUiSystem(engine, pointerSystem) {
|
|
|
20
16
|
for (const entity of renderer.getEntities()) {
|
|
21
17
|
engine.removeEntity(entity);
|
|
22
18
|
}
|
|
23
|
-
for (const [textureRenderer, _] of textureRenderersAndUis) {
|
|
24
|
-
for (const entity of textureRenderer.getEntities()) {
|
|
25
|
-
engine.removeEntity(entity);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
for (const entity of renderer.getEntities()) {
|
|
29
|
-
engine.removeEntity(entity);
|
|
30
|
-
}
|
|
31
19
|
},
|
|
32
20
|
setUiRenderer(ui) {
|
|
33
21
|
uiComponent = ui;
|
|
34
|
-
},
|
|
35
|
-
setTextureRenderer(entity, ui) {
|
|
36
|
-
textureRenderersAndUis.push([createReconciler(engine, pointerSystem, entity), ui]);
|
|
37
22
|
}
|
|
38
23
|
};
|
|
39
24
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcl/react-ecs",
|
|
3
3
|
"description": "Decentraland ECS",
|
|
4
|
-
"version": "7.7.10-
|
|
4
|
+
"version": "7.7.10-13934567813.commit-fb33ab1",
|
|
5
5
|
"author": "DCL",
|
|
6
6
|
"bugs": "https://github.com/decentraland/js-sdk-toolchain/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@dcl/ecs": "7.7.10-
|
|
8
|
+
"@dcl/ecs": "7.7.10-13934567813.commit-fb33ab1",
|
|
9
9
|
"react": "^18.2.0",
|
|
10
10
|
"react-reconciler": "^0.29.0"
|
|
11
11
|
},
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"tsconfig": "./tsconfig.json"
|
|
41
41
|
},
|
|
42
42
|
"types": "./dist/index.d.ts",
|
|
43
|
-
"commit": "
|
|
43
|
+
"commit": "fb33ab1d245c23eac7eb4244af9355e455da1af4"
|
|
44
44
|
}
|