67 lines
1.7 KiB
TypeScript
Raw Normal View History

2024-10-21 13:57:45 -06:00
import { colors } from "@/lib/colors"
2024-05-03 14:27:45 -07:00
import {
AwarenessList,
TypedLiveblocksProvider,
UserAwareness,
} from "@/liveblocks.config"
2024-10-21 13:57:45 -06:00
import { useEffect, useMemo, useState } from "react"
2024-05-03 14:27:45 -07:00
2024-05-26 18:04:43 -07:00
export function Cursors({
yProvider,
userInfo,
}: {
yProvider: TypedLiveblocksProvider
userInfo: {
name: string
email: string
color: "red" | "orange" | "yellow" | "green" | "blue" | "purple" | "pink"
}
}) {
2024-05-03 14:27:45 -07:00
// Get user info from Liveblocks authentication endpoint
2024-05-05 14:33:09 -07:00
2024-05-03 14:27:45 -07:00
const [awarenessUsers, setAwarenessUsers] = useState<AwarenessList>([])
useEffect(() => {
// Add user info to Yjs awareness
const localUser: UserAwareness["user"] = userInfo
yProvider.awareness.setLocalStateField("user", localUser)
// On changes, update `awarenessUsers`
function setUsers() {
setAwarenessUsers(
Array.from(yProvider.awareness.getStates()) as AwarenessList
)
}
yProvider.awareness.on("change", setUsers)
setUsers()
return () => {
yProvider.awareness.off("change", setUsers)
}
}, [yProvider])
// Insert awareness info into cursors with styles
const styleSheet = useMemo(() => {
let cursorStyles = ""
for (const [clientId, client] of awarenessUsers) {
if (client?.user) {
cursorStyles += `
.yRemoteSelection-${clientId},
.yRemoteSelectionHead-${clientId} {
2024-05-05 14:33:09 -07:00
--user-color: ${colors[client.user.color]};
2024-05-03 14:27:45 -07:00
}
.yRemoteSelectionHead-${clientId}::after {
content: "${client.user.name}";
}
`
}
}
return { __html: cursorStyles }
}, [awarenessUsers])
return <style dangerouslySetInnerHTML={styleSheet} />
}