### Verify Project Setup with PNPM Commands Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md After copying files, execute 'pnpm install' to resolve and install all project dependencies, followed by 'pnpm dev' to start the local development server and confirm that the project functions correctly. ```Shell pnpm install pnpm dev ``` -------------------------------- ### Set up Local Development for Axiom and Workflow Builder Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/axiom.md This guide outlines the steps to set up a local development environment for both the Axiom UI library and the Workflow Builder project. It involves cloning repositories, building Axiom, and linking it to Workflow Builder's frontend for live updates. Ensure you do not commit the linking changes. ```Shell # 1. Ensure the Axiom repository is cloned next to the Workflow Builder repository. # 2. Build the distribution files in the Axiom tokens package: pnpm token prepare # 3. Build the distribution files in the Axiom repository and keep the process running for live updates: pnpm ui dev # 4. Update the Axiom dependency in apps/frontend/package.json to a local link: # Locate the line with "@synergycodes/axiom" and change it to: # "@synergycodes/axiom": "link:../../../axiom/packages/ui" # 5. In apps/frontend/src/global.css, replace the Axiom tokens import path: # Replace: @import '@synergycodes/axiom/tokens.css'; # With: @import '../../../../axiom/packages/ui/dist/tokens.css'; # 6. If issues persist, refresh dependencies: pnpm install ``` -------------------------------- ### Add Repository to Bitbucket for Workflow Builder Project Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md This step directs users to an external guide for adding a new repository to Bitbucket, ensuring proper infrastructure setup. It also notes that database-related files can be removed if not required by the implementation. ```Text Follow the steps from this instruction: https://synergiapro.atlassian.net/wiki/spaces/ENG/pages/3516760077/Dodawanie+projektu+-+repozytorium+infrastructure If your implementation doesn't require a database, you can delete the related files (check closed PRs to see how others are handling it). ``` -------------------------------- ### Deployment Setup (To Be Updated) Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md This section is a placeholder that will be updated with detailed deployment instructions once current deployment issues are fully resolved and a stable process is established. ```Text `TODO:` This section should be updated after the deployment issues are resolved. ``` -------------------------------- ### Install Workflow Builder Project Dependencies with pnpm Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/README.md This command installs all necessary project dependencies from the root directory using pnpm. It ensures all packages defined in the monorepo are correctly linked and installed, preparing the project for development. ```Shell pnpm i ``` -------------------------------- ### Commit and Push Initial Project Setup Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md Commit all changes with a clear and descriptive message, then push the branch to the remote repository. A well-articulated commit message is crucial for future reference and project history. ```Text Name your commit clearly (the message will remain visible for many files that may never change), and push it. :) ``` -------------------------------- ### Create npm Package.json for Web Component Distribution Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/web-component-wrapper.decision-log.md This snippet provides an example package.json file to be placed inside the dist/package folder after building the project. It defines the package's metadata, entry points for ES and UMD modules, peer dependencies (React, React DOM), and the files to be included in the npm package, enabling its distribution and consumption. ```json { "name": "workflow-builder", "version": "1.0.0", "description": "Workflow Builder app", "main": "workflow-builder.umd.js", "module": "workflow-builder.es.js", "style": "frontend.css", "author": "SynergyCodes", "peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" }, "dependencies": {}, "files": [ "workflow-builder.umd.js", "workflow-builder.es.js", "frontend.css" ] } ``` -------------------------------- ### Generate Icons via pnpm Install Command Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/icons/README.md After updating icon sources, execute `pnpm i` in your terminal to trigger the icon generation process. This command activates the `@workflow-builder/icons` package's `prepare` script, which runs the `generate-icons` script to create or update `icons.gen.ts` and associated icon chunks. ```shell pnpm i ``` -------------------------------- ### Start Workflow Builder Application in Development Mode Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/README.md This command starts the Workflow Builder application in development mode. It typically launches the frontend and any other necessary services, allowing developers to work on the application locally. ```Shell pnpm dev ``` -------------------------------- ### Example Translation JSON File (English) Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/i18n/i18next.decision-log.md This is an example of a JSON file used by i18next to store English translations. It demonstrates a simple key-value structure for different UI texts. ```JSON { "welcomeMessage": "Welcome to Workflow Builder!", "description": "This application helps you build and manage workflows.", "greeting": "Hello, {{name}}!" } ``` -------------------------------- ### JSON Schema Conditional Validation Example with if/then/else Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-validation.decision-log.md This JSON Schema example demonstrates how to implement conditional validation using if/else/then constructs. It ensures that specific fields are required and validated only when certain conditions are met within the data itself, completely independent of whether those fields are visible or enabled in the UI. This approach aligns with the principle of separating validation concerns from UI rendering logic. ```JSON Schema { "type": "object", "properties": { "paymentMethod": { "type": "string", "enum": ["creditCard", "paypal"] }, "cardNumber": { "type": "string" }, "paypalEmail": { "type": "string", "format": "email" } }, "if": { "properties": { "paymentMethod": { "const": "creditCard" } } }, "then": { "required": ["cardNumber"], "properties": { "cardNumber": { "pattern": "^[0-9]{16}$", "description": "Credit card number (16 digits)" } } }, "else": { "if": { "properties": { "paymentMethod": { "const": "paypal" } } }, "then": { "required": ["paypalEmail"], "properties": { "paypalEmail": { "description": "PayPal email address" } } } } } ``` -------------------------------- ### Use i18next with React Hooks for Translations Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/i18n/i18next.decision-log.md This example shows how to use the 'useTranslation' hook from 'react-i18next' within a React functional component to access translated strings and change the application language dynamically. ```JavaScript import React from 'react'; import { useTranslation } from 'react-i18next'; function MyComponent() { const { t, i18n } = useTranslation(); const changeLanguage = (lng) => { i18n.changeLanguage(lng); }; return (

{t('welcomeMessage')}

{t('description')}

); } export default MyComponent; ``` -------------------------------- ### Copy Workflow Builder Content to New Repository Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md Open the existing WorkflowBuilder project, fetch its latest 'master' branch, and then copy all contents of its directory into the newly cloned repository for the new project. ```Text Open WorkflowBuilder, fetch the latest master branch, and copy the contents of the WorkflowBuilder directory to the new repository. ``` -------------------------------- ### Update Pipeline References for New Repository Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md Navigate to the 'tools' directory and replace all occurrences of 'generic-workflow-editor' with the specific name of your new repository. This ensures that pipeline processes correctly reference the new project. ```Text Find all `generic-workflow-editor` in the `tools` directory and replace them with the name of your repository. ``` -------------------------------- ### Configure Development Branches for New Repository Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md Before pushing, create a 'master' branch to be set as the main branch and establish a development branch, mirroring the branching strategy used in the WorkflowBuilder repository. ```Text Create a new branch `master`, which will be set as the main branch, and set up a development branch, similar to the WorkflowBuilder repository. Don't push it yet. ``` -------------------------------- ### Configure Vite for Web Component Library Mode Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/web-component-wrapper.decision-log.md This snippet shows how to adjust the vite.config.mts file to configure Vite for library mode. This configuration is crucial for bundling the Web Component as an npm package, specifying the entry point, output name, file formats (es, umd), and output directory for distribution. ```typescript export default defineConfig(({ mode }) => ({ //... build: { lib: { entry: path.resolve(__dirname, './src/main.tsx'), name: 'WorkflowBuilder', fileName: (format) => `workflow-builder.${format}.js`, formats: ['es', 'umd'], }, outDir: 'dist/package', }, define: { 'process.env.NODE_ENV': JSON.stringify( process.env.NODE_ENV || 'development', ), }, //... })); ``` -------------------------------- ### Grant Developer Access to New Project Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md Contact the infrastructure team or responsible personnel to request and ensure that all other developers working on the project are granted the necessary access permissions to the new repository. ```Text Ask the people responsible for infrastructure to grant access to other developers on your project. ``` -------------------------------- ### Remove Default Workflow Builder Plugins Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md Locate the 'plugins' directory within the project, remove all existing plugins, and then restart the project. This process helps identify and remove any dependent imports that might cause build failures. ```Text Find the `plugins` directory, remove all plugins, restart the project, and check what failed (probably two imports need to be removed, do that). Check repository again. ``` -------------------------------- ### Override Default Axiom Styles with Figma Tokens Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/docs/setup.md If design provides Figma tokens, utilize the 'variables2css' plugin to generate custom CSS. This allows replacing the default '@synergycodes/axiom/tokens.css' import with a local './tokens.css' file, enabling project-specific styling and theme adjustments. ```CSS If the design team gave you access to figma with tokens, override the default ones from Axiom. Use `variables2css` plugin, after generating tokens you should be able to remove `@import '@synergycodes/axiom/tokens.css';` and add your `./tokens.css`. You can check `[theme="Light"]` and convert `Light` -> `light` and `Dark` to `dark` if needed. ``` -------------------------------- ### Implement Custom Control Component for JSONForm Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-generation.md This snippet illustrates the implementation of a custom control component for JSONForms. It demonstrates using `` to handle shared control logic and rendering an `` component. This component will be rendered based on the UISchema definition for a 'Text' control. ```typescriptreact const TextControl = (props: TextControlProps) => { //... return ( ); }; ``` -------------------------------- ### Configure New Icon Sources in generate-icons Script Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/icons/README.md To expand the set of available icons, modify the `ICON_SOURCES` array in the `generate-icons` script. Add new objects specifying the `path` to directories containing SVG icon files. This allows the icon generation process to include assets from custom locations or external `node_modules` packages. ```typescript const ICON_SOURCES: IconSource[] = [ //... { path: '../../../assets/icons/', }, { path: '../../node_modules/some-cool-icons/dist/svg' } ]; ``` -------------------------------- ### Update index.html for Web Component Embedding Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/web-component-wrapper.decision-log.md This snippet modifies the index.html file to replace the original div element with the newly defined workflow-builder custom element. This update enables framework-agnostic integration by allowing the host application to directly use the Web Component, decoupling the React app from a fixed DOM structure. ```html
``` ```html ``` -------------------------------- ### Implement Custom Layout Component for JSONForm Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-generation.md This snippet illustrates the implementation of a custom layout component for JSONForms. It shows how to use `` for shared logic and `renderElements()` to display child components, creating a container like an Accordion to group related form elements visually. ```typescriptreact const AccordionLayout = (props: LayoutProps) => { const { uischema } = props; return (
{renderElements(props)}
); }; ``` -------------------------------- ### Use Custom Control in UISchema Definition Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-generation.md This snippet demonstrates how to integrate a custom control into a UISchema definition. It shows how to map a data property (`description`) to the custom 'Text' control using the `scope` property, along with other UI configurations like `label` and `placeholder` within a layout. ```typescript export const exampleNode: PaletteItem = { // ... uischema: { type: 'VerticalLayout', elements: [ { type: 'Accordion', label: 'General information', elements: [ // Usage of the new control { label: 'Description', type: 'Text', scope: '#/properties/description', placeholder: 'Type your description here...', }, ], }, }, }; ``` -------------------------------- ### Modify main.tsx for Web Component Integration Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/web-component-wrapper.decision-log.md This snippet transforms the React application's entry point (main.tsx) from directly controlling a #root HTML element to encapsulating it within a custom Web Component. This change allows the Workflow Builder to be embedded anywhere without requiring specific DOM modifications in the host application. It defines a WorkflowBuilder custom element that mounts and unmounts the React app. ```typescript const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement, ); root.render( , ); ``` ```typescript class WorkflowBuilder extends HTMLElement { private root: ReactDOM.Root | null = null; connectedCallback() { if (!this.root) { const container = document.createElement('div'); this.appendChild(container); this.root = ReactDOM.createRoot(container); this.root.render( , ); } } disconnectedCallback() { if (this.root) { this.root.unmount(); this.root = null; } } } customElements.define('workflow-builder', WorkflowBuilder); ``` -------------------------------- ### Commit Generated Icon Files to Version Control Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/icons/README.md Following the icon generation, it is crucial to commit the newly created or modified `icons.gen.ts` file to your version control system. This ensures that the updated icon API and types are tracked and available for other developers and deployment environments. ```shell git commit -m "feat: generate new icons" ``` -------------------------------- ### Use React Icons from @workflow-builder/icons Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/icons/README.md To integrate an icon into your React component, import the `Icon` component from `@workflow-builder/icons`. Pass the desired icon's `name` as a prop to render it. Additional props can be provided and their types extended directly within the icon's definition file for enhanced flexibility. ```typescriptreact import { Icon } from "@workflow-builder/icons"; ``` -------------------------------- ### Configure i18next for React Applications Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/i18n/i18next.decision-log.md This snippet demonstrates the basic configuration for i18next in a React application, integrating 'react-i18next' and 'i18next-browser-languagedetector'. It sets up translation file loading, language detection order, and caching in localStorage. ```JavaScript import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import enTranslation from './locales/en/translation.json'; import esTranslation from './locales/es/translation.json'; i18n .use(LanguageDetector) .use(initReactI18next) .init({ resources: { en: { translation: enTranslation }, es: { translation: esTranslation } }, fallbackLng: 'en', debug: true, detection: { order: ['querystring', 'cookie', 'localStorage', 'navigator'], caches: ['localStorage'] }, interpolation: { escapeValue: false // react already escapes by default } }); export default i18n; ``` -------------------------------- ### JSONForms Rules for Dynamic UI Element Visibility Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-generation.md This section refers to the official JSONForms documentation on rules. Rules are used to dynamically control the visibility and enabled/disabled state of form elements based on data conditions, providing dynamic UI behavior within the properties sidebar. ```APIDOC Rules are used to dynamically toggle visibility of form elements and make them disabled or enabled. This part of JSONForms library is used as it is. Get to know more in the official documentation: https://jsonforms.io/docs/uischema/rules ``` -------------------------------- ### JSONSchema Specification Reference for Node Data Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-generation.md This section provides a reference to the official JSONSchema specification. JSONSchema is used to define the shape of node data, including property types, validation rules, and required fields, ensuring data integrity and consistency for the dynamic properties sidebar. ```APIDOC JSONSchema is used to define the shape of node data, including property types, validation, and required fields. Refer to the official JSONSchema specification for detailed information: https://json-schema.org/ ``` -------------------------------- ### Define Node Data Schema with JSONSchema Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-generation.md This snippet demonstrates how to define the structure and validation rules for node data using JSONSchema. It specifies property types, validation constraints like minimum/maximum for numbers, and required fields. The `PaletteItem['schema']` must include `title` and `subtitle` as default properties for all nodes. ```typescriptreact export const exampleNode: PaletteItem = { // ... schema: { properties: { title: { type: 'string', }, subtitle: { type: 'string', }, age: { type: 'number', minimum: 1, multipleOf: 1, maximum: 100, }, }, required: ['firstName', 'secondName'], }, }; ``` -------------------------------- ### ReactFlow onSelectionChange Callback API Reference Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/properties-bar/selection.decison-log.md Documents the `onSelectionChange` callback provided by ReactFlow, which is triggered upon selection changes. This API reference highlights its parameters, return type, and the known limitation regarding potentially outdated object references. ```APIDOC { "name": "onSelectionChange", "type": "function", "description": "Callback function triggered when the selection of nodes or edges changes in ReactFlow.", "parameters": [ { "name": "params", "type": "object", "description": "Object containing arrays of selected nodes and edges.", "properties": [ { "name": "nodes", "type": "Node[]", "description": "Array of currently selected Node objects. Note: These objects may be outdated if underlying node data has changed." }, { "name": "edges", "type": "Edge[]", "description": "Array of currently selected Edge objects. Note: These objects may be outdated if underlying edge data has changed." } ] } ], "returns": { "type": "void", "description": "Does not return a value." }, "notes": "Due to potential outdated references, it's recommended to store only IDs in an external state management system (e.g., Zustand) and retrieve full objects from the current ReactFlow state." } ``` -------------------------------- ### Define Custom Control Types for JSONForm UI Components Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-generation.md This snippet shows how to define custom types for new UI controls within JSONForms. It includes the UISchema element type and the corresponding control props, extending base types like `ControlElement` and `InputProps` to specify control-specific properties such as `inputType` and `placeholder`. ```typescriptreact export type TextControlElement = Override< ControlElement, { type: 'Text'; inputType?: string; } & Pick >; export type TextControlProps = ControlProps; ``` -------------------------------- ### Define Custom Layout Types for JSONForm UI Containers Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-generation.md This snippet demonstrates how to define custom types for new layout components within JSONForms. It extends `BaseLayoutElement` to specify layout-specific properties like `label` and the layout `type` ('Accordion'), enabling structured grouping of UI elements within the form. ```typescriptreact export type AccordionLayoutElement = Override< BaseLayoutElement, { label: string; type: 'Accordion'; } >; ``` -------------------------------- ### useSingleSelectedElement React Hook API Reference Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/properties-bar/selection.decison-log.md Documents the custom `useSingleSelectedElement` React hook. This API reference details its purpose, parameters, return type, and dependencies, emphasizing its role in providing up-to-date selected element data for UI components. ```APIDOC { "name": "useSingleSelectedElement", "type": "ReactHook", "description": "A custom React hook that computes and returns a single currently selected node or edge from the ReactFlow instance, ensuring the returned object is up-to-date with the latest graph data.", "parameters": [], "returns": { "type": "Node | Edge | null", "description": "Returns the currently selected Node or Edge object, or null if no single element is selected or found. Prioritizes a node if both a node and an edge are selected (configurable logic)." }, "dependencies": [ "ReactFlow (for getNodes, getEdges)", "Zustand (for selectedNodesIds, selectedEdgesIds)" ], "notes": "This hook incorporates a custom comparison mechanism to optimize re-renders. It is primarily used for features like properties sidebars that display details of a single selected item." } ``` -------------------------------- ### Zustand Store for ReactFlow Selection IDs (TypeScript) Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/properties-bar/selection.decison-log.md Defines the structure and update logic for a Zustand store to hold selected node and edge IDs, which are updated by ReactFlow's `onSelectionChange` callback. This ensures consistent and up-to-date selection data. ```TypeScript import { create } from 'zustand'; import { Node, Edge } from 'reactflow'; interface SelectionStore { selectedNodesIds: string[]; selectedEdgesIds: string[]; onSelectionChange: (nodes: Node[], edges: Edge[]) => void; } const useSelectionStore = create((set) => ({ selectedNodesIds: [], selectedEdgesIds: [], onSelectionChange: (nodes, edges) => { set({ selectedNodesIds: nodes.map(node => node.id), selectedEdgesIds: edges.map(edge => edge.id), }); }, })); ``` -------------------------------- ### Register Custom Control Renderer for JSONForms Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/json-form/form-generation.md This snippet shows how to register a custom control component with the JSONForms library. It uses `createControlRenderer()` to associate a control type ('Text') with its corresponding React component, making it available for use in UISchema definitions. The renderer must be included in the main renderers array. ```typescriptreact // ./controls/text-control.tsx export const textControlRenderer = createControlRenderer('Text', TextControl); // ./json-form.tsx const renderers: JsonFormsRendererRegistryEntry[] = [ // ..., textControlRenderer, ]; ``` -------------------------------- ### Dynamically Update HTML Lang Attribute for Accessibility Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/i18n/i18next.decision-log.md This snippet illustrates how to listen for 'languageChanged' events from i18next to dynamically update the 'lang' attribute of the HTML document, improving accessibility for screen readers by indicating the correct document language. ```JavaScript import { useEffect } from 'react'; import i18n from './i18n'; // Assuming i18n instance is exported from a setup file function useDetectLanguageChange() { useEffect(() => { const updateHtmlLang = (lng) => { document.documentElement.setAttribute('lang', lng); }; // Set initial language updateHtmlLang(i18n.language); // Listen for language changes i18n.on('languageChanged', updateHtmlLang); // Cleanup listener on unmount return () => { i18n.off('languageChanged', updateHtmlLang); }; }, []); } // Example usage in a root component or layout: // function App() { // useDetectLanguageChange(); // return (/* ... */); // } ``` -------------------------------- ### React Hook for Single Selected Element Retrieval (TypeScript) Source: https://github.com/workflowbuildersdk/workflowbuilder/blob/main/apps/frontend/src/app/features/properties-bar/selection.decison-log.md A custom React hook (`useSingleSelectedElement`) designed to retrieve a single, up-to-date selected node or edge from the current ReactFlow state. This hook addresses the issue of outdated references from ReactFlow's `onSelectionChange` by re-computing the element based on stored IDs and current graph data. ```TypeScript import { useStore, useReactFlow, Node, Edge } from 'reactflow'; import { shallow } from 'zustand/shallow'; // Define the shape of your Zustand selection store (assuming it's defined elsewhere) interface SelectionState { selectedNodesIds: string[]; selectedEdgesIds: string[]; } // Assume useSelectionStore is your Zustand store hook // const useSelectionStore = create(...); type SelectedElement = Node | Edge | null; const useSingleSelectedElement = (): SelectedElement => { const { getNodes, getEdges } = useReactFlow(); // Get the selected IDs from the Zustand store const { selectedNodesIds, selectedEdgesIds } = useStore( (state: SelectionState) => ({ selectedNodesIds: state.selectedNodesIds, selectedEdgesIds: state.selectedEdgesIds, }), shallow // Use shallow comparison for the selector output ); // Compute the actual selected element from current ReactFlow data const selectedNode = selectedNodesIds.length > 0 ? getNodes().find(node => node.id === selectedNodesIds[0]) : null; const selectedEdge = selectedEdgesIds.length > 0 ? getEdges().find(edge => edge.id === selectedEdgesIds[0]) : null; // Return only one element, prioritizing node if both are selected (example logic) return selectedNode || selectedEdge || null; }; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.