Skip to content

Commit

Permalink
Merge pull request #50 from waldiez/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
lazToum authored Dec 5, 2024
2 parents ae3b560 + 0e2ad90 commit 1f67da7
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 66 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## [Unreleased]

## v0.1.17

- Added node reconnection feature
- Styling and theme/sidebar state updates
- Dependency updates

## v0.1.16

- Dependency updates
Expand Down
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@

![CI Build](https://github.com/waldiez/react/actions/workflows/main.yaml/badge.svg) [![Coverage Status](https://coveralls.io/repos/github/waldiez/react/badge.svg)](https://coveralls.io/github/waldiez/react) [![npm version](https://badge.fury.io/js/@waldiez%2Freact.svg)](https://badge.fury.io/js/@waldiez%2Freact)

## Requirements
## Installation from npm registry

```bash
# any of the following
npm install @waldiez/react
yarn add @waldiez/react
pnpm add @waldiez/react
bun add @waldiez/react
```

## Requirements for development

- Node.js
- [email protected]
Expand All @@ -22,7 +32,7 @@
"react-icons": "^5.3.0",
"react-select": "^5.8.3",
"zundo": "^2.3.0",
"zustand": "^5.0.1"
"zustand": "^5.0.2"
}
```

Expand Down
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@waldiez/react",
"license": "MIT",
"version": "0.1.16",
"version": "0.1.17",
"type": "module",
"main": "./dist/@waldiez.umd.cjs",
"module": "./dist/@waldiez.js",
Expand Down Expand Up @@ -77,10 +77,10 @@
"react-icons": "^5.4.0",
"react-select": "^5.8.3",
"zundo": "^2.3.0",
"zustand": "^5.0.1"
"zustand": "^5.0.2"
},
"devDependencies": {
"@eslint/compat": "^1.2.3",
"@eslint/compat": "^1.2.4",
"@eslint/js": "9.16.0",
"@stylistic/eslint-plugin": "^2.11.0",
"@testing-library/jest-dom": "^6.6.3",
Expand All @@ -91,7 +91,7 @@
"@types/gunzip-maybe": "^1.4.2",
"@types/jest": "^29.5.14",
"@types/jest-image-snapshot": "^6.4.0",
"@types/react": "^18.3.12",
"@types/react": "^18.3.13",
"@types/react-dom": "^18.3.1",
"@types/tar-stream": "^3.1.3",
"@typescript-eslint/eslint-plugin": "^8.17.0",
Expand All @@ -101,10 +101,10 @@
"@vitest/coverage-v8": "^2.1.8",
"@vitest/ui": "^2.1.8",
"ajv": "^8.17.1",
"dotenv": "^16.4.6",
"dotenv": "^16.4.7",
"eslint": "^9.16.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react-refresh": "^0.4.16",
Expand All @@ -115,7 +115,7 @@
"lookpath": "^1.2.2",
"playwright": "^1.49.0",
"pre-commit": "^1.2.2",
"prettier": "^3.4.1",
"prettier": "^3.4.2",
"react-hotkeys-hook": "^4.6.1",
"react-select-event": "^5.5.1",
"rimraf": "^6.0.1",
Expand All @@ -124,13 +124,13 @@
"stylelint-config-standard": "^36.0.1",
"stylelint-prettier": "^5.0.2",
"tar-stream": "^3.1.7",
"terser": "^5.36.0",
"terser": "^5.37.0",
"ts-json-schema-generator": "^2.3.0",
"tsx": "^4.19.2",
"typedoc": "^0.27.2",
"typedoc": "^0.27.3",
"typescript": "^5.7.2",
"typescript-eslint": "^8.17.0",
"vite": "^6.0.2",
"vite": "^6.0.3",
"vite-plugin-dts": "^4.3.0",
"vite-plugin-externalize-deps": "^0.8.0",
"vitest": "^2.1.8",
Expand Down
2 changes: 1 addition & 1 deletion schema.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$id": "https://github.com/waldiez/react/tree/v0.1.16/schema.json",
"$id": "https://github.com/waldiez/react/tree/v0.1.17/schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
Expand Down
2 changes: 1 addition & 1 deletion src/waldiez/components/flow/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export const WaldiezFlow = (props: WaldiezFlowProps) => {
onKeyDown={onKeyDown}
onNodeDoubleClick={onNodeDoubleClick}
onEdgeDoubleClick={onEdgeDoubleClick}
// onReconnect={store.onReconnect}
onReconnect={store.onReconnect}
colorMode={colorMode}
elevateNodesOnSelect={true}
elevateEdgesOnSelect={true}
Expand Down
4 changes: 3 additions & 1 deletion src/waldiez/store/creator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import diff from 'microdiff';
import { temporal } from 'zundo';

import { Edge, EdgeChange, Node, NodeChange, ReactFlowInstance, XYPosition } from '@xyflow/react';
import { Connection, Edge, EdgeChange, Node, NodeChange, ReactFlowInstance, XYPosition } from '@xyflow/react';

import { createStore } from 'zustand';

Expand Down Expand Up @@ -87,6 +87,8 @@ export const createWaldiezStore = (props?: WaldiezStoreProps) => {
updateEdgePath: (id: string, agentType: WaldiezAgentNodeType) =>
EdgesStore.updateEdgePath(id, agentType, get, set),
getEdgeSourceAgent: (edge: Edge) => EdgesStore.getEdgeSourceAgent(edge, get),
onReconnect: (oldEdge: Edge, newConnection: Connection) =>
EdgesStore.onReconnect(oldEdge, newConnection, get, set),
// nodes
getNodes: () => get().nodes,
onNodesChange: (changes: NodeChange<Node>[]) => NodesStore.onNodesChange(changes, get, set),
Expand Down
81 changes: 80 additions & 1 deletion src/waldiez/store/edges/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Edge, EdgeChange, applyEdgeChanges } from '@xyflow/react';
import { Connection, Edge, EdgeChange, applyEdgeChanges } from '@xyflow/react';

import {
WaldiezAgentNode,
Expand Down Expand Up @@ -267,4 +267,83 @@ export class EdgesStore {
updatedAt: new Date().toISOString()
});
};

static onReconnect: (oldEdge: Edge, newConnection: Connection, get: typeOfGet, set: typeOfSet) => void = (
oldEdge,
newConnection,
get,
set
) => {
const { oldSourceNode, oldTargetNode, newSourceNode, newTargetNode, color } = getReconnectNodesAndColor(
oldEdge,
newConnection,
get
);
if (!oldSourceNode || !oldTargetNode || !newSourceNode || !newTargetNode) {
console.error('Not all nodes found');
return;
}
if (oldSourceNode.id === newSourceNode.id && oldTargetNode.id === newTargetNode.id) {
return;
}
if (!color) {
console.error('Color not found');
return false;
}
set({
edges: [
...get().edges.map(edge => {
if (edge.id !== oldEdge.id) {
return edge;
}
return {
...oldEdge,
source: newConnection.source,
target: newConnection.target,
...edgeCommonStyle(oldEdge.type as 'chat' | 'nested' | 'group' | 'hidden', color)
};
})
],
updatedAt: new Date().toISOString()
});
EdgesStore.resetEdgePositions(get, set);
EdgesStore.resetEdgeOrders(get, set);
};
}

const getReconnectNodesAndColor = (
oldEdge: Edge,
newConnection: Connection,
get: typeOfGet
): {
oldSourceNode: WaldiezAgentNode | undefined;
oldTargetNode: WaldiezAgentNode | undefined;
newSourceNode: WaldiezAgentNode | undefined;
newTargetNode: WaldiezAgentNode | undefined;
color: string | undefined;
} => {
let oldSourceNode: WaldiezAgentNode | undefined;
let oldTargetNode: WaldiezAgentNode | undefined;
let newSourceNode: WaldiezAgentNode | undefined;
let newTargetNode: WaldiezAgentNode | undefined;
let color: string | undefined;
for (const node of get().nodes) {
if (node.id === oldEdge.source) {
oldSourceNode = node as WaldiezAgentNode;
}
if (node.id === oldEdge.target) {
oldTargetNode = node as WaldiezAgentNode;
}
if (node.id === newConnection.source) {
newSourceNode = node as WaldiezAgentNode;
color = AGENT_COLORS[newSourceNode.data.agentType];
}
if (node.id === newConnection.target) {
newTargetNode = node as WaldiezAgentNode;
}
if (oldSourceNode && oldTargetNode && newSourceNode && newTargetNode) {
break;
}
}
return { oldSourceNode, oldTargetNode, newSourceNode, newTargetNode, color };
};
1 change: 1 addition & 0 deletions src/waldiez/store/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const selector = (store: WaldiezState) => ({
updateEdgePath: store.updateEdgePath,
updateEdgeData: store.updateEdgeData,
getEdgeSourceAgent: store.getEdgeSourceAgent,
onReconnect: store.onReconnect,
// nodes
getNodes: store.getNodes,
onNodesChange: store.onNodesChange,
Expand Down
2 changes: 2 additions & 0 deletions src/waldiez/store/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
Connection,
Edge,
EdgeChange,
Node,
Expand Down Expand Up @@ -77,6 +78,7 @@ export type WaldiezState = WaldiezStoreProps & {
updateEdgePath: (id: string, agentType: WaldiezAgentNodeType) => void;
updateEdgeData: (id: string, data: Edge['data']) => void;
getEdgeSourceAgent: (edge: Edge) => WaldiezAgentNode | null;
onReconnect: (oldEdge: Edge, newConnection: Connection) => void;
// nodes
getNodes: () => Node[];
onNodesChange: OnNodesChange;
Expand Down
33 changes: 33 additions & 0 deletions src/waldiez/utils/storage/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const __SIDEBAR_STORAGE_KEY = 'waldiez_sidebar';
* @returns boolean
*/
export const isSidebarCollapsed = (storageId: string) => {
const fromBody = getIsSidebarCollapsedFromBody();
if (typeof fromBody === 'boolean') {
return fromBody;
}
const storageValue = localStorage.getItem(__SIDEBAR_STORAGE_KEY);
if (storageValue) {
try {
Expand All @@ -29,6 +33,7 @@ export const setSidebarCollapsed = (storageId: string, isCollapsed: boolean) =>
const lockFile = `waldiez_sidebar_${storageId}.lock`;
if (!window.localStorage.getItem(lockFile)) {
window.localStorage.setItem(lockFile, '1');
setSidebarCollapsedToBody(isCollapsed);
const sidebars = getStoredSidebarStates();
sidebars[storageId] = isCollapsed.toString();
localStorage.setItem(__SIDEBAR_STORAGE_KEY, JSON.stringify(sidebars));
Expand All @@ -54,3 +59,31 @@ const getStoredSidebarStates = () => {
}
return sidebars;
};

/**
* Get the initial state of the sidebar from the body class.
* @returns boolean | undefined
*/
const getIsSidebarCollapsedFromBody = () => {
if (document.body.classList.contains('waldiez-sidebar-collapsed')) {
return true;
}
if (document.body.classList.contains('waldiez-sidebar-expanded')) {
return false;
}
return undefined;
};

/**
* Set the state of the sidebar to the body class.
* @param isCollapsed - The state of the sidebar
*/
const setSidebarCollapsedToBody = (isCollapsed: boolean) => {
if (isCollapsed) {
document.body.classList.add('waldiez-sidebar-collapsed');
document.body.classList.remove('waldiez-sidebar-expanded');
} else {
document.body.classList.add('waldiez-sidebar-expanded');
document.body.classList.remove('waldiez-sidebar-collapsed');
}
};
26 changes: 26 additions & 0 deletions src/waldiez/utils/storage/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ const __THEME_STORAGE_KEY = 'waldiez_theme';
* Check if the current mode is dark
* @returns boolean
**/
// eslint-disable-next-line max-statements
export const isDarkMode = (flowId: string, storageId: string) => {
// first check if the theme is set in local storage
// in storage: {waldiez_theme: {storageId: 'dark/light'}}
const fromBodyClass = classInBody();
if (typeof fromBodyClass === 'boolean') {
return fromBodyClass;
}
const fromLocalStorage = themeInLocalStorage(storageId);
if (typeof fromLocalStorage === 'boolean') {
return fromLocalStorage;
Expand Down Expand Up @@ -42,6 +47,7 @@ export const setDarkMode = (flowId: string, storageId: string, dark: boolean) =>
themes[storageId] = dark ? 'dark' : 'light';
window.localStorage.setItem(__THEME_STORAGE_KEY, JSON.stringify(themes));
updateFlowDivClass(flowId, dark);
updateBodyClass(dark);
setTimeout(() => {
window.localStorage.removeItem(lockFile);
}, 200);
Expand Down Expand Up @@ -86,6 +92,16 @@ const updateFlowDivClass = (flowId: string, dark: boolean) => {
}
};

const updateBodyClass = (dark: boolean) => {
if (dark) {
document.body.classList.add('waldiez-dark');
document.body.classList.remove('waldiez-light');
} else {
document.body.classList.add('waldiez-light');
document.body.classList.remove('waldiez-dark');
}
};

const themeInLocalStorage = (storageId: string) => {
const theme = window.localStorage.getItem(__THEME_STORAGE_KEY);
if (theme) {
Expand Down Expand Up @@ -122,3 +138,13 @@ const themeInRootDiv = (flowId: string) => {
}
return null;
};

const classInBody = () => {
if (document.body.classList.contains('waldiez-dark')) {
return true;
}
if (document.body.classList.contains('waldiez-light')) {
return false;
}
return null;
};
4 changes: 3 additions & 1 deletion tests/browser/__snapshots__/waldiez.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
exports[`All > should render Waldiez components 1`] = `
{
"asFragment": [Function],
"baseElement": <body>
"baseElement": <body
class="waldiez-light"
>
Expand Down
Loading

0 comments on commit 1f67da7

Please sign in to comment.