UNPKG

@kwiz/fluentui

Version:
85 lines 4.98 kB
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