react-router-dom#Outlet TypeScript Examples

The following examples show how to use react-router-dom#Outlet. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AppLayout.tsx    From one-platform with MIT License 6 votes vote down vote up
AppLayout = (): JSX.Element => {
  return (
    <Page>
      <div style={{ border: '1px solid #ddd' }}>
        <Stack>
          <StackItem className="p-4">
            <Title headingLevel="h1" size="2xl">
              Feedback
            </Title>
          </StackItem>
          <StackItem className="p-4">
            <Breadcrumb>
              <BreadcrumbItem to="/">One Platform</BreadcrumbItem>
              <BreadcrumbItem to="#" isActive>
                All Feedback
              </BreadcrumbItem>
            </Breadcrumb>
          </StackItem>
        </Stack>
      </div>
      <Outlet />
    </Page>
  );
}
Example #2
Source File: renderContent.tsx    From Search-Next with GNU General Public License v3.0 6 votes vote down vote up
RenderContent: React.FC<RenderContentProps> = (props) => {
  const { children, pathname, noOutlet = false } = props;
  const location = useLocation();
  let match = useMatch(pathname);

  return (
    <>
      {(pathname === location.pathname ||
        pathname === match?.pattern?.path ||
        (pathname && pathname.indexOf('undefined') !== -1)) &&
        children}
      {!noOutlet && <Outlet />}
    </>
  );
}
Example #3
Source File: Characters.tsx    From Riakuto-StartingReact-ja3.1 with Apache License 2.0 6 votes vote down vote up
Characters: VFC = () => (
  <>
    <header>
      <h1>『SLAM DUNK』登場人物</h1>
    </header>
    <Outlet />
    <Divider hidden />
    <HomeButton />
  </>
)
Example #4
Source File: AccountsNavigator.tsx    From celo-web-wallet with MIT License 6 votes vote down vote up
export function AccountsNavigator() {
  return (
    <ScreenContentFrame showBackButton={true}>
      <div css={contentContainer}>
        <Outlet />
      </div>
    </ScreenContentFrame>
  )
}
Example #5
Source File: OnboardingNavigator.tsx    From celo-web-wallet with MIT License 6 votes vote down vote up
export function OnboardingNavigator() {
  // If wallet exists in storage don't allow user back into onboarding flow
  if (hasAccounts() || hasAccount_v1()) {
    return <Navigate to="/" replace={true} />
  }

  // Force navigation to fail screen if providers are unable to connect
  const isConnected = useAppSelector((s) => s.wallet.isConnected, shallowEqual)
  if (isConnected === false) throw new Error('Unable to connect to network.')

  // Otherwise, render screen as normal
  return <Outlet />
}
Example #6
Source File: HomeNavigator.tsx    From celo-web-wallet with MIT License 6 votes vote down vote up
export function HomeNavigator() {
  const isUnlocked = useAccountLockStatus()

  // Force navigation to fail screen if providers are unable to connect
  const isConnected = useAppSelector((s) => s.wallet.isConnected, shallowEqual)
  if (isConnected === false) throw new Error('Unable to connect to network.')

  // If password has been entered already
  if (isUnlocked) {
    return (
      <ScreenFrame>
        <Outlet />
      </ScreenFrame>
    )
  }

  // If wallet exists in storage but is not unlocked yet
  if (hasAccounts() || hasAccount_v1()) {
    return <LoginScreen />
  }

  // Otherwise, account must not be set up yet
  return <Navigate to="/setup" replace={true} />
}
Example #7
Source File: Layout.tsx    From react-starter-boilerplate with MIT License 6 votes vote down vote up
Layout = () => {
  return (
    <div className="app">
      <header className="app__header">
        <img src={logo} className="app__logo" alt="logo" />
        <p>
          Edit <code>src/layout/Layout.tsx</code> and save to reload.
        </p>
        <a className="app__link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">
          Learn React
        </a>
      </header>
      <nav className="app__navigation">
        <ul className="app__menu">
          <li className="app__menu-item">
            <Link className="app__menu-link" to={'/' + AppRoute.home}>
              Home
            </Link>
          </li>
          <li className="app__menu-item">
            <Link className="app__menu-link" to={'/' + AppRoute.about}>
              About
            </Link>
          </li>
          <li className="app__menu-item">
            <Link className="app__menu-link" to={'/' + AppRoute.help}>
              Help
            </Link>
          </li>
        </ul>
      </nav>
      <main className="app__main">
        <Outlet />
      </main>
    </div>
  );
}
Example #8
Source File: bluna.convert.tsx    From anchor-web-app with Apache License 2.0 6 votes vote down vote up
function Component({ className }: UIElementProps) {
  const navigate = useNavigate();

  const match = useMatch({ path: '/basset/bluna/:page', end: true });

  const tab = useMemo<Item | undefined>(() => {
    return tabItems.find(({ value }) => value === match?.params.page);
  }, [match?.params.page]);

  const tabChange = useCallback(
    (nextTab: Item) => {
      navigate(`/basset/bluna/${nextTab.value}`);
    },
    [navigate],
  );

  return (
    <CenteredLayout maxWidth={800} className={className}>
      <TitleContainer>
        <PageTitle title="MINT & BURN" />
      </TitleContainer>
      <Tab
        className="tab"
        items={tabItems}
        selectedItem={tab ?? tabItems[0]}
        onChange={tabChange}
        labelFunction={({ label }) => label}
        keyFunction={({ value }) => value}
        tooltipFunction={({ tooltip }) => tooltip}
      />
      <Outlet />
    </CenteredLayout>
  );
}
Example #9
Source File: index.tsx    From shippo with MIT License 5 votes vote down vote up
Passport = () => {
  return <Outlet />
}
Example #10
Source File: index.tsx    From shippo with MIT License 5 votes vote down vote up
Setting = () => {
  return <Outlet />
}
Example #11
Source File: App.tsx    From rari-dApp with GNU Affero General Public License v3.0 5 votes vote down vote up
App = memo(() => {
  return (
    <Layout>
      <Routes>
        <Route path="/pools" element={<Outlet />}>
          {Object.values(Pool).map((pool) => {
            return (
              <Route
                key={pool}
                path={pool}
                element={<PoolPortal pool={pool} />}
              />
            );
          })}
        </Route>

        <Route path="/tranches" element={<TranchesPage />} />

        <Route path="/pool2" element={<Pool2Page />} />

        <Route path="/fuse" element={<FusePoolsPage />} />
        <Route path="/fuse/liquidations" element={<FuseLiquidationsPage />} />
        <Route path="/fuse/new-pool" element={<FusePoolCreatePage />} />
        <Route path="/fuse/pool/:poolId" element={<FusePoolPage />} />
        <Route path="/fuse/pool/:poolId/info" element={<FusePoolInfoPage />} />
        <Route path="/fuse/pool/:poolId/edit" element={<FusePoolEditPage />} />

        <Route path="/utils" element={<Navigate to="/" replace={true} />} />
        <Route path="/utils/interest-rates" element={<InterestRatesPage />} />
        <Route path="/utils/positions" element={<StatsPage />} />

        {/* Backwards Compatibility Routes */}
        <Route
          path="/interest_rates"
          element={<Navigate to="/utils/interest-rates" replace={true} />}
        />
        <Route
          path="/interest-rates"
          element={<Navigate to="/utils/interest-rates" replace={true} />}
        />
        <Route
          path="/positions"
          element={<Navigate to="/utils/positions" replace={true} />}
        />
        {/* Backwards Compatibility Routes */}

        <Route path="/" element={<MultiPoolPortal />} />

        <Route path="*" element={<PageNotFound />} />
      </Routes>
    </Layout>
  );
})
Example #12
Source File: trade.tsx    From anchor-web-app with Apache License 2.0 5 votes vote down vote up
function TradeBase({ className }: RewardsPoolProps) {
  const navigate = useNavigate();

  const pageMatch = useMatch(`/trade/:view`);

  const tab = useMemo<Item | undefined>(() => {
    switch (pageMatch?.params.view) {
      case 'buy':
        return tabItems[0];
      case 'sell':
        return tabItems[1];
    }
  }, [pageMatch?.params.view]);

  const tabChange = useCallback(
    (nextTab: Item) => {
      navigate({
        pathname: nextTab.value === 'sell' ? `/trade/sell` : `/trade/buy`,
      });
    },
    [navigate],
  );

  return (
    <CenteredLayout className={className}>
      <Tab
        className="tab"
        items={tabItems}
        selectedItem={tab ?? tabItems[0]}
        onChange={tabChange}
        labelFunction={({ label }) => label}
        keyFunction={({ value }) => value}
        tooltipFunction={({ tooltip }) => tooltip}
      />

      <Section>
        <Routes>
          <Route path="" element={<Navigate to="/trade/buy" />} />
          <Route path="/buy" element={<TradeBuy />} />
          <Route path="/sell" element={<TradeSell />} />
          <Route path="*" element={<Navigate to="/trade/buy" />} />
        </Routes>
        <Outlet />
      </Section>
    </CenteredLayout>
  );
}
Example #13
Source File: rewards.anc-governance.tsx    From anchor-web-app with Apache License 2.0 5 votes vote down vote up
function RewardsAncUstLpBase({ className }: RewardsAncUstLpProps) {
  const navigate = useNavigate();

  const pageMatch = useMatch(`/${ancGovernancePathname}/:view`);

  const subTab = useMemo<Item | undefined>(() => {
    switch (pageMatch?.params.view) {
      case 'stake':
        return stakeItems[0];
      case 'unstake':
        return stakeItems[1];
    }
  }, [pageMatch?.params.view]);

  const subTabChange = useCallback(
    (nextTab: Item) => {
      navigate({
        pathname: `/${ancGovernancePathname}/${nextTab.value}`,
      });
    },
    [navigate],
  );

  return (
    <CenteredLayout className={className}>
      <header>
        <h1>
          <Circles radius={24} backgroundColors={['#2C2C2C']}>
            <GifIcon
              src={anc80gif}
              style={{ fontSize: '2em', borderRadius: '50%' }}
            />
          </Circles>
          ANC Governance
        </h1>
      </header>

      <Section>
        <RulerTab
          className="subtab"
          items={stakeItems}
          selectedItem={subTab ?? stakeItems[0]}
          onChange={subTabChange}
          labelFunction={({ label }) => label}
          keyFunction={({ value }) => value}
          tooltipFunction={({ tooltip }) => tooltip}
        />

        <div className="form">
          <Routes>
            <Route path="/stake" element={<AncGovernanceStake />} />
            <Route path="unstake" element={<AncGovernanceUnstake />} />
            <Route
              index={true}
              element={<Navigate to={`/${ancGovernancePathname}/stake`} />}
            />
            <Route
              path="*"
              element={<Navigate to={`/${ancGovernancePathname}/stake`} />}
            />
          </Routes>
          <Outlet />
        </div>
      </Section>
    </CenteredLayout>
  );
}
Example #14
Source File: wh.convert.tsx    From anchor-web-app with Apache License 2.0 5 votes vote down vote up
function Component({ className }: UIElementProps) {
  const navigate = useNavigate();

  const match = useMatch({ path: '/basset/wh/:tokenSymbol/:page', end: true });

  const { data: bAssetInfo } = useBAssetInfoByTokenSymbolQuery(
    match?.params.tokenSymbol,
  );

  const tabItems = useMemo<Item[]>(() => {
    const bAssetSymbol = bAssetInfo
      ? bAssetInfo.tokenDisplay.anchor?.symbol ?? bAssetInfo.bAsset.symbol
      : 'ASSET';
    const whAssetSymbol = bAssetInfo
      ? bAssetInfo.tokenDisplay.wormhole.symbol
      : 'whASSET';

    return [
      {
        label: `to ${bAssetSymbol}`,
        value: 'to-basset',
        tooltip:
          'Convert wormhole tokens into bAssets that are useable on Anchor.',
      },
      {
        label: `to ${whAssetSymbol}`,
        value: 'to-wbasset',
        tooltip: 'Convert bAssets useable on Anchor into wormhole tokens.',
      },
    ];
  }, [bAssetInfo]);

  const tab = useMemo<Item | undefined>(() => {
    return tabItems.find(({ value }) => value === match?.params.page);
  }, [match?.params.page, tabItems]);

  const tabChange = useCallback(
    (nextTab: Item) => {
      navigate(`/basset/wh/${match?.params.tokenSymbol}/${nextTab.value}`);
    },
    [navigate, match?.params.tokenSymbol],
  );

  return (
    <CenteredLayout className={className} maxWidth={800}>
      <TitleContainer>
        <PageTitle
          title="CONVERT"
          tooltip="Tokens transferred to the terra chain through wormhole must be converted to bAssets useable on Anchor to be deposited as collateral."
        />
      </TitleContainer>
      <Tab
        className="tab"
        items={tabItems}
        selectedItem={tab ?? tabItems[0]}
        onChange={tabChange}
        labelFunction={({ label }) => label}
        keyFunction={({ value }) => value}
        tooltipFunction={({ tooltip }) => tooltip}
      />
      <Outlet />
    </CenteredLayout>
  );
}
Example #15
Source File: App.tsx    From pintora with MIT License 5 votes vote down vote up
AppLayout = () => {
  useEffect(() => {
    const params = new URLSearchParams(location.search)
    let code = ''
    const encodedCode = params.get('code')
    if (encodedCode) {
      try {
        code = pintora.util.decodeCodeInUrl(encodedCode)
      } catch (error) {
        console.error('[live-editor] error when decoding code in url', error)
      }
      const newParams = new URLSearchParams(params)
      newParams.delete('code')
      history.replaceState(null, '', `?${newParams.toString()}`)
    } else if (params.has('example')) {
      const exampleName: keyof typeof EXAMPLES = params.get('example') as any
      if (exampleName) {
        const example = EXAMPLES[exampleName]
        if (example) {
          code = EXAMPLES[exampleName].code
        }
      }
    } else {
      try {
        const rawData = localStorage.getItem(LAST_EDITOR_CODE_KEY)
        if (rawData) {
          const data = JSON.parse(rawData)
          code = data.code
        }
      } catch (error) {
        console.warn('error recovering data from storage', error)
      }
    }

    if (code) {
      store.dispatch(actions.updateEditorCode({ code, syncToPreview: true }))
    }
  }, [])

  return (
    <>
      <Header></Header>
      <div className="App__content flex">
        <AppSidebar></AppSidebar>

        <Outlet />
      </div>
    </>
  )
}
Example #16
Source File: AppEditorShell.tsx    From mui-toolpad with MIT License 5 votes vote down vote up
export default function AppEditorShell({ appId, ...props }: ToolpadAppShellProps) {
  const domLoader = useDomLoader();

  const [createReleaseDialogOpen, setCreateReleaseDialogOpen] = React.useState(false);

  return (
    <ToolpadAppShell
      appId={appId}
      actions={
        <React.Fragment>
          {domLoader.saving ? (
            <Box display="flex" flexDirection="row" alignItems="center">
              <CircularProgress size={16} color="inherit" sx={{ mr: 1 }} />
            </Box>
          ) : null}
          <Typography>{domLoader.unsavedChanges} unsaved change(s).</Typography>
          <IconButton
            aria-label="Create release"
            color="inherit"
            sx={{ ml: 1 }}
            onClick={() => setCreateReleaseDialogOpen(true)}
          >
            <RocketLaunchIcon />
          </IconButton>
        </React.Fragment>
      }
      {...props}
    >
      <Box
        sx={{
          display: 'flex',
          flexDirection: 'row',
          overflow: 'hidden',
          height: '100%',
        }}
      >
        <PagePanel
          appId={appId}
          sx={{
            width: 250,
            borderRight: 1,
            borderColor: 'divider',
          }}
        />
        <Box
          sx={{
            flex: 1,
            overflow: 'hidden',
            position: 'relative',
          }}
        >
          <Outlet />
        </Box>

        <CreateReleaseDialog
          appId={appId}
          open={createReleaseDialogOpen}
          onClose={() => setCreateReleaseDialogOpen(false)}
        />
      </Box>
    </ToolpadAppShell>
  );
}
Example #17
Source File: SettingsView.tsx    From mysterium-vpn-desktop with MIT License 5 votes vote down vote up
SettingsView: React.FC = observer(function SettingsView() {
    const navigate = useNavigate()
    const location = useLocation()
    const isFilterTabActive = location.pathname == locations.settingsFilters
    const isConnectionTabActive = location.pathname == locations.settingsConnection
    const isMysteriumIdTabActive = location.pathname == locations.settingsMysteriumId
    return (
        <ViewContainer>
            <ViewNavBar />
            <ViewSplit>
                <ViewSidebar>
                    <SideTop>
                        <IconSettings color={brandLight} />
                        <Title>Settings</Title>
                    </SideTop>
                    <SideBot>
                        <NavButton active={isFilterTabActive} onClick={() => navigate(locations.settingsFilters)}>
                            <FontAwesomeIcon icon={faSlidersH} />
                            Default filters
                        </NavButton>
                        <NavButton
                            active={isConnectionTabActive}
                            onClick={() => navigate(locations.settingsConnection)}
                        >
                            <FontAwesomeIcon icon={faGlobe} />
                            Connection
                        </NavButton>
                        <NavButton
                            active={isMysteriumIdTabActive}
                            onClick={() => navigate(locations.settingsMysteriumId)}
                        >
                            <FontAwesomeIcon icon={faUserAlt} />
                            Mysterium ID
                        </NavButton>
                        <Version />
                    </SideBot>
                </ViewSidebar>
                <Content>
                    <Outlet />
                </Content>
            </ViewSplit>
        </ViewContainer>
    )
})
Example #18
Source File: AppLayout.tsx    From one-platform with MIT License 5 votes vote down vote up
AppLayout: FC = () => {
  const { pathname } = useLocation();
  const [isSidebarOpen, setIsSidebarOpen] = useToggle(true);
  const { breadcrumbs } = useBreadcrumb();
  const isBreadcrumbHidden = breadcrumbs.length === 0;

  return (
    <Page
      mainContainerId="app-layout-page"
      sidebar={<Sidebar isOpen={isSidebarOpen} />}
      className={styles['app-layout']}
      breadcrumb={
        !isBreadcrumbHidden && (
          <Breadcrumb className={styles['app-layout--breadcrumb']}>
            <BreadcrumbItem>
              <Button variant="link" className="pf-u-p-0" onClick={setIsSidebarOpen.toggle}>
                <BarsIcon />
              </Button>
            </BreadcrumbItem>
            <BreadcrumbItem to="/">One Platform</BreadcrumbItem>
            <BreadcrumbItem>
              {pathname === config.baseURL ? 'API Catalog Home' : <Link to="/">API Catalog</Link>}
            </BreadcrumbItem>
            {breadcrumbs.map(({ label, url }, index) => {
              const isActive = index === breadcrumbs.length - 1;
              return (
                <BreadcrumbItem key={label}>
                  {isActive ? label : <Link to={url}>{label}</Link>}
                </BreadcrumbItem>
              );
            })}
          </Breadcrumb>
        )
      }
    >
      <PageSection
        className={styles['app-layout--content']}
        variant="light"
        padding={{ default: 'noPadding' }}
      >
        <Outlet />
      </PageSection>
    </Page>
  );
}
Example #19
Source File: rewards.anc-ust-lp.tsx    From anchor-web-app with Apache License 2.0 4 votes vote down vote up
function RewardsAncUstLpBase({ className }: RewardsAncUstLpProps) {
  const navigate = useNavigate();

  const pageMatch = useMatch(`/${ancUstLpPathname}/:view`);

  const tab = useMemo<Item | undefined>(() => {
    switch (pageMatch?.params.view) {
      case 'provide':
      case 'withdraw':
        return tabItems[0];
      case 'stake':
      case 'unstake':
        return tabItems[1];
    }
  }, [pageMatch?.params.view]);

  const tabChange = useCallback(
    (nextTab: Item) => {
      navigate(
        nextTab.value === 'stake'
          ? `/${ancUstLpPathname}/stake`
          : `/${ancUstLpPathname}/provide`,
      );
    },
    [navigate],
  );

  const subTab = useMemo<Item | undefined>(() => {
    switch (pageMatch?.params.view) {
      case 'provide':
        return poolItems[0];
      case 'withdraw':
        return poolItems[1];
      case 'stake':
        return stakeItems[0];
      case 'unstake':
        return stakeItems[1];
    }
  }, [pageMatch?.params.view]);

  const subTabChange = useCallback(
    (nextTab: Item) => {
      navigate(`/${ancUstLpPathname}/${nextTab.value}`);
    },
    [navigate],
  );

  return (
    <CenteredLayout className={className}>
      <header>
        <h1>
          <Circles radius={24} backgroundColors={['#ffffff', '#2C2C2C']}>
            <TokenIcon token="ust" style={{ fontSize: '1.1em' }} />
            <GifIcon
              src={anc80gif}
              style={{ fontSize: '2em', borderRadius: '50%' }}
            />
          </Circles>
          ANC-UST LP
        </h1>
        <Tab
          items={tabItems}
          selectedItem={tab ?? tabItems[0]}
          onChange={tabChange}
          labelFunction={({ label }) => label}
          keyFunction={({ value }) => value}
          height={46}
          borderRadius={30}
          fontSize={12}
        />
      </header>

      <Section>
        <RulerTab
          className="subtab"
          items={tab?.value === 'stake' ? stakeItems : poolItems}
          selectedItem={
            subTab ?? (tab?.value === 'stake' ? stakeItems[0] : poolItems[0])
          }
          onChange={subTabChange}
          labelFunction={({ label }) => label}
          keyFunction={({ value }) => value}
          tooltipFunction={({ tooltip }) => tooltip}
        />

        <div className="form">
          {tab?.value === 'stake' && <AncUstLpStakeOverview />}

          <Routes>
            <Route path={`/provide`} element={<AncUstLpProvide />} />
            <Route path={`/withdraw`} element={<AncUstLpWithdraw />} />
            <Route path={`/stake`} element={<AncUstLpStake />} />
            <Route path={`/unstake`} element={<AncUstLpUnstake />} />
            <Route
              path={``}
              element={<Navigate to={`/${ancUstLpPathname}/provide`} />}
            />
            <Route
              path={`*`}
              element={<Navigate to={`/${ancUstLpPathname}/provide`} />}
            />
          </Routes>

          <Outlet />
        </div>
      </Section>
    </CenteredLayout>
  );
}
Example #20
Source File: HelpView.tsx    From mysterium-vpn-desktop with MIT License 4 votes vote down vote up
HelpView: React.FC = observer(function HelpView() {
    const { navigation } = useStores()
    const navigate = useNavigate()
    const location = useLocation()
    const isBugReportActive = location.pathname.includes(locations.helpBugReport)
    const isTermsAndConditionsActive = location.pathname.includes(locations.helpTermsAndConditions)
    return (
        <ViewContainer>
            <ViewNavBar />
            <ViewSplit>
                <ViewSidebar>
                    <SideTop>
                        <IconPerson color={brandLight} />
                        <Title>Get help</Title>
                        <Small>Help using Mysterium VPN</Small>
                    </SideTop>
                    <SideBot>
                        <SupportChatButton onClick={() => navigation.openChat()}>
                            <FontAwesomeIcon icon={faComments} />
                            Support chat
                        </SupportChatButton>
                        <NavButton active={isBugReportActive} onClick={() => navigate(locations.helpBugReport)}>
                            <FontAwesomeIcon icon={faBug} />
                            Bug report
                        </NavButton>
                        <NavButton
                            active={isTermsAndConditionsActive}
                            onClick={() => navigate(locations.helpTermsAndConditions)}
                        >
                            <FontAwesomeIcon icon={faFileContract} />
                            Terms & Conditions
                        </NavButton>
                        <NavButton active={false} onClick={() => shell.openExternal("https://docs.mysterium.network")}>
                            <FontAwesomeIcon icon={faBook} />
                            Documentation
                        </NavButton>
                        <SocialButtons>
                            <IconButton
                                active={false}
                                onClick={() => {
                                    shell.openExternal("https://discordapp.com/invite/n3vtSwc")
                                }}
                            >
                                <FontAwesomeIcon icon={faDiscord} size="2x" />
                            </IconButton>
                            <IconButton
                                active={false}
                                onClick={() => {
                                    shell.openExternal("https://www.reddit.com/r/MysteriumNetwork/")
                                }}
                            >
                                <FontAwesomeIcon icon={faReddit} size="2x" />
                            </IconButton>
                            <IconButton active={false}>
                                <FontAwesomeIcon
                                    icon={faTwitter}
                                    size="2x"
                                    onClick={() => {
                                        shell.openExternal("https://twitter.com/MysteriumNet")
                                    }}
                                />
                            </IconButton>
                            <IconButton active={false}>
                                <FontAwesomeIcon
                                    icon={faFacebookSquare}
                                    size="2x"
                                    onClick={() => {
                                        shell.openExternal("https://www.facebook.com/MysteriumNet")
                                    }}
                                />
                            </IconButton>
                        </SocialButtons>
                        <Version />
                    </SideBot>
                </ViewSidebar>
                <Content>
                    <Outlet />
                </Content>
            </ViewSplit>
        </ViewContainer>
    )
})
Example #21
Source File: index.tsx    From Search-Next with GNU General Public License v3.0 4 votes vote down vote up
SettingPage: React.FC<SettingPageProps> = ({
  children,
  route,
  ...props
}) => {
  const history = useNavigate();
  const location = useLocation();
  const params = useParams();
  const [menuList, setMenuList] = React.useState<Router[] | undefined>([]);
  const [breads, setBreads] = React.useState<Router[]>([]);

  const getBreadCrumbs = (routes: Router[], parentPath: string = '') => {
    let breadCrumbs: Router[] = [];

    const findRoute = (
      routes: Router[] | undefined,
      parentPath: string = '',
    ) => {
      if (!routes) return routes;
      const loc = location;
      routes.forEach((i) => {
        const fullPath = `${parentPath}/${i.path}`;
        const splitPath = fullPath.split(':');
        const paramsPath =
          splitPath[0] +
          Object.values(params)
            .filter((u) => u !== '')
            .join('/');
        if (
          loc.pathname.indexOf(i.path) !== -1 ||
          loc.pathname === paramsPath
        ) {
          breadCrumbs.push(i);
        }
        if (i.routes) {
          findRoute(i.routes, fullPath);
        }
      });
    };
    findRoute(routes, parentPath);

    return breadCrumbs;
  };

  React.useEffect(() => {
    if (location.pathname === '/setting') {
      history(route?.routes?.[0].path || '/setting', { replace: true });
    }
    setMenuList(route?.routes);
  }, []);

  React.useEffect(() => {
    const breads = getBreadCrumbs(route.routes || [], '/setting');
    setBreads(breads);
  }, [location]);

  return (
    <div className="flex flex-row h-screen bg-gray-70">
      <div className="w-72 p-4 h-full">
        <div className="flex gap-1">
          <Tooltip title="回到首页" arrow>
            <IconButton
              size="small"
              onClick={() => {
                history('/');
              }}
            >
              <Home />
            </IconButton>
          </Tooltip>
          <Tooltip title="返回上级" arrow>
            <IconButton
              size="small"
              onClick={() => {
                history(-1);
              }}
            >
              <KeyboardBackspace />
            </IconButton>
          </Tooltip>
        </div>
        <div className="flex flex-col gap-1 my-4">
          {menuList?.map((i) => (
            <div
              key={i.path}
              className={classNames(
                'hover:bg-gray-150',
                'transition-all',
                'px-2.5',
                'py-1.5',
                'cursor-pointer',
                'rounded',
                'text-sm',
                'text-gray-800',
                {
                  'bg-gray-150': location.pathname.indexOf(i.path) > -1,
                },
              )}
              onClick={() => {
                history(i.path);
              }}
            >
              {i.title}
            </div>
          ))}
        </div>
      </div>
      <div className="h-full overflow-hidden flex flex-col w-full px-6 py-4">
        <Breadcrumbs separator="›" aria-label="breadcrumb" className="mb-4">
          {breads.map((i, index) => (
            <div
              className={classNames('text-2xl cursor-pointer mb-0', {
                'font-semibold': index === breads.length - 1,
              })}
              key={i.path}
              onClick={() => {
                const path =
                  '/setting/' +
                  breads
                    .map((i) => i.path)
                    .filter((_, ji) => ji <= index)
                    .join('/');
                index !== breads.length - 1 ? history(path) : null;
              }}
            >
              <div className="flex items-center gap-1">
                {i.title}
                {i?.status === 'process' && (
                  <Chip
                    color="warning"
                    label={i?.status}
                    size="small"
                    variant="outlined"
                  />
                )}
              </div>
            </div>
          ))}
        </Breadcrumbs>
        <div className="flex-grow overflow-y-auto w-full">
          <div className="max-w-4xl">
            <Outlet />
          </div>
        </div>
        <div className="text-center max-w-4xl">
          <Copyright />
        </div>
      </div>
    </div>
  );
}