Skip to content

Commit

Permalink
experimental ui scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
leanmendoza authored Jun 27, 2024
1 parent ae5e11c commit eae6125
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 35 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"bugs": "https://github.com/decentraland/js-sdk-toolchain/issues",
"dependencies": {
"@actions/core": "^1.10.0",
"@dcl/protocol": "1.0.0-9254639032.commit-05cd554",
"@dcl/protocol": "https://sdk-team-cdn.decentraland.org/@dcl/protocol/branch//dcl-protocol-1.0.0-9370950471.commit-b469ec0.tgz",
"@dcl/quickjs-emscripten": "^0.21.0-3680274614.commit-1808aa1",
"@dcl/ts-proto": "1.153.0",
"@types/fs-extra": "^9.0.12",
Expand Down
59 changes: 59 additions & 0 deletions packages/@dcl/playground-assets/etc/playground-assets.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ export const componentDefinitionByName: {
"core::UiDropdownResult": LwwComponentGetter<LastWriteWinElementSetComponentDefinition<PBUiDropdownResult>>;
"core::UiInput": LwwComponentGetter<LastWriteWinElementSetComponentDefinition<PBUiInput>>;
"core::UiInputResult": LwwComponentGetter<LastWriteWinElementSetComponentDefinition<PBUiInputResult>>;
"core::UiScrollResult": LwwComponentGetter<LastWriteWinElementSetComponentDefinition<PBUiScrollResult>>;
"core::UiText": LwwComponentGetter<LastWriteWinElementSetComponentDefinition<PBUiText>>;
"core::UiTransform": LwwComponentGetter<LastWriteWinElementSetComponentDefinition<PBUiTransform>>;
"core::VideoEvent": GSetComponentGetter<GrowOnlyValueSetComponentDefinition<PBVideoEvent>>;
Expand Down Expand Up @@ -2995,6 +2996,20 @@ export namespace PBUiInputResult {
export function encode(message: PBUiInputResult, writer?: _m0.Writer): _m0.Writer;
}

// @public (undocumented)
export interface PBUiScrollResult {
// (undocumented)
value: PBVector2 | undefined;
}

// @public (undocumented)
export namespace PBUiScrollResult {
// (undocumented)
export function decode(input: _m0.Reader | Uint8Array, length?: number): PBUiScrollResult;
// (undocumented)
export function encode(message: PBUiScrollResult, writer?: _m0.Writer): _m0.Writer;
}

// @public (undocumented)
export interface PBUiText {
color?: PBColor4 | undefined;
Expand All @@ -3021,6 +3036,7 @@ export interface PBUiTransform {
alignItems?: YGAlign | undefined;
alignSelf: YGAlign;
display: YGDisplay;
elementId?: string | undefined;
// (undocumented)
flexBasis: number;
flexBasisUnit: YGUnit;
Expand Down Expand Up @@ -3089,6 +3105,8 @@ export interface PBUiTransform {
positionType: YGPositionType;
// (undocumented)
rightOf: number;
scrollPosition?: ScrollPositionValue | undefined;
scrollVisible?: ShowScrollBar | undefined;
// (undocumented)
width: number;
widthUnit: YGUnit;
Expand Down Expand Up @@ -3741,6 +3759,41 @@ export namespace Schemas {
}) => void;
}

// @public (undocumented)
export interface ScrollPositionValue {
// (undocumented)
value?: {
$case: "position";
position: PBVector2;
} | {
$case: "reference";
reference: string;
} | undefined;
}

// @public (undocumented)
export namespace ScrollPositionValue {
// (undocumented)
export function decode(input: _m0.Reader | Uint8Array, length?: number): ScrollPositionValue;
// (undocumented)
export function encode(message: ScrollPositionValue, writer?: _m0.Writer): _m0.Writer;
}

// @public
export type ScrollVisibleType = 'horizontal' | 'vertical' | 'both' | 'hidden';

// @public (undocumented)
export const enum ShowScrollBar {
// (undocumented)
SSB_BOTH = 0,
// (undocumented)
SSB_HIDDEN = 3,
// (undocumented)
SSB_ONLY_HORIZONTAL = 2,
// (undocumented)
SSB_ONLY_VERTICAL = 1
}

// @public (undocumented)
export interface Spec {
// (undocumented)
Expand Down Expand Up @@ -4101,6 +4154,9 @@ export interface UiLabelProps {
// @public
export type uint32 = number;

// @public (undocumented)
export const UiScrollResult: LastWriteWinElementSetComponentDefinition<PBUiScrollResult>;

// @public (undocumented)
export const UiText: LastWriteWinElementSetComponentDefinition<PBUiText>;

Expand All @@ -4120,6 +4176,7 @@ export interface UiTransformProps {
alignItems?: AlignType;
alignSelf?: AlignType;
display?: DisplayType;
elementId?: string;
flex?: number;
flexBasis?: number;
flexDirection?: FlexDirectionType;
Expand All @@ -4139,6 +4196,8 @@ export interface UiTransformProps {
pointerFilter?: PointerFilterType;
position?: Partial<Position> | PositionShorthand;
positionType?: PositionType;
scrollPosition?: PBVector2 | string;
scrollVisible?: ScrollVisibleType;
width?: PositionUnit | 'auto';
}

Expand Down
47 changes: 32 additions & 15 deletions packages/@dcl/react-ecs/src/components/uiTransform/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
import {
PointerFilterMode,
YGAlign,
YGDisplay,
YGFlexDirection,
YGJustify,
YGOverflow,
YGPositionType,
YGUnit
} from '@dcl/ecs'
import { PBUiTransform } from '@dcl/ecs/dist/components'
import { UiTransformProps } from './types'
import {
getAlign,
getDisplay,
Expand All @@ -7,21 +19,11 @@ import {
getOverflow,
getPointerFilter,
getPositionType,
getScrollPosition,
getScrollVisible,
parsePosition,
parseSize
} from './utils'
import { UiTransformProps } from './types'
import {
PointerFilterMode,
YGAlign,
YGDisplay,
YGFlexDirection,
YGJustify,
YGOverflow,
YGPositionType,
YGUnit
} from '@dcl/ecs'
import { PBUiTransform } from '@dcl/ecs/dist/components'

/**
* @internal
Expand Down Expand Up @@ -85,8 +87,21 @@ const defaultUiTransform: PBUiTransform = {
*/
/* @__PURE__ */
export function parseUiTransform(props: UiTransformProps = {}): PBUiTransform {
const { height, minHeight, maxHeight, width, minWidth, maxWidth, alignItems, alignContent, flexWrap, ...otherProps } =
props
const {
scrollPosition,
scrollVisible,
height,
minHeight,
maxHeight,
width,
minWidth,
maxWidth,
alignItems,
alignContent,
flexWrap,
...otherProps
} = props

return {
...defaultUiTransform,
...otherProps,
Expand All @@ -109,6 +124,8 @@ export function parseUiTransform(props: UiTransformProps = {}): PBUiTransform {
// Optional values
...(alignContent && getAlign('alignContent', alignContent)),
...(alignItems && getAlign('alignItems', alignItems)),
...(flexWrap && getFlexWrap(flexWrap))
...(flexWrap && getFlexWrap(flexWrap)),
...(scrollPosition && getScrollPosition(scrollPosition)),
...(scrollVisible && getScrollVisible(scrollVisible))
}
}
13 changes: 13 additions & 0 deletions packages/@dcl/react-ecs/src/components/uiTransform/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Vector2 } from '@dcl/ecs/dist/components/generated/pb/decentraland/common/vectors.gen'
import { ScaleUnit } from '../types'

/**
Expand Down Expand Up @@ -83,6 +84,12 @@ export type PositionType = 'absolute' | 'relative'
*/
export type PointerFilterType = 'none' | 'block'

/**
* @public
* The scroll-visible determines if the scrollbars are shown when the scroll overflow is enabled
*/
export type ScrollVisibleType = 'horizontal' | 'vertical' | 'both' | 'hidden'

/**
* Layout props to position things in the canvas
* @public
Expand Down Expand Up @@ -136,4 +143,10 @@ export interface UiTransformProps {
pointerFilter?: PointerFilterType
/** The opacity property sets the opacity level for an element, it's accumulated across children @defaultValue 1 */
opacity?: number
/** A reference value to identify the element, default empty */
elementId?: string
/** default position=(0,0) if it aplies, a vector or a reference-id */
scrollPosition?: Vector2 | string
/** default ShowScrollBar.SSB_BOTH */
scrollVisible?: ScrollVisibleType
}
48 changes: 46 additions & 2 deletions packages/@dcl/react-ecs/src/components/uiTransform/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import {
YGPositionType,
YGUnit,
YGWrap,
PointerFilterMode
PointerFilterMode,
PBUiTransform,
ShowScrollBar
} from '@dcl/ecs'
import {
AlignType,
Expand All @@ -20,10 +22,12 @@ import {
PositionType,
PositionUnit,
PositionShorthand,
PointerFilterType
PointerFilterType,
ScrollVisibleType
} from './types'
import { calcOnViewport } from '../utils'
import { ScaleUnit } from '../types'
import { Vector2 } from '@dcl/ecs/dist/components/generated/pb/decentraland/common/vectors.gen'

function capitalize<T extends string>(value: T): Capitalize<T> {
return `${value[0].toUpperCase()}${value.slice(1, value.length)}` as Capitalize<T>
Expand Down Expand Up @@ -265,3 +269,43 @@ const parsePointerFilter: Readonly<Record<PointerFilterType, PointerFilterMode>>
none: PointerFilterMode.PFM_NONE,
block: PointerFilterMode.PFM_BLOCK
}

/**
* @internal
*/
export function getScrollPosition(scrollPosition: string | Vector2): Pick<PBUiTransform, 'scrollPosition'> {
if (typeof scrollPosition === 'string') {
return {
scrollPosition: {
value: {
$case: 'reference',
reference: scrollPosition
}
}
}
} else {
return {
scrollPosition: {
value: {
$case: 'position',
position: scrollPosition
}
}
}
}
}

const parseScrollVisible: Record<ScrollVisibleType, ShowScrollBar> = {
both: ShowScrollBar.SSB_BOTH,
hidden: ShowScrollBar.SSB_HIDDEN,
horizontal: ShowScrollBar.SSB_ONLY_HORIZONTAL,
vertical: ShowScrollBar.SSB_ONLY_VERTICAL
}

/**
* @internal
*/

export function getScrollVisible(scrollVisible: ScrollVisibleType): Pick<PBUiTransform, 'scrollVisible'> {
return { scrollVisible: parseScrollVisible[scrollVisible] }
}
11 changes: 9 additions & 2 deletions packages/@dcl/react-ecs/src/reconciler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
_ChildSet
} from './types'
import { componentKeys, isNotUndefined, noopConfig, propsChanged } from './utils'
import { Vector2 } from '@dcl/ecs/dist/components/generated/pb/decentraland/common/vectors.gen'

function getPointerEnum(pointerKey: keyof Listeners): PointerEventType {
const pointers: { [key in keyof Required<Listeners>]: PointerEventType } = {
Expand All @@ -32,7 +33,7 @@ function getPointerEnum(pointerKey: keyof Listeners): PointerEventType {
return pointers[pointerKey]
}

type OnChangeState<T = string | number> = {
type OnChangeState<T = string | number | Vector2> = {
onChangeCallback?: (val?: T) => void
onSubmitCallback?: (val?: T) => void
value?: T
Expand All @@ -58,6 +59,7 @@ export function createReconciler(
const UiInputResult = components.UiInputResult(engine)
const UiDropdown = components.UiDropdown(engine)
const UiDropdownResult = components.UiDropdownResult(engine)
const UiScrollResult = components.UiScrollResult(engine)

// Component ID Helper
const getComponentId: {
Expand Down Expand Up @@ -330,7 +332,10 @@ export function createReconciler(

// Maybe this could be something similar to Input system, but since we
// are going to use this only here, i prefer to scope it here.
function handleOnChange(componentId: number, resultComponent: typeof UiDropdownResult | typeof UiInputResult) {
function handleOnChange(
componentId: number,
resultComponent: typeof UiDropdownResult | typeof UiInputResult | typeof UiScrollResult
) {
for (const [entity, Result] of engine.getEntitiesWith(resultComponent)) {
const entityState = changeEvents.get(entity)?.get(componentId)
const isSubmit = !!(Result as any).isSubmit
Expand All @@ -355,6 +360,8 @@ export function createReconciler(
if (changeEvents.size) {
handleOnChange(UiInput.componentId, UiInputResult)
handleOnChange(UiDropdown.componentId, UiDropdownResult)
// TODO: maybe as componentId could be a virtual id since the scroll input doesn't exist
handleOnChange(UiTransform.componentId, UiScrollResult)
}
return reconciler.updateContainer(component as any, root, null)
},
Expand Down
Loading

0 comments on commit eae6125

Please sign in to comment.