Untitled
unknown
plain_text
a year ago
3.9 kB
5
Indexable
import React, { createContext, useContext, useRef, ReactNode } from 'react'; import ReactDOM from 'react-dom'; import { Portal } from '@mui/material'; //////////////////////////////////////////////////////////// interface TopbarContextProps { titleRef: React.RefObject<HTMLDivElement>; searchInputRef: React.RefObject<HTMLDivElement>; backButtonRef: React.RefObject<HTMLDivElement>; } const TopbarContext = createContext<TopbarContextProps | undefined>(undefined); export const TopbarProvider: React.FC<{ children: ReactNode }> = ({ children }) => { const titleRef = useRef<HTMLDivElement>(null); const searchInputRef = useRef<HTMLDivElement>(null); const backButtonRef = useRef<HTMLDivElement>(null); const value = { titleRef, searchInputRef, backButtonRef, }; return ( <TopbarContext.Provider value={value}> {children} </TopbarContext.Provider> ); }; export const useTopbar = () => { const context = useContext(TopbarContext); if (!context) { throw new Error("useTopbar must be used within a TopbarProvider"); } return context; }; //////////////////////////////////////////////////////////// interface TopbarProps { searchEnabled: boolean; } const Topbar: React.FC<TopbarProps> = ({ searchEnabled }) => { const { titleRef, searchInputRef, backButtonRef } = useTopbar(); return ( <div className="topbar"> <div ref={backButtonRef}></div> <div ref={titleRef}></div> {searchEnabled && <div ref={searchInputRef}></div>} </div> ); }; export default Topbar; //////////////////////////////////////////////////////////// interface TopbarTitleProps { value: string; } export const TopbarTitle: React.FC<TopbarTitleProps> = ({ value }) => { const { titleRef } = useTopbar(); return ( titleRef.current && ( <Portal container={titleRef.current}> <h1>{value}</h1> </Portal> ) ); }; interface TopbarBackButtonProps { onClick: () => void; } export const TopbarBackButton: React.FC<TopbarBackButtonProps> = ({ onClick }) => { const { backButtonRef } = useTopbar(); return ( backButtonRef.current && ( <Portal container={backButtonRef.current}> <button onClick={onClick}>Back</button> </Portal> ) ); }; interface TopbarSearchInputProps { value: string; onChange: (event: React.ChangeEvent<HTMLInputElement>) => void; } export const TopbarSearchInput: React.FC<TopbarSearchInputProps> = ({ value, onChange }) => { const { searchInputRef } = useTopbar(); return ( searchInputRef.current && ( <Portal container={searchInputRef.current}> <input type="text" value={value} onChange={onChange} /> </Portal> ) ); }; //////////////////////////////////////////////////////////// interface SomeDropdownProps { phrase: string; placeholder: string; onClose: () => void; onSearchPhraseChange: (event: React.ChangeEvent<HTMLInputElement>) => void; } const SomeDropdown: React.FC<SomeDropdownProps> = ({ phrase, placeholder, onClose, onSearchPhraseChange }) => { return ( <div> <TopbarTitle value={placeholder} /> <TopbarBackButton onClick={onClose} /> <TopbarSearchInput value={phrase} onChange={onSearchPhraseChange} /> {/* Reszta komponentu */} </div> ); }; export default SomeDropdown; //////////////////////////////////////////////////////////// const App: React.FC = () => { return ( <TopbarProvider> <Topbar searchEnabled={true} /> <Page> <Form /> {/* Zakładam, że SomeDropdown jest używany gdzieś w Form */} </Page> </TopbarProvider> ); }; ReactDOM.render(<App />, document.getElementById('root'));
Editor is loading...
Leave a Comment