mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
d5cde0b60a
commit
ac88461fe6
@ -24,6 +24,7 @@ interface Props extends Omit<React.HTMLAttributes<HTMLDivElement>, 'content'> {
|
|||||||
referenceElement: HTMLElement;
|
referenceElement: HTMLElement;
|
||||||
wrapperClassName?: string;
|
wrapperClassName?: string;
|
||||||
renderArrow?: boolean;
|
renderArrow?: boolean;
|
||||||
|
hidePopper?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Popover({
|
export function Popover({
|
||||||
@ -34,6 +35,7 @@ export function Popover({
|
|||||||
wrapperClassName,
|
wrapperClassName,
|
||||||
referenceElement,
|
referenceElement,
|
||||||
renderArrow,
|
renderArrow,
|
||||||
|
hidePopper,
|
||||||
...rest
|
...rest
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
@ -95,7 +97,7 @@ export function Popover({
|
|||||||
{renderArrow && <FloatingArrow fill={theme.colors.border.weak} ref={arrowRef} context={context} />}
|
{renderArrow && <FloatingArrow fill={theme.colors.border.weak} ref={arrowRef} context={context} />}
|
||||||
{typeof content === 'string' && content}
|
{typeof content === 'string' && content}
|
||||||
{React.isValidElement(content) && React.cloneElement(content)}
|
{React.isValidElement(content) && React.cloneElement(content)}
|
||||||
{typeof content === 'function' && content({})}
|
{typeof content === 'function' && content({ hidePopper })}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Portal>
|
</Portal>
|
||||||
|
@ -7,8 +7,11 @@ export interface PopoverContentProps {
|
|||||||
* It will be removed in a future release.
|
* It will be removed in a future release.
|
||||||
*/
|
*/
|
||||||
updatePopperPosition?: () => void;
|
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 PopoverContent = string | React.ReactElement | ((props: PopoverContentProps) => JSX.Element);
|
||||||
|
|
||||||
export type TooltipPlacement = Placement | 'auto' | 'auto-start' | 'auto-end';
|
export type TooltipPlacement = Placement | 'auto' | 'auto-start' | 'auto-end';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { createRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
@ -42,16 +42,19 @@ export const ResourcePicker = (props: Props) => {
|
|||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
|
|
||||||
const pickerTriggerRef = createRef<HTMLDivElement>();
|
const pickerTriggerRef = useRef<HTMLDivElement>(null);
|
||||||
const popoverElement = (
|
const popoverElement = (props: { hidePopper?: () => void }) => {
|
||||||
|
return (
|
||||||
<ResourcePickerPopover
|
<ResourcePickerPopover
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
value={value}
|
value={value}
|
||||||
mediaType={mediaType}
|
mediaType={mediaType}
|
||||||
folderName={folderName}
|
folderName={folderName}
|
||||||
maxFiles={maxFiles}
|
maxFiles={maxFiles}
|
||||||
|
hidePopper={props.hidePopper}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
let sanitizedSrc = src;
|
let sanitizedSrc = src;
|
||||||
if (!sanitizedSrc && value) {
|
if (!sanitizedSrc && value) {
|
||||||
@ -101,6 +104,7 @@ export const ResourcePicker = (props: Props) => {
|
|||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
closePopover(event, hidePopper);
|
closePopover(event, hidePopper);
|
||||||
}}
|
}}
|
||||||
|
hidePopper={hidePopper}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
|||||||
import { useDialog } from '@react-aria/dialog';
|
import { useDialog } from '@react-aria/dialog';
|
||||||
import { FocusScope } from '@react-aria/focus';
|
import { FocusScope } from '@react-aria/focus';
|
||||||
import { useOverlay } from '@react-aria/overlays';
|
import { useOverlay } from '@react-aria/overlays';
|
||||||
import { createRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { getBackendSrv } from '@grafana/runtime';
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
@ -21,20 +21,22 @@ interface Props {
|
|||||||
mediaType: MediaType;
|
mediaType: MediaType;
|
||||||
folderName: ResourceFolderName;
|
folderName: ResourceFolderName;
|
||||||
maxFiles?: number;
|
maxFiles?: number;
|
||||||
|
hidePopper?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ErrorResponse {
|
interface ErrorResponse {
|
||||||
message: string;
|
message: string;
|
||||||
}
|
}
|
||||||
export const ResourcePickerPopover = (props: Props) => {
|
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 styles = useStyles2(getStyles);
|
||||||
|
|
||||||
const onClose = () => {
|
const onClose = () => {
|
||||||
onChange(value);
|
onChange(value);
|
||||||
|
hidePopper?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
const ref = createRef<HTMLElement>();
|
const ref = useRef<HTMLElement>(null);
|
||||||
const { dialogProps } = useDialog({}, ref);
|
const { dialogProps } = useDialog({}, ref);
|
||||||
const { overlayProps } = useOverlay({ onClose, isDismissable: true, isOpen: true }, ref);
|
const { overlayProps } = useOverlay({ onClose, isDismissable: true, isOpen: true }, ref);
|
||||||
|
|
||||||
@ -124,11 +126,13 @@ export const ResourcePickerPopover = (props: Props) => {
|
|||||||
getBackendSrv()
|
getBackendSrv()
|
||||||
.get(`api/storage/read/${data.path}`)
|
.get(`api/storage/read/${data.path}`)
|
||||||
.then(() => setNewValue(`${config.appUrl}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));
|
.catch((err) => console.error(err));
|
||||||
} else {
|
} else {
|
||||||
onChange(newValue);
|
onChange(newValue);
|
||||||
|
hidePopper?.();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user