 85bf1341f3
			
		
	
	85bf1341f3
	
	
	
		
			
			Frontend Enhancements: - Complete React TypeScript frontend with modern UI components - Distributed workflows management interface with real-time updates - Socket.IO integration for live agent status monitoring - Agent management dashboard with cluster visualization - Project management interface with metrics and task tracking - Responsive design with proper error handling and loading states Backend Infrastructure: - Distributed coordinator for multi-agent workflow orchestration - Cluster management API with comprehensive agent operations - Enhanced database models for agents and projects - Project service for filesystem-based project discovery - Performance monitoring and metrics collection - Comprehensive API documentation and error handling Documentation: - Complete distributed development guide (README_DISTRIBUTED.md) - Comprehensive development report with architecture insights - System configuration templates and deployment guides The platform now provides a complete web interface for managing the distributed AI cluster with real-time monitoring, workflow orchestration, and agent coordination capabilities. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			170 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import * as React from 'react';
 | |
| import { useContext, useRef, cloneElement, Children, isValidElement } from 'react';
 | |
| import { useForceUpdate } from '../../utils/use-force-update.mjs';
 | |
| import { useIsMounted } from '../../utils/use-is-mounted.mjs';
 | |
| import { PresenceChild } from './PresenceChild.mjs';
 | |
| import { LayoutGroupContext } from '../../context/LayoutGroupContext.mjs';
 | |
| import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';
 | |
| import { useUnmountEffect } from '../../utils/use-unmount-effect.mjs';
 | |
| import { invariant } from '../../utils/errors.mjs';
 | |
| 
 | |
| const getChildKey = (child) => child.key || "";
 | |
| function updateChildLookup(children, allChildren) {
 | |
|     children.forEach((child) => {
 | |
|         const key = getChildKey(child);
 | |
|         allChildren.set(key, child);
 | |
|     });
 | |
| }
 | |
| function onlyElements(children) {
 | |
|     const filtered = [];
 | |
|     // We use forEach here instead of map as map mutates the component key by preprending `.$`
 | |
|     Children.forEach(children, (child) => {
 | |
|         if (isValidElement(child))
 | |
|             filtered.push(child);
 | |
|     });
 | |
|     return filtered;
 | |
| }
 | |
| /**
 | |
|  * `AnimatePresence` enables the animation of components that have been removed from the tree.
 | |
|  *
 | |
|  * When adding/removing more than a single child, every child **must** be given a unique `key` prop.
 | |
|  *
 | |
|  * Any `motion` components that have an `exit` property defined will animate out when removed from
 | |
|  * the tree.
 | |
|  *
 | |
|  * ```jsx
 | |
|  * import { motion, AnimatePresence } from 'framer-motion'
 | |
|  *
 | |
|  * export const Items = ({ items }) => (
 | |
|  *   <AnimatePresence>
 | |
|  *     {items.map(item => (
 | |
|  *       <motion.div
 | |
|  *         key={item.id}
 | |
|  *         initial={{ opacity: 0 }}
 | |
|  *         animate={{ opacity: 1 }}
 | |
|  *         exit={{ opacity: 0 }}
 | |
|  *       />
 | |
|  *     ))}
 | |
|  *   </AnimatePresence>
 | |
|  * )
 | |
|  * ```
 | |
|  *
 | |
|  * You can sequence exit animations throughout a tree using variants.
 | |
|  *
 | |
|  * If a child contains multiple `motion` components with `exit` props, it will only unmount the child
 | |
|  * once all `motion` components have finished animating out. Likewise, any components using
 | |
|  * `usePresence` all need to call `safeToRemove`.
 | |
|  *
 | |
|  * @public
 | |
|  */
 | |
| const AnimatePresence = ({ children, custom, initial = true, onExitComplete, exitBeforeEnter, presenceAffectsLayout = true, mode = "sync", }) => {
 | |
|     invariant(!exitBeforeEnter, "Replace exitBeforeEnter with mode='wait'");
 | |
|     // We want to force a re-render once all exiting animations have finished. We
 | |
|     // either use a local forceRender function, or one from a parent context if it exists.
 | |
|     const forceRender = useContext(LayoutGroupContext).forceRender || useForceUpdate()[0];
 | |
|     const isMounted = useIsMounted();
 | |
|     // Filter out any children that aren't ReactElements. We can only track ReactElements with a props.key
 | |
|     const filteredChildren = onlyElements(children);
 | |
|     let childrenToRender = filteredChildren;
 | |
|     const exitingChildren = useRef(new Map()).current;
 | |
|     // Keep a living record of the children we're actually rendering so we
 | |
|     // can diff to figure out which are entering and exiting
 | |
|     const presentChildren = useRef(childrenToRender);
 | |
|     // A lookup table to quickly reference components by key
 | |
|     const allChildren = useRef(new Map()).current;
 | |
|     // If this is the initial component render, just deal with logic surrounding whether
 | |
|     // we play onMount animations or not.
 | |
|     const isInitialRender = useRef(true);
 | |
|     useIsomorphicLayoutEffect(() => {
 | |
|         isInitialRender.current = false;
 | |
|         updateChildLookup(filteredChildren, allChildren);
 | |
|         presentChildren.current = childrenToRender;
 | |
|     });
 | |
|     useUnmountEffect(() => {
 | |
|         isInitialRender.current = true;
 | |
|         allChildren.clear();
 | |
|         exitingChildren.clear();
 | |
|     });
 | |
|     if (isInitialRender.current) {
 | |
|         return (React.createElement(React.Fragment, null, childrenToRender.map((child) => (React.createElement(PresenceChild, { key: getChildKey(child), isPresent: true, initial: initial ? undefined : false, presenceAffectsLayout: presenceAffectsLayout, mode: mode }, child)))));
 | |
|     }
 | |
|     // If this is a subsequent render, deal with entering and exiting children
 | |
|     childrenToRender = [...childrenToRender];
 | |
|     // Diff the keys of the currently-present and target children to update our
 | |
|     // exiting list.
 | |
|     const presentKeys = presentChildren.current.map(getChildKey);
 | |
|     const targetKeys = filteredChildren.map(getChildKey);
 | |
|     // Diff the present children with our target children and mark those that are exiting
 | |
|     const numPresent = presentKeys.length;
 | |
|     for (let i = 0; i < numPresent; i++) {
 | |
|         const key = presentKeys[i];
 | |
|         if (targetKeys.indexOf(key) === -1 && !exitingChildren.has(key)) {
 | |
|             exitingChildren.set(key, undefined);
 | |
|         }
 | |
|     }
 | |
|     // If we currently have exiting children, and we're deferring rendering incoming children
 | |
|     // until after all current children have exiting, empty the childrenToRender array
 | |
|     if (mode === "wait" && exitingChildren.size) {
 | |
|         childrenToRender = [];
 | |
|     }
 | |
|     // Loop through all currently exiting components and clone them to overwrite `animate`
 | |
|     // with any `exit` prop they might have defined.
 | |
|     exitingChildren.forEach((component, key) => {
 | |
|         // If this component is actually entering again, early return
 | |
|         if (targetKeys.indexOf(key) !== -1)
 | |
|             return;
 | |
|         const child = allChildren.get(key);
 | |
|         if (!child)
 | |
|             return;
 | |
|         const insertionIndex = presentKeys.indexOf(key);
 | |
|         let exitingComponent = component;
 | |
|         if (!exitingComponent) {
 | |
|             const onExit = () => {
 | |
|                 // clean up the exiting children map
 | |
|                 exitingChildren.delete(key);
 | |
|                 // compute the keys of children that were rendered once but are no longer present
 | |
|                 // this could happen in case of too many fast consequent renderings
 | |
|                 // @link https://github.com/framer/motion/issues/2023
 | |
|                 const leftOverKeys = Array.from(allChildren.keys()).filter((childKey) => !targetKeys.includes(childKey));
 | |
|                 // clean up the all children map
 | |
|                 leftOverKeys.forEach((leftOverKey) => allChildren.delete(leftOverKey));
 | |
|                 // make sure to render only the children that are actually visible
 | |
|                 presentChildren.current = filteredChildren.filter((presentChild) => {
 | |
|                     const presentChildKey = getChildKey(presentChild);
 | |
|                     return (
 | |
|                     // filter out the node exiting
 | |
|                     presentChildKey === key ||
 | |
|                         // filter out the leftover children
 | |
|                         leftOverKeys.includes(presentChildKey));
 | |
|                 });
 | |
|                 // Defer re-rendering until all exiting children have indeed left
 | |
|                 if (!exitingChildren.size) {
 | |
|                     if (isMounted.current === false)
 | |
|                         return;
 | |
|                     forceRender();
 | |
|                     onExitComplete && onExitComplete();
 | |
|                 }
 | |
|             };
 | |
|             exitingComponent = (React.createElement(PresenceChild, { key: getChildKey(child), isPresent: false, onExitComplete: onExit, custom: custom, presenceAffectsLayout: presenceAffectsLayout, mode: mode }, child));
 | |
|             exitingChildren.set(key, exitingComponent);
 | |
|         }
 | |
|         childrenToRender.splice(insertionIndex, 0, exitingComponent);
 | |
|     });
 | |
|     // Add `MotionContext` even to children that don't need it to ensure we're rendering
 | |
|     // the same tree between renders
 | |
|     childrenToRender = childrenToRender.map((child) => {
 | |
|         const key = child.key;
 | |
|         return exitingChildren.has(key) ? (child) : (React.createElement(PresenceChild, { key: getChildKey(child), isPresent: true, presenceAffectsLayout: presenceAffectsLayout, mode: mode }, child));
 | |
|     });
 | |
|     if (process.env.NODE_ENV !== "production" &&
 | |
|         mode === "wait" &&
 | |
|         childrenToRender.length > 1) {
 | |
|         console.warn(`You're attempting to animate multiple children within AnimatePresence, but its mode is set to "wait". This will lead to odd visual behaviour.`);
 | |
|     }
 | |
|     return (React.createElement(React.Fragment, null, exitingChildren.size
 | |
|         ? childrenToRender
 | |
|         : childrenToRender.map((child) => cloneElement(child))));
 | |
| };
 | |
| 
 | |
| export { AnimatePresence };
 |