From a61b8e2f7272ad36b8bcac874fcbe5fbed9fb477 Mon Sep 17 00:00:00 2001 From: Hayleigh Thompson Date: Tue, 3 Dec 2024 13:53:00 +0100 Subject: [PATCH 01/13] :memo: --- apps/example-apps/package.json | 2 + .../tutorials/components/tooltip/App.tsx | 62 ++++ .../tooltip/components/base-node.tsx | 19 + .../tooltip/components/tooltip-node.tsx | 41 +++ .../components/tooltip/dependencies.json | 1 + .../tutorials/components/tooltip/index.css | 64 ++++ .../tutorials/components/tooltip/index.html | 70 ++++ .../tutorials/components/tooltip/index.tsx | 9 + .../tutorials/components/tooltip/lib/utils.ts | 6 + .../widgets/remote-code-viewer/index.tsx | 9 +- pnpm-lock.yaml | 12 +- .../img/tutorials/components/base-node.png | Bin 0 -> 229103 bytes .../src/pages/learn/tutorials/_meta.ts | 2 + ...ing-started-with-react-flow-components.mdx | 338 ++++++++++++++++++ 14 files changed, 628 insertions(+), 7 deletions(-) create mode 100644 apps/example-apps/react/tutorials/components/tooltip/App.tsx create mode 100644 apps/example-apps/react/tutorials/components/tooltip/components/base-node.tsx create mode 100644 apps/example-apps/react/tutorials/components/tooltip/components/tooltip-node.tsx create mode 100644 apps/example-apps/react/tutorials/components/tooltip/dependencies.json create mode 100644 apps/example-apps/react/tutorials/components/tooltip/index.css create mode 100644 apps/example-apps/react/tutorials/components/tooltip/index.html create mode 100644 apps/example-apps/react/tutorials/components/tooltip/index.tsx create mode 100644 apps/example-apps/react/tutorials/components/tooltip/lib/utils.ts create mode 100644 sites/reactflow.dev/public/img/tutorials/components/base-node.png create mode 100644 sites/reactflow.dev/src/pages/learn/tutorials/getting-started-with-react-flow-components.mdx diff --git a/apps/example-apps/package.json b/apps/example-apps/package.json index 6d5c4bd7f..39d737cf5 100644 --- a/apps/example-apps/package.json +++ b/apps/example-apps/package.json @@ -32,6 +32,7 @@ "@threlte/core": "^7.3.1", "@xyflow/react": "^12.3.2", "@xyflow/svelte": "^0.1.21", + "clsx": "^2.1.1", "d3-drag": "^3.0.0", "d3-force": "^3.0.0", "d3-hierarchy": "^3.1.2", @@ -49,6 +50,7 @@ "styled-components": "^6.1.13", "svelte": "^4.2.19", "svelte-feather-icons": "^4.1.0", + "tailwind-merge": "^2.5.4", "twind": "^0.16.19", "webcola": "^3.4.0", "zustand": "5.0.0" diff --git a/apps/example-apps/react/tutorials/components/tooltip/App.tsx b/apps/example-apps/react/tutorials/components/tooltip/App.tsx new file mode 100644 index 000000000..e71bd0944 --- /dev/null +++ b/apps/example-apps/react/tutorials/components/tooltip/App.tsx @@ -0,0 +1,62 @@ +import React, { useCallback } from 'react'; +import { + ReactFlow, + type Node, + type Edge, + type OnConnect, + Position, + addEdge, + useNodesState, + useEdgesState, +} from '@xyflow/react'; + +import '@xyflow/react/dist/style.css'; + +import { TooltipNode } from './components/tooltip-node'; + +const nodeTypes = { + tooltip: TooltipNode, +}; + +const initialNodes: Node[] = [ + { + id: '1', + position: { x: 0, y: 0 }, + data: { + label: 'Hover me', + tooltip: { + label: 'Boo!', + position: Position.Bottom, + }, + }, + type: 'tooltip', + }, +]; + +const initialEdges: Edge[] = []; + +function Flow() { + const [nodes, , onNodesChange] = useNodesState(initialNodes); + const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); + + const onConnect: OnConnect = (params) => { + setEdges((edges) => addEdge(params, edges)); + }; + + return ( +
+ +
+ ); +} +export function App() { + return ; +} diff --git a/apps/example-apps/react/tutorials/components/tooltip/components/base-node.tsx b/apps/example-apps/react/tutorials/components/tooltip/components/base-node.tsx new file mode 100644 index 000000000..08e5c5782 --- /dev/null +++ b/apps/example-apps/react/tutorials/components/tooltip/components/base-node.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { cn } from '../lib/utils'; + +export const BaseNode = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & { selected?: boolean } +>(({ className, selected, ...props }, ref) => ( +
+)); +BaseNode.displayName = 'BaseNode'; diff --git a/apps/example-apps/react/tutorials/components/tooltip/components/tooltip-node.tsx b/apps/example-apps/react/tutorials/components/tooltip/components/tooltip-node.tsx new file mode 100644 index 000000000..3844af16c --- /dev/null +++ b/apps/example-apps/react/tutorials/components/tooltip/components/tooltip-node.tsx @@ -0,0 +1,41 @@ +import React, { useState } from 'react'; +import { + type Node, + type NodeProps, + type NodeToolbarProps, + NodeToolbar, + Handle, + Position, +} from '@xyflow/react'; +import { BaseNode } from './base-node'; + +export type TooltipNodeType = Node<{ + label: string; + tooltip?: { + label: string; + position?: NodeToolbarProps['position']; + }; +}>; + +export function TooltipNode({ data, selected }: NodeProps) { + const [isTooltipVisible, setTooltipVisible] = useState(false); + + return ( + setTooltipVisible(true)} + onMouseLeave={() => setTooltipVisible(false)} + selected={selected} + > + + {data.tooltip?.label} + +
{data.label}
+ + +
+ ); +} diff --git a/apps/example-apps/react/tutorials/components/tooltip/dependencies.json b/apps/example-apps/react/tutorials/components/tooltip/dependencies.json new file mode 100644 index 000000000..9029a0f77 --- /dev/null +++ b/apps/example-apps/react/tutorials/components/tooltip/dependencies.json @@ -0,0 +1 @@ +["@xyflow/react", "react-dom", "react", "tailwindcss", "clsx", "tailwind-merge"] diff --git a/apps/example-apps/react/tutorials/components/tooltip/index.css b/apps/example-apps/react/tutorials/components/tooltip/index.css new file mode 100644 index 000000000..b7b0c0fd3 --- /dev/null +++ b/apps/example-apps/react/tutorials/components/tooltip/index.css @@ -0,0 +1,64 @@ +html, +body { + margin: 0; + font-family: sans-serif; +} + +#app { + width: 100vw; + height: 100vh; +} + +:root { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + --ring: 0 0% 3.9%; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + --radius: 0.5rem; +} +.dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 0% 83.1%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; +} diff --git a/apps/example-apps/react/tutorials/components/tooltip/index.html b/apps/example-apps/react/tutorials/components/tooltip/index.html new file mode 100644 index 000000000..dde3f1a9c --- /dev/null +++ b/apps/example-apps/react/tutorials/components/tooltip/index.html @@ -0,0 +1,70 @@ + + + + + + React Flow Example + + + + +
+ + + diff --git a/apps/example-apps/react/tutorials/components/tooltip/index.tsx b/apps/example-apps/react/tutorials/components/tooltip/index.tsx new file mode 100644 index 000000000..ff3636363 --- /dev/null +++ b/apps/example-apps/react/tutorials/components/tooltip/index.tsx @@ -0,0 +1,9 @@ +import { createRoot } from 'react-dom/client'; +import { App } from './App'; + +import './index.css'; + +const container = document.querySelector('#app'); +const root = createRoot(container); + +root.render(); \ No newline at end of file diff --git a/apps/example-apps/react/tutorials/components/tooltip/lib/utils.ts b/apps/example-apps/react/tutorials/components/tooltip/lib/utils.ts new file mode 100644 index 000000000..2819a830d --- /dev/null +++ b/apps/example-apps/react/tutorials/components/tooltip/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/packages/xy-shared/widgets/remote-code-viewer/index.tsx b/packages/xy-shared/widgets/remote-code-viewer/index.tsx index 52eaeb24b..59b9cc7e1 100644 --- a/packages/xy-shared/widgets/remote-code-viewer/index.tsx +++ b/packages/xy-shared/widgets/remote-code-viewer/index.tsx @@ -14,7 +14,6 @@ import { RemoteContent } from '../../components/remote-content'; import { SharedContext } from '../../context/shared-context'; import { CompiledMdx } from '../../types'; - import './style.css'; import { OpenInStackblitz } from './open-in-stackblitz'; import { OpenInCodesandbox } from './open-in-codesandbox'; @@ -26,7 +25,6 @@ const defaultOptions = { readOnly: false, }; - export type RemoteCodeViewerProps = { route: string; framework?: Framework; @@ -52,7 +50,7 @@ export function RemoteCodeViewer({ }: RemoteCodeViewerProps) { const _framework: Framework = framework ?? (process.env.NEXT_PUBLIC_Framework as Framework) ?? 'react'; - + const preview = `${process.env.NEXT_PUBLIC_EXAMPLES_URL}/${_framework}/${route}/index.html`; const isExample = route.includes('examples/'); @@ -92,7 +90,10 @@ export function RemoteCodeViewer({ >