/** * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { ReactNode } from "react"; import React, { useState } from "react"; import type { TooltipProps } from "./tooltip"; import { Tooltip } from "./tooltip"; import { isReactNode } from "@k8slens/utilities"; import uniqueId from "lodash/uniqueId"; import type { SingleOrMany } from "@k8slens/utilities"; export interface TooltipDecoratorProps { tooltip?: ReactNode | Omit; /** * forces tooltip to detect the target's parent for mouse events. This is * useful for displaying tooltips even when the target is "disabled" */ tooltipOverrideDisabled?: boolean; id?: string; children?: SingleOrMany; } export function withTooltip( Target: TargetProps extends Pick ? React.FunctionComponent : never, ): React.FunctionComponent { const DecoratedComponent = (props: TargetProps & TooltipDecoratorProps) => { // TODO: Remove side-effect to allow deterministic unit testing const [defaultTooltipId] = useState(uniqueId("tooltip_target_")); let { id: targetId, children: targetChildren } = props; const { tooltip, tooltipOverrideDisabled, id: _unusedId, children: _unusedTargetChildren, ...targetProps } = props; if (tooltip) { const tooltipProps: TooltipProps = { targetId: targetId || defaultTooltipId, tooltipOnParentHover: tooltipOverrideDisabled, formatters: { narrow: true }, ...(isReactNode(tooltip) ? { children: tooltip } : tooltip), }; targetId = tooltipProps.targetId; targetChildren = ( <>
{targetChildren}
); } return ( {targetChildren} ); }; DecoratedComponent.displayName = `withTooltip(${Target.displayName || Target.name})`; return DecoratedComponent; }