UNPKG

@xyo-network/react-node

Version:

Common React library for all XYO projects that use React

456 lines (425 loc) 18.4 kB
// src/components/NodeDescriptionBox.tsx import { FlexCol } from "@xylabs/react-flexbox"; // src/hooks/getModuleFilterOptions.ts var getModuleFilterOptions = (config) => { const { direction, identity, maxDepth } = config ?? {}; return { direction, identity, maxDepth }; }; // src/hooks/getWeakModuleFilterOptions.ts var getWeakModuleFilterOptions = (config) => { const { direction, identity, maxDepth } = config ?? {}; return { direction, identity, maxDepth }; }; // src/hooks/ModuleFromNodeConfig.ts var getModuleFromNodeConfigLogger = (config) => { return config?.logger; }; // src/hooks/provided/useProvidedNode.tsx import { NodeContext } from "@xyo-network/react-node-context"; import { use } from "react"; var useProvidedNode = () => { const { node } = use(NodeContext); return [node]; }; // src/hooks/provided/useWeakProvidedNode.tsx import { NodeContext as NodeContext2 } from "@xyo-network/react-node-context"; import { use as use2, useMemo } from "react"; var useWeakProvidedNode = () => { const { node } = use2(NodeContext2); const weakNode = useMemo(() => node ? new WeakRef(node) : null, [node]); return [weakNode]; }; // src/hooks/useModuleFromNode.ts import { usePromise as usePromise2 } from "@xylabs/react-promise"; import { isModuleInstance } from "@xyo-network/module-model"; import { useState } from "react"; // src/hooks/useNode.ts import { usePromise } from "@xylabs/react-promise"; import { asNodeInstance } from "@xyo-network/node-model"; // src/hooks/useNodeConfigNodeField.ts import { useMemo as useMemo2 } from "react"; var useNodeConfigNodeField = (config) => { const nodeAddress = useMemo2(() => typeof config?.node === "string" ? config?.node : void 0, [config?.node]); const nodeInstance = useMemo2(() => typeof config?.node === "object" ? config?.node : void 0, [config?.node]); return [nodeAddress, nodeInstance]; }; // src/hooks/useNode.ts var useNode = (config) => { const [nodeAddress, nodeInstance] = useNodeConfigNodeField(config); const [providedNode] = useProvidedNode(); const [nodeAddressNode, error] = usePromise(async () => { if (providedNode && nodeAddress) { return asNodeInstance(await providedNode.resolve(nodeAddress), "Module is not a node"); } }, [providedNode, nodeAddress]); return [nodeAddressNode ?? nodeInstance ?? providedNode ?? void 0, error]; }; // src/hooks/useModuleFromNode.ts var useModuleFromNode = (nameOrAddressOrInstance = void 0, config) => { const [node, nodeError] = useNode(config); const logger = getModuleFromNodeConfigLogger(config); const filterOptions = getModuleFilterOptions(config); const [result, setResult] = useState(); const [, error] = usePromise2(async () => { logger?.debug("useModuleFromNode: resolving"); const identity = config?.identity ?? isModuleInstance; if (node && nameOrAddressOrInstance) { node.on("moduleAttached", ({ mod }) => { logger?.debug(`useModuleFromNode: moduleAttached [${mod.config.name ?? mod.address}]`); if (mod.address === nameOrAddressOrInstance || mod.config?.name === nameOrAddressOrInstance) { setResult(identity(mod) ? mod : void 0); } }); node.on("moduleDetached", ({ mod }) => { logger?.debug(`useModuleFromNode: moduleDetached [${mod.config.name ?? mod.address}]`); if (mod.address === nameOrAddressOrInstance || mod.config?.name === nameOrAddressOrInstance) { setResult(void 0); } }); if (identity(nameOrAddressOrInstance)) { setResult(nameOrAddressOrInstance); } else { const result2 = await node.resolve(nameOrAddressOrInstance, filterOptions); logger?.debug(`Result: ${result2?.address}`); setResult(identity(result2) ? result2 : void 0); } return result; } logger?.debug("Result: No Node"); }, [node, nameOrAddressOrInstance]); return [result, nodeError ?? error]; }; // src/hooks/useModulesFromNode.ts import { exists } from "@xylabs/exists"; import { usePromise as usePromise3 } from "@xylabs/react-promise"; import { useState as useState2 } from "react"; var useModulesFromNode = (ids, config) => { const [node, nodeError] = useNode(config); const logger = config?.logger; const filterOptions = getModuleFilterOptions(); const [result, setResult] = useState2(); const [, error] = usePromise3(async () => { logger?.debug("useModuleFromNode: resolving"); if (node) { const refreshModules = async () => { const moduleInstances = ids ? (await Promise.all(ids.map((id) => node.resolve(id, filterOptions)))).filter(exists) : await node.resolve("*", filterOptions); setResult(moduleInstances); return moduleInstances; }; node.on("moduleAttached", async ({ mod }) => { logger?.debug(`useModuleFromNode: moduleAttached [${mod.config.name ?? mod.address}]`); await refreshModules(); }); node.on("moduleDetached", async ({ mod }) => { logger?.debug(`useModuleFromNode: moduleDetached [${mod.config.name ?? mod.address}]`); await refreshModules(); }); return await refreshModules(); } console.log("Result: No Node"); }, [node, ids]); return [result, nodeError ?? error]; }; // src/hooks/useNodeDescription.ts import { usePromise as usePromise4 } from "@xylabs/react-promise"; import { ModuleDescriptionSchema } from "@xyo-network/module-model"; import { isPayloadOfSchemaType } from "@xyo-network/payload-model"; var useNodeDescription = (config) => { const [activeNode, nodeError] = useNode(config); const [description, error] = usePromise4(async () => { const state = await activeNode?.state(); return state?.find(isPayloadOfSchemaType(ModuleDescriptionSchema)); }, [activeNode]); return [description, nodeError ?? error]; }; // src/hooks/useNodeFromNode.tsx import { asNodeInstance as asNodeInstance2 } from "@xyo-network/node-model"; var useNodeFromNode = (nameOrAddressOrInstance, config) => { const [mod, error] = useModuleFromNode(nameOrAddressOrInstance, config); const instance = asNodeInstance2(mod); if (mod && !instance) { const error2 = new Error(`Resolved module is not a NodeInstance [${mod.config?.schema}:${mod.config?.name}:${mod.address}]`); console.error(error2.message); return [void 0, error2]; } return [instance, error]; }; // src/hooks/useNodesFromNode.tsx import { isNodeInstance } from "@xyo-network/node-model"; var useNodesFromNode = (ids, config) => { const [modules, error] = useModulesFromNode(ids, config); if (error) { return [null, error]; } return modules ? [ // eslint-disable-next-line unicorn/no-array-reduce modules.reduce((prev, mod) => { if (isNodeInstance(mod)) { prev.push(mod); } return prev; }, []), void 0 ] : [modules, error]; }; // src/hooks/useWeakModuleFromNode.ts import { usePromise as usePromise6 } from "@xylabs/react-promise"; import { isModuleInstance as isModuleInstance2 } from "@xyo-network/module-model"; import { useState as useState3 } from "react"; // src/hooks/useWeakNode.ts import { usePromise as usePromise5 } from "@xylabs/react-promise"; import { isDefined } from "@xylabs/typeof"; import { asNodeInstance as asNodeInstance3 } from "@xyo-network/node-model"; // src/hooks/useWeakNodeConfigNodeField.ts import { useMemo as useMemo3 } from "react"; var useWeakNodeConfigNodeField = (config) => { const nodeAddress = useMemo3(() => typeof config?.node === "string" ? config?.node : void 0, [config?.node]); const nodeInstance = useMemo3(() => typeof config?.node === "object" ? config?.node : void 0, [config?.node]); return [nodeAddress, nodeInstance]; }; // src/hooks/useWeakNode.ts var useWeakNode = (config) => { const [nodeAddress, nodeInstance] = useWeakNodeConfigNodeField(config); const [providedNode] = useWeakProvidedNode(); const [nodeAddressNode, error] = usePromise5(async () => { const providedNodeInstance = providedNode?.deref(); if (providedNodeInstance && isDefined(nodeAddress)) { return new WeakRef(asNodeInstance3(await providedNodeInstance.resolve(nodeAddress), () => "Module is not a node", { required: true })); } }, [providedNode, nodeAddress]); return [nodeAddressNode ?? nodeInstance ?? providedNode ?? void 0, error]; }; // src/hooks/WeakModuleFromNodeConfig.ts var getWeakModuleFromNodeConfigLogger = (config) => { return config?.logger; }; // src/hooks/useWeakModuleFromNode.ts var useWeakModuleFromNode = (nameOrAddressOrInstance = void 0, config) => { const [node, nodeError] = useWeakNode(config); const logger = getWeakModuleFromNodeConfigLogger(config); const filterOptions = getWeakModuleFilterOptions(config); const [result, setResult] = useState3(); const [, error] = usePromise6(async () => { logger?.debug("useModuleFromNode: resolving"); const identity = config?.identity ?? isModuleInstance2; const nodeInstance = node?.deref(); if (nodeInstance && nameOrAddressOrInstance) { nodeInstance.on("moduleAttached", ({ mod }) => { logger?.debug(`useModuleFromNode: moduleAttached [${mod.config.name ?? mod.address}]`); if (mod.address === nameOrAddressOrInstance || mod.config?.name === nameOrAddressOrInstance) { setResult(identity(mod) ? new WeakRef(mod) : void 0); } }); nodeInstance.on("moduleDetached", ({ mod }) => { logger?.debug(`useModuleFromNode: moduleDetached [${mod.config.name ?? mod.address}]`); if (mod.address === nameOrAddressOrInstance || mod.config?.name === nameOrAddressOrInstance) { setResult(void 0); } }); if (identity(nameOrAddressOrInstance)) { setResult(new WeakRef(nameOrAddressOrInstance)); } else { const result2 = await nodeInstance.resolve(nameOrAddressOrInstance, filterOptions); logger?.debug(`Result: ${result2?.address}`); setResult(identity(result2) ? new WeakRef(result2) : void 0); } return result; } logger?.debug("Result: No Node"); }, [node, nameOrAddressOrInstance]); return [result, nodeError ?? error]; }; // src/hooks/useWeakModulesFromNode.ts import { exists as exists2 } from "@xylabs/exists"; import { usePromise as usePromise7 } from "@xylabs/react-promise"; import { useState as useState4 } from "react"; var useWeakModulesFromNode = (ids, config) => { const [node, nodeError] = useNode(config); const logger = config?.logger; const filterOptions = getModuleFilterOptions(); const [result, setResult] = useState4(); const [, error] = usePromise7(async () => { logger?.debug("useModuleFromNode: resolving"); const nodeInstance = node; if (nodeInstance) { const refreshModules = async () => { const moduleInstances = ids ? (await Promise.all(ids.map((id) => node.resolve(id, filterOptions)))).filter(exists2) : await node.resolve("*", filterOptions); setResult(moduleInstances.map((mod) => new WeakRef(mod))); return moduleInstances; }; nodeInstance.on("moduleAttached", async ({ mod }) => { logger?.debug(`useModuleFromNode: moduleAttached [${mod.config.name ?? mod.address}]`); await refreshModules(); }); nodeInstance.on("moduleDetached", async ({ mod }) => { logger?.debug(`useModuleFromNode: moduleDetached [${mod.config.name ?? mod.address}]`); await refreshModules(); }); return await refreshModules(); } console.log("Result: No Node"); return; }, [node, ids]); return [result, nodeError ?? error]; }; // src/hooks/useWeakNodeDescription.ts import { usePromise as usePromise8 } from "@xylabs/react-promise"; import { ModuleDescriptionSchema as ModuleDescriptionSchema2 } from "@xyo-network/module-model"; import { isPayloadOfSchemaType as isPayloadOfSchemaType2 } from "@xyo-network/payload-model"; var useWeakNodeDescription = (config) => { const [activeNode, nodeError] = useWeakNode(config); const [description, error] = usePromise8(async () => { const state = await activeNode?.deref()?.state(); return state?.find(isPayloadOfSchemaType2(ModuleDescriptionSchema2)); }, [activeNode]); return [description, nodeError ?? error]; }; // src/hooks/useWeakNodeFromNode.tsx import { isNodeInstance as isNodeInstance2 } from "@xyo-network/node-model"; var useWeakNodeFromNode = (nameOrAddressOrInstance, config) => { return useWeakModuleFromNode(nameOrAddressOrInstance, { identity: isNodeInstance2, ...config }); }; // src/components/NodeDescriptionBox.tsx import { jsx } from "react/jsx-runtime"; var NodeDescriptionBox = ({ node, ...props }) => { const [description, error] = useWeakNodeDescription({ node }); return /* @__PURE__ */ jsx(FlexCol, { ...props, children: /* @__PURE__ */ jsx("code", { color: error ? "red" : void 0, children: error ? error.message : JSON.stringify(description, null, 2) }) }); }; // src/components/Node.tsx import { jsx as jsx2 } from "react/jsx-runtime"; var NodeBox = ({ variant, ...props }) => { switch (variant) { // eslint-disable-next-line unicorn/no-useless-switch-case case "description": default: { return /* @__PURE__ */ jsx2(NodeDescriptionBox, { ...props }); } } }; // src/components/NodeDrawer.tsx import { Close as CloseIcon } from "@mui/icons-material"; import { ClickAwayListener, Drawer, IconButton } from "@mui/material"; import { FlexGrowCol, FlexRow } from "@xylabs/react-flexbox"; import { useNodeDrawer } from "@xyo-network/react-node-provider"; // src/components/render/ModuleDescriptionBox.tsx import { ChevronRight as ChevronRightIcon, ExpandMore as ExpandMoreIcon } from "@mui/icons-material"; import { styled as styled2, Typography } from "@mui/material"; import { SimpleTreeView } from "@mui/x-tree-view"; import { useRef } from "react"; // src/components/render/RenderModule.tsx import { styled } from "@mui/material"; import { TreeItem } from "@mui/x-tree-view"; import { useAsyncEffect } from "@xylabs/react-async-effect"; import { useState as useState5 } from "react"; import { jsx as jsx3, jsxs } from "react/jsx-runtime"; var RenderModule = ({ mod, idRef }) => { const [childModules, setChildModules] = useState5(); useAsyncEffect( async (mounted) => { const moduleInstance2 = mod.deref(); const { address: address2 } = moduleInstance2 ?? {}; if (moduleInstance2) { const children = (await moduleInstance2.resolve("*")).filter((childModule) => childModule.address !== address2); if (mounted()) { setChildModules(children.map((childModule) => new WeakRef(childModule))); } } }, [mod] ); const increment = () => { const newId = (idRef.current.idIncrementor++).toString(); idRef.current.ids.push(newId); return newId; }; const moduleInstance = mod.deref(); const { queries, address } = moduleInstance ?? {}; return /* @__PURE__ */ jsxs(StyledAddressTreeItem, { itemId: increment(), label: `address: ${address}`, children: [ queries?.map((query, index) => { return /* @__PURE__ */ jsx3(TreeItem, { itemId: increment(), label: `query : ${query}`, sx: { mb: index === queries.length - 1 ? 1.5 : 0.5 } }, query); }), childModules && childModules.length > 0 ? /* @__PURE__ */ jsx3(TreeItem, { itemId: increment(), label: "children", sx: { mb: 0.5 }, children: childModules.map((childModuleRef) => { const childModule = childModuleRef.deref(); return childModule ? /* @__PURE__ */ jsx3(RenderModule, { mod: childModuleRef, idRef }, childModule?.address) : null; }) }) : null ] }); }; var StyledAddressTreeItem = styled(TreeItem, { name: "StyledAddressTreeItem" })(({ theme }) => ({ "& .MuiTreeItem-content": { marginBottom: theme.spacing(0.25) } })); // src/components/render/ModuleDescriptionBox.tsx import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime"; var ModuleDescriptionBox = ({ mod }) => { const idRef = useRef({ idIncrementor: 0, ids: [] }); return /* @__PURE__ */ jsx4(Fragment, { children: mod ? /* @__PURE__ */ jsxs2(Fragment, { children: [ /* @__PURE__ */ jsx4(Typography, { variant: "h4", children: "Node Configuration" }), /* @__PURE__ */ jsx4( StyledTreeView, { "aria-label": "file system navigator", slots: { collapseIcon: ExpandMoreIcon, expandIcon: ChevronRightIcon }, sx: { flexGrow: 1 }, children: /* @__PURE__ */ jsx4(RenderModule, { mod, idRef }) } ) ] }) : mod === null ? /* @__PURE__ */ jsx4(Typography, { variant: "h4", children: "Node loading..." }) : /* @__PURE__ */ jsx4(Typography, { variant: "h4", children: "Node not found" }) }); }; var StyledTreeView = styled2(SimpleTreeView, { name: "StyledTreeView" })(() => ({ height: "auto", maxWidth: "auto" })); // src/components/NodeDrawer.tsx import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime"; var NodeDrawer = ({ children, ...props }) => { const { open, setOpen } = useNodeDrawer(); const [node] = useWeakProvidedNode(); return /* @__PURE__ */ jsx5(Drawer, { open: open ?? false, anchor: "right", ...props, children: /* @__PURE__ */ jsx5(ClickAwayListener, { onClickAway: () => setOpen?.(false), children: /* @__PURE__ */ jsxs3(FlexGrowCol, { role: "presentation", justifyContent: "start", p: 2, rowGap: 2, minWidth: "33vw", children: [ /* @__PURE__ */ jsx5(FlexRow, { alignContent: "start", justifyContent: "start", width: "100%", children: /* @__PURE__ */ jsx5(IconButton, { onClick: () => setOpen?.(false), children: /* @__PURE__ */ jsx5(CloseIcon, {}) }) }), /* @__PURE__ */ jsx5(ModuleDescriptionBox, { mod: node }), children ] }) }) }); }; // src/index.ts export * from "@xyo-network/react-node-context"; export * from "@xyo-network/react-node-provider"; export { NodeBox, NodeDrawer, getModuleFilterOptions, getModuleFromNodeConfigLogger, getWeakModuleFilterOptions, getWeakModuleFromNodeConfigLogger, useModuleFromNode, useModulesFromNode, useNode, useNodeConfigNodeField, useNodeDescription, useNodeFromNode, useNodesFromNode, useProvidedNode, useWeakModuleFromNode, useWeakModulesFromNode, useWeakNodeConfigNodeField, useWeakNodeDescription, useWeakNodeFromNode, useWeakProvidedNode }; //# sourceMappingURL=index.mjs.map