/**
* MyBricks Opensource
* https://mybricks.world
* This source code is licensed under the MIT license.
*
* CheMingjun @2019
* mybricks@126.com
*/
import React, { memo, useEffect, useMemo, useState } from "react";
import { View } from '@tarojs/components';
import { isNumber, uuid } from "./utils";
// import css from "./RenderSlot.less";
import ErrorBoundary from "./ErrorBoundary";
import { observer } from './observable'
const css = {};
export default function RenderSlot({
scope,
slot,
params,
inputs,
outputs,
_inputs,
_outputs,
wrapper,
template,
env,
getComDef,
getContext,
__rxui_child__,
onError,
logger
}) {
const { style, comAry } = slot
const itemAry = []
comAry.forEach((com, index) => {//组件逐个渲染
const { id, def }: Com = com
const comDef = getComDef(def)
if (comDef) {
const props = getContext(id, scope, {
inputs, outputs, _inputs, _outputs
})
itemAry.push({
id,
jsx: ,
inputs: props.inputsCallable,
style: props.style
})
} else {
const jsx = (
组件 (namespace = {def.namespace})未找到.
)
itemAry.push({
id, jsx
})
}
})
if (typeof wrapper === 'function') {
return wrapper(itemAry)
} else {
const paramsStyle = params?.style;
const slotStyle = paramsStyle || style;
return (
{itemAry.map((item, index) => {
return item.jsx;
})}
)
}
}
const RenderCom = observer(function ({
com,
props,
scope,
template,
env,
getComDef,
getContext,
__rxui_child__,
onError,
logger
}) {
const { id, def, slots = {} }: Com = com
const {
data,
style,
inputs: myInputs,
outputs: myOutputs,
_inputs: _myInputs,
_outputs: _myOutputs
} = props
console.error(style, "renderslot style")
const comDef = getComDef(def)
const slotsProxy = new Proxy(slots, {
get(target, slotId: string) {
const props = getContext(id, slotId)
const errorStringPrefix = `组件(namespace=${def.namespace})的插槽(id=${slotId})`
if (!props) {
throw new Error(`${errorStringPrefix} 获取context失败.`)
}
return {
render(params: { key, inputValues, inputs, outputs, _inputs, _outputs, wrap, itemWrap, style }) {
const slot = slots[slotId]
if (slot) {
return
} else {
return (
{errorStringPrefix} 未找到.
)
}
},
_inputs: props._inputs,
inputs: props.inputs,
outputs: props.outputs
}
}
})
const parentSlot = useMemo(() => {
if (props.frameId && props.parentComId) {
const slotProps = getContext(props.parentComId, props.frameId, scope?.parent)
if (slotProps) {
return {
get _inputs() {
return new Proxy({}, {
get(target, name) {
const fn = slotProps._inputRegs[name]
return fn
}
})
}
}
}
}
}, [])
const classes = getClasses({ style })
const sizeStyle = getSizeStyle({ style })
const marginStyle = getMarginStyle({ style })
const otherStyle: any = {}
if (['fixed', 'absolute'].includes(style.position)) {
if (style.position === "fixed" && style.fixedY === "bottom") {
otherStyle.bottom = style.bottom;
} else if (style.top) {
otherStyle.top = style.top;
}
if (style.position === "fixed" && style.fixedX === "right") {
otherStyle.right = style.right;
} else if (style.left) {
otherStyle.left = style.left;
}
otherStyle.zIndex = 1000;
}
let jsx = (
{ }}
parentSlot={parentSlot}
__rxui_child__={__rxui_child__}
onError={onError}
logger={logger}
/>
)
if (typeof template === 'function') {
jsx = template({ id, jsx })
}
// console.error(rawToProxy, "==============rawToProxy==============");
// console.error(proxyToRaw, "==============proxyToRaw==============");
// console.error(rawToProxy.get(style));
// console.error(proxyToRaw.get(style));
// const [_r, _setR] = useState(style.display);
// console.warn(style, "style");
// console.warn(isProxy(style), "isProxy");
// setInterval(()=>{
// // console.warn(style.display);
// _setR(style.display);
// }, 500);
// setTimeout(() => {
// console.warn("setTimeout");
// _setR(Math.random());
// }, 2000);
jsx = (
{jsx}
)
return jsx
})
const SlotRender = memo(({
slotId,
props,
slot,
params,
scope,
env,
style,
getComDef,
getContext,
onError,
logger,
__rxui_child__
}) => {
console.log("执行 SlotRender")
let curScope
if (params) {
let nowScopeId = uuid()
curScope = {
id: nowScopeId,
frameId: slotId
}
if (scope) {
curScope.parent = scope
}
} else {
curScope = scope
}
props.run(curScope)//传递scope
let wrapFn
if (params) {
const ivs = params.inputValues
if (typeof ivs === 'object') {
//requestAnimationFrame(() => {
for (let pro in ivs) {
props.inputs[pro](ivs[pro], curScope)
}
//})
}
if (typeof params.wrap === 'function') {
wrapFn = params.wrap
}
//})
}
return (
//
//
)
}, (prevProps, nextProps) => {
if (prevProps.params?.key !== nextProps?.params?.key) {//key 不同才刷新
return false
}
return true
})
//-----------------------------------------------------------------------
function calSlotStyles(style, hasParamsStyle) {
// 兼容旧的style
const {
paddingLeft,
paddingTop,
paddingRight,
paddingBottom,
background,
...otherStyle
} = style;
let slotStyle = {
paddingLeft: paddingLeft || 0,
paddingTop: paddingTop || 0,
paddingRight: paddingRight || 0,
paddingBottom: paddingBottom || 0,
//height: style.customHeight || '100%'
} as any
// 兼容旧的style
const isOldBackground = typeof background === 'object'
if (isOldBackground) {
const {
background: bg,
backgroundImage,
backgroundColor,
backgroundRepeat,
backgroundSize
} = background;
slotStyle.backgroundRepeat = backgroundRepeat
slotStyle.backgroundSize = backgroundSize
if (bg) {
slotStyle.background = bg
} else {
slotStyle.backgroundImage = backgroundImage
slotStyle.backgroundColor = backgroundColor
}
} else {
slotStyle.background = background
}
if (hasParamsStyle) {
slotStyle = Object.assign(slotStyle, otherStyle)
}
return slotStyle
}
function calSlotClasses(slotStyle) {
const rtn = [css.slot]
const style = slotStyle
if (style) {
if (style.layout?.toLowerCase() == 'flex-column') {
rtn.push(css.lyFlexColumn)
} else if (style.layout?.toLowerCase() == 'flex-row') {
rtn.push(css.lyFlexRow)
}
const justifyContent = style.justifyContent
if (justifyContent) {
if (justifyContent.toUpperCase() === 'FLEX-START') {
rtn.push(css.justifyContentFlexStart)
} else if (justifyContent.toUpperCase() === 'CENTER') {
rtn.push(css.justifyContentFlexCenter)
} else if (justifyContent.toUpperCase() === 'FLEX-END') {
rtn.push(css.justifyContentFlexFlexEnd)
} else if (justifyContent.toUpperCase() === 'SPACE-AROUND') {
rtn.push(css.justifyContentFlexSpaceAround)
} else if (justifyContent.toUpperCase() === 'SPACE-BETWEEN') {
rtn.push(css.justifyContentFlexSpaceBetween)
}
}
const alignItems = style.alignItems
if (alignItems) {
if (alignItems.toUpperCase() === 'FLEX-START') {
rtn.push(css.alignItemsFlexStart)
} else if (alignItems.toUpperCase() === 'CENTER') {
rtn.push(css.alignItemsFlexCenter)
} else if (alignItems.toUpperCase() === 'FLEX-END') {
rtn.push(css.alignItemsFlexFlexEnd)
}
}
}
return rtn.join(' ')
}
function getClasses({ style }) {
const classes = [css.com]
if (style.flex === 1) {
classes.push(css.flex)
}
return classes.join(" ")
}
function getSizeStyle({ style }) {
const sizeStyle: any = {}
const { width, height } = style
if (!width) {
sizeStyle.width = "100%"
} else if (isNumber(width)) {
sizeStyle.width = width + "px"
} else if (width) {
sizeStyle.width = width
}
if (isNumber(height)) {
sizeStyle.height = height + "px"
} else if (height) {
sizeStyle.height = height
}
return sizeStyle
}
function getMarginStyle({ style }) {
const marginStyle: any = {}
const {
width,
marginTop,
marginLeft,
marginRight,
marginBottom
} = style
if (isNumber(marginTop)) {
marginStyle.marginTop = marginTop + "px"
}
if (isNumber(marginLeft)) {
if (typeof width === "number" || marginLeft < 0) {
marginStyle.marginLeft = marginLeft + "px"
} else {
marginStyle.paddingLeft = marginLeft + "px"
}
}
if (isNumber(marginRight)) {
if (typeof width === "number" || marginRight < 0) {
marginStyle.marginRight = marginRight + "px"
} else {
marginStyle.paddingRight = marginRight + "px"
}
}
if (isNumber(marginBottom)) {
marginStyle.marginBottom = marginBottom + "px"
}
return marginStyle
}