# any of the following
npm install @waldiez/react
yarn add @waldiez/react
pnpm add @waldiez/react
bun add @waldiez/react
{
"@monaco-editor/react": "^4.6.0",
"@xyflow/react": "^12.3.6",
"microdiff": "^1.4.0",
"nanoid": "^5.0.9",
"rc-slider": "^11.1.7",
"react": "^18.3.1 || ^19.0.0",
"react-dom": "^18.3.1 || ^19.0.0",
"react-error-boundary": "^4.1.2",
"react-hotkeys-hook": "^4.6.1",
"react-icons": "^5.4.0",
"react-select": "^5.9.0",
"zundo": "^2.3.0",
"zustand": "^5.0.2"
}
// npm|yarn|pnpm|bun|whatever add|install @waldiez/react
import '@waldiez/react/dist/@waldiez.css';
import { Waldiez } from '@waldiez/react';
import React from 'react';
import ReactDOM from 'react-dom/client';
const isProd = import.meta.env.PROD;
// the actions should be handled by other components
// that use `Waldiez` as a child component
/**
*OnChange
*/
const onChange = null;
// const onChange = (flowJson: any) => {
// console.info(JSON.stringify(JSON.parse(flowJson), null, 2));
// };
/**
* OnSave
* if enabled, add a listener for the key combination (ctrl+s/mod+s)
* to save the flow
* the flow string is the JSON stringified flow
* the action should be handled by the parent component
*/
const onSaveDev = (flowString: string) => {
console.info('saving', flowString);
};
const onSave = isProd ? null : onSaveDev;
/**
* UserInput
*/
// to check/test the user input, use `onUserInput` and `inputPrompt`
// reset `inputPrompt` to `null` to remove/hide the modal
// these two props are used to show a modal to the user
// and get the user input
// Example:
//
// const [ inputPrompt, setInputPrompt ] = useState<{
// previousMessages: string[];
// prompt: string;
// } | null>(null);
//
// const onUserInput = (input: string) => {
// const allMessages = input.split('\n');
// const previousMessages = allMessages.slice(0, allMessages.length - 1);
// const prompt = allMessages[allMessages.length - 1];
// setInputPrompt({ previousMessages, prompt });
// };
// const inputPrompt = {
// previousMessages: ['Hello, World!', 'How\n are you?'],
// prompt: 'What is your name?'
// };
// const onUserInput = (input: string) => {
// console.info(input);
// };
const inputPrompt = null;
const onUserInput = null;
/**
* OnRun
* adds a button to the main panel, to run the code.
* The action should be handled by the parent component
* "running" the flow happens in the python part / backend
* the flow string is the JSON stringified flow
*/
const onRunDev = (flowString: string) => {
console.info(flowString);
};
const onRun = isProd ? null : onRunDev;
/**
* OnConvert
* adds two buttons to the main panel, to convert the flow to python or jupyter notebook
* The action should be handled by the parent component
* the flow string is the JSON stringified flow
* the `to` parameter is either 'py' or 'ipynb'
* the conversion happens in the python part / backend
*/
const onConvertDev = (_flowString: string, to: 'py' | 'ipynb') => {
console.info('converting to', to);
};
const onConvert = isProd ? null : onConvertDev;
/**
* OnUpload
* on RAG user: adds a dropzone to upload files
* when triggered, the files are sent to the backend,
* returning the paths of the uploaded files
* and the 'docsPath' in RAG retrieveConfig is updated.
* the paths can be either relative or absolute,
* this depends on how we run the flow
* (the docsPath will have to be updated accordingly if needed on the backend)
*/
const onUploadDev = (files: File[]) => {
return new Promise<string[]>(resolve => {
const uploadedFiles: string[] = [];
const promises = files.map(file => {
// simulate uploading files
return new Promise<string>(resolve => {
setTimeout(() => {
uploadedFiles.push(`path/to/${file.name}`);
resolve(`path/to/${file.name}`);
}, 2000);
});
});
Promise.all(promises).then(() => {
resolve(uploadedFiles);
});
});
};
const onUpload = isProd ? null : onUploadDev;
/**
* Monaco Editor
*/
// DEV: downloaded in `public/vs` folder (.gitignored)
// PROD:
// either served and `VITE_VS_PATH` is set to the path, or
// use the default cdn (jsdelivr) that monaco loader uses
// make sure the csp allows the cdn
let vsPath = !isProd ? 'vs' : (import.meta.env.VITE_VS_PATH ?? null);
if (!vsPath) {
// if set to empty string, make it null
vsPath = null;
}
/**
* Other props:
* we can use:
* `import { importFlow } from '@waldiez/react';`
* to import an existing flow from a waldiez/json file
* then we can pass the additional props:
* - edges: Edge[]; initial edges to render
* - nodes: Node[]; initial nodes to render
* - name: string;
* - description: string;
* - tags: string[];
* - requirements: string[];
* - createdAt?: string;
* - updatedAt?: string;
*/
const startApp = () => {
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<Waldiez
monacoVsPath={vsPath}
onUserInput={onUserInput}
flowId="flow-0"
storageId="storage-0"
inputPrompt={inputPrompt}
onRun={onRun}
onConvert={onConvert}
onChange={onChange}
onUpload={onUpload}
onSave={onSave}
/>
</React.StrictMode>
);
};
startApp();
This project is licensed under the MIT License - see the LICENSE file for details.