Untitled
unknown
plain_text
a year ago
3.9 kB
14
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