@grafana/ui
Version:
Grafana Components Library
104 lines (101 loc) • 3.27 kB
JavaScript
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import { css } from '@emotion/css';
import { debounce } from 'lodash';
import * as React from 'react';
import { useRef, useCallback, useMemo } from 'react';
import { Trans } from '@grafana/i18n';
import { useStyles2 } from '../../themes/ThemeContext.mjs';
import { Field } from '../Forms/Field.mjs';
import { InlineToast } from '../InlineToast/InlineToast.mjs';
import { EllipsisAnimated } from './EllipsisAnimated.mjs';
"use strict";
const SHOW_SUCCESS_DURATION = 2 * 1e3;
function AutoSaveField(props) {
const {
invalid,
loading,
onFinishChange,
saveErrorMessage = "Error saving this value",
error,
children,
disabled,
...restProps
} = props;
const [fieldState, setFieldState] = React.useState({
isLoading: false,
showSuccess: false,
showError: invalid
});
const fieldRef = useRef(null);
React.useEffect(() => {
let timeoutId;
if (fieldState.showSuccess) {
const time = fieldState.showError ? 0 : SHOW_SUCCESS_DURATION;
timeoutId = setTimeout(() => {
setFieldState({ ...fieldState, showSuccess: false });
}, time);
}
return () => {
window.clearTimeout(timeoutId);
};
}, [fieldState]);
const handleChange = useCallback(
(nextValue) => {
if (invalid) {
return;
}
setFieldState({ ...fieldState, isLoading: true, showSuccess: false });
onFinishChange(nextValue).then(() => {
setFieldState({
isLoading: false,
showSuccess: true,
showError: false
});
}).catch(() => {
setFieldState({
...fieldState,
isLoading: false,
showError: true
});
});
},
[invalid, fieldState, onFinishChange]
);
const lodashDebounce = useMemo(() => debounce(handleChange, 600, { leading: false }), [handleChange]);
const isInvalid = invalid || fieldState.showError || void 0;
const styles = useStyles2(getStyles);
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(
Field,
{
...restProps,
loading: loading || void 0,
invalid: isInvalid,
disabled,
error: error || fieldState.showError && saveErrorMessage,
ref: fieldRef,
className: styles.widthFitContent,
children: React.cloneElement(
children((newValue) => {
lodashDebounce(newValue);
})
)
}
),
fieldState.isLoading && /* @__PURE__ */ jsx(InlineToast, { referenceElement: fieldRef.current, placement: "right", children: /* @__PURE__ */ jsxs(Trans, { i18nKey: "grafana-ui.auto-save-field.saving", children: [
"Saving ",
/* @__PURE__ */ jsx(EllipsisAnimated, {})
] }) }),
fieldState.showSuccess && /* @__PURE__ */ jsx(InlineToast, { suffixIcon: "check", referenceElement: fieldRef.current, placement: "right", children: /* @__PURE__ */ jsx(Trans, { i18nKey: "grafana-ui.auto-save-field.saved", children: "Saved!" }) })
] });
}
AutoSaveField.displayName = "AutoSaveField";
const getStyles = () => {
return {
widthFitContent: css({
width: "fit-content"
})
};
};
export { AutoSaveField };
//# sourceMappingURL=AutoSaveField.mjs.map