@blocknote/react
Version:
A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.
71 lines (63 loc) • 2.27 kB
text/typescript
import { User } from "@blocknote/core";
import {
VersioningExtension,
VersionSnapshot,
} from "@blocknote/core/extensions";
import { useEffect } from "react";
import { useExtension } from "../../hooks/useExtension.js";
import { useStore } from "../../hooks/useStore.js";
/**
* Reads users from the versioning extension's user store, loading any that
* aren't cached yet. Re-renders only when one of the requested users changes
* (the store uses a shallow `Map` comparison).
*
* Versioning-scoped: it reads the store the {@link VersioningExtension} builds
* from its `resolveUsers` option and exposes on its instance, so it must be
* used within a versioning UI where that extension is registered.
*/
export function useVersionUsers<U extends User = User>(
userIds: string[],
): Map<string, U> {
const { userStore } = useExtension(VersioningExtension);
// `userIds` is often a fresh array each render, so key the effect on its
// contents rather than its identity to avoid re-loading on every render.
const userIdsKey = userIds.join(",");
useEffect(() => {
void userStore.loadUsers(userIds);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [userStore, userIdsKey]);
return useStore(userStore.store, (state) => {
const users = new Map<string, U>();
for (const id of userIds) {
const user = state.get(id) as U | undefined;
if (user) {
users.set(id, user);
}
}
return users;
});
}
/**
* Computes the secondary label to display for a snapshot row: the snapshot's
* explicit `secondaryLabel` when set, otherwise its `by` author ids resolved
* to usernames (falling back to the raw id for users the store can't
* resolve). Reactive: re-renders as user info loads into the store.
*/
export function useSnapshotLabel(
snapshot: VersionSnapshot | undefined,
): string | undefined {
const byIds =
snapshot?.by === undefined
? []
: Array.isArray(snapshot.by)
? snapshot.by
: [snapshot.by];
const users = useVersionUsers(byIds);
if (snapshot?.secondaryLabel !== undefined) {
return snapshot.secondaryLabel;
}
if (byIds.length === 0) {
return undefined;
}
return byIds.map((id) => users.get(id)?.username ?? id).join(", ");
}