Release v0.1.2
This commit is contained in:
@@ -12,6 +12,7 @@ type DismissibleAlertProps = {
|
||||
compact?: boolean;
|
||||
floating?: boolean;
|
||||
resetKey?: string | number;
|
||||
dismissStorageKey?: string;
|
||||
};
|
||||
|
||||
let floatingAlertRoot: HTMLElement | null = null;
|
||||
@@ -34,6 +35,29 @@ function getFloatingAlertRoot(): HTMLElement | null {
|
||||
return floatingAlertRoot;
|
||||
}
|
||||
|
||||
function resolveDismissStorageKey(dismissStorageKey: string | undefined, resetKey: string | number | undefined): string | null {
|
||||
if (!dismissStorageKey) return null;
|
||||
return `govoplan.alert.dismissed:${dismissStorageKey}:${resetKey ?? "default"}`;
|
||||
}
|
||||
|
||||
function readDismissed(storageKey: string | null): boolean {
|
||||
if (!storageKey || typeof window === "undefined") return false;
|
||||
try {
|
||||
return window.localStorage.getItem(storageKey) === "1";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function writeDismissed(storageKey: string | null): void {
|
||||
if (!storageKey || typeof window === "undefined") return;
|
||||
try {
|
||||
window.localStorage.setItem(storageKey, "1");
|
||||
} catch {
|
||||
// localStorage may be unavailable in private or restricted contexts.
|
||||
}
|
||||
}
|
||||
|
||||
export default function DismissibleAlert({
|
||||
tone = "info",
|
||||
children,
|
||||
@@ -41,16 +65,24 @@ export default function DismissibleAlert({
|
||||
className = "",
|
||||
compact = false,
|
||||
floating = false,
|
||||
resetKey
|
||||
resetKey,
|
||||
dismissStorageKey
|
||||
}: DismissibleAlertProps) {
|
||||
const [visible, setVisible] = useState(true);
|
||||
const storageKey = resolveDismissStorageKey(dismissStorageKey, resetKey);
|
||||
const [alertState, setAlertState] = useState(() => ({ storageKey, visible: !readDismissed(storageKey) }));
|
||||
const visible = alertState.storageKey === storageKey ? alertState.visible : !readDismissed(storageKey);
|
||||
|
||||
useEffect(() => {
|
||||
setVisible(true);
|
||||
}, [resetKey, children]);
|
||||
setAlertState({ storageKey, visible: !readDismissed(storageKey) });
|
||||
}, [storageKey, resetKey, children]);
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
function dismiss() {
|
||||
writeDismissed(storageKey);
|
||||
setAlertState({ storageKey, visible: false });
|
||||
}
|
||||
|
||||
const role = tone === "danger" || tone === "warning" ? "alert" : "status";
|
||||
const alert = (
|
||||
<div
|
||||
@@ -60,7 +92,7 @@ export default function DismissibleAlert({
|
||||
>
|
||||
<div className="alert-message">{children}</div>
|
||||
{dismissible && (
|
||||
<button type="button" className="alert-dismiss" aria-label="Dismiss notice" onClick={() => setVisible(false)}>
|
||||
<button type="button" className="alert-dismiss" aria-label="Dismiss notice" onClick={dismiss}>
|
||||
<X size={16} strokeWidth={2.4} aria-hidden="true" />
|
||||
</button>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user