diff --git a/packages/app/src/components/NodeCanvas.tsx b/packages/app/src/components/NodeCanvas.tsx index 3e171440b..e4150e756 100644 --- a/packages/app/src/components/NodeCanvas.tsx +++ b/packages/app/src/components/NodeCanvas.tsx @@ -46,6 +46,7 @@ import { useSearchGraph } from '../hooks/useSearchGraph'; import Portal from '@atlaskit/portal'; import { zoomSensitivityState } from '../state/settings'; import { MouseIcon } from './MouseIcon'; +import { PortInfo } from './PortInfo'; const styles = css` width: 100vw; @@ -134,60 +135,6 @@ const styles = css` ${nodeStyles} `; -const portInfoBoxStyles = css` - position: absolute; - - padding: 12px; - border-radius: 5px; - background-color: var(--grey-darker); - color: var(--foreground); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); - border: 1px solid var(--grey); - z-index: 1000; - font-size: 12px; - display: flex; - flex-direction: column; - gap: 4px; - - dl { - display: grid; - grid-template-columns: auto 2fr; - flex-direction: column; - margin: 0; - padding: 0; - align-items: center; - column-gap: 16px; - row-gap: 4px; - - dt { - font-weight: bold; - margin: 0; - white-space: nowrap; - padding: 0; - } - - dd { - margin: 0; - padding: 0; - min-width: 200px; - } - - dt.id-title { - grid-column: 1 / span 2; - - .id { - font-family: var(--font-family-monospace); - font-weight: 400; - font-size: 12px; - } - } - - dd.description { - grid-column: 1 / span 2; - } - } -`; - export interface NodeCanvasProps { nodes: ChartNode[]; connections: NodeConnection[]; @@ -225,7 +172,7 @@ export const NodeCanvas: FC = ({ const { clientToCanvasPosition } = useCanvasPositioning(); const setLastMousePosition = useSetRecoilState(lastMousePositionState); - const { refs, floatingStyles, update } = useFloating({ + const { refs, floatingStyles } = useFloating({ placement: 'bottom-end', whileElementsMounted: autoUpdate, middleware: [offset(5), shift({ crossAxis: true })], @@ -734,38 +681,7 @@ export const NodeCanvas: FC = ({ portPositions={nodePortPositions} /> {hoveringPort && hoveringShowPortInfo && ( - -
-
-
- {hoveringPort.definition.title === hoveringPort.definition.id ? ( - hoveringPort.definition.title - ) : ( - - {hoveringPort.definition.title} ({hoveringPort.definition.id}) - - )} -
-
Data Type
-
- {Array.isArray(hoveringPort.definition.dataType) - ? hoveringPort.definition.dataType.join(' or ') - : hoveringPort.definition.dataType} -
- {(hoveringPort.definition as NodeInputDefinition).required && ( - <> -
Required
-
Yes
- - )} - {hoveringPort.definition.description && ( - <> -
{hoveringPort.definition.description}
- - )} -
-
-
+ )} diff --git a/packages/app/src/components/PortInfo.tsx b/packages/app/src/components/PortInfo.tsx new file mode 100644 index 000000000..4ee677624 --- /dev/null +++ b/packages/app/src/components/PortInfo.tsx @@ -0,0 +1,119 @@ +import Portal from '@atlaskit/portal'; +import { css } from '@emotion/react'; +import { + getScalarTypeOf, + type NodeId, + type NodeInputDefinition, + type NodeOutputDefinition, + type PortId, +} from '@ironclad/rivet-core'; +import { type CSSProperties, forwardRef } from 'react'; + +const style = css` + position: absolute; + + padding: 12px; + border-radius: 5px; + background-color: var(--grey-darker); + color: var(--foreground); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); + border: 1px solid var(--grey); + z-index: 1000; + font-size: 12px; + display: flex; + flex-direction: column; + gap: 4px; + + dl { + display: grid; + grid-template-columns: auto 2fr; + flex-direction: column; + margin: 0; + padding: 0; + align-items: center; + column-gap: 16px; + row-gap: 4px; + + dt { + font-weight: bold; + margin: 0; + white-space: nowrap; + padding: 0; + } + + dd { + margin: 0; + padding: 0; + min-width: 200px; + } + + dt.id-title { + grid-column: 1 / span 2; + + .id { + font-family: var(--font-family-monospace); + font-weight: 400; + font-size: 12px; + } + } + + dd.description { + grid-column: 1 / span 2; + } + } +`; + +export const PortInfo = forwardRef< + HTMLDivElement, + { + port: { + nodeId: NodeId; + isInput: boolean; + portId: PortId; + definition: NodeInputDefinition | NodeOutputDefinition; + }; + floatingStyles: CSSProperties; + } +>(({ port, floatingStyles }, ref) => { + const { definition } = port; + const { dataType, title, description, id } = definition; + + let dataTypeDisplay: string = Array.isArray(dataType) ? dataType.join(' or ') : (dataType as string); + + if (port.isInput && ((definition as NodeInputDefinition).coerced ?? true)) { + dataTypeDisplay += ' (coerced)'; + } + + return ( + +
+
+
+ {title === id ? ( + title + ) : ( + + {title} ({id}) + + )} +
+
Data Type
+
{dataTypeDisplay}
+ + {(definition as NodeInputDefinition).required && ( + <> +
Required
+
Yes
+ + )} + + {description && ( + <> +
{description}
+ + )} +
+
+
+ ); +});