Canvas: Fix references for ResourcePicker (#95580)

* useRef instead of create ref for functional components, pass function to close popper if needed

* Cleanup, hide on save as well

* add comment about when hidePopper is available to content
This commit is contained in:
Kristina 2024-11-07 11:37:49 -06:00 committed by GitHub
parent d5cde0b60a
commit ac88461fe6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 29 additions and 16 deletions

View File

@ -24,6 +24,7 @@ interface Props extends Omit<React.HTMLAttributes<HTMLDivElement>, 'content'> {
referenceElement: HTMLElement;
wrapperClassName?: string;
renderArrow?: boolean;
hidePopper?: () => void;
}
export function Popover({
@ -34,6 +35,7 @@ export function Popover({
wrapperClassName,
referenceElement,
renderArrow,
hidePopper,
...rest
}: Props) {
const theme = useTheme2();
@ -95,7 +97,7 @@ export function Popover({
{renderArrow && <FloatingArrow fill={theme.colors.border.weak} ref={arrowRef} context={context} />}
{typeof content === 'string' && content}
{React.isValidElement(content) && React.cloneElement(content)}
{typeof content === 'function' && content({})}
{typeof content === 'function' && content({ hidePopper })}
</div>
</div>
</Portal>

View File

@ -7,8 +7,11 @@ export interface PopoverContentProps {
* It will be removed in a future release.
*/
updatePopperPosition?: () => void;
hidePopper?: () => void;
}
// hidePopper is only available to popover content when it is passed as a function
export type PopoverContent = string | React.ReactElement | ((props: PopoverContentProps) => JSX.Element);
export type TooltipPlacement = Placement | 'auto' | 'auto-start' | 'auto-end';

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css';
import { createRef } from 'react';
import { useRef } from 'react';
import * as React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
@ -42,16 +42,19 @@ export const ResourcePicker = (props: Props) => {
const styles = useStyles2(getStyles);
const theme = useTheme2();
const pickerTriggerRef = createRef<HTMLDivElement>();
const popoverElement = (
<ResourcePickerPopover
onChange={onChange}
value={value}
mediaType={mediaType}
folderName={folderName}
maxFiles={maxFiles}
/>
);
const pickerTriggerRef = useRef<HTMLDivElement>(null);
const popoverElement = (props: { hidePopper?: () => void }) => {
return (
<ResourcePickerPopover
onChange={onChange}
value={value}
mediaType={mediaType}
folderName={folderName}
maxFiles={maxFiles}
hidePopper={props.hidePopper}
/>
);
};
let sanitizedSrc = src;
if (!sanitizedSrc && value) {
@ -101,6 +104,7 @@ export const ResourcePicker = (props: Props) => {
onKeyDown={(event) => {
closePopover(event, hidePopper);
}}
hidePopper={hidePopper}
/>
)}

View File

@ -2,7 +2,7 @@ import { css } from '@emotion/css';
import { useDialog } from '@react-aria/dialog';
import { FocusScope } from '@react-aria/focus';
import { useOverlay } from '@react-aria/overlays';
import { createRef, useState } from 'react';
import { useRef, useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
@ -21,20 +21,22 @@ interface Props {
mediaType: MediaType;
folderName: ResourceFolderName;
maxFiles?: number;
hidePopper?: () => void;
}
interface ErrorResponse {
message: string;
}
export const ResourcePickerPopover = (props: Props) => {
const { value, onChange, mediaType, folderName, maxFiles } = props;
const { value, onChange, mediaType, folderName, maxFiles, hidePopper } = props;
const styles = useStyles2(getStyles);
const onClose = () => {
onChange(value);
hidePopper?.();
};
const ref = createRef<HTMLElement>();
const ref = useRef<HTMLElement>(null);
const { dialogProps } = useDialog({}, ref);
const { overlayProps } = useOverlay({ onClose, isDismissable: true, isOpen: true }, ref);
@ -124,11 +126,13 @@ export const ResourcePickerPopover = (props: Props) => {
getBackendSrv()
.get(`api/storage/read/${data.path}`)
.then(() => setNewValue(`${config.appUrl}api/storage/read/${data.path}`))
.then(() => onChange(`${config.appUrl}api/storage/read/${data.path}`));
.then(() => onChange(`${config.appUrl}api/storage/read/${data.path}`))
.then(() => hidePopper?.());
})
.catch((err) => console.error(err));
} else {
onChange(newValue);
hidePopper?.();
}
}}
>