Untitled

 avatar
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