mt-flowbite-react
Version:
Official React components built for Flowbite and Tailwind CSS
156 lines (155 loc) • 6.18 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { random } from "lodash-es";
import { createContext, useRef, useContext, useEffect } from "react";
import { create, useStore } from 'zustand';
import { persist, subscribeWithSelector } from "zustand/middleware";
import { findChildrenById as findNodeById } from "./helper";
export const createRenderlice = (set, get, initState) => {
return ({
some: "some1",
setSomeValue(someValue) {
set({ ...get(), some: someValue });
},
async addChild(viewType, nodeId) {
const pre = get();
if (nodeId) {
const addToNodeId = nodeId || pre.rootNode.id;
console.log("rootStore中添加子节点:", nodeId, viewType);
const rootNode = get().rootNode;
const parentNode = findNodeById(rootNode, addToNodeId);
if (!parentNode) {
console.log("找不到父节点");
return;
}
console.log("找到 parent 节点", parentNode);
const newNode = {
id: random(1, 999999999),
name: "test1",
enabled: true,
comNode: {
id: random(1, 999999999),
name: "name1",
comType: viewType,
}
};
parentNode.children = [...parentNode.children || [], newNode];
set((state) => ({
rootNode: rootNode,
}));
}
else {
const pre = get();
set({
...get(), rootNode: {
...pre.rootNode, children: [...pre.rootNode.children || [], {
id: random(1, 999999999),
name: "test2",
enabled: true,
comNode: {
id: random(1, 999999999),
name: "name1",
comType: viewType,
}
}]
}
});
}
},
printState() {
console.log("print state: ", get().rootNode);
},
...initState,
});
};
export const createNodeStore = (initProps) => {
return create()(persist(subscribeWithSelector((...a) => ({
...createRenderlice(...a),
...initProps,
})), {
name: `render-${(initProps?.rootNode?.id) ? initProps.rootNode?.id : ""}`,
version: 1,
skipHydration: true,
onRehydrateStorage(state) { },
}));
};
//-------------------------------------------------------------------------------------------
// 一般情况下的 嵌套使用的 context 及其 hooks, (树状结构)
const Context = createContext(null);
export function NodeProvider({ children, ...props }) {
//思考: NodeProvider 必定在GlobalNodeProvider里面,
// 不知道,是否可以考虑以 GlobalNodeProvider 上下文作为基准,来构造NodeProvider
const storeRef = useRef();
if (!storeRef.current) {
storeRef.current = createNodeStore(props);
}
// const rootStore = useRootNodeStore(x => x.rootNode)
// useEffect(() => {
// console.log(" rootStore 变更", rootStore)
// // storeRef.current = createListItemStore(props)
// }, [
// rootStore
// ])
return (_jsxs(Context.Provider, { value: storeRef.current, children: [children, _jsx(Setup, {})] }));
}
function Setup() {
const rootNode = useNodeGlobalStore(x => x.rootNode);
// const rootSomeValue = useNodeGlobalStore(x => x.some)
const rootSetSomeValue = useNodeGlobalStore(x => x.setSomeValue);
const currentNode = useNodeStore(x => x.rootNode);
useEffect(() => {
console.log("rootNode变更", rootNode);
}, [rootNode]);
useEffect(() => {
console.log("currentNode变更", currentNode);
//当前节点的变更触发 根节点的变更,为了构建完整的树结构,毕竟,在节点上下文目前,仅仅保存了当前节点及下属节点的信息。
// 1: 先试试 调用根节点的函数看是否生效。
rootSetSomeValue("先试试 调用根节点的函数看是否生效。");
}, [currentNode]);
const store = useNodeStore();
useEffect(() => {
const unsub2 = store.subscribe((state) => state.some, (a) => {
console.log("a", a);
// rootSetSomeValue("subscribed:" + a.toString())
});
return () => {
unsub2();
};
}, []);
return (_jsx(_Fragment, {}));
}
export function useNodeStore(selector, equals) {
const store = useContext(Context);
if (!store)
throw new Error('Missing NodeProvider');
if (selector) {
return useStore(store, selector, equals);
}
else {
return store;
}
}
//-------------------------------------------------------------------------------------------
// 全局 Context 及其hooks
// 用途: 因为动态UI节点是树状嵌套的,下层的context,不能直接获取到全局(根节点)的完整信息。
// 所以额外的增加一个全局非嵌套的Context。 这样可以获取完整的树状元素节点数据,方便进一步处理。
//
const ContextGlobal = createContext(null);
export function GlobalNodeProvider({ children, ...props }) {
const storeRef = useRef();
if (!storeRef.current) {
storeRef.current = createNodeStore(props);
}
return (_jsx(ContextGlobal.Provider, { value: storeRef.current, children: children }));
}
export function useNodeGlobalStore(selector, equals) {
const store = useContext(ContextGlobal);
if (!store)
throw new Error('Missing GlobalNodeProvider');
if (selector) {
return useStore(store, selector, equals);
}
else {
return store;
}
}