mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-28 04:52:07 +00:00
Merge branch 'develop' into feature/search-return-df
This commit is contained in:
@@ -2,7 +2,22 @@
|
||||
sidebar_position: 1
|
||||
title: Installation
|
||||
description: The OpenBB Terminal can be directly installed on your computer via our installation programs. Within this section, you are guided through the installation process and how to launch the program. If you struggle with the installation process, please don’t hesitate to reach us on Discord or visit our contact page.
|
||||
keywords: [installation, installer, install, guide, mac, windows, linux, python, github, macos, how to, explanation, openbb terminal]
|
||||
keywords:
|
||||
[
|
||||
installation,
|
||||
installer,
|
||||
install,
|
||||
guide,
|
||||
mac,
|
||||
windows,
|
||||
linux,
|
||||
python,
|
||||
github,
|
||||
macos,
|
||||
how to,
|
||||
explanation,
|
||||
openbb terminal,
|
||||
]
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
@@ -41,8 +56,6 @@ OpenBB Terminal is available on all major platforms. With Windows and macOS you
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="gdoc-columns__content gdoc-markdown--nested">
|
||||
<p><strong>Step 3: Double-click on the application that appeared on your Desktop, you are now able to run the OpenBB Terminal</strong></p>
|
||||
<p align="center"><a target="_blank" href="https://openbb-web-assets.s3.amazonaws.com/docs/installation/icon.png"><img width="100" alt="run_the_terminal" src="https://openbb-web-assets.s3.amazonaws.com/docs/installation/icon.png"></img></a></p>
|
||||
@@ -58,14 +71,16 @@ OpenBB Terminal is available on all major platforms. With Windows and macOS you
|
||||
|
||||
For Mac there are two installers available, one for Intel and one for Apple Silicon (M1). Please download the correct one for your machine.
|
||||
|
||||
<ul>
|
||||
<li>If you are using Mac Intel: <br />
|
||||
<div className="flex justify-between">
|
||||
<div className="flex items-center flex-col">If you are using Mac Intel:
|
||||
<InstallerButton href="https://github.com/OpenBB-finance/OpenBBTerminal/releases/download/v2.3.1/x86.64.MacOS.OpenBB.Terminal.v2.3.1.dmg" label="Mac Intel Installer" />
|
||||
</li>
|
||||
<li>If you are using Mac Apple Silicon (M1): <br />
|
||||
</div>
|
||||
<br/>
|
||||
<div className="flex items-center flex-col">
|
||||
If you are using Mac Apple Silicon (M1):
|
||||
<InstallerButton href="https://github.com/OpenBB-finance/OpenBBTerminal/releases/download/v2.3.1/ARM64.MacOS.OpenBB.Terminal.v2.3.1.dmg" label="Mac M1 Installer" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Follow along with the instructions of the video or use the steps below to run the OpenBB Terminal:</p>
|
||||
|
||||
@@ -99,7 +114,6 @@ Right-Click the app and select <code>Open</code>. You will see a message saying
|
||||
|
||||
<iframe width="100%" height="450" src="https://www.youtube.com/embed/NjXPIfDzQMk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
|
||||
|
||||
## 1. Windows
|
||||
|
||||
### 1.1. Install Docker Desktop
|
||||
@@ -180,7 +194,7 @@ Make sure both of these options are enabled:
|
||||
- `Allow connections from network clients`
|
||||
|
||||
It should look like this:
|
||||

|
||||

|
||||
|
||||
### 2.3. Get Docker IP
|
||||
|
||||
@@ -265,14 +279,15 @@ Miniconda is a python environment and package manager. It is required if you wan
|
||||
have the dependencies working straight away.
|
||||
|
||||
- Go [here](https://docs.conda.io/en/latest/miniconda.html#latest-miniconda-installer-links) to find the download for your operating system or use the links below:
|
||||
|
||||
- If you are using macOS [Miniconda for MacOS](https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh)
|
||||
- If you are using WSL or Linux [Miniconda for Linux](https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh)
|
||||
- If you are using a Raspberry PI [Miniconda for Raspberry PI](https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh)
|
||||
- If you are using Windows [Miniconda for Windows](https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe).
|
||||
|
||||
**ONLY REQUIRED ON WINDOWS IF NOT USING WSL**, Install/update Microsoft C++ Build Tools from here: <https://visualstudio.microsoft.com/visual-cpp-build-tools/>
|
||||
**ONLY REQUIRED ON WINDOWS IF NOT USING WSL**, Install/update Microsoft C++ Build Tools from here: <https://visualstudio.microsoft.com/visual-cpp-build-tools/>
|
||||
|
||||
**NOTE for macOS users:** The link above gets you the Intel version of miniconda meaning if you're on an Apple Silicon powered machine you will be using the terminal through Apple's rosetta2 layer. We recommend sticking to this distribution for better compatibility until the dependency developers fully catch up with Apple's transition to Apple Silicon.
|
||||
**NOTE for macOS users:** The link above gets you the Intel version of miniconda meaning if you're on an Apple Silicon powered machine you will be using the terminal through Apple's rosetta2 layer. We recommend sticking to this distribution for better compatibility until the dependency developers fully catch up with Apple's transition to Apple Silicon.
|
||||
|
||||
- After following the steps, confirm that you have it by opening a terminal and running: `conda -V`. The output should be something along the lines of: `conda 22.9.0`
|
||||
|
||||
@@ -412,9 +427,9 @@ Requirements files that you can find in the project root:
|
||||
|
||||
You can install them with with pip
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
The dependency tree is solved by poetry.
|
||||
|
||||
|
||||
10
website/docusaurus.config.js
vendored
10
website/docusaurus.config.js
vendored
@@ -62,7 +62,6 @@ const config = {
|
||||
sidebarPath: require.resolve("./sidebars.js"),
|
||||
},
|
||||
],
|
||||
require.resolve("@cmfcmf/docusaurus-search-local"),
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
@@ -79,10 +78,6 @@ const config = {
|
||||
theme: {
|
||||
customCss: require.resolve("./src/css/custom.css"),
|
||||
},
|
||||
gtag: {
|
||||
trackingID: "G-YN9SL785J6",
|
||||
anonymizeIP: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
],
|
||||
@@ -100,6 +95,11 @@ const config = {
|
||||
disableSwitch: false,
|
||||
respectPrefersColorScheme: false,
|
||||
},
|
||||
algolia: {
|
||||
appId: "7D1HQ0IXAS",
|
||||
apiKey: "a2e289977b4b663ed9cf3d4635a438fd",
|
||||
indexName: "openbbterminal",
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
16418
website/package-lock.json
generated
vendored
16418
website/package-lock.json
generated
vendored
File diff suppressed because it is too large
Load Diff
9
website/package.json
vendored
9
website/package.json
vendored
@@ -16,11 +16,10 @@
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cmfcmf/docusaurus-search-local": "^0.11.0",
|
||||
"@docusaurus/core": "2.2.0",
|
||||
"@docusaurus/core": "^2.3.1",
|
||||
"@docusaurus/plugin-client-redirects": "^2.3.1",
|
||||
"@docusaurus/plugin-content-docs": "^2.2.0",
|
||||
"@docusaurus/preset-classic": "2.3.1",
|
||||
"@docusaurus/plugin-content-docs": "^2.3.1",
|
||||
"@docusaurus/preset-classic": "^2.3.1",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"@radix-ui/react-popover": "^1.0.3",
|
||||
"clsx": "^1.2.1",
|
||||
@@ -30,7 +29,7 @@
|
||||
"tailwindcss-radix": "^2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "2.2.0",
|
||||
"@docusaurus/module-type-aliases": "^2.3.1",
|
||||
"@tailwindcss/typography": "^0.5.8",
|
||||
"@tsconfig/docusaurus": "^1.0.5",
|
||||
"autoprefixer": "^10.4.13",
|
||||
|
||||
@@ -1,25 +1,41 @@
|
||||
import React from "react"
|
||||
export default function InstallerButton({
|
||||
href,
|
||||
label,
|
||||
type
|
||||
}) {
|
||||
return <a href={href} className="button button--primary !no-underline inline-flex gap-4 h-10 items-center" rel="noreferrer noopener" target="_blank">
|
||||
{type === "windows" ? <svg xmlns="http://www.w3.org/2000/svg" className="w-4" height={88} width={88} viewBox="0 0 88 88">
|
||||
<path
|
||||
d="m0 12.402 35.687-4.86.016 34.423-35.67.203zm35.67 33.529.028 34.453L.028 75.48.026 45.7zm4.326-39.025L87.314 0v41.527l-47.318.376zm47.329 39.349-.011 41.34-47.318-6.678-.066-34.739z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg> : <svg
|
||||
className="w-4 -mt-1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlSpace="preserve"
|
||||
width={814}
|
||||
height={1000}
|
||||
viewBox="0 0 814 1000"
|
||||
import React from "react";
|
||||
export default function InstallerButton({ href, label, type }) {
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
className="button button--primary !no-underline inline-flex gap-4 h-10 items-center"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
{type === "windows" ? (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-4"
|
||||
height={88}
|
||||
width={88}
|
||||
viewBox="0 0 88 88"
|
||||
>
|
||||
<path fill="currentColor" d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z" />
|
||||
</svg>}
|
||||
{label}
|
||||
<path
|
||||
d="m0 12.402 35.687-4.86.016 34.423-35.67.203zm35.67 33.529.028 34.453L.028 75.48.026 45.7zm4.326-39.025L87.314 0v41.527l-47.318.376zm47.329 39.349-.011 41.34-47.318-6.678-.066-34.739z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
) : (
|
||||
<svg
|
||||
className="w-4 -mt-1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlSpace="preserve"
|
||||
width={814}
|
||||
height={1000}
|
||||
viewBox="0 0 814 1000"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"
|
||||
/>
|
||||
</svg>
|
||||
)}
|
||||
{label}
|
||||
</a>
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
85
website/src/css/custom.css
vendored
85
website/src/css/custom.css
vendored
@@ -110,16 +110,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 440px) {
|
||||
.aa-DetachedSearchButtonPlaceholder {
|
||||
display: none;
|
||||
}
|
||||
.aa-DetachedSearchButton {
|
||||
width: 34px !important;
|
||||
height: 34px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.menu__link--sublist-caret::after {
|
||||
background: var(--ifm-menu-link-sublist-icon) 50% / 2rem 1.5rem !important;
|
||||
}
|
||||
@@ -152,6 +142,26 @@
|
||||
--aa-background-color-rgb: 0, 0, 0 !important;
|
||||
}
|
||||
|
||||
.DocSearch-Button {
|
||||
border-radius: 4px !important;
|
||||
border: 1px solid #2e2e2e !important;
|
||||
background-color: #070707ff !important;
|
||||
border-color: #a2a2a2ff !important;
|
||||
}
|
||||
|
||||
@media (max-width: 440px) {
|
||||
.DocSearch-Button {
|
||||
width: 34px !important;
|
||||
height: 34px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.DocSearch-Button:hover {
|
||||
outline: none !important;
|
||||
border-color: white !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
/*
|
||||
--ifm-color-primary: #25c2a0;
|
||||
@@ -175,27 +185,44 @@
|
||||
--aa-background-color-rgb: 0, 0, 0 !important;
|
||||
}
|
||||
|
||||
.aa-DetachedSearchButtonPlaceholder {
|
||||
font-size: 12px;
|
||||
[data-theme="light"] .DocSearch {
|
||||
/* --docsearch-primary-color: var(--ifm-color-primary); */
|
||||
/* --docsearch-text-color: var(--ifm-font-color-base); */
|
||||
--docsearch-muted-color: var(--ifm-color-secondary-darkest);
|
||||
--docsearch-container-background: rgba(94, 100, 112, 0.7);
|
||||
/* Modal */
|
||||
--docsearch-modal-background: var(--ifm-color-secondary-lighter);
|
||||
/* Search box */
|
||||
--docsearch-searchbox-background: var(--ifm-color-secondary);
|
||||
--docsearch-searchbox-focus-background: var(--ifm-color-white);
|
||||
/* Hit */
|
||||
--docsearch-hit-color: var(--ifm-font-color-base);
|
||||
--docsearch-hit-active-color: var(--ifm-color-white);
|
||||
--docsearch-hit-background: var(--ifm-color-white);
|
||||
/* Footer */
|
||||
--docsearch-footer-background: var(--ifm-color-white);
|
||||
}
|
||||
|
||||
.aa-DetachedSearchButton {
|
||||
margin-top: -1px !important;
|
||||
padding-right: 20px !important;
|
||||
border-color: #a2a2a2ff !important;
|
||||
color: #a2a2a2ff !important;
|
||||
}
|
||||
|
||||
.aa-DetachedSearchButton:hover {
|
||||
border-color: white !important;
|
||||
}
|
||||
|
||||
.aa-DetachedSearchButtonIcon {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.aa-DetachedFormContainer {
|
||||
border-bottom: none !important;
|
||||
[data-theme="dark"] .DocSearch {
|
||||
--docsearch-text-color: var(--ifm-font-color-base);
|
||||
--docsearch-muted-color: var(--ifm-color-secondary-darkest);
|
||||
--docsearch-container-background: rgba(47, 55, 69, 0.7);
|
||||
/* Modal */
|
||||
--docsearch-modal-background: var(--ifm-background-color);
|
||||
/* Search box */
|
||||
--docsearch-searchbox-background: var(--ifm-background-color);
|
||||
--docsearch-searchbox-focus-background: var(--ifm-color-black);
|
||||
/* Hit */
|
||||
--docsearch-hit-color: var(--ifm-font-color-base);
|
||||
--docsearch-hit-active-color: var(--ifm-color-white);
|
||||
--docsearch-hit-background: var(--ifm-color-emphasis-100);
|
||||
/* Footer */
|
||||
--docsearch-footer-background: var(--ifm-background-surface-color);
|
||||
--docsearch-key-gradient: linear-gradient(
|
||||
-26.5deg,
|
||||
var(--ifm-color-emphasis-200) 0%,
|
||||
var(--ifm-color-emphasis-100) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.header_docs_sdk {
|
||||
|
||||
18
website/src/theme/ColorModeToggle/index.js
vendored
18
website/src/theme/ColorModeToggle/index.js
vendored
@@ -17,19 +17,19 @@ function ColorModeToggle({ className, value, onChange }) {
|
||||
mode:
|
||||
value === "dark"
|
||||
? translate({
|
||||
message: "dark mode",
|
||||
id: "theme.colorToggle.ariaLabel.mode.dark",
|
||||
description: "The name for the dark color mode",
|
||||
})
|
||||
message: "dark mode",
|
||||
id: "theme.colorToggle.ariaLabel.mode.dark",
|
||||
description: "The name for the dark color mode",
|
||||
})
|
||||
: translate({
|
||||
message: "light mode",
|
||||
id: "theme.colorToggle.ariaLabel.mode.light",
|
||||
description: "The name for the light color mode",
|
||||
}),
|
||||
message: "light mode",
|
||||
id: "theme.colorToggle.ariaLabel.mode.light",
|
||||
description: "The name for the light color mode",
|
||||
}),
|
||||
}
|
||||
);
|
||||
return (
|
||||
<div className="flex gap-4 ml-4 md:ml-0">
|
||||
<div className="flex gap-4 mr-12 md:mr-0">
|
||||
<PopoverPrimitive.Root>
|
||||
<PopoverPrimitive.Trigger className="bg-grey-900 radix-state-open:text-white hover:border-grey-200 hover:text-grey-200 radix-state-open:border-white border -mt-[0.6px] h-[34px] w-[34px] text-grey-400 border-grey-400 rounded flex items-center justify-center">
|
||||
{value !== "dark" ? (
|
||||
|
||||
294
website/src/theme/Tabs/index.js
vendored
294
website/src/theme/Tabs/index.js
vendored
@@ -1,20 +1,34 @@
|
||||
import React, { useState, cloneElement, isValidElement } from 'react';
|
||||
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
||||
import clsx from 'clsx';
|
||||
import useIsBrowser from '@docusaurus/useIsBrowser';
|
||||
import { duplicates } from '@docusaurus/theme-common';
|
||||
import React, { cloneElement, useEffect } from "react";
|
||||
import clsx from "clsx";
|
||||
import {
|
||||
useScrollPositionBlocker,
|
||||
useTabGroupChoice,
|
||||
} from '@docusaurus/theme-common/internal';
|
||||
import styles from './styles.module.css';
|
||||
import { useLocation } from '@docusaurus/router';
|
||||
useTabs,
|
||||
} from "@docusaurus/theme-common/internal";
|
||||
import useIsBrowser from "@docusaurus/useIsBrowser";
|
||||
import styles from "./styles.module.css";
|
||||
import { useLocation } from "@docusaurus/router";
|
||||
import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
|
||||
|
||||
function getOSName() {
|
||||
const userAgent = ExecutionEnvironment.canUseDOM ? navigator.userAgent : "";
|
||||
if (userAgent.indexOf("Windows") > -1) {
|
||||
return "Windows";
|
||||
} else if (userAgent.indexOf("Mac") > -1) {
|
||||
return "Mac";
|
||||
} else if (userAgent.indexOf("X11") > -1) {
|
||||
return "UNIX";
|
||||
} else if (userAgent.indexOf("Linux") > -1) {
|
||||
return "Linux";
|
||||
} else {
|
||||
return "Other";
|
||||
}
|
||||
}
|
||||
|
||||
function getQueryVariable(query, variable) {
|
||||
// substring query
|
||||
const vars = query.substring(1).split('&');
|
||||
// substring query
|
||||
const vars = query.substring(1).split("&");
|
||||
for (let i = 0; i < vars.length; i++) {
|
||||
let pair = vars[i].split('=');
|
||||
let pair = vars[i].split("=");
|
||||
if (decodeURIComponent(pair[0]) == variable) {
|
||||
return decodeURIComponent(pair[1]);
|
||||
}
|
||||
@@ -22,137 +36,63 @@ function getQueryVariable(query, variable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// A very rough duck type, but good enough to guard against mistakes while
|
||||
// allowing customization
|
||||
function isTabItem(comp) {
|
||||
return 'value' in comp.props;
|
||||
}
|
||||
|
||||
function getOSName() {
|
||||
const userAgent = ExecutionEnvironment.canUseDOM ? navigator.userAgent : "";
|
||||
if (userAgent.indexOf('Windows') > -1) {
|
||||
return 'Windows';
|
||||
} else if (userAgent.indexOf('Mac') > -1) {
|
||||
return 'Mac';
|
||||
} else if (userAgent.indexOf('X11') > -1) {
|
||||
return 'UNIX';
|
||||
} else if (userAgent.indexOf('Linux') > -1) {
|
||||
return 'Linux';
|
||||
} else {
|
||||
return 'Other';
|
||||
}
|
||||
}
|
||||
|
||||
function getInstallationTabType() {
|
||||
const osName = getOSName();
|
||||
if (osName === 'Windows') {
|
||||
return 'windows';
|
||||
} else if (osName === 'Mac') {
|
||||
return 'mac';
|
||||
} else if(osName === 'Linux' || osName === 'UNIX') {
|
||||
return 'python';
|
||||
if (osName === "Windows") {
|
||||
return "windows";
|
||||
} else if (osName === "Mac") {
|
||||
return "mac";
|
||||
} else if (osName === "Linux" || osName === "UNIX") {
|
||||
return "python";
|
||||
}
|
||||
return 'windows';
|
||||
return "windows";
|
||||
}
|
||||
|
||||
function TabsComponent(props) {
|
||||
const {
|
||||
lazy,
|
||||
block,
|
||||
defaultValue: defaultValueProp,
|
||||
values: valuesProp,
|
||||
groupId,
|
||||
className,
|
||||
} = props;
|
||||
const children = React.Children.map(props.children, (child) => {
|
||||
if (isValidElement(child) && isTabItem(child)) {
|
||||
return child;
|
||||
}
|
||||
// child.type.name will give non-sensical values in prod because of
|
||||
// minification, but we assume it won't throw in prod.
|
||||
throw new Error(
|
||||
`Docusaurus error: Bad <Tabs> child <${
|
||||
// @ts-expect-error: guarding against unexpected cases
|
||||
typeof child.type === 'string' ? child.type : child.type.name
|
||||
}>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.`,
|
||||
);
|
||||
});
|
||||
const values =
|
||||
valuesProp ??
|
||||
// Only pick keys that we recognize. MDX would inject some keys by default
|
||||
children.map(({ props: { value, label, attributes } }) => ({
|
||||
value,
|
||||
label,
|
||||
attributes,
|
||||
}));
|
||||
const dup = duplicates(values, (a, b) => a.value === b.value);
|
||||
if (dup.length > 0) {
|
||||
throw new Error(
|
||||
`Docusaurus error: Duplicate values "${dup
|
||||
.map((a) => a.value)
|
||||
.join(', ')}" found in <Tabs>. Every value needs to be unique.`,
|
||||
);
|
||||
}
|
||||
// When defaultValueProp is null, don't show a default tab
|
||||
const defaultValue =
|
||||
defaultValueProp === null
|
||||
? defaultValueProp
|
||||
: defaultValueProp ??
|
||||
children.find((child) => child.props.default)?.props.value ??
|
||||
children[0].props.value;
|
||||
if (defaultValue !== null && !values.some((a) => a.value === defaultValue)) {
|
||||
throw new Error(
|
||||
`Docusaurus error: The <Tabs> has a defaultValue "${defaultValue}" but none of its children has the corresponding value. Available values are: ${values
|
||||
.map((a) => a.value)
|
||||
.join(
|
||||
', ',
|
||||
)}. If you intend to show no default tab, use defaultValue={null} instead.`,
|
||||
);
|
||||
}
|
||||
const { tabGroupChoices, setTabGroupChoices } = useTabGroupChoice();
|
||||
|
||||
const { pathname, search } = useLocation()
|
||||
const value = getQueryVariable(search, 'tab')
|
||||
const osTabValue = getInstallationTabType()
|
||||
const [selectedValue, setSelectedValue] = useState(pathname.startsWith("/terminal/quickstart/installation") ? value ? ['mac', 'windows', 'python', 'docker'].includes(value) ? value : osTabValue : osTabValue : defaultValue);
|
||||
function TabList({ className, block, selectedValue, selectValue, tabValues }) {
|
||||
const tabRefs = [];
|
||||
const { blockElementScrollPositionUntilNextRender } =
|
||||
useScrollPositionBlocker();
|
||||
if (groupId != null) {
|
||||
const relevantTabGroupChoice = tabGroupChoices[groupId];
|
||||
if (
|
||||
relevantTabGroupChoice != null &&
|
||||
relevantTabGroupChoice !== selectedValue &&
|
||||
values.some((value) => value.value === relevantTabGroupChoice)
|
||||
) {
|
||||
setSelectedValue(relevantTabGroupChoice);
|
||||
}
|
||||
}
|
||||
const { pathname, search } = useLocation();
|
||||
|
||||
const handleTabChange = (event) => {
|
||||
const newTab = event.currentTarget;
|
||||
const newTabIndex = tabRefs.indexOf(newTab);
|
||||
const newTabValue = values[newTabIndex].value;
|
||||
const newTabValue = tabValues[newTabIndex].value;
|
||||
if (newTabValue !== selectedValue) {
|
||||
blockElementScrollPositionUntilNextRender(newTab);
|
||||
setSelectedValue(newTabValue);
|
||||
if (groupId != null) {
|
||||
setTabGroupChoices(groupId, String(newTabValue));
|
||||
}
|
||||
selectValue(newTabValue);
|
||||
}
|
||||
};
|
||||
|
||||
if (ExecutionEnvironment.canUseDOM) {
|
||||
useEffect(() => {
|
||||
if (pathname.startsWith("/terminal/quickstart/installation")) {
|
||||
const value = getQueryVariable(search, "tab");
|
||||
const osTabValue = getInstallationTabType();
|
||||
selectValue(
|
||||
value
|
||||
? ["mac", "windows", "python", "docker"].includes(value)
|
||||
? value
|
||||
: osTabValue
|
||||
: osTabValue
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
}
|
||||
|
||||
const handleKeydown = (event) => {
|
||||
let focusElement = null;
|
||||
switch (event.key) {
|
||||
case 'Enter': {
|
||||
case "Enter": {
|
||||
handleTabChange(event);
|
||||
break;
|
||||
}
|
||||
case 'ArrowRight': {
|
||||
case "ArrowRight": {
|
||||
const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
|
||||
focusElement = tabRefs[nextTab] ?? tabRefs[0];
|
||||
break;
|
||||
}
|
||||
case 'ArrowLeft': {
|
||||
case "ArrowLeft": {
|
||||
const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
|
||||
focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1];
|
||||
break;
|
||||
@@ -162,63 +102,79 @@ function TabsComponent(props) {
|
||||
}
|
||||
focusElement?.focus();
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ul
|
||||
role="tablist"
|
||||
aria-orientation="horizontal"
|
||||
className={clsx(
|
||||
'_group-tab list-none -ml-7 my-6 overflow-auto',
|
||||
)}>
|
||||
{values.map(({ value, label, attributes }) => (
|
||||
<li
|
||||
role="tab"
|
||||
tabIndex={selectedValue === value ? 0 : -1}
|
||||
aria-selected={selectedValue === value}
|
||||
key={value}
|
||||
ref={(tabControl) => tabRefs.push(tabControl)}
|
||||
onKeyDown={handleKeydown}
|
||||
onClick={handleTabChange}
|
||||
{...attributes}
|
||||
className={clsx(
|
||||
'font-bold tracking-widest w-fit px-3 inline-flex py-1 uppercase border-b text-lg cursor-pointer',
|
||||
styles.tabItem,
|
||||
attributes?.className,
|
||||
{
|
||||
'border-b-2 pointer-events-none': selectedValue === value,
|
||||
'border-b-2 text-[#669dcb] border-[#669dcb]': selectedValue === value && pathname.startsWith("/terminal"),
|
||||
'border-b-2 text-[#FB923C] border-[#FB923C]': selectedValue === value && pathname.startsWith("/sdk"),
|
||||
'border-grey-400 text-grey-400 hover:text-[#ffd4b1] hover:border-[#ffd4b1]': selectedValue !== value && pathname.startsWith("/sdk"),
|
||||
'border-grey-400 text-grey-400 hover:text-[#abd2f1] hover:border-[#abd2f1]': selectedValue !== value && pathname.startsWith("/terminal"),
|
||||
},
|
||||
)}>
|
||||
{label ?? value}
|
||||
</li>
|
||||
))}
|
||||
<li className='w-full border-b border-grey-400 pointer-events-none py-1 mb-[12px]'></li>
|
||||
</ul>
|
||||
|
||||
{lazy ? (
|
||||
cloneElement(
|
||||
children.filter(
|
||||
(tabItem) => tabItem.props.value === selectedValue,
|
||||
)[0],
|
||||
{ className: 'margin-top--md' },
|
||||
)
|
||||
) : (
|
||||
<div className="margin-top--md">
|
||||
{children.map((tabItem, i) =>
|
||||
cloneElement(tabItem, {
|
||||
key: i,
|
||||
hidden: tabItem.props.value !== selectedValue,
|
||||
}),
|
||||
<ul
|
||||
role="tablist"
|
||||
aria-orientation="horizontal"
|
||||
className={clsx("_group-tab list-none -ml-7 my-6 overflow-auto")}
|
||||
>
|
||||
{tabValues.map(({ value, label, attributes }) => (
|
||||
<li
|
||||
// TODO extract TabListItem
|
||||
role="tab"
|
||||
tabIndex={selectedValue === value ? 0 : -1}
|
||||
aria-selected={selectedValue === value}
|
||||
key={value}
|
||||
ref={(tabControl) => tabRefs.push(tabControl)}
|
||||
onKeyDown={handleKeydown}
|
||||
onClick={handleTabChange}
|
||||
{...attributes}
|
||||
className={clsx(
|
||||
"font-bold tracking-widest w-fit px-3 inline-flex py-1 uppercase border-b text-lg cursor-pointer",
|
||||
styles.tabItem,
|
||||
attributes?.className,
|
||||
{
|
||||
"border-b-2 pointer-events-none": selectedValue === value,
|
||||
"border-b-2 text-[#669dcb] border-[#669dcb]":
|
||||
selectedValue === value && pathname.startsWith("/terminal"),
|
||||
"border-b-2 text-[#FB923C] border-[#FB923C]":
|
||||
selectedValue === value && pathname.startsWith("/sdk"),
|
||||
"border-grey-400 text-grey-400 hover:text-[#ffd4b1] hover:border-[#ffd4b1]":
|
||||
selectedValue !== value && pathname.startsWith("/sdk"),
|
||||
"border-grey-400 text-grey-400 hover:text-[#abd2f1] hover:border-[#abd2f1]":
|
||||
selectedValue !== value && pathname.startsWith("/terminal"),
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
>
|
||||
{label ?? value}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
function TabContent({ lazy, children, selectedValue }) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
children = Array.isArray(children) ? children : [children];
|
||||
if (lazy) {
|
||||
const selectedTabItem = children.find(
|
||||
(tabItem) => tabItem.props.value === selectedValue
|
||||
);
|
||||
if (!selectedTabItem) {
|
||||
// fail-safe or fail-fast? not sure what's best here
|
||||
return null;
|
||||
}
|
||||
return cloneElement(selectedTabItem, { className: "margin-top--md" });
|
||||
}
|
||||
return (
|
||||
<div className="margin-top--md">
|
||||
{children.map((tabItem, i) =>
|
||||
cloneElement(tabItem, {
|
||||
key: i,
|
||||
hidden: tabItem.props.value !== selectedValue,
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function TabsComponent(props) {
|
||||
const tabs = useTabs(props);
|
||||
return (
|
||||
<div className={clsx("tabs-container", styles.tabList)}>
|
||||
<TabList {...props} {...tabs} />
|
||||
<TabContent {...props} {...tabs} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default function Tabs(props) {
|
||||
const isBrowser = useIsBrowser();
|
||||
return (
|
||||
|
||||
11468
website/yarn.lock
vendored
11468
website/yarn.lock
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user