1+ import React , {
2+ PropsWithChildren ,
3+ createContext ,
4+ useCallback ,
5+ useState
6+ } from "react" ;
7+
8+ export const EventTypes = {
9+ rowClick : 'rowClick'
10+ } as const ;
11+
12+ export type DataViewEvent = typeof EventTypes [ keyof typeof EventTypes ] ;
13+
14+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15+ type Callback = ( ...args : any [ ] ) => void ;
16+ interface Subscriptions { [ id : string ] : Callback }
17+ type ContextType = { [ event in DataViewEvent ] : Subscriptions } ;
18+ type Subscribe = ( event : DataViewEvent , callback : Callback ) => ( ) => void ;
19+
20+ export const DataViewContext = createContext < {
21+ subscribe : Subscribe ;
22+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23+ trigger : ( event : DataViewEvent , ...payload : any [ ] ) => void ;
24+ } > ( {
25+ subscribe : ( ) => ( ) => null ,
26+ trigger : ( ) => null
27+ } ) ;
28+
29+ export const DataViewProvider = ( { children } : PropsWithChildren ) => {
30+ const [ subscriptions , setSubscriptions ] = useState < ContextType > ( {
31+ [ EventTypes . rowClick ] : { }
32+ } ) ;
33+
34+ const subscribe : Subscribe = ( event , callback ) => {
35+ const id = crypto . randomUUID ( ) ;
36+
37+ // set new subscription
38+ setSubscriptions ( ( prevSubscriptions ) => ( {
39+ ...prevSubscriptions ,
40+ [ event ] : { ...prevSubscriptions [ event ] , [ id ] : callback }
41+ } ) ) ;
42+
43+ // return unsubscribe function
44+ return ( ) => {
45+ setSubscriptions ( ( prevSubscriptions ) => {
46+ const updatedSubscriptions = { ...prevSubscriptions } ;
47+ delete updatedSubscriptions [ event ] [ id ] ;
48+ return updatedSubscriptions ;
49+ } ) ;
50+ } ;
51+ } ;
52+
53+ const trigger = useCallback (
54+ ( event : DataViewEvent , ...payload : unknown [ ] ) => {
55+ Object . values ( subscriptions [ event ] ) . forEach ( ( callback ) => {
56+ callback ( ...payload ) ;
57+ } ) ;
58+ } ,
59+ [ subscriptions ]
60+ ) ;
61+
62+ return (
63+ < DataViewContext . Provider value = { { subscribe, trigger } } >
64+ { children }
65+ </ DataViewContext . Provider >
66+ ) ;
67+ } ;
68+
69+ export default DataViewContext ;
0 commit comments