@kwiz/fluentui
Version:
KWIZ common controls for FluentUI
85 lines • 4.98 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Toast, Toaster, ToastTitle, useId, useToastController } from "@fluentui/react-components";
import { GetError, isBoolean } from "@kwiz/common";
import { useCallback, useMemo, useState } from "react";
import { PleaseWait } from "../controls/please-wait";
import { useBlockNav } from "./block-nav";
import { useKWIZFluentContext } from "./context-internal";
import { useEffectOnlyOnMount, useStateEX } from "./hooks";
import { useAlerts } from "./use-alerts";
/* Provides useful helpers for tracking if control has changes, and handling the save changes with progress bar and on success/fail messages. */
export function useTrackChanges({ blockNav } = {}) {
const ctx = useKWIZFluentContext();
const unsavedChangesPrompt = useMemo(() => { var _a, _b; return ((_b = (_a = ctx.strings) === null || _a === void 0 ? void 0 : _a.prompt_unsaved_changes) === null || _b === void 0 ? void 0 : _b.call(_a)) || "You will lose unsaved changes. Continue?"; }, [ctx.strings]);
const alerts = useAlerts();
const [showProgress, setShowProgress] = useState(false);
//we just need it to register the window unload event... no need for its element or onNav we handle it in this element.
const navBlockData = useBlockNav();
const [hasChanges, setHasChanges, hasChangesRef] = useStateEX(false, {
name: "hasChanges", skipUpdateIfSame: true, onChange: (newValue, isValueChanged) => {
if (isValueChanged)
navBlockData.setMessage("useTrackChanges", (blockNav && newValue === true) ? unsavedChangesPrompt : undefined);
return newValue;
}
});
const toasterId = useId("toaster");
const { dispatchToast } = useToastController(toasterId);
const onSaveChanges = useCallback((worker, props) => __awaiter(this, void 0, void 0, function* () {
var _a, _b;
setShowProgress((props === null || props === void 0 ? void 0 : props.waitProps) || true);
let success;
try {
success = yield worker();
}
catch (e) {
success = { success: false, message: `Something went wrong: ${GetError(e)}` };
}
setShowProgress(false);
if (success.success !== true) {
dispatchToast(_jsx(Toast, { children: _jsx(ToastTitle, { children: success.message || ((_b = (_a = ctx.strings) === null || _a === void 0 ? void 0 : _a.error_cannot_save_changes) === null || _b === void 0 ? void 0 : _b.call(_a, { cap: true })) || "Could not save your changes." }) }), { intent: "warning", timeout: 10000 });
}
else {
setHasChanges(false);
//todo: trasnlate
dispatchToast(_jsx(Toast, { children: _jsx(ToastTitle, { children: success.message || "Changes saved!" }) }), { intent: "success", timeout: 2000 });
}
}), useEffectOnlyOnMount);
const doIfNoChanges = useCallback((handler, prompt) => {
if (hasChanges)
alerts.confirmEX(prompt || unsavedChangesPrompt, { okProps: { variant: "danger" } }).then(result => {
if (result) {
setHasChanges(false);
return handler();
}
});
else
return handler();
}, [hasChanges, alerts]);
const trackChanges = useMemo(() => ({
hasChanges,
hasChangesRef,
setHasChanges,
onSaveChanges,
doIfNoChanges
}), [hasChanges, hasChangesRef, setHasChanges, onSaveChanges, doIfNoChanges]);
const trackChangesElement = useMemo(() => (_jsxs(_Fragment, { children: [alerts.alertPrompt, showProgress && _jsx(PleaseWait, Object.assign({}, (isBoolean(showProgress) ? {} : showProgress))), _jsx(Toaster, { toasterId: toasterId })] })), [alerts.alertPrompt, showProgress, toasterId]);
return useMemo(() => ({
trackChanges,
trackChangesElement
}), [trackChanges, trackChangesElement]);
}
/** @deprecated renamed to useTrackChanges */
export function useEditableControl() {
const { trackChanges, trackChangesElement } = useTrackChanges();
return Object.assign(Object.assign({}, trackChanges), { editablePageElement: trackChangesElement });
}
//# sourceMappingURL=use-track-changes.js.map