diff --git a/packages/app/.storybook/preview.tsx b/packages/app/.storybook/preview.tsx
index 6a3076082..8a96bea44 100644
--- a/packages/app/.storybook/preview.tsx
+++ b/packages/app/.storybook/preview.tsx
@@ -1,5 +1,6 @@
import React from 'react';
import type { Preview } from '@storybook/react';
+import { QueryClient, QueryClientProvider } from 'react-query';
import '@mantine/core/styles.css';
import '@mantine/notifications/styles.css';
@@ -9,12 +10,16 @@ import '../src/LandingPage.scss';
import { ThemeWrapper } from '../src/ThemeWrapper';
+const queryClient = new QueryClient();
+
const preview: Preview = {
decorators: [
Story => (
-
-
-
+
+
+
+
+
),
],
};
diff --git a/packages/app/package.json b/packages/app/package.json
index fbeeaf7b0..8980d6f24 100644
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -23,6 +23,7 @@
"@hyperdx/lucene": "^3.1.1",
"@lezer/highlight": "^1.2.0",
"@mantine/core": "7.9.2",
+ "@mantine/form": "^7.10.1",
"@mantine/hooks": "7.9.2",
"@mantine/notifications": "^7.9.2",
"@mantine/spotlight": "7.9.2",
diff --git a/packages/app/pages/_app.tsx b/packages/app/pages/_app.tsx
index 61442329d..9c92a5836 100644
--- a/packages/app/pages/_app.tsx
+++ b/packages/app/pages/_app.tsx
@@ -122,10 +122,10 @@ export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
{getLayout( )}
+ {confirmModal}
+ {background}
- {confirmModal}
- {background}
diff --git a/packages/app/src/AppNav.tsx b/packages/app/src/AppNav.tsx
index 747f63610..59cbfa0a9 100644
--- a/packages/app/src/AppNav.tsx
+++ b/packages/app/src/AppNav.tsx
@@ -3,7 +3,6 @@ import Link from 'next/link';
import Router, { useRouter } from 'next/router';
import cx from 'classnames';
import Fuse from 'fuse.js';
-import { Button } from 'react-bootstrap';
import {
NumberParam,
StringParam,
@@ -14,7 +13,7 @@ import {
import HyperDX from '@hyperdx/browser';
import {
ActionIcon,
- Button as MButton,
+ Button,
CloseButton,
Collapse,
Input,
@@ -939,16 +938,15 @@ export default function AppNav({ fixed = false }: { fixed?: boolean }) {
)}
- setIsPreferCollapsed(v => !v)}
>
-
+
@@ -1328,14 +1326,14 @@ export default function AppNav({ fixed = false }: { fixed?: boolean }) {
passHref
legacyBehavior
>
-
Get Started for Free
-
+
diff --git a/packages/app/src/Clipboard.tsx b/packages/app/src/Clipboard.tsx
index 34b1f626a..e95aadfbe 100644
--- a/packages/app/src/Clipboard.tsx
+++ b/packages/app/src/Clipboard.tsx
@@ -1,7 +1,7 @@
import { useState } from 'react';
import cx from 'classnames';
-import { Button } from 'react-bootstrap';
import { CopyToClipboard } from 'react-copy-to-clipboard';
+import { UnstyledButton } from '@mantine/core';
export default function Clipboard({
text,
@@ -22,12 +22,9 @@ export default function Clipboard({
setTimeout(() => setIsCopied(false), 2000);
}}
>
-
+
{children({ isCopied })}
-
+
);
}
diff --git a/packages/app/src/InstallInstructionsModal.stories.tsx b/packages/app/src/InstallInstructionsModal.stories.tsx
new file mode 100644
index 000000000..77a3a5825
--- /dev/null
+++ b/packages/app/src/InstallInstructionsModal.stories.tsx
@@ -0,0 +1,13 @@
+import type { Meta } from '@storybook/react';
+
+import InstallInstructionsModal from './InstallInstructionsModal';
+
+const meta = {
+ component: InstallInstructionsModal,
+} satisfies Meta;
+
+export default meta;
+
+export const Default = () => {
+ return {}} />;
+};
diff --git a/packages/app/src/InstallInstructionsModal.tsx b/packages/app/src/InstallInstructionsModal.tsx
index e99fda763..200380616 100644
--- a/packages/app/src/InstallInstructionsModal.tsx
+++ b/packages/app/src/InstallInstructionsModal.tsx
@@ -1,5 +1,5 @@
import cx from 'classnames';
-import { Button, Modal } from 'react-bootstrap';
+import { Button, Modal } from '@mantine/core';
import api from './api';
import Clipboard from './Clipboard';
@@ -56,156 +56,153 @@ export default function InstallInstructionModal({
return (
-
- Install HyperDX
- {team != null && (
-
- Your API Key: }
- value={team.apiKey}
- />
-
- )}
-
- Click on a link below to view installation instructions for your
- application.
-
- Backend
-
-
-
-
-
-
- Platform
-
-
-
- Browser
-
- Data Collector
-
-
-
-
onHide()}>
- Cancel
-
+ {team != null && (
+
+ Your API Key: }
+ value={team.apiKey}
+ />
-
+ )}
+
+ Click on a link below to view installation instructions for your
+ application.
+
+
Backend
+
+
+
+
+
+
+
Platform
+
+
+
+
Browser
+
+
Data Collector
+
+
+
+ onHide()}>
+ Cancel
+
+
);
}
diff --git a/packages/app/src/JoinTeamPage.stories.tsx b/packages/app/src/JoinTeamPage.stories.tsx
new file mode 100644
index 000000000..43d8f30fc
--- /dev/null
+++ b/packages/app/src/JoinTeamPage.stories.tsx
@@ -0,0 +1,13 @@
+import type { Meta, StoryObj } from '@storybook/react';
+
+import JoinTeamPage from './JoinTeamPage';
+
+const meta = {
+ component: JoinTeamPage,
+} satisfies Meta
;
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {};
diff --git a/packages/app/src/JoinTeamPage.tsx b/packages/app/src/JoinTeamPage.tsx
index 0cc9c13c9..cda6b769e 100644
--- a/packages/app/src/JoinTeamPage.tsx
+++ b/packages/app/src/JoinTeamPage.tsx
@@ -1,6 +1,13 @@
import { useRouter } from 'next/router';
import { NextSeo } from 'next-seo';
-import { Button, Form } from 'react-bootstrap';
+import {
+ Button,
+ Card,
+ Center,
+ PasswordInput,
+ Stack,
+ Text,
+} from '@mantine/core';
import { SERVER_URL } from './config';
@@ -11,58 +18,30 @@ export default function JoinTeam() {
return (
-
-
-
-
Join Team
-
-
-
-
- Password
-
-
- {err != null && (
-
- {err === 'invalid'
+
+
+
-
-
-
-
+ : 'Unknown error occurred, please try again later.'
+ : null
+ }
+ />
+
+ Setup a password
+
+
+
+
+
);
}
diff --git a/packages/app/src/LandingHeader.stories.tsx b/packages/app/src/LandingHeader.stories.tsx
new file mode 100644
index 000000000..93756aa39
--- /dev/null
+++ b/packages/app/src/LandingHeader.stories.tsx
@@ -0,0 +1,17 @@
+import type { Meta, StoryObj } from '@storybook/react';
+
+import LandingHeader from './LandingHeader';
+
+const meta = {
+ component: LandingHeader,
+} satisfies Meta
;
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ activeKey: 'activeKey',
+ },
+};
diff --git a/packages/app/src/LandingHeader.tsx b/packages/app/src/LandingHeader.tsx
index 3840e03d5..da1713359 100644
--- a/packages/app/src/LandingHeader.tsx
+++ b/packages/app/src/LandingHeader.tsx
@@ -3,7 +3,6 @@ import { Button, Container, Nav, Navbar, NavDropdown } from 'react-bootstrap';
import api from './api';
import Logo from './Logo';
-import NavHoverDropdown from './NavHoverDropdown';
export default function LandingHeader({
activeKey,
diff --git a/packages/app/src/NavHoverDropdown.tsx b/packages/app/src/NavHoverDropdown.tsx
deleted file mode 100644
index 57856d760..000000000
--- a/packages/app/src/NavHoverDropdown.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { useState } from 'react';
-import { NavDropdown } from 'react-bootstrap';
-
-export default function NavHoverDropdown(
- props: React.ComponentProps,
-) {
- const [show, setShow] = useState(false);
- return (
- setShow(v => !v)}
- onMouseEnter={() => setShow(true)}
- onMouseLeave={() => setShow(false)}
- />
- );
-}
diff --git a/packages/app/src/PasswordResetPage.stories.tsx b/packages/app/src/PasswordResetPage.stories.tsx
new file mode 100644
index 000000000..31b2f34fb
--- /dev/null
+++ b/packages/app/src/PasswordResetPage.stories.tsx
@@ -0,0 +1,19 @@
+import type { Meta, StoryObj } from '@storybook/react';
+
+import PasswordResetPage from './PasswordResetPage';
+
+const meta = {
+ component: PasswordResetPage,
+} satisfies Meta;
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Forgot = () => {
+ return ;
+};
+
+export const ResetPassword = () => {
+ return ;
+};
diff --git a/packages/app/src/SaveSearchModal.tsx b/packages/app/src/SaveSearchModal.tsx
index 98a3efbab..de903b423 100644
--- a/packages/app/src/SaveSearchModal.tsx
+++ b/packages/app/src/SaveSearchModal.tsx
@@ -1,6 +1,6 @@
import { FormEvent, useEffect, useState } from 'react';
-import { Button, Form, Modal } from 'react-bootstrap';
-import { Button as MButton, Text } from '@mantine/core';
+import { Form, Modal } from 'react-bootstrap';
+import { Button as Button, Text } from '@mantine/core';
import { notifications } from '@mantine/notifications';
import api from './api';
@@ -115,9 +115,9 @@ export default function SaveSearchModal({
defaultValue={searchName}
/>
-
+
{mode === 'update' ? 'Update' : 'Save'}
-
+
diff --git a/packages/app/src/SearchPage.tsx b/packages/app/src/SearchPage.tsx
index d0e3fb606..f04d0029a 100644
--- a/packages/app/src/SearchPage.tsx
+++ b/packages/app/src/SearchPage.tsx
@@ -14,7 +14,6 @@ import { useRouter } from 'next/router';
import cx from 'classnames';
import { clamp, format, sub } from 'date-fns';
import { formatInTimeZone } from 'date-fns-tz';
-import { Button } from 'react-bootstrap';
import { ErrorBoundary } from 'react-error-boundary';
import { useHotkeys } from 'react-hotkeys-hook';
import {
@@ -32,7 +31,7 @@ import {
useQueryParams,
withDefault,
} from 'use-query-params';
-import { ActionIcon, Indicator } from '@mantine/core';
+import { ActionIcon, Button, Indicator } from '@mantine/core';
import { notifications } from '@mantine/notifications';
import api from './api';
@@ -984,13 +983,15 @@ function SearchPage() {
{
setIsLive(true);
}}
+ leftSection={
+
+ }
>
-
Resume Live Tail
diff --git a/packages/app/src/TeamPage.tsx b/packages/app/src/TeamPage.tsx
index 36f3f62a1..8594facc3 100644
--- a/packages/app/src/TeamPage.tsx
+++ b/packages/app/src/TeamPage.tsx
@@ -1,7 +1,6 @@
import { useCallback, useState } from 'react';
import Head from 'next/head';
import {
- Button,
Form,
Modal,
Row,
@@ -41,6 +40,11 @@ import CodeMirror, { placeholder } from '@uiw/react-codemirror';
import api from './api';
import { withAppNav } from './layout';
import { WebhookFlatIcon } from './SVGIcons';
+import {
+ AddSlackWebhookModal,
+ ConfirmDeleteTeamMember,
+ ConfirmRotateAPIKeyModal,
+} from './TeamPageComponents';
import { WebhookService } from './types';
import { truncateMiddle } from './utils';
import { isValidJson, isValidUrl } from './utils';
@@ -349,12 +353,18 @@ export default function TeamPage() {
setTeamInviteModalShow(false);
};
- const onSubmitAddWebhookForm = (e: any, service: WebhookService) => {
- e.preventDefault();
- const name = e.target.name.value;
- const description = e.target.description.value;
- const url = e.target.url.value;
-
+ const onSubmitAddWebhookForm = (
+ {
+ name,
+ description,
+ url,
+ }: {
+ name: string;
+ description?: string;
+ url: string;
+ },
+ service: WebhookService,
+ ) => {
if (!name) {
notifications.show({
color: 'red',
@@ -526,42 +536,11 @@ export default function TeamPage() {
)}
-
- setRotateApiKeyConfirmationModalShow(false)}
- show={rotateApiKeyConfirmationModalShow}
- size="lg"
- >
-
- Rotate API Key
-
- Rotating the API key will invalidate your existing API
- key and generate a new one for you. This action is not
- reversible.
-
-
- setRotateApiKeyConfirmationModalShow(false)
- }
- >
- Cancel
-
-
- Confirm
-
-
-
-
+
setRotateApiKeyConfirmationModalShow(false)}
+ onConfirm={onConfirmUpdateTeamApiKey}
+ />
{!isLoadingMe && me != null && (
@@ -636,63 +615,13 @@ export default function TeamPage() {
Add Slack Incoming Webhook
- setAddSlackWebhookModalShow(false)}
- show={addSlackWebhookModalShow}
- size="lg"
- >
-
- Add Slack Incoming Webhook
-
- Webhook Name
-
-
-
- Webhook URL
-
-
-
- Webhook Description (optional)
-
-
-
- Add
-
-
-
-
+ setAddSlackWebhookModalShow(false)}
+ onSubmit={webhook =>
+ onSubmitAddWebhookForm(webhook, WebhookService.Slack)
+ }
+ />
@@ -768,9 +697,17 @@ export default function TeamPage() {
Add Generic Incoming Webhook
Webhook Name
@@ -904,56 +841,23 @@ export default function TeamPage() {
)}
>
)}
-
+
setDeleteTeamMemberConfirmationModalData({
mode: null,
id: null,
email: null,
})
}
- show={deleteTeamMemberConfirmationModalData.id != null}
- size="lg"
- >
-
- Delete Team Member
-
- Deleting this team member (
- {deleteTeamMemberConfirmationModalData.email}) will revoke
- their access to the team's resources and services. This
- action is not reversible.
-
-
- setDeleteTeamMemberConfirmationModalData({
- mode: null,
- id: null,
- email: null,
- })
- }
- >
- Cancel
-
-
- deleteTeamMemberConfirmationModalData.id &&
- onConfirmDeleteTeamMember(
- deleteTeamMemberConfirmationModalData.id,
- )
- }
- >
- Confirm
-
-
-
+ onConfirm={() => {
+ deleteTeamMemberConfirmationModalData.id &&
+ onConfirmDeleteTeamMember(
+ deleteTeamMemberConfirmationModalData.id,
+ );
+ }}
+ email={deleteTeamMemberConfirmationModalData.email}
+ />
Team
diff --git a/packages/app/src/TeamPageComponents.stories.tsx b/packages/app/src/TeamPageComponents.stories.tsx
new file mode 100644
index 000000000..f536fe82e
--- /dev/null
+++ b/packages/app/src/TeamPageComponents.stories.tsx
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/react';
+
+import {
+ AddSlackWebhookModal,
+ ConfirmDeleteTeamMember,
+ ConfirmRotateAPIKeyModal,
+} from './TeamPageComponents';
+
+const meta = {
+ component: ConfirmRotateAPIKeyModal,
+} satisfies Meta;
+
+export default meta;
+
+type Story = StoryObj;
+
+export const ConfirmRotateAPIKeyModalStory = () => {
+ return ;
+};
+
+export const AddSlackWebhookModalStory = () => {
+ return ;
+};
+
+export const ConfirmDeleteTeamMemberStory = () => {
+ return ;
+};
diff --git a/packages/app/src/TeamPageComponents.tsx b/packages/app/src/TeamPageComponents.tsx
new file mode 100644
index 000000000..5ddd036cd
--- /dev/null
+++ b/packages/app/src/TeamPageComponents.tsx
@@ -0,0 +1,136 @@
+import React from 'react';
+import { Button, Group, Modal, Stack, Text, TextInput } from '@mantine/core';
+import { useForm } from '@mantine/form';
+
+export const ConfirmRotateAPIKeyModal = ({
+ opened,
+ onClose,
+ onConfirm,
+}: {
+ opened: boolean;
+ onClose: VoidFunction;
+ onConfirm: VoidFunction;
+}) => (
+
+
+ Rotating the API key will invalidate your existing API key and generate a
+ new one for you. This action is not reversible.
+
+
+
+ Cancel
+
+
+ Confirm
+
+
+
+);
+
+export const AddSlackWebhookModal = ({
+ opened,
+ onClose,
+ onSubmit = () => {},
+}: {
+ opened: boolean;
+ onClose: VoidFunction;
+ onSubmit?: (arg0: {
+ name: string;
+ description?: string;
+ url: string;
+ }) => void;
+}) => {
+ const form = useForm<{
+ name: string;
+ url: string;
+ description?: string;
+ }>({
+ mode: 'uncontrolled',
+ validate: {
+ name: value => (value.trim().length > 0 ? null : 'Name is required'),
+ url: value => (value.startsWith('http') ? null : 'Invalid URL'),
+ },
+ });
+
+ React.useEffect(() => {
+ form.reset();
+ }, [opened]);
+
+ return (
+
+
+
+ );
+};
+
+export const ConfirmDeleteTeamMember = ({
+ email,
+ opened,
+ onClose,
+ onConfirm,
+}: {
+ email?: string | null;
+ opened: boolean;
+ onClose: VoidFunction;
+ onConfirm: VoidFunction;
+}) => (
+
+
+ Deleting this team member {email && ({email}) } will
+ revoke their access to the team's resources and services. This action
+ is not reversible.
+
+
+
+ Cancel
+
+
+ Confirm
+
+
+
+);
diff --git a/packages/app/src/ThemeWrapper.tsx b/packages/app/src/ThemeWrapper.tsx
index acb4b93ae..b00daa72d 100644
--- a/packages/app/src/ThemeWrapper.tsx
+++ b/packages/app/src/ThemeWrapper.tsx
@@ -3,7 +3,7 @@ import { MantineProvider, MantineThemeOverride } from '@mantine/core';
import { Notifications } from '@mantine/notifications';
const makeTheme = ({
- fontFamily = 'IBM Plex Sans, sans-serif',
+ fontFamily = '"IBM Plex Sans", monospace',
}: {
fontFamily?: string;
}): MantineThemeOverride => ({
diff --git a/packages/app/src/useConfirm.tsx b/packages/app/src/useConfirm.tsx
index 7b0ec6b66..8c9e41130 100644
--- a/packages/app/src/useConfirm.tsx
+++ b/packages/app/src/useConfirm.tsx
@@ -1,7 +1,6 @@
import * as React from 'react';
import { atom, useAtomValue, useSetAtom } from 'jotai';
-import Button from 'react-bootstrap/Button';
-import Modal from 'react-bootstrap/Modal';
+import { Button, Modal } from '@mantine/core';
type ConfirmAtom = {
message: string;
@@ -46,18 +45,15 @@ export const useConfirmModal = () => {
}, [confirm, setConfirm]);
return confirm ? (
-
-
- {confirm.message}
-
-
- Cancel
-
-
- {confirm.confirmLabel || 'OK'}
-
-
-
+
+
+
+ Cancel
+
+
+ {confirm.confirmLabel || 'OK'}
+
+
) : null;
};
diff --git a/yarn.lock b/yarn.lock
index 5ae7e0447..5d4fe4a56 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3530,6 +3530,14 @@
react-textarea-autosize "8.5.3"
type-fest "^4.12.0"
+"@mantine/form@^7.10.1":
+ version "7.10.1"
+ resolved "https://registry.yarnpkg.com/@mantine/form/-/form-7.10.1.tgz#86b867454b7490f4ca58c924d85d4170520cec4d"
+ integrity sha512-mZwzg4GEWKEDKEIZu9FmSpGFzYYhFD2YArVOXUM0MMciUqX7yxSCon1PaPJxrV8ldc6FE+JLVI2+G2KVxJ3ZXA==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+ klona "^2.0.6"
+
"@mantine/hooks@7.9.2":
version "7.9.2"
resolved "https://registry.yarnpkg.com/@mantine/hooks/-/hooks-7.9.2.tgz#5cb2abc5b293b6571456443cee858f98503cc7c5"
@@ -6768,7 +6776,7 @@
dependencies:
"@types/react" "*"
-"@types/react@*", "@types/react@18.2.23", "@types/react@>=16", "@types/react@>=16.9.11":
+"@types/react@*", "@types/react@18.2.23", "@types/react@>=16", "@types/react@>=16.9.11", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0":
version "18.2.23"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.23.tgz#60ad6cf4895e93bed858db0e03bcc4ff97d0410e"
integrity sha512-qHLW6n1q2+7KyBEYnrZpcsAmU/iiCh9WGCKgXvMxx89+TYdJWRjZohVIo9XTcoLhfX3+/hP0Pbulu3bCZQ9PSA==
@@ -6777,14 +6785,6 @@
"@types/scheduler" "*"
csstype "^3.0.2"
-"@types/react@^16.8.0 || ^17.0.0 || ^18.0.0":
- version "18.3.3"
- resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f"
- integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==
- dependencies:
- "@types/prop-types" "*"
- csstype "^3.0.2"
-
"@types/resolve@^1.20.2":
version "1.20.6"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.6.tgz#e6e60dad29c2c8c206c026e6dd8d6d1bdda850b8"
@@ -13075,7 +13075,7 @@ kleur@^4.0.3, kleur@^4.1.5:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780"
integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==
-klona@^2.0.4:
+klona@^2.0.4, klona@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22"
integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==
@@ -15635,6 +15635,7 @@ prelude-ls@~1.1.2:
integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==
"prettier-fallback@npm:prettier@^3", prettier@^3.1.1:
+ name prettier-fallback
version "3.2.5"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368"
integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==
@@ -16346,14 +16347,7 @@ react-useportal@^1.0.18:
dependencies:
use-ssr "^1.0.25"
-"react@^16.8.0 || ^17.0.0 || ^18.0.0":
- version "18.3.1"
- resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
- integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
- dependencies:
- loose-envify "^1.1.0"
-
-react@^18.2.0:
+"react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==