hexabot/widget/src/providers/WidgetProvider.tsx
2024-09-29 13:02:28 +01:00

97 lines
2.7 KiB
TypeScript

/*
* Copyright © 2024 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import React, { createContext, ReactNode, useContext, useState } from 'react';
import { ChatScreen } from '../types/state.types';
export interface WidgetContextType {
syncState: boolean;
isOpen: boolean;
screen: ChatScreen;
scroll: number;
setSyncState: (syncState: boolean) => void;
setIsOpen: (isOpen: boolean) => void;
setScreen: (screen: ChatScreen) => void;
setScroll: (scroll: number) => void;
}
const WidgetContext = createContext<WidgetContextType | undefined>(undefined);
const WidgetProvider: React.FC<{
onOpen?: () => void;
onClose?: () => void;
onScrollToTop?: () => void;
defaultScreen?: ChatScreen;
children: ReactNode;
}> = ({
onOpen,
onClose,
onScrollToTop,
defaultScreen = 'prechat',
children,
}) => {
const [syncState, setSyncState] = useState<boolean>(true);
const [isOpen, setIsOpen] = useState<boolean>(false);
const [screen, setScreen] = useState<ChatScreen>(defaultScreen);
const [scroll, setScroll] = useState<number>(100);
const handleSetSyncState = (newState: boolean) => {
setSyncState(newState);
};
const handleSetIsOpen = (newState: boolean) => {
setIsOpen(newState);
if (syncState) {
if (newState) {
onOpen && onOpen();
} else {
onClose && onClose();
}
}
};
const handleSetScreen = (newScreen: ChatScreen) => {
setScreen(
['prechat', 'postchat', 'webview'].includes(newScreen)
? newScreen
: 'chat',
);
};
const handleSetScroll = (newScroll: number) => {
setScroll(newScroll);
if (onScrollToTop && syncState && newScroll === 0) {
onScrollToTop();
}
};
const contextValue = {
syncState,
isOpen,
screen,
scroll,
setSyncState: handleSetSyncState,
setIsOpen: handleSetIsOpen,
setScreen: handleSetScreen,
setScroll: handleSetScroll,
};
return (
<WidgetContext.Provider value={contextValue}>
{children}
</WidgetContext.Provider>
);
};
export const useWidget = () => {
const context = useContext(WidgetContext);
if (context === undefined) {
throw new Error('useWidget must be used within a WidgetProvider');
}
return context;
};
export default WidgetProvider;