@wener/console
Version:
Base console UI toolkit
166 lines (165 loc) • 4.81 kB
JavaScript
import React, { createContext, forwardRef, Fragment, lazy, useContext, useMemo, useRef } from "react";
let _components = [];
export function defineComponent({ Component: _Component, load, ...opts }) {
{
const Component = createComponent({
Component: _Component,
load
});
// if (Component === Fragment) {
// console.warn(`Component ${opts.name} not resolved`);
// }
const def = {
title: opts.title || opts.name,
...opts,
Component,
metadata: {}
};
let last = _components.find((v)=>v.name === def.name);
if (last) {
console.error(`Component ${def.name} already defined`);
// last.schema = def.schema;
// last.props = def.props;
// last.metadata = def.metadata;
}
_components.unshift(def);
}
const name = opts.name;
let component = Object.assign(/*#__PURE__*/ forwardRef((props, ref)=>{
return /*#__PURE__*/ React.createElement(ConsumeComponent, {
$name: name,
...props,
ref: ref
});
}), {
[ComponentNamePropKey]: name
});
return component;
}
export function getComponents() {
return _components;
}
export const ConsumeComponent = /*#__PURE__*/ forwardRef(({ $name, ...props }, ref)=>{
const [Component] = useComponent($name);
return /*#__PURE__*/ React.createElement(Component, {
...props,
ref: ref
});
});
const ComponentNamePropKey = '$ContextComponentName';
export function createContextComponent(name) {
let component = Object.assign(/*#__PURE__*/ forwardRef((props, ref)=>{
return /*#__PURE__*/ React.createElement(ConsumeComponent, {
$name: name,
...props,
ref: ref
});
}), {
[ComponentNamePropKey]: name
});
component.displayName = `${ComponentNamePropKey}(${name})`;
return component;
}
const RootValue = {
get components () {
return _components.map((v)=>{
return {
provide: v.name,
Component: v.Component
};
});
},
useComponent: (name)=>resolveComponent(name, RootValue)
};
const ComponentContext = /*#__PURE__*/ createContext(RootValue);
function resolveName(def) {
let name = typeof def === 'string' ? def : def[ComponentNamePropKey];
return {
name
};
}
export function useComponent(comp) {
const { useComponent } = useContext(ComponentContext);
return useComponent(comp);
}
export const ComponentProvider = ({ components, children })=>{
const parent = useContext(ComponentContext);
const provideRef = useRef(components);
const parentRef = useRef(parent);
provideRef.current = components;
parentRef.current = parent;
const val = useMemo(()=>{
return {
get parent () {
return parentRef.current;
},
get components () {
return provideRef.current;
},
useComponent: (comp)=>{
return resolveComponent(comp, val);
}
};
}, []);
return /*#__PURE__*/ React.createElement(ComponentContext.Provider, {
value: val
}, children);
};
function resolveComponent(comp, obj) {
const { name } = resolveName(comp);
let cur = obj;
let Component = Fragment;
let found = false;
outer: while(cur){
for (let item of cur.components){
if (resolveName(item.provide).name === name) {
Component = createComponent(item);
found = true;
break outer;
}
}
cur = cur.parent;
}
if (Component === Fragment || !found) {
console.warn(`Component ${name} not found`);
}
return [
Component,
[
{
found
}
]
];
}
function createComponent({ Component, load }) {
if (Component) {
return Component;
}
if (load) {
return /*#__PURE__*/ lazy(async ()=>{
try {
const v = await load();
if ('default' in v) {
return v;
}
if (!v) {
throw new Error(`Component not found`);
}
return {
default: v
};
} catch (e) {
console.error(`Failed to load component`, {
load,
Component
}, e);
return {
default: Fragment
};
}
});
}
return Fragment;
}
//# sourceMappingURL=ComponentProvider.js.map