UNPKG

@wonderlandengine/react-ui

Version:
84 lines (83 loc) 4.71 kB
import React, { createContext, forwardRef, useContext, useMemo, useState, } from 'react'; import { FlexDirection, Align, PositionType, } from './renderer.js'; import { parseColor } from './utils.js'; export const MaterialContext = createContext({}); export const ThemeContext = createContext({}); const tempColor = new Float32Array(4); export const Container = forwardRef((props, ref) => { return (React.createElement("container", { ...props, ref: ref }, props.children)); }); Container.displayName = 'Container'; export const Panel = forwardRef((props, ref) => { const context = useContext(MaterialContext); const mat = useMemo(() => context.panelMaterial?.clone(), []); mat && mat.setColor(parseColor(props.backgroundColor ?? 'fff', tempColor)); const bmat = useMemo(() => context.panelMaterial?.clone(), []); bmat && bmat.setColor(parseColor(props.borderColor ?? 'fff', tempColor)); return (React.createElement("roundedRectangle", { ...props, material: props.material ?? mat, borderMaterial: props.borderMaterial ?? bmat, ref: ref }, props.children)); }); Panel.displayName = 'Panel'; export const Panel9Slice = forwardRef((props, ref) => { const context = useContext(MaterialContext); const mat = useMemo(() => context.panelMaterialTextured?.clone(), []); if (mat && props.texture) mat.flatTexture = props.texture; return (React.createElement("nineSlice", { ...props, material: props.material ?? mat, ref: ref }, props.children)); }); Panel9Slice.displayName = 'Panel9Slice'; export const Image = forwardRef((props, ref) => { const context = useContext(MaterialContext); const mat = props.material ?? useMemo(() => context.panelMaterialTextured?.clone(), []); const texture = typeof props.src === 'string' ? useMemo(() => mat.engine.textures.load(props.src), [props.src]) : Promise.resolve(props.src); texture.then((t) => (mat.flatTexture = t)); return (React.createElement(Panel, { ...props, material: mat, ref: ref }, props.children)); }); Image.displayName = 'Image'; export const Plane = forwardRef((props, ref) => { return (React.createElement("mesh", { ...props, ref: ref }, props.children)); }); Plane.displayName = 'Plane'; export const Column = forwardRef((props, ref) => { return (React.createElement(Container, { flexDirection: FlexDirection.Column, ...props, ref: ref }, props.children)); }); Column.displayName = 'Column'; export const Row = forwardRef((props, ref) => { return (React.createElement(Container, { flexDirection: FlexDirection.Row, ...props, ref: ref }, props.children)); }); Row.displayName = 'Row'; export const Text = forwardRef((props, ref) => { const context = useContext(MaterialContext); const theme = useContext(ThemeContext); const mat = props.material ?? useMemo(() => context.textMaterial?.clone(), []); if (mat) { mat.setColor(parseColor(props.color ?? theme.colors?.text ?? (props.material ?? context.textMaterial) .color, tempColor)); } return (React.createElement("text3d", { ...props, text: props.children?.toString() ?? props.text, material: mat, ref: ref })); }); Text.displayName = 'Text'; export const Button = forwardRef((props, ref) => { const [hovered, setHovered] = useState(false); const [active, setActive] = useState(false); let propsMerged = { ...props, ...(hovered ? props.hovered : undefined), ...(active ? props.active : undefined), }; return (React.createElement(Panel, { ...propsMerged, onHover: () => setHovered(true), onUnhover: () => setHovered(false), onDown: () => setActive(true), onUp: () => setActive(false), ref: ref }, props.children)); }); Button.displayName = 'Button'; export const ProgressBar = forwardRef((props, ref) => { const rounding = props.rounding ?? 30; const value = Math.max(Math.min(1, props.value), 0); // clamp between 0 and 1 return (React.createElement(Panel, { material: props.bgMaterial, backgroundColor: props.bgColor, ...props, flexDirection: FlexDirection.Row, padding: props.padding ?? 6, paddingLeft: props.paddingLeft ?? 8, paddingRight: props.paddingRight ?? 8, resolution: 6, rounding: rounding * 1.5, ref: ref }, React.createElement(Container, { alignItems: Align.FlexStart, position: PositionType.Absolute, width: "100%", height: "100%", left: props.barLeftMargin ?? 12 }, props.children), React.createElement(Panel, { width: `${100 * value}%`, minWidth: rounding * 2, height: "100%", material: props.fgMaterial, backgroundColor: props.fgColor, alignItems: Align.Center, rounding: rounding }))); }); ProgressBar.displayName = 'ProgressBar';